1//===- subzero/src/IceInstARM32.cpp - ARM32 instruction implementation ----===//
2//
3//                        The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief Implements the InstARM32 and OperandARM32 classes, primarily the
12/// constructors and the dump()/emit() methods.
13///
14//===----------------------------------------------------------------------===//
15
16#include "IceInstARM32.h"
17
18#include "IceAssemblerARM32.h"
19#include "IceCfg.h"
20#include "IceCfgNode.h"
21#include "IceInst.h"
22#include "IceOperand.h"
23#include "IceTargetLoweringARM32.h"
24
25namespace Ice {
26namespace ARM32 {
27
28namespace {
29
30using Register = RegARM32::AllRegisters;
31
32// maximum number of registers allowed in vpush/vpop.
33static constexpr SizeT VpushVpopMaxConsecRegs = 16;
34
35const struct TypeARM32Attributes_ {
36  const char *WidthString;     // b, h, <blank>, or d
37  const char *FpWidthString;   // i8, i16, i32, f32, f64
38  const char *SVecWidthString; // s8, s16, s32, f32
39  const char *UVecWidthString; // u8, u16, u32, f32
40  int8_t SExtAddrOffsetBits;
41  int8_t ZExtAddrOffsetBits;
42} TypeARM32Attributes[] = {
43#define X(tag, elementty, int_width, fp_width, uvec_width, svec_width, sbits,  \
44          ubits, rraddr, shaddr)                                               \
45  { int_width, fp_width, svec_width, uvec_width, sbits, ubits }                \
46  ,
47    ICETYPEARM32_TABLE
48#undef X
49};
50
51const struct InstARM32ShiftAttributes_ {
52  const char *EmitString;
53} InstARM32ShiftAttributes[] = {
54#define X(tag, emit)                                                           \
55  { emit }                                                                     \
56  ,
57    ICEINSTARM32SHIFT_TABLE
58#undef X
59};
60
61const struct InstARM32CondAttributes_ {
62  CondARM32::Cond Opposite;
63  const char *EmitString;
64} InstARM32CondAttributes[] = {
65#define X(tag, encode, opp, emit)                                              \
66  { CondARM32::opp, emit }                                                     \
67  ,
68    ICEINSTARM32COND_TABLE
69#undef X
70};
71
72size_t getVecElmtBitsize(Type Ty) {
73  return typeWidthInBytes(typeElementType(Ty)) * CHAR_BIT;
74}
75
76const char *getWidthString(Type Ty) {
77  return TypeARM32Attributes[Ty].WidthString;
78}
79
80const char *getFpWidthString(Type Ty) {
81  return TypeARM32Attributes[Ty].FpWidthString;
82}
83
84const char *getSVecWidthString(Type Ty) {
85  return TypeARM32Attributes[Ty].SVecWidthString;
86}
87
88const char *getUVecWidthString(Type Ty) {
89  return TypeARM32Attributes[Ty].UVecWidthString;
90}
91
92const char *getVWidthString(Type Ty, InstARM32::FPSign SignType) {
93  switch (SignType) {
94  case InstARM32::FS_None:
95    return getFpWidthString(Ty);
96  case InstARM32::FS_Signed:
97    return getSVecWidthString(Ty);
98  case InstARM32::FS_Unsigned:
99    return getUVecWidthString(Ty);
100  }
101  llvm_unreachable("Invalid Sign Type.");
102  return getFpWidthString(Ty);
103}
104
105} // end of anonymous namespace
106
107const char *InstARM32Pred::predString(CondARM32::Cond Pred) {
108  return InstARM32CondAttributes[Pred].EmitString;
109}
110
111void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode,
112                                   Type Ty) const {
113  Str << Opcode << getPredicate() << "." << Ty;
114}
115
116CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) {
117  return InstARM32CondAttributes[Cond].Opposite;
118}
119
120void InstARM32::startNextInst(const Cfg *Func) const {
121  if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>())
122    Asm->incEmitTextSize(InstSize);
123}
124
125void InstARM32::emitUsingTextFixup(const Cfg *Func) const {
126  if (!BuildDefs::dump())
127    return;
128  GlobalContext *Ctx = Func->getContext();
129  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
130  if (getFlags().getDisableHybridAssembly() &&
131      getFlags().getSkipUnimplemented()) {
132    Asm->trap();
133    Asm->resetNeedsTextFixup();
134    return;
135  }
136  std::string Buffer;
137  llvm::raw_string_ostream StrBuf(Buffer);
138  OstreamLocker L(Ctx);
139  Ostream &OldStr = Ctx->getStrEmit();
140  Ctx->setStrEmit(StrBuf);
141  // Start counting instructions here, so that emit() methods don't
142  // need to call this for the first instruction.
143  Asm->resetEmitTextSize();
144  Asm->incEmitTextSize(InstSize);
145  emit(Func);
146  Ctx->setStrEmit(OldStr);
147  if (getFlags().getDisableHybridAssembly()) {
148    if (getFlags().getSkipUnimplemented()) {
149      Asm->trap();
150    } else {
151      llvm::errs() << "Can't assemble: " << StrBuf.str() << "\n";
152      UnimplementedError(getFlags());
153    }
154    Asm->resetNeedsTextFixup();
155    return;
156  }
157  Asm->emitTextInst(StrBuf.str(), Asm->getEmitTextSize());
158}
159
160void InstARM32::emitIAS(const Cfg *Func) const { emitUsingTextFixup(Func); }
161
162void InstARM32Pred::emitUnaryopGPR(const char *Opcode,
163                                   const InstARM32Pred *Instr, const Cfg *Func,
164                                   bool NeedsWidthSuffix) {
165  Ostream &Str = Func->getContext()->getStrEmit();
166  assert(Instr->getSrcSize() == 1);
167  Type SrcTy = Instr->getSrc(0)->getType();
168  Str << "\t" << Opcode;
169  if (NeedsWidthSuffix)
170    Str << getWidthString(SrcTy);
171  Str << Instr->getPredicate() << "\t";
172  Instr->getDest()->emit(Func);
173  Str << ", ";
174  Instr->getSrc(0)->emit(Func);
175}
176
177void InstARM32Pred::emitUnaryopFP(const char *Opcode, FPSign Sign,
178                                  const InstARM32Pred *Instr, const Cfg *Func) {
179  Ostream &Str = Func->getContext()->getStrEmit();
180  assert(Instr->getSrcSize() == 1);
181  Type SrcTy = Instr->getSrc(0)->getType();
182  Str << "\t" << Opcode << Instr->getPredicate();
183  switch (Sign) {
184  case FS_None:
185    Str << getFpWidthString(SrcTy);
186    break;
187  case FS_Signed:
188    Str << getSVecWidthString(SrcTy);
189    break;
190  case FS_Unsigned:
191    Str << getUVecWidthString(SrcTy);
192    break;
193  }
194  Str << "\t";
195  Instr->getDest()->emit(Func);
196  Str << ", ";
197  Instr->getSrc(0)->emit(Func);
198}
199
200void InstARM32Pred::emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr,
201                                const Cfg *Func) {
202  if (!BuildDefs::dump())
203    return;
204  Ostream &Str = Func->getContext()->getStrEmit();
205  assert(Instr->getSrcSize() == 2);
206  Variable *Dest = Instr->getDest();
207  assert(Dest == Instr->getSrc(0));
208  Str << "\t" << Opcode << Instr->getPredicate() << "\t";
209  Dest->emit(Func);
210  Str << ", ";
211  Instr->getSrc(1)->emit(Func);
212}
213
214void InstARM32Pred::emitThreeAddr(const char *Opcode,
215                                  const InstARM32Pred *Instr, const Cfg *Func,
216                                  bool SetFlags) {
217  if (!BuildDefs::dump())
218    return;
219  Ostream &Str = Func->getContext()->getStrEmit();
220  assert(Instr->getSrcSize() == 2);
221  Str << "\t" << Opcode << (SetFlags ? "s" : "") << Instr->getPredicate()
222      << "\t";
223  Instr->getDest()->emit(Func);
224  Str << ", ";
225  Instr->getSrc(0)->emit(Func);
226  Str << ", ";
227  Instr->getSrc(1)->emit(Func);
228}
229
230void InstARM32::emitThreeAddrFP(const char *Opcode, FPSign SignType,
231                                const InstARM32 *Instr, const Cfg *Func,
232                                Type OpType) {
233  if (!BuildDefs::dump())
234    return;
235  Ostream &Str = Func->getContext()->getStrEmit();
236  assert(Instr->getSrcSize() == 2);
237  Str << "\t" << Opcode << getVWidthString(OpType, SignType) << "\t";
238  Instr->getDest()->emit(Func);
239  Str << ", ";
240  Instr->getSrc(0)->emit(Func);
241  Str << ", ";
242  Instr->getSrc(1)->emit(Func);
243}
244
245void InstARM32::emitFourAddrFP(const char *Opcode, FPSign SignType,
246                               const InstARM32 *Instr, const Cfg *Func) {
247  if (!BuildDefs::dump())
248    return;
249  Ostream &Str = Func->getContext()->getStrEmit();
250  assert(Instr->getSrcSize() == 3);
251  assert(Instr->getSrc(0) == Instr->getDest());
252  Str << "\t" << Opcode
253      << getVWidthString(Instr->getDest()->getType(), SignType) << "\t";
254  Instr->getDest()->emit(Func);
255  Str << ", ";
256  Instr->getSrc(1)->emit(Func);
257  Str << ", ";
258  Instr->getSrc(2)->emit(Func);
259}
260
261void InstARM32Pred::emitFourAddr(const char *Opcode, const InstARM32Pred *Instr,
262                                 const Cfg *Func) {
263  if (!BuildDefs::dump())
264    return;
265  Ostream &Str = Func->getContext()->getStrEmit();
266  assert(Instr->getSrcSize() == 3);
267  Str << "\t" << Opcode << Instr->getPredicate() << "\t";
268  Instr->getDest()->emit(Func);
269  Str << ", ";
270  Instr->getSrc(0)->emit(Func);
271  Str << ", ";
272  Instr->getSrc(1)->emit(Func);
273  Str << ", ";
274  Instr->getSrc(2)->emit(Func);
275}
276
277template <InstARM32::InstKindARM32 K>
278void InstARM32FourAddrGPR<K>::emitIAS(const Cfg *Func) const {
279  emitUsingTextFixup(Func);
280}
281
282template <InstARM32::InstKindARM32 K>
283void InstARM32FourAddrFP<K>::emitIAS(const Cfg *Func) const {
284  emitUsingTextFixup(Func);
285}
286
287template <InstARM32::InstKindARM32 K>
288void InstARM32ThreeAddrFP<K>::emitIAS(const Cfg *Func) const {
289  emitUsingTextFixup(Func);
290}
291
292template <InstARM32::InstKindARM32 K>
293void InstARM32ThreeAddrSignAwareFP<K>::emitIAS(const Cfg *Func) const {
294  InstARM32::emitUsingTextFixup(Func);
295}
296
297template <> void InstARM32Mla::emitIAS(const Cfg *Func) const {
298  assert(getSrcSize() == 3);
299  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
300  Asm->mla(getDest(), getSrc(0), getSrc(1), getSrc(2), getPredicate());
301  if (Asm->needsTextFixup())
302    emitUsingTextFixup(Func);
303}
304
305template <> void InstARM32Mls::emitIAS(const Cfg *Func) const {
306  assert(getSrcSize() == 3);
307  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
308  Asm->mls(getDest(), getSrc(0), getSrc(1), getSrc(2), getPredicate());
309  if (Asm->needsTextFixup())
310    emitUsingTextFixup(Func);
311}
312
313void InstARM32Pred::emitCmpLike(const char *Opcode, const InstARM32Pred *Instr,
314                                const Cfg *Func) {
315  if (!BuildDefs::dump())
316    return;
317  Ostream &Str = Func->getContext()->getStrEmit();
318  assert(Instr->getSrcSize() == 2);
319  Str << "\t" << Opcode << Instr->getPredicate() << "\t";
320  Instr->getSrc(0)->emit(Func);
321  Str << ", ";
322  Instr->getSrc(1)->emit(Func);
323}
324
325OperandARM32Mem::OperandARM32Mem(Cfg * /* Func */, Type Ty, Variable *Base,
326                                 ConstantInteger32 *ImmOffset, AddrMode Mode)
327    : OperandARM32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Index(nullptr),
328      ShiftOp(kNoShift), ShiftAmt(0), Mode(Mode) {
329  // The Neg modes are only needed for Reg +/- Reg.
330  assert(!isNegAddrMode());
331  NumVars = 1;
332  Vars = &this->Base;
333}
334
335OperandARM32Mem::OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
336                                 Variable *Index, ShiftKind ShiftOp,
337                                 uint16_t ShiftAmt, AddrMode Mode)
338    : OperandARM32(kMem, Ty), Base(Base), ImmOffset(0), Index(Index),
339      ShiftOp(ShiftOp), ShiftAmt(ShiftAmt), Mode(Mode) {
340  if (Index->isRematerializable()) {
341    llvm::report_fatal_error("Rematerializable Index Register is not allowed.");
342  }
343  NumVars = 2;
344  Vars = Func->allocateArrayOf<Variable *>(2);
345  Vars[0] = Base;
346  Vars[1] = Index;
347}
348
349OperandARM32ShAmtImm::OperandARM32ShAmtImm(ConstantInteger32 *SA)
350    : OperandARM32(kShAmtImm, IceType_i8), ShAmt(SA) {}
351
352bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
353  int32_t Bits = SignExt ? TypeARM32Attributes[Ty].SExtAddrOffsetBits
354                         : TypeARM32Attributes[Ty].ZExtAddrOffsetBits;
355  if (Bits == 0)
356    return Offset == 0;
357  // Note that encodings for offsets are sign-magnitude for ARM, so we check
358  // with IsAbsoluteUint().
359  // Scalar fp, and vector types require an offset that is aligned to a multiple
360  // of 4.
361  if (isScalarFloatingType(Ty) || isVectorType(Ty))
362    return Utils::IsAligned(Offset, 4) && Utils::IsAbsoluteUint(Bits, Offset);
363  return Utils::IsAbsoluteUint(Bits, Offset);
364}
365
366OperandARM32FlexImm::OperandARM32FlexImm(Cfg * /* Func */, Type Ty,
367                                         uint32_t Imm, uint32_t RotateAmt)
368    : OperandARM32Flex(kFlexImm, Ty), Imm(Imm), RotateAmt(RotateAmt) {
369  NumVars = 0;
370  Vars = nullptr;
371}
372
373bool OperandARM32FlexImm::canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
374                                     uint32_t *Immed_8) {
375  // Avoid the more expensive test for frequent small immediate values.
376  if (Immediate <= 0xFF) {
377    *RotateAmt = 0;
378    *Immed_8 = Immediate;
379    return true;
380  }
381  // Note that immediate must be unsigned for the test to work correctly.
382  for (int Rot = 1; Rot < 16; Rot++) {
383    uint32_t Imm8 = Utils::rotateLeft32(Immediate, 2 * Rot);
384    if (Imm8 <= 0xFF) {
385      *RotateAmt = Rot;
386      *Immed_8 = Imm8;
387      return true;
388    }
389  }
390  return false;
391}
392
393OperandARM32FlexFpImm::OperandARM32FlexFpImm(Cfg * /*Func*/, Type Ty,
394                                             uint32_t ModifiedImm)
395    : OperandARM32Flex(kFlexFpImm, Ty), ModifiedImm(ModifiedImm) {}
396
397bool OperandARM32FlexFpImm::canHoldImm(const Operand *C,
398                                       uint32_t *ModifiedImm) {
399  switch (C->getType()) {
400  default:
401    llvm::report_fatal_error("Unhandled fp constant type.");
402  case IceType_f32: {
403    // We violate llvm naming conventions a bit here so that the constants are
404    // named after the bit fields they represent. See "A7.5.1 Operation of
405    // modified immediate constants, Floating-point" in the ARM ARM.
406    static constexpr uint32_t a = 0x80000000u;
407    static constexpr uint32_t B = 0x40000000;
408    static constexpr uint32_t bbbbb = 0x3E000000;
409    static constexpr uint32_t cdefgh = 0x01F80000;
410    static constexpr uint32_t AllowedBits = a | B | bbbbb | cdefgh;
411    static_assert(AllowedBits == 0xFFF80000u,
412                  "Invalid mask for f32 modified immediates.");
413    const float F32 = llvm::cast<const ConstantFloat>(C)->getValue();
414    const uint32_t I32 = Utils::bitCopy<uint32_t>(F32);
415    if (I32 & ~AllowedBits) {
416      // constant has disallowed bits.
417      return false;
418    }
419
420    if ((I32 & bbbbb) != bbbbb && (I32 & bbbbb)) {
421      // not all bbbbb bits are 0 or 1.
422      return false;
423    }
424
425    if (((I32 & B) != 0) == ((I32 & bbbbb) != 0)) {
426      // B ^ b = 0;
427      return false;
428    }
429
430    *ModifiedImm = ((I32 & a) ? 0x80 : 0x00) | ((I32 & bbbbb) ? 0x40 : 0x00) |
431                   ((I32 & cdefgh) >> 19);
432    return true;
433  }
434  case IceType_f64: {
435    static constexpr uint32_t a = 0x80000000u;
436    static constexpr uint32_t B = 0x40000000;
437    static constexpr uint32_t bbbbbbbb = 0x3FC00000;
438    static constexpr uint32_t cdefgh = 0x003F0000;
439    static constexpr uint32_t AllowedBits = a | B | bbbbbbbb | cdefgh;
440    static_assert(AllowedBits == 0xFFFF0000u,
441                  "Invalid mask for f64 modified immediates.");
442    const double F64 = llvm::cast<const ConstantDouble>(C)->getValue();
443    const uint64_t I64 = Utils::bitCopy<uint64_t>(F64);
444    if (I64 & 0xFFFFFFFFu) {
445      // constant has disallowed bits.
446      return false;
447    }
448    const uint32_t I32 = I64 >> 32;
449
450    if (I32 & ~AllowedBits) {
451      // constant has disallowed bits.
452      return false;
453    }
454
455    if ((I32 & bbbbbbbb) != bbbbbbbb && (I32 & bbbbbbbb)) {
456      // not all bbbbb bits are 0 or 1.
457      return false;
458    }
459
460    if (((I32 & B) != 0) == ((I32 & bbbbbbbb) != 0)) {
461      // B ^ b = 0;
462      return false;
463    }
464
465    *ModifiedImm = ((I32 & a) ? 0x80 : 0x00) |
466                   ((I32 & bbbbbbbb) ? 0x40 : 0x00) | ((I32 & cdefgh) >> 16);
467    return true;
468  }
469  }
470}
471
472OperandARM32FlexFpZero::OperandARM32FlexFpZero(Cfg * /*Func*/, Type Ty)
473    : OperandARM32Flex(kFlexFpZero, Ty) {}
474
475OperandARM32FlexReg::OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg,
476                                         ShiftKind ShiftOp, Operand *ShiftAmt)
477    : OperandARM32Flex(kFlexReg, Ty), Reg(Reg), ShiftOp(ShiftOp),
478      ShiftAmt(ShiftAmt) {
479  NumVars = 1;
480  auto *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt);
481  if (ShiftVar)
482    ++NumVars;
483  Vars = Func->allocateArrayOf<Variable *>(NumVars);
484  Vars[0] = Reg;
485  if (ShiftVar)
486    Vars[1] = ShiftVar;
487}
488
489InstARM32Br::InstARM32Br(Cfg *Func, const CfgNode *TargetTrue,
490                         const CfgNode *TargetFalse,
491                         const InstARM32Label *Label, CondARM32::Cond Pred)
492    : InstARM32Pred(Func, InstARM32::Br, 0, nullptr, Pred),
493      TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {}
494
495bool InstARM32Br::optimizeBranch(const CfgNode *NextNode) {
496  // If there is no next block, then there can be no fallthrough to optimize.
497  if (NextNode == nullptr)
498    return false;
499  // Intra-block conditional branches can't be optimized.
500  if (Label)
501    return false;
502  // If there is no fallthrough node, such as a non-default case label for a
503  // switch instruction, then there is no opportunity to optimize.
504  if (getTargetFalse() == nullptr)
505    return false;
506
507  // Unconditional branch to the next node can be removed.
508  if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
509    assert(getTargetTrue() == nullptr);
510    setDeleted();
511    return true;
512  }
513  // If the fallthrough is to the next node, set fallthrough to nullptr to
514  // indicate.
515  if (getTargetFalse() == NextNode) {
516    TargetFalse = nullptr;
517    return true;
518  }
519  // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
520  // already tested above), then invert the branch condition, swap the targets,
521  // and set new fallthrough to nullptr.
522  if (getTargetTrue() == NextNode) {
523    assert(Predicate != CondARM32::AL);
524    setPredicate(getOppositeCondition(getPredicate()));
525    TargetTrue = getTargetFalse();
526    TargetFalse = nullptr;
527    return true;
528  }
529  return false;
530}
531
532bool InstARM32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
533  bool Found = false;
534  if (TargetFalse == OldNode) {
535    TargetFalse = NewNode;
536    Found = true;
537  }
538  if (TargetTrue == OldNode) {
539    TargetTrue = NewNode;
540    Found = true;
541  }
542  return Found;
543}
544
545template <InstARM32::InstKindARM32 K>
546void InstARM32ThreeAddrGPR<K>::emitIAS(const Cfg *Func) const {
547  emitUsingTextFixup(Func);
548}
549
550template <> void InstARM32Adc::emitIAS(const Cfg *Func) const {
551  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
552  Asm->adc(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
553  if (Asm->needsTextFixup())
554    emitUsingTextFixup(Func);
555}
556
557template <> void InstARM32Add::emitIAS(const Cfg *Func) const {
558  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
559  Asm->add(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
560  assert(!Asm->needsTextFixup());
561}
562
563template <> void InstARM32And::emitIAS(const Cfg *Func) const {
564  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
565  Asm->and_(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
566  if (Asm->needsTextFixup())
567    emitUsingTextFixup(Func);
568}
569
570template <> void InstARM32Bic::emitIAS(const Cfg *Func) const {
571  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
572  Asm->bic(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
573  if (Asm->needsTextFixup())
574    emitUsingTextFixup(Func);
575}
576
577template <> void InstARM32Eor::emitIAS(const Cfg *Func) const {
578  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
579  Asm->eor(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
580  if (Asm->needsTextFixup())
581    emitUsingTextFixup(Func);
582}
583
584template <> void InstARM32Asr::emitIAS(const Cfg *Func) const {
585  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
586  Asm->asr(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
587  if (Asm->needsTextFixup())
588    emitUsingTextFixup(Func);
589}
590
591template <> void InstARM32Lsl::emitIAS(const Cfg *Func) const {
592  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
593  Asm->lsl(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
594  if (Asm->needsTextFixup())
595    emitUsingTextFixup(Func);
596}
597
598template <> void InstARM32Lsr::emitIAS(const Cfg *Func) const {
599  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
600  Asm->lsr(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
601  if (Asm->needsTextFixup())
602    emitUsingTextFixup(Func);
603}
604
605template <> void InstARM32Orr::emitIAS(const Cfg *Func) const {
606  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
607  Asm->orr(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
608  if (Asm->needsTextFixup())
609    emitUsingTextFixup(Func);
610}
611
612template <> void InstARM32Mul::emitIAS(const Cfg *Func) const {
613  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
614  Asm->mul(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
615  if (Asm->needsTextFixup())
616    emitUsingTextFixup(Func);
617}
618
619template <> void InstARM32Rsb::emitIAS(const Cfg *Func) const {
620  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
621  Asm->rsb(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
622  if (Asm->needsTextFixup())
623    emitUsingTextFixup(Func);
624}
625
626template <> void InstARM32Rsc::emitIAS(const Cfg *Func) const {
627  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
628  Asm->rsc(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
629  if (Asm->needsTextFixup())
630    emitUsingTextFixup(Func);
631}
632
633template <> void InstARM32Sbc::emitIAS(const Cfg *Func) const {
634  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
635  Asm->sbc(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
636  if (Asm->needsTextFixup())
637    emitUsingTextFixup(Func);
638}
639
640template <> void InstARM32Sdiv::emitIAS(const Cfg *Func) const {
641  assert(!SetFlags);
642  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
643  Asm->sdiv(getDest(), getSrc(0), getSrc(1), getPredicate());
644  if (Asm->needsTextFixup())
645    emitUsingTextFixup(Func);
646}
647
648template <> void InstARM32Sub::emitIAS(const Cfg *Func) const {
649  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
650  Asm->sub(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
651  if (Asm->needsTextFixup())
652    emitUsingTextFixup(Func);
653}
654
655template <> void InstARM32Udiv::emitIAS(const Cfg *Func) const {
656  assert(!SetFlags);
657  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
658  Asm->udiv(getDest(), getSrc(0), getSrc(1), getPredicate());
659  if (Asm->needsTextFixup())
660    emitUsingTextFixup(Func);
661}
662
663template <> void InstARM32Vadd::emitIAS(const Cfg *Func) const {
664  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
665  const Variable *Dest = getDest();
666  Type DestTy = Dest->getType();
667  switch (DestTy) {
668  default:
669    llvm::report_fatal_error("Vadd not defined on type " +
670                             typeStdString(DestTy));
671  case IceType_v16i8:
672  case IceType_v8i16:
673  case IceType_v4i32:
674    Asm->vaddqi(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
675    break;
676  case IceType_v4f32:
677    Asm->vaddqf(Dest, getSrc(0), getSrc(1));
678    break;
679  case IceType_f32:
680    Asm->vadds(Dest, getSrc(0), getSrc(1), CondARM32::AL);
681    break;
682  case IceType_f64:
683    Asm->vaddd(Dest, getSrc(0), getSrc(1), CondARM32::AL);
684    break;
685  }
686  assert(!Asm->needsTextFixup());
687}
688
689template <> void InstARM32Vand::emitIAS(const Cfg *Func) const {
690  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
691  const Variable *Dest = getDest();
692  switch (Dest->getType()) {
693  default:
694    llvm::report_fatal_error("Vand not defined on type " +
695                             typeStdString(Dest->getType()));
696  case IceType_v4i1:
697  case IceType_v8i1:
698  case IceType_v16i1:
699  case IceType_v16i8:
700  case IceType_v8i16:
701  case IceType_v4i32:
702    Asm->vandq(Dest, getSrc(0), getSrc(1));
703  }
704  assert(!Asm->needsTextFixup());
705}
706
707template <> void InstARM32Vceq::emitIAS(const Cfg *Func) const {
708  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
709  const Variable *Dest = getDest();
710  const Type SrcTy = getSrc(0)->getType();
711  switch (SrcTy) {
712  default:
713    llvm::report_fatal_error("Vceq not defined on type " +
714                             typeStdString(SrcTy));
715  case IceType_v4i1:
716  case IceType_v8i1:
717  case IceType_v16i1:
718  case IceType_v16i8:
719  case IceType_v8i16:
720  case IceType_v4i32:
721    Asm->vceqqi(typeElementType(SrcTy), Dest, getSrc(0), getSrc(1));
722    break;
723  case IceType_v4f32:
724    Asm->vceqqs(Dest, getSrc(0), getSrc(1));
725    break;
726  }
727  assert(!Asm->needsTextFixup());
728}
729
730template <> void InstARM32Vcge::emitIAS(const Cfg *Func) const {
731  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
732  const Variable *Dest = getDest();
733  const Type SrcTy = getSrc(0)->getType();
734  switch (SrcTy) {
735  default:
736    llvm::report_fatal_error("Vcge not defined on type " +
737                             typeStdString(Dest->getType()));
738  case IceType_v4i1:
739  case IceType_v8i1:
740  case IceType_v16i1:
741  case IceType_v16i8:
742  case IceType_v8i16:
743  case IceType_v4i32: {
744    const Type ElmtTy = typeElementType(SrcTy);
745    assert(Sign != InstARM32::FS_None);
746    switch (Sign) {
747    case InstARM32::FS_None: // defaults to unsigned.
748      llvm_unreachable("Sign should not be FS_None.");
749    case InstARM32::FS_Unsigned:
750      Asm->vcugeqi(ElmtTy, Dest, getSrc(0), getSrc(1));
751      break;
752    case InstARM32::FS_Signed:
753      Asm->vcgeqi(ElmtTy, Dest, getSrc(0), getSrc(1));
754      break;
755    }
756  } break;
757  case IceType_v4f32:
758    Asm->vcgeqs(Dest, getSrc(0), getSrc(1));
759    break;
760  }
761}
762
763template <> void InstARM32Vcgt::emitIAS(const Cfg *Func) const {
764  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
765  const Variable *Dest = getDest();
766  const Type SrcTy = getSrc(0)->getType();
767  switch (SrcTy) {
768  default:
769    llvm::report_fatal_error("Vcgt not defined on type " +
770                             typeStdString(Dest->getType()));
771  case IceType_v4i1:
772  case IceType_v8i1:
773  case IceType_v16i1:
774  case IceType_v16i8:
775  case IceType_v8i16:
776  case IceType_v4i32: {
777    const Type ElmtTy = typeElementType(SrcTy);
778    assert(Sign != InstARM32::FS_None);
779    switch (Sign) {
780    case InstARM32::FS_None: // defaults to unsigned.
781      llvm_unreachable("Sign should not be FS_None.");
782    case InstARM32::FS_Unsigned:
783      Asm->vcugtqi(ElmtTy, Dest, getSrc(0), getSrc(1));
784      break;
785    case InstARM32::FS_Signed:
786      Asm->vcgtqi(ElmtTy, Dest, getSrc(0), getSrc(1));
787      break;
788    }
789  } break;
790  case IceType_v4f32:
791    Asm->vcgtqs(Dest, getSrc(0), getSrc(1));
792    break;
793  }
794}
795
796template <> void InstARM32Vbsl::emitIAS(const Cfg *Func) const {
797  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
798  const Variable *Dest = getDest();
799  switch (Dest->getType()) {
800  default:
801    llvm::report_fatal_error("Vbsl not defined on type " +
802                             typeStdString(Dest->getType()));
803  case IceType_v4i1:
804  case IceType_v8i1:
805  case IceType_v16i1:
806  case IceType_v16i8:
807  case IceType_v8i16:
808  case IceType_v4i32:
809    Asm->vbslq(Dest, getSrc(0), getSrc(1));
810  }
811  assert(!Asm->needsTextFixup());
812}
813
814template <> void InstARM32Vdiv::emitIAS(const Cfg *Func) const {
815  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
816  const Variable *Dest = getDest();
817  switch (Dest->getType()) {
818  default:
819    // TODO(kschimpf) Figure if more cases are needed.
820    Asm->setNeedsTextFixup();
821    break;
822  case IceType_f32:
823    Asm->vdivs(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
824    break;
825  case IceType_f64:
826    Asm->vdivd(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
827    break;
828  }
829  assert(!Asm->needsTextFixup());
830}
831
832template <> void InstARM32Veor::emitIAS(const Cfg *Func) const {
833  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
834  const Variable *Dest = getDest();
835  if (isVectorType(Dest->getType())) {
836    Asm->veorq(Dest, getSrc(0), getSrc(1));
837    assert(!Asm->needsTextFixup());
838    return;
839  }
840  assert(Dest->getType() == IceType_f64);
841  Asm->veord(Dest, getSrc(0), getSrc(1));
842  assert(!Asm->needsTextFixup());
843}
844
845template <> void InstARM32Vmla::emitIAS(const Cfg *Func) const {
846  // Note: Dest == getSrc(0) for four address FP instructions.
847  assert(getSrcSize() == 3);
848  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
849  const Variable *Dest = getDest();
850  switch (Dest->getType()) {
851  default:
852    // TODO(kschimpf) Figure out how vector operations apply.
853    emitUsingTextFixup(Func);
854    return;
855  case IceType_f32:
856    Asm->vmlas(getDest(), getSrc(1), getSrc(2), CondARM32::AL);
857    assert(!Asm->needsTextFixup());
858    return;
859  case IceType_f64:
860    Asm->vmlad(getDest(), getSrc(1), getSrc(2), CondARM32::AL);
861    assert(!Asm->needsTextFixup());
862    return;
863  }
864}
865
866template <> void InstARM32Vmls::emitIAS(const Cfg *Func) const {
867  // Note: Dest == getSrc(0) for four address FP instructions.
868  assert(getSrcSize() == 3);
869  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
870  const Variable *Dest = getDest();
871  switch (Dest->getType()) {
872  default:
873    // TODO(kschimpf) Figure out how vector operations apply.
874    emitUsingTextFixup(Func);
875    return;
876  case IceType_f32:
877    Asm->vmlss(getDest(), getSrc(1), getSrc(2), CondARM32::AL);
878    assert(!Asm->needsTextFixup());
879    return;
880  case IceType_f64:
881    Asm->vmlsd(getDest(), getSrc(1), getSrc(2), CondARM32::AL);
882    assert(!Asm->needsTextFixup());
883    return;
884  }
885}
886
887template <> void InstARM32Vmvn::emitIAS(const Cfg *Func) const {
888  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
889  const Variable *Dest = getDest();
890  switch (Dest->getType()) {
891  default:
892    llvm::report_fatal_error("Vmvn not defined on type " +
893                             typeStdString(Dest->getType()));
894  case IceType_v4i1:
895  case IceType_v8i1:
896  case IceType_v16i1:
897  case IceType_v16i8:
898  case IceType_v8i16:
899  case IceType_v4i32:
900  case IceType_v4f32: {
901    Asm->vmvnq(Dest, getSrc(0));
902  } break;
903  }
904}
905
906template <> void InstARM32Vmovl::emitIAS(const Cfg *Func) const {
907  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
908  const Variable *Dest = getDest();
909  switch (Dest->getType()) {
910  default:
911    llvm::report_fatal_error("Vmovlq not defined on type " +
912                             typeStdString(Dest->getType()));
913  case IceType_v4i1:
914  case IceType_v8i1:
915  case IceType_v16i1:
916  case IceType_v16i8:
917  case IceType_v8i16:
918  case IceType_v4i32:
919  case IceType_v4f32: {
920    Asm->vmovlq(Dest, getSrc(0), getSrc(1));
921  } break;
922  }
923}
924
925template <> void InstARM32Vmovh::emitIAS(const Cfg *Func) const {
926  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
927  const Variable *Dest = getDest();
928  switch (Dest->getType()) {
929  default:
930    llvm::report_fatal_error("Vmovhq not defined on type " +
931                             typeStdString(Dest->getType()));
932  case IceType_v4i1:
933  case IceType_v8i1:
934  case IceType_v16i1:
935  case IceType_v16i8:
936  case IceType_v8i16:
937  case IceType_v4i32:
938  case IceType_v4f32: {
939    Asm->vmovhq(Dest, getSrc(0), getSrc(1));
940  } break;
941  }
942}
943
944template <> void InstARM32Vmovhl::emitIAS(const Cfg *Func) const {
945  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
946  const Variable *Dest = getDest();
947  switch (Dest->getType()) {
948  default:
949    llvm::report_fatal_error("Vmovhlq not defined on type " +
950                             typeStdString(Dest->getType()));
951  case IceType_v4i1:
952  case IceType_v8i1:
953  case IceType_v16i1:
954  case IceType_v16i8:
955  case IceType_v8i16:
956  case IceType_v4i32:
957  case IceType_v4f32: {
958    Asm->vmovhlq(Dest, getSrc(0), getSrc(1));
959  } break;
960  }
961}
962
963template <> void InstARM32Vmovlh::emitIAS(const Cfg *Func) const {
964  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
965  const Variable *Dest = getDest();
966  switch (Dest->getType()) {
967  default:
968    llvm::report_fatal_error("Vmovlhq not defined on type " +
969                             typeStdString(Dest->getType()));
970  case IceType_v4i1:
971  case IceType_v8i1:
972  case IceType_v16i1:
973  case IceType_v16i8:
974  case IceType_v8i16:
975  case IceType_v4i32:
976  case IceType_v4f32: {
977    Asm->vmovlhq(Dest, getSrc(0), getSrc(1));
978  } break;
979  }
980}
981
982template <> void InstARM32Vneg::emitIAS(const Cfg *Func) const {
983  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
984  const Variable *Dest = getDest();
985  const Type DestTy = Dest->getType();
986  switch (Dest->getType()) {
987  default:
988    llvm::report_fatal_error("Vneg not defined on type " +
989                             typeStdString(Dest->getType()));
990  case IceType_v4i1:
991  case IceType_v8i1:
992  case IceType_v16i1:
993  case IceType_v16i8:
994  case IceType_v8i16:
995  case IceType_v4i32:
996  case IceType_v4f32: {
997    const Type ElmtTy = typeElementType(DestTy);
998    Asm->vnegqs(ElmtTy, Dest, getSrc(0));
999  } break;
1000  }
1001}
1002
1003template <> void InstARM32Vorr::emitIAS(const Cfg *Func) const {
1004  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1005  const Variable *Dest = getDest();
1006  switch (Dest->getType()) {
1007  default:
1008    llvm::report_fatal_error("Vorr not defined on type " +
1009                             typeStdString(Dest->getType()));
1010  case IceType_v4i1:
1011  case IceType_v8i1:
1012  case IceType_v16i1:
1013  case IceType_v16i8:
1014  case IceType_v8i16:
1015  case IceType_v4i32:
1016    Asm->vorrq(Dest, getSrc(0), getSrc(1));
1017  }
1018  assert(!Asm->needsTextFixup());
1019}
1020
1021template <> void InstARM32Vshl::emitIAS(const Cfg *Func) const {
1022  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1023  const Variable *Dest = getDest();
1024  const Type DestTy = Dest->getType();
1025  switch (DestTy) {
1026  default:
1027    llvm::report_fatal_error("Vshl not defined on type " +
1028                             typeStdString(Dest->getType()));
1029  // TODO(jpp): handle i1 vectors in terms of element count instead of element
1030  // type.
1031  case IceType_v4i1:
1032  case IceType_v8i1:
1033  case IceType_v16i1:
1034  case IceType_v16i8:
1035  case IceType_v8i16:
1036  case IceType_v4i32: {
1037    const Type ElmtTy = typeElementType(DestTy);
1038    assert(Sign != InstARM32::FS_None);
1039    switch (Sign) {
1040    case InstARM32::FS_None: // defaults to unsigned.
1041    case InstARM32::FS_Unsigned:
1042      if (const auto *Imm6 = llvm::dyn_cast<ConstantInteger32>(getSrc(1))) {
1043        Asm->vshlqc(ElmtTy, Dest, getSrc(0), Imm6);
1044      } else {
1045        Asm->vshlqu(ElmtTy, Dest, getSrc(0), getSrc(1));
1046      }
1047      break;
1048    case InstARM32::FS_Signed:
1049      if (const auto *Imm6 = llvm::dyn_cast<ConstantInteger32>(getSrc(1))) {
1050        Asm->vshlqc(ElmtTy, Dest, getSrc(0), Imm6);
1051      } else {
1052        Asm->vshlqi(ElmtTy, Dest, getSrc(0), getSrc(1));
1053      }
1054      break;
1055    }
1056  } break;
1057  }
1058}
1059
1060template <> void InstARM32Vshr::emitIAS(const Cfg *Func) const {
1061  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1062  const Variable *Dest = getDest();
1063  const Type DestTy = Dest->getType();
1064  switch (DestTy) {
1065  default:
1066    llvm::report_fatal_error("Vshr not defined on type " +
1067                             typeStdString(Dest->getType()));
1068  // TODO(jpp): handle i1 vectors in terms of element count instead of element
1069  // type.
1070  case IceType_v4i1:
1071  case IceType_v8i1:
1072  case IceType_v16i1:
1073  case IceType_v16i8:
1074  case IceType_v8i16:
1075  case IceType_v4i32: {
1076    const Type ElmtTy = typeElementType(DestTy);
1077    const auto *Imm6 = llvm::cast<ConstantInteger32>(getSrc(1));
1078    switch (Sign) {
1079    case InstARM32::FS_Signed:
1080    case InstARM32::FS_Unsigned:
1081      Asm->vshrqc(ElmtTy, Dest, getSrc(0), Imm6, Sign);
1082      break;
1083    default:
1084      assert(false && "Vshr requires signedness specification.");
1085    }
1086  } break;
1087  }
1088}
1089
1090template <> void InstARM32Vsub::emitIAS(const Cfg *Func) const {
1091  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1092  const Variable *Dest = getDest();
1093  Type DestTy = Dest->getType();
1094  switch (DestTy) {
1095  default:
1096    llvm::report_fatal_error("Vsub not defined on type " +
1097                             typeStdString(DestTy));
1098  case IceType_v16i8:
1099  case IceType_v8i16:
1100  case IceType_v4i32:
1101    Asm->vsubqi(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1102    break;
1103  case IceType_v4f32:
1104    Asm->vsubqf(Dest, getSrc(0), getSrc(1));
1105    break;
1106  case IceType_f32:
1107    Asm->vsubs(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
1108    break;
1109  case IceType_f64:
1110    Asm->vsubd(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
1111    break;
1112  }
1113  assert(!Asm->needsTextFixup());
1114}
1115
1116template <> void InstARM32Vqadd::emitIAS(const Cfg *Func) const {
1117  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1118  const Variable *Dest = getDest();
1119  Type DestTy = Dest->getType();
1120  switch (DestTy) {
1121  default:
1122    llvm::report_fatal_error("Vqadd not defined on type " +
1123                             typeStdString(DestTy));
1124  case IceType_v16i8:
1125  case IceType_v8i16:
1126  case IceType_v4i32:
1127    switch (Sign) {
1128    case InstARM32::FS_None: // defaults to unsigned.
1129    case InstARM32::FS_Unsigned:
1130      Asm->vqaddqu(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1131      break;
1132    case InstARM32::FS_Signed:
1133      Asm->vqaddqi(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1134      break;
1135    }
1136    break;
1137  }
1138  assert(!Asm->needsTextFixup());
1139}
1140
1141template <> void InstARM32Vqsub::emitIAS(const Cfg *Func) const {
1142  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1143  const Variable *Dest = getDest();
1144  Type DestTy = Dest->getType();
1145  switch (DestTy) {
1146  default:
1147    llvm::report_fatal_error("Vqsub not defined on type " +
1148                             typeStdString(DestTy));
1149  case IceType_v16i8:
1150  case IceType_v8i16:
1151  case IceType_v4i32:
1152    switch (Sign) {
1153    case InstARM32::FS_None: // defaults to unsigned.
1154    case InstARM32::FS_Unsigned:
1155      Asm->vqsubqu(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1156      break;
1157    case InstARM32::FS_Signed:
1158      Asm->vqsubqi(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1159      break;
1160    }
1161    break;
1162  }
1163  assert(!Asm->needsTextFixup());
1164}
1165
1166template <> void InstARM32Vqmovn2::emitIAS(const Cfg *Func) const {
1167  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1168  const Operand *Src0 = getSrc(0);
1169  const Operand *Src1 = getSrc(1);
1170  Type SrcTy = Src0->getType();
1171  Type DestTy = Dest->getType();
1172  bool Unsigned = true;
1173  bool Saturating = true;
1174  switch (SrcTy) {
1175  default:
1176    llvm::report_fatal_error("Vqmovn2 not defined on type " +
1177                             typeStdString(SrcTy));
1178  case IceType_v8i16:
1179  case IceType_v4i32:
1180    switch (Sign) {
1181    case InstARM32::FS_None:
1182      Unsigned = true;
1183      Saturating = false;
1184      Asm->vqmovn2(typeElementType(DestTy), Dest, Src0, Src1, Unsigned,
1185                   Saturating);
1186      break;
1187    case InstARM32::FS_Unsigned:
1188      Unsigned = true;
1189      Saturating = true;
1190      Asm->vqmovn2(typeElementType(DestTy), Dest, Src0, Src1, Unsigned,
1191                   Saturating);
1192      break;
1193    case InstARM32::FS_Signed:
1194      Unsigned = false;
1195      Saturating = true;
1196      Asm->vqmovn2(typeElementType(DestTy), Dest, Src0, Src1, Unsigned,
1197                   Saturating);
1198      break;
1199    }
1200    break;
1201  }
1202  assert(!Asm->needsTextFixup());
1203}
1204
1205template <> void InstARM32Vmulh::emitIAS(const Cfg *Func) const {
1206  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1207  const Operand *Src0 = getSrc(0);
1208  Type SrcTy = Src0->getType();
1209  bool Unsigned = true;
1210  switch (SrcTy) {
1211  default:
1212    llvm::report_fatal_error("Vmulh not defined on type " +
1213                             typeStdString(SrcTy));
1214  case IceType_v8i16:
1215    switch (Sign) {
1216    case InstARM32::FS_None: // defaults to unsigned.
1217    case InstARM32::FS_Unsigned:
1218      Unsigned = true;
1219      Asm->vmulh(typeElementType(SrcTy), Dest, getSrc(0), getSrc(1), Unsigned);
1220      break;
1221    case InstARM32::FS_Signed:
1222      Unsigned = false;
1223      Asm->vmulh(typeElementType(SrcTy), Dest, getSrc(0), getSrc(1), Unsigned);
1224      break;
1225    }
1226    break;
1227  }
1228  assert(!Asm->needsTextFixup());
1229}
1230
1231template <> void InstARM32Vmlap::emitIAS(const Cfg *Func) const {
1232  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1233  const Operand *Src0 = getSrc(0);
1234  const Operand *Src1 = getSrc(1);
1235  Type SrcTy = Src0->getType();
1236  switch (SrcTy) {
1237  default:
1238    llvm::report_fatal_error("Vmlap not defined on type " +
1239                             typeStdString(SrcTy));
1240  case IceType_v8i16:
1241    Asm->vmlap(typeElementType(SrcTy), Dest, Src0, Src1);
1242    break;
1243  }
1244  assert(!Asm->needsTextFixup());
1245}
1246
1247template <> void InstARM32Vzip::emitIAS(const Cfg *Func) const {
1248  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1249  const Operand *Src0 = getSrc(0);
1250  const Operand *Src1 = getSrc(1);
1251  Type DestTy = Dest->getType();
1252  Asm->vzip(typeElementType(DestTy), Dest, Src0, Src1);
1253  assert(!Asm->needsTextFixup());
1254}
1255
1256template <> void InstARM32Vmul::emitIAS(const Cfg *Func) const {
1257  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1258  const Variable *Dest = getDest();
1259  const Type DestTy = Dest->getType();
1260  switch (DestTy) {
1261  default:
1262    llvm::report_fatal_error("Vmul not defined on type " +
1263                             typeStdString(DestTy));
1264
1265  case IceType_v16i8:
1266  case IceType_v8i16:
1267  case IceType_v4i32:
1268    Asm->vmulqi(typeElementType(DestTy), Dest, getSrc(0), getSrc(1));
1269    break;
1270  case IceType_v4f32:
1271    Asm->vmulqf(Dest, getSrc(0), getSrc(1));
1272    break;
1273  case IceType_f32:
1274    Asm->vmuls(Dest, getSrc(0), getSrc(1), CondARM32::AL);
1275    break;
1276  case IceType_f64:
1277    Asm->vmuld(Dest, getSrc(0), getSrc(1), CondARM32::AL);
1278    break;
1279  }
1280}
1281
1282InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
1283    : InstARM32(Func, InstARM32::Call, 1, Dest) {
1284  HasSideEffects = true;
1285  addSource(CallTarget);
1286}
1287
1288InstARM32Label::InstARM32Label(Cfg *Func, TargetARM32 *Target)
1289    : InstARM32(Func, InstARM32::Label, 0, nullptr),
1290      Number(Target->makeNextLabelNumber()) {
1291  if (BuildDefs::dump()) {
1292    Name = GlobalString::createWithString(
1293        Func->getContext(),
1294        ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number));
1295  } else {
1296    Name = GlobalString::createWithoutString(Func->getContext());
1297  }
1298}
1299
1300namespace {
1301// Requirements for Push/Pop:
1302//  1) All the Variables have the same type;
1303//  2) All the variables have registers assigned to them.
1304void validatePushOrPopRegisterListOrDie(const VarList &RegList) {
1305  Type PreviousTy = IceType_void;
1306  for (Variable *Reg : RegList) {
1307    if (PreviousTy != IceType_void && Reg->getType() != PreviousTy) {
1308      llvm::report_fatal_error("Type mismatch when popping/pushing "
1309                               "registers.");
1310    }
1311
1312    if (!Reg->hasReg()) {
1313      llvm::report_fatal_error("Push/pop operand does not have a register "
1314                               "assigned to it.");
1315    }
1316
1317    PreviousTy = Reg->getType();
1318  }
1319}
1320} // end of anonymous namespace
1321
1322void InstARM32RegisterStackOp::emit(const Cfg *Func) const {
1323  if (!BuildDefs::dump())
1324    return;
1325  emitUsingForm(Func, Emit_Text);
1326}
1327
1328void InstARM32RegisterStackOp::emitIAS(const Cfg *Func) const {
1329  emitUsingForm(Func, Emit_Binary);
1330  assert(!Func->getAssembler<ARM32::AssemblerARM32>()->needsTextFixup());
1331}
1332
1333void InstARM32RegisterStackOp::dump(const Cfg *Func) const {
1334  if (!BuildDefs::dump())
1335    return;
1336  Ostream &Str = Func->getContext()->getStrDump();
1337  Str << getDumpOpcode() << " ";
1338  SizeT NumRegs = getNumStackRegs();
1339  for (SizeT I = 0; I < NumRegs; ++I) {
1340    if (I > 0)
1341      Str << ", ";
1342    getStackReg(I)->dump(Func);
1343  }
1344}
1345
1346void InstARM32RegisterStackOp::emitGPRsAsText(const Cfg *Func) const {
1347  if (!BuildDefs::dump())
1348    return;
1349  Ostream &Str = Func->getContext()->getStrEmit();
1350  Str << "\t" << getGPROpcode() << "\t{";
1351  getStackReg(0)->emit(Func);
1352  const SizeT NumRegs = getNumStackRegs();
1353  for (SizeT i = 1; i < NumRegs; ++i) {
1354    Str << ", ";
1355    getStackReg(i)->emit(Func);
1356  }
1357  Str << "}";
1358}
1359
1360void InstARM32RegisterStackOp::emitSRegsAsText(const Cfg *Func,
1361                                               const Variable *BaseReg,
1362                                               SizeT RegCount) const {
1363  if (!BuildDefs::dump())
1364    return;
1365  Ostream &Str = Func->getContext()->getStrEmit();
1366  Str << "\t" << getSRegOpcode() << "\t{";
1367  bool IsFirst = true;
1368  const auto Base = BaseReg->getRegNum();
1369  for (SizeT i = 0; i < RegCount; ++i) {
1370    if (IsFirst)
1371      IsFirst = false;
1372    else
1373      Str << ", ";
1374    Str << RegARM32::getRegName(RegNumT::fixme(Base + i));
1375  }
1376  Str << "}";
1377}
1378
1379void InstARM32RegisterStackOp::emitSRegsOp(const Cfg *Func, EmitForm Form,
1380                                           const Variable *BaseReg,
1381                                           SizeT RegCount,
1382                                           SizeT InstIndex) const {
1383  if (Form == Emit_Text && BuildDefs::dump() && InstIndex > 0) {
1384    startNextInst(Func);
1385    Func->getContext()->getStrEmit() << "\n";
1386  }
1387  emitSRegs(Func, Form, BaseReg, RegCount);
1388}
1389
1390namespace {
1391
1392bool isAssignedConsecutiveRegisters(const Variable *Before,
1393                                    const Variable *After) {
1394  assert(Before->hasReg());
1395  assert(After->hasReg());
1396  return RegNumT::fixme(Before->getRegNum() + 1) == After->getRegNum();
1397}
1398
1399} // end of anonymous namespace
1400
1401void InstARM32RegisterStackOp::emitUsingForm(const Cfg *Func,
1402                                             const EmitForm Form) const {
1403  SizeT NumRegs = getNumStackRegs();
1404  assert(NumRegs);
1405
1406  const auto *Reg = llvm::cast<Variable>(getStackReg(0));
1407  if (isScalarIntegerType(Reg->getType())) {
1408    // Push/pop GPR registers.
1409    SizeT IntegerCount = 0;
1410    ARM32::IValueT GPRegisters = 0;
1411    const Variable *LastDest = nullptr;
1412    for (SizeT i = 0; i < NumRegs; ++i) {
1413      const Variable *Var = getStackReg(i);
1414      assert(Var->hasReg() && "stack op only applies to registers");
1415      const RegARM32::GPRRegister Reg =
1416          RegARM32::getEncodedGPR(Var->getRegNum());
1417      LastDest = Var;
1418      GPRegisters |= (1 << Reg);
1419      ++IntegerCount;
1420    }
1421    if (IntegerCount == 1) {
1422      emitSingleGPR(Func, Form, LastDest);
1423    } else {
1424      emitMultipleGPRs(Func, Form, GPRegisters);
1425    }
1426    return;
1427  }
1428
1429  // Push/pop floating point registers. Divide into a list of instructions,
1430  // defined on consecutive register ranges. Then generate the corresponding
1431  // instructions.
1432
1433  // Typical max number of registers ranges pushed/popd is no more than 5.
1434  llvm::SmallVector<std::pair<const Variable *, SizeT>, 5> InstData;
1435  const Variable *BaseReg = nullptr;
1436  SizeT RegCount = 0;
1437  for (SizeT i = 0; i < NumRegs; ++i) {
1438    const Variable *NextReg = getStackReg(i);
1439    assert(NextReg->hasReg());
1440    if (BaseReg == nullptr) {
1441      BaseReg = NextReg;
1442      RegCount = 1;
1443    } else if (RegCount < VpushVpopMaxConsecRegs &&
1444               isAssignedConsecutiveRegisters(Reg, NextReg)) {
1445      ++RegCount;
1446    } else {
1447      InstData.emplace_back(BaseReg, RegCount);
1448      BaseReg = NextReg;
1449      RegCount = 1;
1450    }
1451    Reg = NextReg;
1452  }
1453  if (RegCount) {
1454    InstData.emplace_back(BaseReg, RegCount);
1455  }
1456  SizeT InstCount = 0;
1457  if (llvm::isa<InstARM32Push>(*this)) {
1458    for (const auto &Pair : InstData)
1459      emitSRegsOp(Func, Form, Pair.first, Pair.second, InstCount++);
1460    return;
1461  }
1462  assert(llvm::isa<InstARM32Pop>(*this));
1463  for (const auto &Pair : reverse_range(InstData))
1464    emitSRegsOp(Func, Form, Pair.first, Pair.second, InstCount++);
1465}
1466
1467InstARM32Pop::InstARM32Pop(Cfg *Func, const VarList &Dests)
1468    : InstARM32RegisterStackOp(Func, InstARM32::Pop, 0, nullptr), Dests(Dests) {
1469  // Track modifications to Dests separately via FakeDefs. Also, a pop
1470  // instruction affects the stack pointer and so it should not be allowed to
1471  // be automatically dead-code eliminated. This is automatic since we leave
1472  // the Dest as nullptr.
1473  validatePushOrPopRegisterListOrDie(Dests);
1474}
1475
1476InstARM32Push::InstARM32Push(Cfg *Func, const VarList &Srcs)
1477    : InstARM32RegisterStackOp(Func, InstARM32::Push, Srcs.size(), nullptr) {
1478  validatePushOrPopRegisterListOrDie(Srcs);
1479  for (Variable *Source : Srcs) {
1480    addSource(Source);
1481  }
1482}
1483
1484InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source)
1485    : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) {
1486  addSource(LR);
1487  if (Source)
1488    addSource(Source);
1489}
1490
1491InstARM32Str::InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1492                           CondARM32::Cond Predicate)
1493    : InstARM32Pred(Func, InstARM32::Str, 2, nullptr, Predicate) {
1494  addSource(Value);
1495  addSource(Mem);
1496}
1497
1498InstARM32Strex::InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
1499                               OperandARM32Mem *Mem, CondARM32::Cond Predicate)
1500    : InstARM32Pred(Func, InstARM32::Strex, 2, Dest, Predicate) {
1501  addSource(Value);
1502  addSource(Mem);
1503}
1504
1505InstARM32Vstr1::InstARM32Vstr1(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1506                               CondARM32::Cond Predicate, SizeT Size)
1507    : InstARM32Pred(Func, InstARM32::Vstr1, 2, nullptr, Predicate) {
1508  addSource(Value);
1509  addSource(Mem);
1510  this->Size = Size;
1511}
1512
1513InstARM32Vdup::InstARM32Vdup(Cfg *Func, Variable *Dest, Variable *Src,
1514                             IValueT Idx)
1515    : InstARM32Pred(Func, InstARM32::Vdup, 1, Dest, CondARM32::AL), Idx(Idx) {
1516  addSource(Src);
1517}
1518
1519InstARM32Trap::InstARM32Trap(Cfg *Func)
1520    : InstARM32(Func, InstARM32::Trap, 0, nullptr) {}
1521
1522InstARM32Umull::InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi,
1523                               Variable *Src0, Variable *Src1,
1524                               CondARM32::Cond Predicate)
1525    : InstARM32Pred(Func, InstARM32::Umull, 2, DestLo, Predicate),
1526      // DestHi is expected to have a FakeDef inserted by the lowering code.
1527      DestHi(DestHi) {
1528  addSource(Src0);
1529  addSource(Src1);
1530}
1531
1532InstARM32Vcvt::InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src,
1533                             VcvtVariant Variant, CondARM32::Cond Predicate)
1534    : InstARM32Pred(Func, InstARM32::Vcvt, 1, Dest, Predicate),
1535      Variant(Variant) {
1536  addSource(Src);
1537}
1538
1539InstARM32Mov::InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
1540                           CondARM32::Cond Predicate)
1541    : InstARM32Pred(Func, InstARM32::Mov, 2, Dest, Predicate) {
1542  auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
1543  auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
1544
1545  assert(Dest64 == nullptr || Src64 == nullptr);
1546
1547  if (Dest64 != nullptr) {
1548    // this-> is needed below because there is a parameter named Dest.
1549    this->Dest = Dest64->getLo();
1550    DestHi = Dest64->getHi();
1551  }
1552
1553  if (Src64 == nullptr) {
1554    addSource(Src);
1555  } else {
1556    addSource(Src64->getLo());
1557    addSource(Src64->getHi());
1558  }
1559}
1560
1561namespace {
1562
1563// These next two functions find the D register that maps to the half of the Q
1564// register that this instruction is accessing.
1565Register getDRegister(const Variable *Src, uint32_t Index) {
1566  assert(Src->hasReg());
1567  const auto SrcReg = Src->getRegNum();
1568
1569  const RegARM32::RegTableType &SrcEntry = RegARM32::RegTable[SrcReg];
1570  assert(SrcEntry.IsVec128);
1571
1572  const uint32_t NumElements = typeNumElements(Src->getType());
1573
1574  // This code assumes the Aliases list goes Q_n, S_2n, S_2n+1. The asserts in
1575  // the next two branches help to check that this is still true.
1576  if (Index < NumElements / 2) {
1577    // We have a Q register that's made up of two D registers. This assert is
1578    // to help ensure that we picked the right D register.
1579    //
1580    // TODO(jpp): find a way to do this that doesn't rely on ordering of the
1581    // alias list.
1582    assert(RegARM32::RegTable[SrcEntry.Aliases[1]].Encoding + 1 ==
1583           RegARM32::RegTable[SrcEntry.Aliases[2]].Encoding);
1584    return static_cast<Register>(SrcEntry.Aliases[1]);
1585  } else {
1586    // We have a Q register that's made up of two D registers. This assert is
1587    // to help ensure that we picked the right D register.
1588    //
1589    // TODO(jpp): find a way to do this that doesn't rely on ordering of the
1590    // alias list.
1591    assert(RegARM32::RegTable[SrcEntry.Aliases[2]].Encoding - 1 ==
1592           RegARM32::RegTable[SrcEntry.Aliases[1]].Encoding);
1593    return static_cast<Register>(SrcEntry.Aliases[2]);
1594  }
1595}
1596
1597uint32_t adjustDIndex(Type Ty, uint32_t DIndex) {
1598  // If Ty is a vector of i1, we may need to adjust DIndex. This is needed
1599  // because, e.g., the second i1 in a v4i1 is accessed with a
1600  //
1601  // vmov.s8 Qd[4], Rn
1602  switch (Ty) {
1603  case IceType_v4i1:
1604    return DIndex * 4;
1605  case IceType_v8i1:
1606    return DIndex * 2;
1607  case IceType_v16i1:
1608    return DIndex;
1609  default:
1610    return DIndex;
1611  }
1612}
1613
1614uint32_t getDIndex(Type Ty, uint32_t NumElements, uint32_t Index) {
1615  const uint32_t DIndex =
1616      (Index < NumElements / 2) ? Index : Index - (NumElements / 2);
1617  return adjustDIndex(Ty, DIndex);
1618}
1619
1620// For floating point values, we can insertelement or extractelement by moving
1621// directly from an S register. This function finds the right one.
1622Register getSRegister(const Variable *Src, uint32_t Index) {
1623  assert(Src->hasReg());
1624  const auto SrcReg = Src->getRegNum();
1625
1626  // For floating point values, we need to be allocated to Q0 - Q7, so we can
1627  // directly access the value we want as one of the S registers.
1628  assert(Src->getType() == IceType_v4f32);
1629  assert(SrcReg < RegARM32::Reg_q8);
1630
1631  // This part assumes the register alias list goes q0, d0, d1, s0, s1, s2, s3.
1632  assert(Index < 4);
1633
1634  // TODO(jpp): find a way to do this that doesn't rely on ordering of the alias
1635  // list.
1636  return static_cast<Register>(RegARM32::RegTable[SrcReg].Aliases[Index + 3]);
1637}
1638
1639} // end of anonymous namespace
1640
1641void InstARM32Extract::emit(const Cfg *Func) const {
1642  Ostream &Str = Func->getContext()->getStrEmit();
1643  const Type DestTy = getDest()->getType();
1644
1645  const auto *Src = llvm::cast<Variable>(getSrc(0));
1646
1647  if (isIntegerType(DestTy)) {
1648    Str << "\t"
1649        << "vmov" << getPredicate();
1650    const uint32_t BitSize = typeWidthInBytes(DestTy) * CHAR_BIT;
1651    if (BitSize < 32) {
1652      Str << ".s" << BitSize;
1653    } else {
1654      Str << "." << BitSize;
1655    }
1656    Str << "\t";
1657    getDest()->emit(Func);
1658    Str << ", ";
1659
1660    const Type SrcTy = Src->getType();
1661    const size_t VectorSize = typeNumElements(SrcTy);
1662
1663    const Register SrcReg = getDRegister(Src, Index);
1664
1665    Str << RegARM32::RegTable[SrcReg].Name;
1666    Str << "[" << getDIndex(SrcTy, VectorSize, Index) << "]";
1667  } else if (isFloatingType(DestTy)) {
1668    const Register SrcReg = getSRegister(Src, Index);
1669
1670    Str << "\t"
1671        << "vmov" << getPredicate() << ".f32"
1672        << "\t";
1673    getDest()->emit(Func);
1674    Str << ", " << RegARM32::RegTable[SrcReg].Name;
1675  } else {
1676    assert(false && "Invalid extract type");
1677  }
1678}
1679
1680void InstARM32Extract::emitIAS(const Cfg *Func) const {
1681  const Operand *Dest = getDest();
1682  const Type DestTy = Dest->getType();
1683  const Operand *Src = getSrc(0);
1684  const Type SrcTy = Src->getType();
1685  assert(isVectorType(Src->getType()));
1686  assert(DestTy == typeElementType(Src->getType()));
1687  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1688  if (isIntegerType(DestTy)) {
1689    Asm->vmovrqi(Dest, Src, adjustDIndex(SrcTy, Index), getPredicate());
1690    assert(!Asm->needsTextFixup());
1691    return;
1692  }
1693  assert(isFloatingType(DestTy));
1694  Asm->vmovsqi(Dest, Src, Index, getPredicate());
1695  assert(!Asm->needsTextFixup());
1696}
1697
1698namespace {
1699Type insertionType(Type Ty) {
1700  assert(isVectorType(Ty));
1701  switch (Ty) {
1702  case IceType_v4i1:
1703    return IceType_v4i32;
1704  case IceType_v8i1:
1705    return IceType_v8i16;
1706  case IceType_v16i1:
1707    return IceType_v16i8;
1708  default:
1709    return Ty;
1710  }
1711}
1712} // end of anonymous namespace
1713
1714void InstARM32Insert::emit(const Cfg *Func) const {
1715  Ostream &Str = Func->getContext()->getStrEmit();
1716  const Variable *Dest = getDest();
1717  const auto *Src = llvm::cast<Variable>(getSrc(0));
1718  const Type DestTy = insertionType(getDest()->getType());
1719  assert(isVectorType(DestTy));
1720
1721  if (isIntegerType(DestTy)) {
1722    Str << "\t"
1723        << "vmov" << getPredicate();
1724    const size_t BitSize = typeWidthInBytes(typeElementType(DestTy)) * CHAR_BIT;
1725    Str << "." << BitSize << "\t";
1726
1727    const size_t VectorSize = typeNumElements(DestTy);
1728    const Register DestReg = getDRegister(Dest, Index);
1729    const uint32_t Index =
1730        getDIndex(insertionType(DestTy), VectorSize, this->Index);
1731    Str << RegARM32::RegTable[DestReg].Name;
1732    Str << "[" << Index << "], ";
1733    Src->emit(Func);
1734  } else if (isFloatingType(DestTy)) {
1735    Str << "\t"
1736        << "vmov" << getPredicate() << ".f32"
1737        << "\t";
1738    const Register DestReg = getSRegister(Dest, Index);
1739    Str << RegARM32::RegTable[DestReg].Name << ", ";
1740    Src->emit(Func);
1741  } else {
1742    assert(false && "Invalid insert type");
1743  }
1744}
1745
1746void InstARM32Insert::emitIAS(const Cfg *Func) const {
1747  const Variable *Dest = getDest();
1748  const auto *Src = llvm::cast<Variable>(getSrc(0));
1749  const Type DestTy = insertionType(Dest->getType());
1750  const Type SrcTy = typeElementType(DestTy);
1751  assert(SrcTy == Src->getType() || Src->getType() == IceType_i1);
1752  assert(isVectorType(DestTy));
1753  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1754  if (isIntegerType(SrcTy)) {
1755    Asm->vmovqir(Dest->asType(Func, DestTy, Dest->getRegNum()),
1756                 adjustDIndex(DestTy, Index),
1757                 Src->asType(Func, SrcTy, Src->getRegNum()), getPredicate());
1758    assert(!Asm->needsTextFixup());
1759    return;
1760  }
1761  assert(isFloatingType(SrcTy));
1762  Asm->vmovqis(Dest, Index, Src, getPredicate());
1763  assert(!Asm->needsTextFixup());
1764}
1765
1766template <InstARM32::InstKindARM32 K>
1767void InstARM32CmpLike<K>::emitIAS(const Cfg *Func) const {
1768  emitUsingTextFixup(Func);
1769}
1770
1771template <> void InstARM32Cmn::emitIAS(const Cfg *Func) const {
1772  assert(getSrcSize() == 2);
1773  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1774  Asm->cmn(getSrc(0), getSrc(1), getPredicate());
1775  if (Asm->needsTextFixup())
1776    emitUsingTextFixup(Func);
1777}
1778
1779template <> void InstARM32Cmp::emitIAS(const Cfg *Func) const {
1780  assert(getSrcSize() == 2);
1781  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1782  Asm->cmp(getSrc(0), getSrc(1), getPredicate());
1783  if (Asm->needsTextFixup())
1784    emitUsingTextFixup(Func);
1785}
1786
1787template <> void InstARM32Tst::emitIAS(const Cfg *Func) const {
1788  assert(getSrcSize() == 2);
1789  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
1790  Asm->tst(getSrc(0), getSrc(1), getPredicate());
1791  if (Asm->needsTextFixup())
1792    emitUsingTextFixup(Func);
1793}
1794
1795InstARM32Dmb::InstARM32Dmb(Cfg *Func)
1796    : InstARM32Pred(Func, InstARM32::Dmb, 0, nullptr, CondARM32::AL) {}
1797
1798InstARM32Nop::InstARM32Nop(Cfg *Func)
1799    : InstARM32Pred(Func, InstARM32::Nop, 0, nullptr, CondARM32::AL) {}
1800
1801InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
1802                             CondARM32::Cond Predicate)
1803    : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) {
1804  HasSideEffects = true;
1805  addSource(Src0);
1806  addSource(Src1);
1807}
1808
1809InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate)
1810    : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {
1811  HasSideEffects = true;
1812}
1813
1814InstARM32Vabs::InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
1815                             CondARM32::Cond Predicate)
1816    : InstARM32Pred(Func, InstARM32::Vabs, 1, Dest, Predicate) {
1817  addSource(Src);
1818}
1819
1820// ======================== Dump routines ======================== //
1821
1822// Two-addr ops
1823template <> const char *InstARM32Movt::Opcode = "movt";
1824// Unary ops
1825template <> const char *InstARM32Movw::Opcode = "movw";
1826template <> const char *InstARM32Clz::Opcode = "clz";
1827template <> const char *InstARM32Mvn::Opcode = "mvn";
1828template <> const char *InstARM32Rbit::Opcode = "rbit";
1829template <> const char *InstARM32Rev::Opcode = "rev";
1830template <> const char *InstARM32Sxt::Opcode = "sxt"; // still requires b/h
1831template <> const char *InstARM32Uxt::Opcode = "uxt"; // still requires b/h
1832// FP
1833template <> const char *InstARM32Vsqrt::Opcode = "vsqrt";
1834// Mov-like ops
1835template <> const char *InstARM32Ldr::Opcode = "ldr";
1836template <> const char *InstARM32Ldrex::Opcode = "ldrex";
1837template <> const char *InstARM32Vldr1d::Opcode = "vldr1d";
1838template <> const char *InstARM32Vldr1q::Opcode = "vldr1q";
1839// Three-addr ops
1840template <> const char *InstARM32Adc::Opcode = "adc";
1841template <> const char *InstARM32Add::Opcode = "add";
1842template <> const char *InstARM32And::Opcode = "and";
1843template <> const char *InstARM32Asr::Opcode = "asr";
1844template <> const char *InstARM32Bic::Opcode = "bic";
1845template <> const char *InstARM32Eor::Opcode = "eor";
1846template <> const char *InstARM32Lsl::Opcode = "lsl";
1847template <> const char *InstARM32Lsr::Opcode = "lsr";
1848template <> const char *InstARM32Mul::Opcode = "mul";
1849template <> const char *InstARM32Orr::Opcode = "orr";
1850template <> const char *InstARM32Rsb::Opcode = "rsb";
1851template <> const char *InstARM32Rsc::Opcode = "rsc";
1852template <> const char *InstARM32Sbc::Opcode = "sbc";
1853template <> const char *InstARM32Sdiv::Opcode = "sdiv";
1854template <> const char *InstARM32Sub::Opcode = "sub";
1855template <> const char *InstARM32Udiv::Opcode = "udiv";
1856// FP
1857template <> const char *InstARM32Vadd::Opcode = "vadd";
1858template <> const char *InstARM32Vand::Opcode = "vand";
1859template <> const char *InstARM32Vbsl::Opcode = "vbsl";
1860template <> const char *InstARM32Vceq::Opcode = "vceq";
1861template <> const char *InstARM32ThreeAddrFP<InstARM32::Vcge>::Opcode = "vcge";
1862template <> const char *InstARM32ThreeAddrFP<InstARM32::Vcgt>::Opcode = "vcgt";
1863template <> const char *InstARM32Vdiv::Opcode = "vdiv";
1864template <> const char *InstARM32Veor::Opcode = "veor";
1865template <> const char *InstARM32Vmla::Opcode = "vmla";
1866template <> const char *InstARM32Vmls::Opcode = "vmls";
1867template <> const char *InstARM32Vmul::Opcode = "vmul";
1868template <> const char *InstARM32Vmvn::Opcode = "vmvn";
1869template <> const char *InstARM32Vmovl::Opcode = "vmovl";
1870template <> const char *InstARM32Vmovh::Opcode = "vmovh";
1871template <> const char *InstARM32Vmovhl::Opcode = "vmovhl";
1872template <> const char *InstARM32Vmovlh::Opcode = "vmovlh";
1873template <> const char *InstARM32Vorr::Opcode = "vorr";
1874template <> const char *InstARM32UnaryopFP<InstARM32::Vneg>::Opcode = "vneg";
1875template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshl>::Opcode = "vshl";
1876template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshr>::Opcode = "vshr";
1877template <> const char *InstARM32Vsub::Opcode = "vsub";
1878template <>
1879const char *InstARM32ThreeAddrFP<InstARM32::Vqadd>::Opcode = "vqadd";
1880template <>
1881const char *InstARM32ThreeAddrFP<InstARM32::Vqsub>::Opcode = "vqsub";
1882template <>
1883const char *InstARM32ThreeAddrFP<InstARM32::Vqmovn2>::Opcode = "vqmovn2";
1884template <>
1885const char *InstARM32ThreeAddrFP<InstARM32::Vmulh>::Opcode = "vmulh";
1886template <>
1887const char *InstARM32ThreeAddrFP<InstARM32::Vmlap>::Opcode = "vmlap";
1888template <> const char *InstARM32ThreeAddrFP<InstARM32::Vzip>::Opcode = "vzip";
1889// Four-addr ops
1890template <> const char *InstARM32Mla::Opcode = "mla";
1891template <> const char *InstARM32Mls::Opcode = "mls";
1892// Cmp-like ops
1893template <> const char *InstARM32Cmn::Opcode = "cmn";
1894template <> const char *InstARM32Cmp::Opcode = "cmp";
1895template <> const char *InstARM32Tst::Opcode = "tst";
1896
1897void InstARM32::dump(const Cfg *Func) const {
1898  if (!BuildDefs::dump())
1899    return;
1900  Ostream &Str = Func->getContext()->getStrDump();
1901  Str << "[ARM32] ";
1902  Inst::dump(Func);
1903}
1904
1905void InstARM32Mov::emitMultiDestSingleSource(const Cfg *Func) const {
1906  if (!BuildDefs::dump())
1907    return;
1908  Ostream &Str = Func->getContext()->getStrEmit();
1909  Variable *DestLo = getDest();
1910  Variable *DestHi = getDestHi();
1911  auto *Src = llvm::cast<Variable>(getSrc(0));
1912
1913  assert(DestHi->hasReg());
1914  assert(DestLo->hasReg());
1915  assert(Src->hasReg());
1916
1917  Str << "\t"
1918         "vmov" << getPredicate() << "\t";
1919  DestLo->emit(Func);
1920  Str << ", ";
1921  DestHi->emit(Func);
1922  Str << ", ";
1923  Src->emit(Func);
1924}
1925
1926void InstARM32Mov::emitSingleDestMultiSource(const Cfg *Func) const {
1927  if (!BuildDefs::dump())
1928    return;
1929  Ostream &Str = Func->getContext()->getStrEmit();
1930  Variable *Dest = getDest();
1931  auto *SrcLo = llvm::cast<Variable>(getSrc(0));
1932  auto *SrcHi = llvm::cast<Variable>(getSrc(1));
1933
1934  assert(SrcHi->hasReg());
1935  assert(SrcLo->hasReg());
1936  assert(Dest->hasReg());
1937  assert(getSrcSize() == 2);
1938
1939  Str << "\t"
1940         "vmov" << getPredicate() << "\t";
1941  Dest->emit(Func);
1942  Str << ", ";
1943  SrcLo->emit(Func);
1944  Str << ", ";
1945  SrcHi->emit(Func);
1946}
1947
1948namespace {
1949
1950bool isVariableWithoutRegister(const Operand *Op) {
1951  if (const auto *OpV = llvm::dyn_cast<Variable>(Op)) {
1952    return !OpV->hasReg();
1953  }
1954  return false;
1955}
1956bool isMemoryAccess(Operand *Op) {
1957  return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op);
1958}
1959
1960bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) {
1961  const Type DestTy = Dest->getType();
1962  const Type SrcTy = Src->getType();
1963  return !isVectorType(DestTy) && !isVectorType(SrcTy) &&
1964         (isScalarIntegerType(DestTy) == isScalarFloatingType(SrcTy));
1965}
1966
1967} // end of anonymous namespace
1968
1969void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
1970  if (!BuildDefs::dump())
1971    return;
1972  Ostream &Str = Func->getContext()->getStrEmit();
1973  Variable *Dest = getDest();
1974
1975  if (!Dest->hasReg()) {
1976    llvm::report_fatal_error("mov can't store.");
1977  }
1978
1979  Operand *Src0 = getSrc(0);
1980  if (isMemoryAccess(Src0)) {
1981    llvm::report_fatal_error("mov can't load.");
1982  }
1983
1984  Type Ty = Dest->getType();
1985  const bool IsVector = isVectorType(Ty);
1986  const bool IsScalarFP = isScalarFloatingType(Ty);
1987  const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
1988  const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove);
1989  const char *Opcode = IsVMove ? "vmov" : "mov";
1990  // when vmov{c}'ing, we need to emit a width string. Otherwise, the
1991  // assembler might be tempted to assume we want a vector vmov{c}, and that
1992  // is disallowed because ARM.
1993  const char *WidthString = !CoreVFPMove ? getFpWidthString(Ty) : "";
1994  CondARM32::Cond Cond = getPredicate();
1995  if (IsVector)
1996    assert(CondARM32::isUnconditional(Cond) &&
1997           "Moves on vectors must be unconditional!");
1998  Str << "\t" << Opcode;
1999  if (IsVMove) {
2000    Str << Cond << WidthString;
2001  } else {
2002    Str << WidthString << Cond;
2003  }
2004  Str << "\t";
2005  Dest->emit(Func);
2006  Str << ", ";
2007  Src0->emit(Func);
2008}
2009
2010void InstARM32Mov::emit(const Cfg *Func) const {
2011  if (!BuildDefs::dump())
2012    return;
2013  assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
2014  if (isMultiDest()) {
2015    emitMultiDestSingleSource(Func);
2016    return;
2017  }
2018
2019  if (isMultiSource()) {
2020    emitSingleDestMultiSource(Func);
2021    return;
2022  }
2023
2024  emitSingleDestSingleSource(Func);
2025}
2026
2027void InstARM32Mov::emitIAS(const Cfg *Func) const {
2028  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2029  const Variable *Dest = getDest();
2030  Operand *Src0 = getSrc(0);
2031  const CondARM32::Cond Cond = getPredicate();
2032  if (!Dest->hasReg()) {
2033    llvm::report_fatal_error("mov can't store.");
2034  }
2035  if (isMemoryAccess(Src0)) {
2036    llvm::report_fatal_error("mov can't load.");
2037  }
2038
2039  assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
2040  if (isMultiDest()) {
2041    Asm->vmovrrd(Dest, getDestHi(), Src0, Cond);
2042    return;
2043  }
2044  if (isMultiSource()) {
2045    Asm->vmovdrr(Dest, Src0, getSrc(1), Cond);
2046    return;
2047  }
2048
2049  const Type DestTy = Dest->getType();
2050  const Type SrcTy = Src0->getType();
2051  switch (DestTy) {
2052  default:
2053    break; // Error
2054  case IceType_i1:
2055  case IceType_i8:
2056  case IceType_i16:
2057  case IceType_i32:
2058    switch (SrcTy) {
2059    default:
2060      break; // Error
2061    case IceType_i1:
2062    case IceType_i8:
2063    case IceType_i16:
2064    case IceType_i32:
2065    case IceType_i64:
2066      Asm->mov(Dest, Src0, Cond);
2067      return;
2068    case IceType_f32:
2069      Asm->vmovrs(Dest, Src0, Cond);
2070      return;
2071    }
2072    break; // Error
2073  case IceType_i64:
2074    if (isScalarIntegerType(SrcTy)) {
2075      Asm->mov(Dest, Src0, Cond);
2076      return;
2077    }
2078    if (SrcTy == IceType_f64) {
2079      if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
2080        Asm->vmovdd(Dest, Var, Cond);
2081        return;
2082      }
2083      if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
2084        Asm->vmovd(Dest, FpImm, Cond);
2085        return;
2086      }
2087    }
2088    break; // Error
2089  case IceType_f32:
2090    switch (SrcTy) {
2091    default:
2092      break; // Error
2093    case IceType_i1:
2094    case IceType_i8:
2095    case IceType_i16:
2096    case IceType_i32:
2097      return Asm->vmovsr(Dest, Src0, Cond);
2098    case IceType_f32:
2099      if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
2100        Asm->vmovss(Dest, Var, Cond);
2101        return;
2102      }
2103      if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
2104        Asm->vmovs(Dest, FpImm, Cond);
2105        return;
2106      }
2107      break; // Error
2108    }
2109    break; // Error
2110  case IceType_f64:
2111    if (SrcTy == IceType_f64) {
2112      if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
2113        Asm->vmovdd(Dest, Var, Cond);
2114        return;
2115      }
2116      if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
2117        Asm->vmovd(Dest, FpImm, Cond);
2118        return;
2119      }
2120    }
2121    break; // Error
2122  // TODO(jpp): Remove vectors of i1.
2123  case IceType_v4i1:
2124  case IceType_v8i1:
2125  case IceType_v16i1:
2126  case IceType_v16i8:
2127  case IceType_v8i16:
2128  case IceType_v4i32:
2129  case IceType_v4f32:
2130    assert(CondARM32::isUnconditional(Cond) &&
2131           "Moves on vector must be unconditional!");
2132    if (isVectorType(SrcTy)) {
2133      // Mov between different Src and Dest types is used for bitcasting
2134      // vectors.  We still want to make sure SrcTy is a vector type.
2135      Asm->vorrq(Dest, Src0, Src0);
2136      return;
2137    } else if (const auto *C = llvm::dyn_cast<ConstantInteger32>(Src0)) {
2138      // Mov with constant argument, allowing the initializing all elements of
2139      // the vector.
2140      if (Asm->vmovqc(Dest, C))
2141        return;
2142    }
2143  }
2144  llvm::report_fatal_error("Mov: don't know how to move " +
2145                           typeStdString(SrcTy) + " to " +
2146                           typeStdString(DestTy));
2147}
2148
2149void InstARM32Mov::dump(const Cfg *Func) const {
2150  if (!BuildDefs::dump())
2151    return;
2152  assert(getSrcSize() == 1 || getSrcSize() == 2);
2153  Ostream &Str = Func->getContext()->getStrDump();
2154  Variable *Dest = getDest();
2155  Variable *DestHi = getDestHi();
2156  Dest->dump(Func);
2157  if (DestHi) {
2158    Str << ", ";
2159    DestHi->dump(Func);
2160  }
2161
2162  dumpOpcodePred(Str, " = mov", getDest()->getType());
2163  Str << " ";
2164
2165  dumpSources(Func);
2166}
2167
2168void InstARM32Br::emit(const Cfg *Func) const {
2169  if (!BuildDefs::dump())
2170    return;
2171  Ostream &Str = Func->getContext()->getStrEmit();
2172  Str << "\t"
2173         "b" << getPredicate() << "\t";
2174  if (Label) {
2175    Str << Label->getLabelName();
2176  } else {
2177    if (isUnconditionalBranch()) {
2178      Str << getTargetFalse()->getAsmName();
2179    } else {
2180      Str << getTargetTrue()->getAsmName();
2181      if (getTargetFalse()) {
2182        startNextInst(Func);
2183        Str << "\n\t"
2184            << "b"
2185            << "\t" << getTargetFalse()->getAsmName();
2186      }
2187    }
2188  }
2189}
2190
2191void InstARM32Br::emitIAS(const Cfg *Func) const {
2192  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2193  if (Label) {
2194    Asm->b(Asm->getOrCreateLocalLabel(Label->getNumber()), getPredicate());
2195  } else if (isUnconditionalBranch()) {
2196    Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()),
2197           getPredicate());
2198  } else {
2199    Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()),
2200           getPredicate());
2201    if (const CfgNode *False = getTargetFalse())
2202      Asm->b(Asm->getOrCreateCfgNodeLabel(False->getIndex()), CondARM32::AL);
2203  }
2204  if (Asm->needsTextFixup())
2205    emitUsingTextFixup(Func);
2206}
2207
2208void InstARM32Br::dump(const Cfg *Func) const {
2209  if (!BuildDefs::dump())
2210    return;
2211  Ostream &Str = Func->getContext()->getStrDump();
2212  Str << "br ";
2213
2214  if (getPredicate() == CondARM32::AL) {
2215    if (Label) {
2216      Str << "label %" << Label->getLabelName();
2217    } else {
2218      Str << "label %" << getTargetFalse()->getName();
2219    }
2220    return;
2221  }
2222
2223  if (Label) {
2224    Str << getPredicate() << ", label %" << Label->getLabelName();
2225  } else {
2226    Str << getPredicate() << ", label %" << getTargetTrue()->getName();
2227    if (getTargetFalse()) {
2228      Str << ", label %" << getTargetFalse()->getName();
2229    }
2230  }
2231}
2232
2233void InstARM32Call::emit(const Cfg *Func) const {
2234  if (!BuildDefs::dump())
2235    return;
2236  Ostream &Str = Func->getContext()->getStrEmit();
2237  assert(getSrcSize() == 1);
2238  if (llvm::isa<ConstantInteger32>(getCallTarget())) {
2239    // This shouldn't happen (typically have to copy the full 32-bits to a
2240    // register and do an indirect jump).
2241    llvm::report_fatal_error("ARM32Call to ConstantInteger32");
2242  } else if (const auto *CallTarget =
2243                 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
2244    // Calls only have 24-bits, but the linker should insert veneers to extend
2245    // the range if needed.
2246    Str << "\t"
2247           "bl"
2248           "\t";
2249    CallTarget->emitWithoutPrefix(Func->getTarget());
2250  } else {
2251    Str << "\t"
2252           "blx"
2253           "\t";
2254    getCallTarget()->emit(Func);
2255  }
2256}
2257
2258void InstARM32Call::emitIAS(const Cfg *Func) const {
2259  assert(getSrcSize() == 1);
2260  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2261  if (llvm::isa<ConstantInteger32>(getCallTarget())) {
2262    // This shouldn't happen (typically have to copy the full 32-bits to a
2263    // register and do an indirect jump).
2264    llvm::report_fatal_error("ARM32Call to ConstantInteger32");
2265  } else if (const auto *CallTarget =
2266                 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
2267    // Calls only have 24-bits, but the linker should insert veneers to extend
2268    // the range if needed.
2269    Asm->bl(CallTarget);
2270  } else {
2271    Asm->blx(getCallTarget());
2272  }
2273  if (Asm->needsTextFixup())
2274    return emitUsingTextFixup(Func);
2275}
2276
2277void InstARM32Call::dump(const Cfg *Func) const {
2278  if (!BuildDefs::dump())
2279    return;
2280  Ostream &Str = Func->getContext()->getStrDump();
2281  if (getDest()) {
2282    dumpDest(Func);
2283    Str << " = ";
2284  }
2285  Str << "call ";
2286  getCallTarget()->dump(Func);
2287}
2288
2289void InstARM32Label::emit(const Cfg *Func) const {
2290  if (!BuildDefs::dump())
2291    return;
2292  // A label is not really an instruction. Hence, we need to fix the
2293  // emitted text size.
2294  if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>())
2295    Asm->decEmitTextSize(InstSize);
2296  Ostream &Str = Func->getContext()->getStrEmit();
2297  Str << getLabelName() << ":";
2298}
2299
2300void InstARM32Label::emitIAS(const Cfg *Func) const {
2301  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2302  Asm->bindLocalLabel(this, Number);
2303  if (OffsetReloc != nullptr) {
2304    Asm->bindRelocOffset(OffsetReloc);
2305  }
2306  if (Asm->needsTextFixup())
2307    emitUsingTextFixup(Func);
2308}
2309
2310void InstARM32Label::dump(const Cfg *Func) const {
2311  if (!BuildDefs::dump())
2312    return;
2313  Ostream &Str = Func->getContext()->getStrDump();
2314  Str << getLabelName() << ":";
2315}
2316
2317template <InstARM32::InstKindARM32 K>
2318void InstARM32LoadBase<K>::emitIAS(const Cfg *Func) const {
2319  emitUsingTextFixup(Func);
2320}
2321
2322template <> void InstARM32Ldr::emit(const Cfg *Func) const {
2323  if (!BuildDefs::dump())
2324    return;
2325  Ostream &Str = Func->getContext()->getStrEmit();
2326  assert(getSrcSize() == 1);
2327  assert(getDest()->hasReg());
2328  Variable *Dest = getDest();
2329  Type Ty = Dest->getType();
2330  const bool IsVector = isVectorType(Ty);
2331  const bool IsScalarFloat = isScalarFloatingType(Ty);
2332  const char *ActualOpcode =
2333      IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
2334  const char *WidthString = IsVector ? "" : getWidthString(Ty);
2335  Str << "\t" << ActualOpcode;
2336  const bool IsVInst = IsVector || IsScalarFloat;
2337  if (IsVInst) {
2338    Str << getPredicate() << WidthString;
2339  } else {
2340    Str << WidthString << getPredicate();
2341  }
2342  if (IsVector)
2343    Str << "." << getVecElmtBitsize(Ty);
2344  Str << "\t";
2345  getDest()->emit(Func);
2346  Str << ", ";
2347  getSrc(0)->emit(Func);
2348}
2349
2350template <> void InstARM32Vldr1d::emit(const Cfg *Func) const {
2351  if (!BuildDefs::dump())
2352    return;
2353  Ostream &Str = Func->getContext()->getStrEmit();
2354  assert(getSrcSize() == 1);
2355  assert(getDest()->hasReg());
2356  Variable *Dest = getDest();
2357  Type Ty = Dest->getType();
2358  const bool IsVector = isVectorType(Ty);
2359  const bool IsScalarFloat = isScalarFloatingType(Ty);
2360  const char *ActualOpcode =
2361      IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
2362  const char *WidthString = IsVector ? "" : getWidthString(Ty);
2363  Str << "\t" << ActualOpcode;
2364  const bool IsVInst = IsVector || IsScalarFloat;
2365  if (IsVInst) {
2366    Str << getPredicate() << WidthString;
2367  } else {
2368    Str << WidthString << getPredicate();
2369  }
2370  if (IsVector)
2371    Str << "." << getVecElmtBitsize(Ty);
2372  Str << "\t";
2373  getDest()->emit(Func);
2374  Str << ", ";
2375  getSrc(0)->emit(Func);
2376}
2377
2378template <> void InstARM32Vldr1q::emit(const Cfg *Func) const {
2379  if (!BuildDefs::dump())
2380    return;
2381  Ostream &Str = Func->getContext()->getStrEmit();
2382  assert(getSrcSize() == 1);
2383  assert(getDest()->hasReg());
2384  Variable *Dest = getDest();
2385  Type Ty = Dest->getType();
2386  const bool IsVector = isVectorType(Ty);
2387  const bool IsScalarFloat = isScalarFloatingType(Ty);
2388  const char *ActualOpcode =
2389      IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
2390  const char *WidthString = IsVector ? "" : getWidthString(Ty);
2391  Str << "\t" << ActualOpcode;
2392  const bool IsVInst = IsVector || IsScalarFloat;
2393  if (IsVInst) {
2394    Str << getPredicate() << WidthString;
2395  } else {
2396    Str << WidthString << getPredicate();
2397  }
2398  if (IsVector)
2399    Str << "." << getVecElmtBitsize(Ty);
2400  Str << "\t";
2401  getDest()->emit(Func);
2402  Str << ", ";
2403  getSrc(0)->emit(Func);
2404}
2405
2406template <> void InstARM32Ldr::emitIAS(const Cfg *Func) const {
2407  assert(getSrcSize() == 1);
2408  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2409  Variable *Dest = getDest();
2410  const Type DestTy = Dest->getType();
2411  switch (DestTy) {
2412  default:
2413    llvm::report_fatal_error("Ldr on unknown type: " + typeStdString(DestTy));
2414  case IceType_i1:
2415  case IceType_i8:
2416  case IceType_i16:
2417  case IceType_i32:
2418  case IceType_i64:
2419    Asm->ldr(Dest, getSrc(0), getPredicate(), Func->getTarget());
2420    break;
2421  case IceType_f32:
2422    Asm->vldrs(Dest, getSrc(0), getPredicate(), Func->getTarget());
2423    break;
2424  case IceType_f64:
2425    Asm->vldrd(Dest, getSrc(0), getPredicate(), Func->getTarget());
2426    break;
2427  case IceType_v16i8:
2428  case IceType_v8i16:
2429  case IceType_v4i32:
2430  case IceType_v4f32:
2431  case IceType_v16i1:
2432  case IceType_v8i1:
2433  case IceType_v4i1:
2434    Asm->vld1qr(getVecElmtBitsize(DestTy), Dest, getSrc(0), Func->getTarget());
2435    break;
2436  }
2437}
2438
2439template <> void InstARM32Vldr1d::emitIAS(const Cfg *Func) const {
2440  assert(getSrcSize() == 1);
2441  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2442  Variable *Dest = getDest();
2443  Asm->vld1(32, Dest, getSrc(0), Func->getTarget());
2444}
2445
2446template <> void InstARM32Vldr1q::emitIAS(const Cfg *Func) const {
2447  assert(getSrcSize() == 1);
2448  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2449  Variable *Dest = getDest();
2450  Asm->vld1(64, Dest, getSrc(0), Func->getTarget());
2451}
2452
2453template <> void InstARM32Ldrex::emit(const Cfg *Func) const {
2454  if (!BuildDefs::dump())
2455    return;
2456  Ostream &Str = Func->getContext()->getStrEmit();
2457  assert(getSrcSize() == 1);
2458  assert(getDest()->hasReg());
2459  Variable *Dest = getDest();
2460  Type DestTy = Dest->getType();
2461  assert(isScalarIntegerType(DestTy));
2462  const char *WidthString = getWidthString(DestTy);
2463  Str << "\t" << Opcode << WidthString << getPredicate() << "\t";
2464  getDest()->emit(Func);
2465  Str << ", ";
2466  getSrc(0)->emit(Func);
2467}
2468
2469template <> void InstARM32Ldrex::emitIAS(const Cfg *Func) const {
2470  assert(getSrcSize() == 1);
2471  assert(getDest()->hasReg());
2472  Variable *Dest = getDest();
2473  assert(isScalarIntegerType(Dest->getType()));
2474  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2475  Asm->ldrex(Dest, getSrc(0), getPredicate(), Func->getTarget());
2476  if (Asm->needsTextFixup())
2477    emitUsingTextFixup(Func);
2478}
2479
2480template <InstARM32::InstKindARM32 K>
2481void InstARM32TwoAddrGPR<K>::emitIAS(const Cfg *Func) const {
2482  emitUsingTextFixup(Func);
2483}
2484
2485template <InstARM32::InstKindARM32 K, bool Nws>
2486void InstARM32UnaryopGPR<K, Nws>::emitIAS(const Cfg *Func) const {
2487  emitUsingTextFixup(Func);
2488}
2489
2490template <> void InstARM32Rbit::emitIAS(const Cfg *Func) const {
2491  assert(getSrcSize() == 1);
2492  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2493  Asm->rbit(getDest(), getSrc(0), getPredicate());
2494  if (Asm->needsTextFixup())
2495    emitUsingTextFixup(Func);
2496}
2497
2498template <> void InstARM32Rev::emitIAS(const Cfg *Func) const {
2499  assert(getSrcSize() == 1);
2500  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2501  Asm->rev(getDest(), getSrc(0), getPredicate());
2502  if (Asm->needsTextFixup())
2503    emitUsingTextFixup(Func);
2504}
2505
2506template <> void InstARM32Movw::emit(const Cfg *Func) const {
2507  if (!BuildDefs::dump())
2508    return;
2509  Ostream &Str = Func->getContext()->getStrEmit();
2510  assert(getSrcSize() == 1);
2511  Str << "\t" << Opcode << getPredicate() << "\t";
2512  getDest()->emit(Func);
2513  Str << ", ";
2514  auto *Src0 = llvm::cast<Constant>(getSrc(0));
2515  if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
2516    Str << "#:lower16:";
2517    CR->emitWithoutPrefix(Func->getTarget());
2518    if (getFlags().getUseNonsfi()) {
2519      Str << " - .";
2520    }
2521  } else {
2522    Src0->emit(Func);
2523  }
2524}
2525
2526template <> void InstARM32Movw::emitIAS(const Cfg *Func) const {
2527  assert(getSrcSize() == 1);
2528  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2529  Asm->movw(getDest(), getSrc(0), getPredicate());
2530  if (Asm->needsTextFixup())
2531    emitUsingTextFixup(Func);
2532}
2533
2534template <> void InstARM32Movt::emit(const Cfg *Func) const {
2535  if (!BuildDefs::dump())
2536    return;
2537  Ostream &Str = Func->getContext()->getStrEmit();
2538  assert(getSrcSize() == 2);
2539  Variable *Dest = getDest();
2540  auto *Src1 = llvm::cast<Constant>(getSrc(1));
2541  Str << "\t" << Opcode << getPredicate() << "\t";
2542  Dest->emit(Func);
2543  Str << ", ";
2544  if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src1)) {
2545    Str << "#:upper16:";
2546    CR->emitWithoutPrefix(Func->getTarget());
2547    if (getFlags().getUseNonsfi()) {
2548      Str << " - .";
2549    }
2550  } else {
2551    Src1->emit(Func);
2552  }
2553}
2554
2555template <> void InstARM32Movt::emitIAS(const Cfg *Func) const {
2556  assert(getSrcSize() == 2);
2557  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2558  Asm->movt(getDest(), getSrc(1), getPredicate());
2559  if (Asm->needsTextFixup())
2560    emitUsingTextFixup(Func);
2561}
2562
2563template <> void InstARM32Clz::emitIAS(const Cfg *Func) const {
2564  assert(getSrcSize() == 1);
2565  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2566  Asm->clz(getDest(), getSrc(0), getPredicate());
2567  if (Asm->needsTextFixup())
2568    emitUsingTextFixup(Func);
2569}
2570
2571template <> void InstARM32Mvn::emitIAS(const Cfg *Func) const {
2572  assert(getSrcSize() == 1);
2573  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2574  Asm->mvn(getDest(), getSrc(0), getPredicate());
2575  if (Asm->needsTextFixup())
2576    emitUsingTextFixup(Func);
2577}
2578
2579template <> void InstARM32Sxt::emitIAS(const Cfg *Func) const {
2580  assert(getSrcSize() == 1);
2581  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2582  Asm->sxt(getDest(), getSrc(0), getPredicate());
2583  if (Asm->needsTextFixup())
2584    emitUsingTextFixup(Func);
2585}
2586
2587template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const {
2588  assert(getSrcSize() == 1);
2589  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2590  Asm->uxt(getDest(), getSrc(0), getPredicate());
2591  if (Asm->needsTextFixup())
2592    emitUsingTextFixup(Func);
2593}
2594
2595template <InstARM32::InstKindARM32 K>
2596void InstARM32UnaryopFP<K>::emitIAS(const Cfg *Func) const {
2597  emitUsingTextFixup(Func);
2598}
2599
2600template <InstARM32::InstKindARM32 K>
2601void InstARM32UnaryopSignAwareFP<K>::emitIAS(const Cfg *Func) const {
2602  InstARM32::emitUsingTextFixup(Func);
2603}
2604
2605template <> void InstARM32Vsqrt::emitIAS(const Cfg *Func) const {
2606  assert(getSrcSize() == 1);
2607  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2608  const Operand *Dest = getDest();
2609  switch (Dest->getType()) {
2610  case IceType_f32:
2611    Asm->vsqrts(Dest, getSrc(0), getPredicate());
2612    break;
2613  case IceType_f64:
2614    Asm->vsqrtd(Dest, getSrc(0), getPredicate());
2615    break;
2616  default:
2617    llvm::report_fatal_error("Vsqrt of non-floating type");
2618  }
2619  if (Asm->needsTextFixup())
2620    emitUsingTextFixup(Func);
2621}
2622
2623const char *InstARM32Pop::getGPROpcode() const { return "pop"; }
2624
2625const char *InstARM32Pop::getSRegOpcode() const { return "vpop"; }
2626
2627Variable *InstARM32Pop::getStackReg(SizeT Index) const { return Dests[Index]; }
2628
2629SizeT InstARM32Pop::getNumStackRegs() const { return Dests.size(); }
2630
2631void InstARM32Pop::emitSingleGPR(const Cfg *Func, const EmitForm Form,
2632                                 const Variable *Reg) const {
2633  switch (Form) {
2634  case Emit_Text:
2635    emitGPRsAsText(Func);
2636    return;
2637  case Emit_Binary:
2638    Func->getAssembler<ARM32::AssemblerARM32>()->pop(Reg, CondARM32::AL);
2639    return;
2640  }
2641}
2642
2643void InstARM32Pop::emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
2644                                    IValueT Registers) const {
2645  switch (Form) {
2646  case Emit_Text:
2647    emitGPRsAsText(Func);
2648    return;
2649  case Emit_Binary:
2650    Func->getAssembler<ARM32::AssemblerARM32>()->popList(Registers,
2651                                                         CondARM32::AL);
2652    return;
2653  }
2654}
2655
2656void InstARM32Pop::emitSRegs(const Cfg *Func, const EmitForm Form,
2657                             const Variable *BaseReg, SizeT RegCount) const {
2658  switch (Form) {
2659  case Emit_Text:
2660    emitSRegsAsText(Func, BaseReg, RegCount);
2661    return;
2662  case Emit_Binary:
2663    Func->getAssembler<ARM32::AssemblerARM32>()->vpop(BaseReg, RegCount,
2664                                                      CondARM32::AL);
2665    return;
2666  }
2667}
2668
2669const char *InstARM32Push::getGPROpcode() const { return "push"; }
2670
2671const char *InstARM32Push::getSRegOpcode() const { return "vpush"; }
2672
2673Variable *InstARM32Push::getStackReg(SizeT Index) const {
2674  return llvm::cast<Variable>(getSrc(Index));
2675}
2676
2677SizeT InstARM32Push::getNumStackRegs() const { return getSrcSize(); }
2678
2679void InstARM32Push::emitSingleGPR(const Cfg *Func, const EmitForm Form,
2680                                  const Variable *Reg) const {
2681  switch (Form) {
2682  case Emit_Text:
2683    emitGPRsAsText(Func);
2684    return;
2685  case Emit_Binary:
2686    Func->getAssembler<ARM32::AssemblerARM32>()->push(Reg, CondARM32::AL);
2687    return;
2688  }
2689}
2690
2691void InstARM32Push::emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
2692                                     IValueT Registers) const {
2693  switch (Form) {
2694  case Emit_Text:
2695    emitGPRsAsText(Func);
2696    return;
2697  case Emit_Binary:
2698    Func->getAssembler<ARM32::AssemblerARM32>()->pushList(Registers,
2699                                                          CondARM32::AL);
2700    return;
2701  }
2702}
2703
2704void InstARM32Push::emitSRegs(const Cfg *Func, const EmitForm Form,
2705                              const Variable *BaseReg, SizeT RegCount) const {
2706  switch (Form) {
2707  case Emit_Text:
2708    emitSRegsAsText(Func, BaseReg, RegCount);
2709    return;
2710  case Emit_Binary:
2711    Func->getAssembler<ARM32::AssemblerARM32>()->vpush(BaseReg, RegCount,
2712                                                       CondARM32::AL);
2713    return;
2714  }
2715}
2716
2717void InstARM32Ret::emit(const Cfg *Func) const {
2718  if (!BuildDefs::dump())
2719    return;
2720  assert(getSrcSize() > 0);
2721  auto *LR = llvm::cast<Variable>(getSrc(0));
2722  assert(LR->hasReg());
2723  assert(LR->getRegNum() == RegARM32::Reg_lr);
2724  Ostream &Str = Func->getContext()->getStrEmit();
2725  Str << "\t"
2726         "bx"
2727         "\t";
2728  LR->emit(Func);
2729}
2730
2731void InstARM32Ret::emitIAS(const Cfg *Func) const {
2732  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2733  Asm->bx(RegARM32::Encoded_Reg_lr);
2734  if (Asm->needsTextFixup())
2735    emitUsingTextFixup(Func);
2736}
2737
2738void InstARM32Ret::dump(const Cfg *Func) const {
2739  if (!BuildDefs::dump())
2740    return;
2741  Ostream &Str = Func->getContext()->getStrDump();
2742  Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
2743  Str << "ret." << Ty << " ";
2744  dumpSources(Func);
2745}
2746
2747void InstARM32Str::emit(const Cfg *Func) const {
2748  if (!BuildDefs::dump())
2749    return;
2750  Ostream &Str = Func->getContext()->getStrEmit();
2751  assert(getSrcSize() == 2);
2752  Type Ty = getSrc(0)->getType();
2753  const bool IsVectorStore = isVectorType(Ty);
2754  const bool IsScalarFloat = isScalarFloatingType(Ty);
2755  const char *Opcode =
2756      IsVectorStore ? "vst1" : (IsScalarFloat ? "vstr" : "str");
2757  Str << "\t" << Opcode;
2758  const bool IsVInst = IsVectorStore || IsScalarFloat;
2759  if (IsVInst) {
2760    Str << getPredicate() << getWidthString(Ty);
2761  } else {
2762    Str << getWidthString(Ty) << getPredicate();
2763  }
2764  if (IsVectorStore)
2765    Str << "." << getVecElmtBitsize(Ty);
2766  Str << "\t";
2767  getSrc(0)->emit(Func);
2768  Str << ", ";
2769  getSrc(1)->emit(Func);
2770}
2771
2772void InstARM32Str::emitIAS(const Cfg *Func) const {
2773  assert(getSrcSize() == 2);
2774  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2775  const Operand *Src0 = getSrc(0);
2776  const Operand *Src1 = getSrc(1);
2777  Type Ty = Src0->getType();
2778  switch (Ty) {
2779  default:
2780    llvm::report_fatal_error("Str on unknown type: " + typeStdString(Ty));
2781  case IceType_i1:
2782  case IceType_i8:
2783  case IceType_i16:
2784  case IceType_i32:
2785  case IceType_i64:
2786    Asm->str(Src0, Src1, getPredicate(), Func->getTarget());
2787    break;
2788  case IceType_f32:
2789    Asm->vstrs(Src0, Src1, getPredicate(), Func->getTarget());
2790    break;
2791  case IceType_f64:
2792    Asm->vstrd(Src0, Src1, getPredicate(), Func->getTarget());
2793    break;
2794  case IceType_v16i8:
2795  case IceType_v8i16:
2796  case IceType_v4i32:
2797  case IceType_v4f32:
2798  case IceType_v16i1:
2799  case IceType_v8i1:
2800  case IceType_v4i1:
2801    Asm->vst1qr(getVecElmtBitsize(Ty), Src0, Src1, Func->getTarget());
2802    break;
2803  }
2804}
2805
2806void InstARM32Str::dump(const Cfg *Func) const {
2807  if (!BuildDefs::dump())
2808    return;
2809  Ostream &Str = Func->getContext()->getStrDump();
2810  Type Ty = getSrc(0)->getType();
2811  dumpOpcodePred(Str, "str", Ty);
2812  Str << " ";
2813  getSrc(1)->dump(Func);
2814  Str << ", ";
2815  getSrc(0)->dump(Func);
2816}
2817
2818void InstARM32Strex::emit(const Cfg *Func) const {
2819  if (!BuildDefs::dump())
2820    return;
2821  assert(getSrcSize() == 2);
2822  Type Ty = getSrc(0)->getType();
2823  assert(isScalarIntegerType(Ty));
2824  Variable *Dest = getDest();
2825  Ostream &Str = Func->getContext()->getStrEmit();
2826  static constexpr char Opcode[] = "strex";
2827  const char *WidthString = getWidthString(Ty);
2828  Str << "\t" << Opcode << WidthString << getPredicate() << "\t";
2829  Dest->emit(Func);
2830  Str << ", ";
2831  emitSources(Func);
2832}
2833
2834void InstARM32Strex::emitIAS(const Cfg *Func) const {
2835  assert(getSrcSize() == 2);
2836  const Operand *Src0 = getSrc(0);
2837  assert(isScalarIntegerType(Src0->getType()));
2838  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2839  Asm->strex(Dest, Src0, getSrc(1), getPredicate(), Func->getTarget());
2840  if (Asm->needsTextFixup())
2841    emitUsingTextFixup(Func);
2842}
2843
2844void InstARM32Strex::dump(const Cfg *Func) const {
2845  if (!BuildDefs::dump())
2846    return;
2847  Ostream &Str = Func->getContext()->getStrDump();
2848  Variable *Dest = getDest();
2849  Dest->dump(Func);
2850  Str << " = ";
2851  Type Ty = getSrc(0)->getType();
2852  dumpOpcodePred(Str, "strex", Ty);
2853  Str << " ";
2854  getSrc(1)->dump(Func);
2855  Str << ", ";
2856  getSrc(0)->dump(Func);
2857}
2858
2859void InstARM32Vstr1::emit(const Cfg *Func) const {
2860  if (!BuildDefs::dump())
2861    return;
2862  Ostream &Str = Func->getContext()->getStrEmit();
2863  assert(getSrcSize() == 2);
2864  Type Ty = getSrc(0)->getType();
2865  const bool IsVectorStore = isVectorType(Ty);
2866  const bool IsScalarFloat = isScalarFloatingType(Ty);
2867  const char *Opcode =
2868      IsVectorStore ? "vst1" : (IsScalarFloat ? "vstr" : "str");
2869  Str << "\t" << Opcode;
2870  const bool IsVInst = IsVectorStore || IsScalarFloat;
2871  if (IsVInst) {
2872    Str << getPredicate() << getWidthString(Ty);
2873  } else {
2874    Str << getWidthString(Ty) << getPredicate();
2875  }
2876  if (IsVectorStore)
2877    Str << "." << getVecElmtBitsize(Ty);
2878  Str << "\t";
2879  getSrc(0)->emit(Func);
2880  Str << ", ";
2881  getSrc(1)->emit(Func);
2882}
2883
2884void InstARM32Vstr1::emitIAS(const Cfg *Func) const {
2885  assert(getSrcSize() == 2);
2886  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2887  const Operand *Src0 = getSrc(0);
2888  const Operand *Src1 = getSrc(1);
2889  Asm->vst1(Size, Src0, Src1, Func->getTarget());
2890}
2891
2892void InstARM32Vstr1::dump(const Cfg *Func) const {
2893  if (!BuildDefs::dump())
2894    return;
2895  Ostream &Str = Func->getContext()->getStrDump();
2896  Type Ty = getSrc(0)->getType();
2897  dumpOpcodePred(Str, "str", Ty);
2898  Str << " ";
2899  getSrc(1)->dump(Func);
2900  Str << ", ";
2901  getSrc(0)->dump(Func);
2902}
2903
2904void InstARM32Vdup::emit(const Cfg *Func) const {
2905  if (!BuildDefs::dump())
2906    return;
2907  Ostream &Str = Func->getContext()->getStrEmit();
2908  assert(getSrcSize() == 2);
2909  Type Ty = getSrc(0)->getType();
2910  const char *Opcode = "vdup";
2911  Str << "\t" << Opcode;
2912  Str << getPredicate() << "." << getWidthString(Ty) << getVecElmtBitsize(Ty);
2913  Str << "\t";
2914  getSrc(0)->emit(Func);
2915  Str << ", ";
2916  getSrc(1)->emit(Func);
2917  Str << ", " << Idx;
2918}
2919
2920void InstARM32Vdup::emitIAS(const Cfg *Func) const {
2921  assert(getSrcSize() == 1);
2922  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2923  const Operand *Dest = getDest();
2924  const Operand *Src = getSrc(0);
2925  Type DestTy = Dest->getType();
2926  Asm->vdup(typeElementType(DestTy), Dest, Src, Idx);
2927}
2928
2929void InstARM32Vdup::dump(const Cfg *Func) const {
2930  if (!BuildDefs::dump())
2931    return;
2932  Ostream &Str = Func->getContext()->getStrDump();
2933  dumpDest(Func);
2934  Str << " = ";
2935  dumpOpcodePred(Str, "vdup", getDest()->getType());
2936  Str << " ";
2937  dumpSources(Func);
2938  Str << ", " << Idx;
2939}
2940
2941void InstARM32Trap::emit(const Cfg *Func) const {
2942  if (!BuildDefs::dump())
2943    return;
2944  Ostream &Str = Func->getContext()->getStrEmit();
2945  assert(getSrcSize() == 0);
2946  // There isn't a mnemonic for the special NaCl Trap encoding, so dump
2947  // the raw bytes.
2948  Str << "\t.long 0x";
2949  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2950  for (uint8_t I : Asm->getNonExecBundlePadding()) {
2951    Str.write_hex(I);
2952  }
2953}
2954
2955void InstARM32Trap::emitIAS(const Cfg *Func) const {
2956  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2957  Asm->trap();
2958  assert(!Asm->needsTextFixup());
2959}
2960
2961void InstARM32Trap::dump(const Cfg *Func) const {
2962  if (!BuildDefs::dump())
2963    return;
2964  Ostream &Str = Func->getContext()->getStrDump();
2965  Str << "trap";
2966}
2967
2968void InstARM32Umull::emit(const Cfg *Func) const {
2969  if (!BuildDefs::dump())
2970    return;
2971  Ostream &Str = Func->getContext()->getStrEmit();
2972  assert(getSrcSize() == 2);
2973  assert(getDest()->hasReg());
2974  Str << "\t"
2975         "umull" << getPredicate() << "\t";
2976  getDest()->emit(Func);
2977  Str << ", ";
2978  DestHi->emit(Func);
2979  Str << ", ";
2980  getSrc(0)->emit(Func);
2981  Str << ", ";
2982  getSrc(1)->emit(Func);
2983}
2984
2985void InstARM32Umull::emitIAS(const Cfg *Func) const {
2986  assert(getSrcSize() == 2);
2987  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
2988  Asm->umull(getDest(), DestHi, getSrc(0), getSrc(1), getPredicate());
2989  if (Asm->needsTextFixup())
2990    emitUsingTextFixup(Func);
2991}
2992
2993void InstARM32Umull::dump(const Cfg *Func) const {
2994  if (!BuildDefs::dump())
2995    return;
2996  Ostream &Str = Func->getContext()->getStrDump();
2997  dumpDest(Func);
2998  Str << " = ";
2999  dumpOpcodePred(Str, "umull", getDest()->getType());
3000  Str << " ";
3001  dumpSources(Func);
3002}
3003
3004namespace {
3005const char *vcvtVariantSuffix(const InstARM32Vcvt::VcvtVariant Variant) {
3006  switch (Variant) {
3007  case InstARM32Vcvt::S2si:
3008    return ".s32.f32";
3009  case InstARM32Vcvt::S2ui:
3010    return ".u32.f32";
3011  case InstARM32Vcvt::Si2s:
3012    return ".f32.s32";
3013  case InstARM32Vcvt::Ui2s:
3014    return ".f32.u32";
3015  case InstARM32Vcvt::D2si:
3016    return ".s32.f64";
3017  case InstARM32Vcvt::D2ui:
3018    return ".u32.f64";
3019  case InstARM32Vcvt::Si2d:
3020    return ".f64.s32";
3021  case InstARM32Vcvt::Ui2d:
3022    return ".f64.u32";
3023  case InstARM32Vcvt::S2d:
3024    return ".f64.f32";
3025  case InstARM32Vcvt::D2s:
3026    return ".f32.f64";
3027  case InstARM32Vcvt::Vs2si:
3028    return ".s32.f32";
3029  case InstARM32Vcvt::Vs2ui:
3030    return ".u32.f32";
3031  case InstARM32Vcvt::Vsi2s:
3032    return ".f32.s32";
3033  case InstARM32Vcvt::Vui2s:
3034    return ".f32.u32";
3035  }
3036  llvm::report_fatal_error("Invalid VcvtVariant enum.");
3037}
3038} // end of anonymous namespace
3039
3040void InstARM32Vcvt::emit(const Cfg *Func) const {
3041  if (!BuildDefs::dump())
3042    return;
3043  Ostream &Str = Func->getContext()->getStrEmit();
3044  assert(getSrcSize() == 1);
3045  assert(getDest()->hasReg());
3046  Str << "\t"
3047         "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << "\t";
3048  getDest()->emit(Func);
3049  Str << ", ";
3050  getSrc(0)->emit(Func);
3051}
3052
3053void InstARM32Vcvt::emitIAS(const Cfg *Func) const {
3054  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3055  switch (Variant) {
3056  case S2si:
3057    Asm->vcvtis(getDest(), getSrc(0), getPredicate());
3058    break;
3059  case S2ui:
3060    Asm->vcvtus(getDest(), getSrc(0), getPredicate());
3061    break;
3062  case Si2s:
3063    Asm->vcvtsi(getDest(), getSrc(0), getPredicate());
3064    break;
3065  case Ui2s:
3066    Asm->vcvtsu(getDest(), getSrc(0), getPredicate());
3067    break;
3068  case D2si:
3069    Asm->vcvtid(getDest(), getSrc(0), getPredicate());
3070    break;
3071  case D2ui:
3072    Asm->vcvtud(getDest(), getSrc(0), getPredicate());
3073    break;
3074  case Si2d:
3075    Asm->vcvtdi(getDest(), getSrc(0), getPredicate());
3076    break;
3077  case Ui2d:
3078    Asm->vcvtdu(getDest(), getSrc(0), getPredicate());
3079    break;
3080  case S2d:
3081    Asm->vcvtds(getDest(), getSrc(0), getPredicate());
3082    break;
3083  case D2s:
3084    Asm->vcvtsd(getDest(), getSrc(0), getPredicate());
3085    break;
3086  case Vs2si:
3087    Asm->vcvtqsi(getDest(), getSrc(0));
3088    break;
3089  case Vs2ui:
3090    Asm->vcvtqsu(getDest(), getSrc(0));
3091    break;
3092  case Vsi2s:
3093    Asm->vcvtqis(getDest(), getSrc(0));
3094    break;
3095  case Vui2s:
3096    Asm->vcvtqus(getDest(), getSrc(0));
3097    break;
3098  }
3099  assert(!Asm->needsTextFixup());
3100}
3101
3102void InstARM32Vcvt::dump(const Cfg *Func) const {
3103  if (!BuildDefs::dump())
3104    return;
3105  Ostream &Str = Func->getContext()->getStrDump();
3106  dumpDest(Func);
3107  Str << " = "
3108      << "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << " ";
3109  dumpSources(Func);
3110}
3111
3112void InstARM32Vcmp::emit(const Cfg *Func) const {
3113  if (!BuildDefs::dump())
3114    return;
3115  Ostream &Str = Func->getContext()->getStrEmit();
3116  assert(getSrcSize() == 2);
3117  Str << "\t"
3118         "vcmp" << getPredicate() << getFpWidthString(getSrc(0)->getType())
3119      << "\t";
3120  getSrc(0)->emit(Func);
3121  Str << ", ";
3122  getSrc(1)->emit(Func);
3123}
3124
3125void InstARM32Vcmp::emitIAS(const Cfg *Func) const {
3126  assert(getSrcSize() == 2);
3127  const Operand *Src0 = getSrc(0);
3128  const Type Ty = Src0->getType();
3129  const Operand *Src1 = getSrc(1);
3130  const CondARM32::Cond Cond = getPredicate();
3131  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3132  if (llvm::isa<OperandARM32FlexFpZero>(Src1)) {
3133    switch (Ty) {
3134    case IceType_f32:
3135      Asm->vcmpsz(Src0, Cond);
3136      break;
3137    case IceType_f64:
3138      Asm->vcmpdz(Src0, Cond);
3139      break;
3140    default:
3141      llvm::report_fatal_error("Vcvt on non floating value");
3142    }
3143  } else {
3144    switch (Ty) {
3145    case IceType_f32:
3146      Asm->vcmps(Src0, Src1, Cond);
3147      break;
3148    case IceType_f64:
3149      Asm->vcmpd(Src0, Src1, Cond);
3150      break;
3151    default:
3152      llvm::report_fatal_error("Vcvt on non floating value");
3153    }
3154  }
3155  assert(!Asm->needsTextFixup());
3156}
3157
3158void InstARM32Vcmp::dump(const Cfg *Func) const {
3159  if (!BuildDefs::dump())
3160    return;
3161  Ostream &Str = Func->getContext()->getStrDump();
3162  Str << "vcmp" << getPredicate() << getFpWidthString(getSrc(0)->getType());
3163  dumpSources(Func);
3164}
3165
3166void InstARM32Vmrs::emit(const Cfg *Func) const {
3167  if (!BuildDefs::dump())
3168    return;
3169  Ostream &Str = Func->getContext()->getStrEmit();
3170  assert(getSrcSize() == 0);
3171  Str << "\t"
3172         "vmrs" << getPredicate() << "\t"
3173                                     "APSR_nzcv"
3174                                     ", "
3175                                     "FPSCR";
3176}
3177
3178void InstARM32Vmrs::emitIAS(const Cfg *Func) const {
3179  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3180  Asm->vmrsAPSR_nzcv(getPredicate());
3181  assert(!Asm->needsTextFixup());
3182}
3183
3184void InstARM32Vmrs::dump(const Cfg *Func) const {
3185  if (!BuildDefs::dump())
3186    return;
3187  Ostream &Str = Func->getContext()->getStrDump();
3188  Str << "APSR{n,z,v,c} = vmrs" << getPredicate() << "\t"
3189                                                     "FPSCR{n,z,c,v}";
3190}
3191
3192void InstARM32Vabs::emit(const Cfg *Func) const {
3193  if (!BuildDefs::dump())
3194    return;
3195  Ostream &Str = Func->getContext()->getStrEmit();
3196  assert(getSrcSize() == 1);
3197  Str << "\t"
3198         "vabs" << getPredicate() << getFpWidthString(getSrc(0)->getType())
3199      << "\t";
3200  getDest()->emit(Func);
3201  Str << ", ";
3202  getSrc(0)->emit(Func);
3203}
3204
3205void InstARM32Vabs::emitIAS(const Cfg *Func) const {
3206  assert(getSrcSize() == 1);
3207  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3208  const Variable *Dest = getDest();
3209  switch (Dest->getType()) {
3210  default:
3211    llvm::report_fatal_error("fabs not defined on type " +
3212                             typeStdString(Dest->getType()));
3213  case IceType_f32:
3214    Asm->vabss(Dest, getSrc(0), getPredicate());
3215    break;
3216  case IceType_f64:
3217    Asm->vabsd(Dest, getSrc(0), getPredicate());
3218    break;
3219  case IceType_v4f32:
3220    assert(CondARM32::isUnconditional(getPredicate()) &&
3221           "fabs must be unconditional");
3222    Asm->vabsq(Dest, getSrc(0));
3223  }
3224  assert(!Asm->needsTextFixup());
3225}
3226
3227void InstARM32Vabs::dump(const Cfg *Func) const {
3228  if (!BuildDefs::dump())
3229    return;
3230  Ostream &Str = Func->getContext()->getStrDump();
3231  dumpDest(Func);
3232  Str << " = vabs" << getPredicate() << getFpWidthString(getSrc(0)->getType());
3233}
3234
3235void InstARM32Dmb::emit(const Cfg *Func) const {
3236  if (!BuildDefs::dump())
3237    return;
3238  Ostream &Str = Func->getContext()->getStrEmit();
3239  assert(getSrcSize() == 0);
3240  Str << "\t"
3241         "dmb"
3242         "\t"
3243         "sy";
3244}
3245
3246void InstARM32Dmb::emitIAS(const Cfg *Func) const {
3247  assert(getSrcSize() == 0);
3248  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
3249  constexpr ARM32::IValueT SyOption = 0xF; // i.e. 1111
3250  Asm->dmb(SyOption);
3251  if (Asm->needsTextFixup())
3252    emitUsingTextFixup(Func);
3253}
3254
3255void InstARM32Dmb::dump(const Cfg *Func) const {
3256  if (!BuildDefs::dump())
3257    return;
3258  Func->getContext()->getStrDump() << "dmb\t"
3259                                      "sy";
3260}
3261
3262void InstARM32Nop::emit(const Cfg *Func) const {
3263  if (!BuildDefs::dump())
3264    return;
3265  assert(getSrcSize() == 0);
3266  Func->getContext()->getStrEmit() << "\t"
3267                                   << "nop";
3268}
3269
3270void InstARM32Nop::emitIAS(const Cfg *Func) const {
3271  assert(getSrcSize() == 0);
3272  Func->getAssembler<ARM32::AssemblerARM32>()->nop();
3273}
3274
3275void InstARM32Nop::dump(const Cfg *Func) const {
3276  if (!BuildDefs::dump())
3277    return;
3278  assert(getSrcSize() == 0);
3279  Func->getContext()->getStrDump() << "nop";
3280}
3281
3282void OperandARM32Mem::emit(const Cfg *Func) const {
3283  if (!BuildDefs::dump())
3284    return;
3285  Ostream &Str = Func->getContext()->getStrEmit();
3286  Str << "[";
3287  getBase()->emit(Func);
3288  switch (getAddrMode()) {
3289  case PostIndex:
3290  case NegPostIndex:
3291    Str << "]";
3292    break;
3293  default:
3294    break;
3295  }
3296  if (isRegReg()) {
3297    Str << ", ";
3298    if (isNegAddrMode()) {
3299      Str << "-";
3300    }
3301    getIndex()->emit(Func);
3302    if (getShiftOp() != kNoShift) {
3303      Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
3304          << getShiftAmt();
3305    }
3306  } else {
3307    ConstantInteger32 *Offset = getOffset();
3308    if (Offset && Offset->getValue() != 0) {
3309      Str << ", ";
3310      Offset->emit(Func);
3311    }
3312  }
3313  switch (getAddrMode()) {
3314  case Offset:
3315  case NegOffset:
3316    Str << "]";
3317    break;
3318  case PreIndex:
3319  case NegPreIndex:
3320    Str << "]!";
3321    break;
3322  case PostIndex:
3323  case NegPostIndex:
3324    // Brace is already closed off.
3325    break;
3326  }
3327}
3328
3329void OperandARM32Mem::dump(const Cfg *Func, Ostream &Str) const {
3330  if (!BuildDefs::dump())
3331    return;
3332  Str << "[";
3333  if (Func)
3334    getBase()->dump(Func);
3335  else
3336    getBase()->dump(Str);
3337  Str << ", ";
3338  if (isRegReg()) {
3339    if (isNegAddrMode()) {
3340      Str << "-";
3341    }
3342    if (Func)
3343      getIndex()->dump(Func);
3344    else
3345      getIndex()->dump(Str);
3346    if (getShiftOp() != kNoShift) {
3347      Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
3348          << getShiftAmt();
3349    }
3350  } else {
3351    getOffset()->dump(Func, Str);
3352  }
3353  Str << "] AddrMode==" << getAddrMode();
3354}
3355
3356void OperandARM32ShAmtImm::emit(const Cfg *Func) const { ShAmt->emit(Func); }
3357
3358void OperandARM32ShAmtImm::dump(const Cfg *, Ostream &Str) const {
3359  ShAmt->dump(Str);
3360}
3361
3362OperandARM32FlexImm *OperandARM32FlexImm::create(Cfg *Func, Type Ty,
3363                                                 uint32_t Imm,
3364                                                 uint32_t RotateAmt) {
3365  // The assembler wants the smallest rotation. Rotate if needed. Note: Imm is
3366  // an 8-bit value.
3367  assert(Utils::IsUint(8, Imm) &&
3368         "Flex immediates can only be defined on 8-bit immediates");
3369  while ((Imm & 0x03) == 0 && RotateAmt > 0) {
3370    --RotateAmt;
3371    Imm = Imm >> 2;
3372  }
3373  return new (Func->allocate<OperandARM32FlexImm>())
3374      OperandARM32FlexImm(Func, Ty, Imm, RotateAmt);
3375}
3376
3377void OperandARM32FlexImm::emit(const Cfg *Func) const {
3378  if (!BuildDefs::dump())
3379    return;
3380  Ostream &Str = Func->getContext()->getStrEmit();
3381  uint32_t Imm = getImm();
3382  uint32_t RotateAmt = getRotateAmt();
3383  Str << "#" << Utils::rotateRight32(Imm, 2 * RotateAmt);
3384}
3385
3386void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const {
3387  if (!BuildDefs::dump())
3388    return;
3389  uint32_t Imm = getImm();
3390  uint32_t RotateAmt = getRotateAmt();
3391  Str << "#(" << Imm << " ror 2*" << RotateAmt << ")";
3392}
3393
3394namespace {
3395static constexpr uint32_t a = 0x80;
3396static constexpr uint32_t b = 0x40;
3397static constexpr uint32_t cdefgh = 0x3F;
3398static constexpr uint32_t AllowedBits = a | b | cdefgh;
3399static_assert(AllowedBits == 0xFF,
3400              "Invalid mask for f32/f64 constant rematerialization.");
3401
3402// There's no loss in always returning the modified immediate as float.
3403// TODO(jpp): returning a double causes problems when outputting the constants
3404// for filetype=asm. Why?
3405float materializeFloatImmediate(uint32_t ModifiedImm) {
3406  const uint32_t Ret = ((ModifiedImm & a) ? 0x80000000 : 0) |
3407                       ((ModifiedImm & b) ? 0x3E000000 : 0x40000000) |
3408                       ((ModifiedImm & cdefgh) << 19);
3409  return Utils::bitCopy<float>(Ret);
3410}
3411
3412} // end of anonymous namespace
3413
3414void OperandARM32FlexFpImm::emit(const Cfg *Func) const {
3415  if (!BuildDefs::dump())
3416    return;
3417  Ostream &Str = Func->getContext()->getStrEmit();
3418  switch (Ty) {
3419  default:
3420    llvm::report_fatal_error("Invalid flex fp imm type.");
3421  case IceType_f64:
3422  case IceType_f32:
3423    Str << "#" << materializeFloatImmediate(ModifiedImm)
3424        << " @ Modified: " << ModifiedImm;
3425    break;
3426  }
3427}
3428
3429void OperandARM32FlexFpImm::dump(const Cfg * /*Func*/, Ostream &Str) const {
3430  if (!BuildDefs::dump())
3431    return;
3432  Str << "#" << materializeFloatImmediate(ModifiedImm) << getFpWidthString(Ty);
3433}
3434
3435void OperandARM32FlexFpZero::emit(const Cfg *Func) const {
3436  if (!BuildDefs::dump())
3437    return;
3438  Ostream &Str = Func->getContext()->getStrEmit();
3439  switch (Ty) {
3440  default:
3441    llvm::report_fatal_error("Invalid flex fp imm type.");
3442  case IceType_f64:
3443  case IceType_f32:
3444    Str << "#0.0";
3445  }
3446}
3447
3448void OperandARM32FlexFpZero::dump(const Cfg * /*Func*/, Ostream &Str) const {
3449  if (!BuildDefs::dump())
3450    return;
3451  Str << "#0.0" << getFpWidthString(Ty);
3452}
3453
3454void OperandARM32FlexReg::emit(const Cfg *Func) const {
3455  if (!BuildDefs::dump())
3456    return;
3457  Ostream &Str = Func->getContext()->getStrEmit();
3458  getReg()->emit(Func);
3459  if (getShiftOp() != kNoShift) {
3460    Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
3461    getShiftAmt()->emit(Func);
3462  }
3463}
3464
3465void OperandARM32FlexReg::dump(const Cfg *Func, Ostream &Str) const {
3466  if (!BuildDefs::dump())
3467    return;
3468  Variable *Reg = getReg();
3469  if (Func)
3470    Reg->dump(Func);
3471  else
3472    Reg->dump(Str);
3473  if (getShiftOp() != kNoShift) {
3474    Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
3475    if (Func)
3476      getShiftAmt()->dump(Func);
3477    else
3478      getShiftAmt()->dump(Str);
3479  }
3480}
3481
3482// Force instantition of template classes
3483template class InstARM32ThreeAddrGPR<InstARM32::Adc>;
3484template class InstARM32ThreeAddrGPR<InstARM32::Add>;
3485template class InstARM32ThreeAddrGPR<InstARM32::And>;
3486template class InstARM32ThreeAddrGPR<InstARM32::Asr>;
3487template class InstARM32ThreeAddrGPR<InstARM32::Bic>;
3488template class InstARM32ThreeAddrGPR<InstARM32::Eor>;
3489template class InstARM32ThreeAddrGPR<InstARM32::Lsl>;
3490template class InstARM32ThreeAddrGPR<InstARM32::Lsr>;
3491template class InstARM32ThreeAddrGPR<InstARM32::Mul>;
3492template class InstARM32ThreeAddrGPR<InstARM32::Orr>;
3493template class InstARM32ThreeAddrGPR<InstARM32::Rsb>;
3494template class InstARM32ThreeAddrGPR<InstARM32::Rsc>;
3495template class InstARM32ThreeAddrGPR<InstARM32::Sbc>;
3496template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
3497template class InstARM32ThreeAddrGPR<InstARM32::Sub>;
3498template class InstARM32ThreeAddrGPR<InstARM32::Udiv>;
3499
3500template class InstARM32ThreeAddrFP<InstARM32::Vadd>;
3501template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>;
3502template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>;
3503template class InstARM32ThreeAddrFP<InstARM32::Vdiv>;
3504template class InstARM32ThreeAddrFP<InstARM32::Veor>;
3505template class InstARM32FourAddrFP<InstARM32::Vmla>;
3506template class InstARM32FourAddrFP<InstARM32::Vmls>;
3507template class InstARM32ThreeAddrFP<InstARM32::Vmul>;
3508template class InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
3509template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
3510template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
3511template class InstARM32ThreeAddrFP<InstARM32::Vsub>;
3512template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqadd>;
3513template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqsub>;
3514template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqmovn2>;
3515template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vmulh>;
3516template class InstARM32ThreeAddrFP<InstARM32::Vmlap>;
3517
3518template class InstARM32LoadBase<InstARM32::Ldr>;
3519template class InstARM32LoadBase<InstARM32::Ldrex>;
3520template class InstARM32LoadBase<InstARM32::Vldr1d>;
3521template class InstARM32LoadBase<InstARM32::Vldr1q>;
3522template class InstARM32ThreeAddrFP<InstARM32::Vzip>;
3523template class InstARM32TwoAddrGPR<InstARM32::Movt>;
3524
3525template class InstARM32UnaryopGPR<InstARM32::Movw, false>;
3526template class InstARM32UnaryopGPR<InstARM32::Clz, false>;
3527template class InstARM32UnaryopGPR<InstARM32::Mvn, false>;
3528template class InstARM32UnaryopGPR<InstARM32::Rbit, false>;
3529template class InstARM32UnaryopGPR<InstARM32::Rev, false>;
3530template class InstARM32UnaryopGPR<InstARM32::Sxt, true>;
3531template class InstARM32UnaryopGPR<InstARM32::Uxt, true>;
3532template class InstARM32UnaryopFP<InstARM32::Vsqrt>;
3533
3534template class InstARM32FourAddrGPR<InstARM32::Mla>;
3535template class InstARM32FourAddrGPR<InstARM32::Mls>;
3536
3537template class InstARM32CmpLike<InstARM32::Cmn>;
3538template class InstARM32CmpLike<InstARM32::Cmp>;
3539template class InstARM32CmpLike<InstARM32::Tst>;
3540
3541} // end of namespace ARM32
3542} // end of namespace Ice
3543