Home | History | Annotate | Download | only in src
      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 
     25 namespace Ice {
     26 namespace ARM32 {
     27 
     28 namespace {
     29 
     30 using Register = RegARM32::AllRegisters;
     31 
     32 // maximum number of registers allowed in vpush/vpop.
     33 static constexpr SizeT VpushVpopMaxConsecRegs = 16;
     34 
     35 const 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 
     51 const struct InstARM32ShiftAttributes_ {
     52   const char *EmitString;
     53 } InstARM32ShiftAttributes[] = {
     54 #define X(tag, emit)                                                           \
     55   { emit }                                                                     \
     56   ,
     57     ICEINSTARM32SHIFT_TABLE
     58 #undef X
     59 };
     60 
     61 const 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 
     72 size_t getVecElmtBitsize(Type Ty) {
     73   return typeWidthInBytes(typeElementType(Ty)) * CHAR_BIT;
     74 }
     75 
     76 const char *getWidthString(Type Ty) {
     77   return TypeARM32Attributes[Ty].WidthString;
     78 }
     79 
     80 const char *getFpWidthString(Type Ty) {
     81   return TypeARM32Attributes[Ty].FpWidthString;
     82 }
     83 
     84 const char *getSVecWidthString(Type Ty) {
     85   return TypeARM32Attributes[Ty].SVecWidthString;
     86 }
     87 
     88 const char *getUVecWidthString(Type Ty) {
     89   return TypeARM32Attributes[Ty].UVecWidthString;
     90 }
     91 
     92 const 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 
    107 const char *InstARM32Pred::predString(CondARM32::Cond Pred) {
    108   return InstARM32CondAttributes[Pred].EmitString;
    109 }
    110 
    111 void InstARM32Pred::dumpOpcodePred(Ostream &Str, const char *Opcode,
    112                                    Type Ty) const {
    113   Str << Opcode << getPredicate() << "." << Ty;
    114 }
    115 
    116 CondARM32::Cond InstARM32::getOppositeCondition(CondARM32::Cond Cond) {
    117   return InstARM32CondAttributes[Cond].Opposite;
    118 }
    119 
    120 void InstARM32::startNextInst(const Cfg *Func) const {
    121   if (auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>())
    122     Asm->incEmitTextSize(InstSize);
    123 }
    124 
    125 void 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 
    160 void InstARM32::emitIAS(const Cfg *Func) const { emitUsingTextFixup(Func); }
    161 
    162 void 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 
    177 void 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 
    200 void 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 
    214 void 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 
    230 void 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 
    245 void 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 
    261 void 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 
    277 template <InstARM32::InstKindARM32 K>
    278 void InstARM32FourAddrGPR<K>::emitIAS(const Cfg *Func) const {
    279   emitUsingTextFixup(Func);
    280 }
    281 
    282 template <InstARM32::InstKindARM32 K>
    283 void InstARM32FourAddrFP<K>::emitIAS(const Cfg *Func) const {
    284   emitUsingTextFixup(Func);
    285 }
    286 
    287 template <InstARM32::InstKindARM32 K>
    288 void InstARM32ThreeAddrFP<K>::emitIAS(const Cfg *Func) const {
    289   emitUsingTextFixup(Func);
    290 }
    291 
    292 template <InstARM32::InstKindARM32 K>
    293 void InstARM32ThreeAddrSignAwareFP<K>::emitIAS(const Cfg *Func) const {
    294   InstARM32::emitUsingTextFixup(Func);
    295 }
    296 
    297 template <> 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 
    305 template <> 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 
    313 void 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 
    325 OperandARM32Mem::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 
    335 OperandARM32Mem::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 
    349 OperandARM32ShAmtImm::OperandARM32ShAmtImm(ConstantInteger32 *SA)
    350     : OperandARM32(kShAmtImm, IceType_i8), ShAmt(SA) {}
    351 
    352 bool 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 
    366 OperandARM32FlexImm::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 
    373 bool 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 
    393 OperandARM32FlexFpImm::OperandARM32FlexFpImm(Cfg * /*Func*/, Type Ty,
    394                                              uint32_t ModifiedImm)
    395     : OperandARM32Flex(kFlexFpImm, Ty), ModifiedImm(ModifiedImm) {}
    396 
    397 bool 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 
    472 OperandARM32FlexFpZero::OperandARM32FlexFpZero(Cfg * /*Func*/, Type Ty)
    473     : OperandARM32Flex(kFlexFpZero, Ty) {}
    474 
    475 OperandARM32FlexReg::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 
    489 InstARM32Br::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 
    495 bool 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 
    532 bool 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 
    545 template <InstARM32::InstKindARM32 K>
    546 void InstARM32ThreeAddrGPR<K>::emitIAS(const Cfg *Func) const {
    547   emitUsingTextFixup(Func);
    548 }
    549 
    550 template <> 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 
    557 template <> 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 
    563 template <> 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 
    570 template <> 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 
    577 template <> 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 
    584 template <> 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 
    591 template <> 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 
    598 template <> 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 
    605 template <> 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 
    612 template <> 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 
    619 template <> 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 
    626 template <> 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 
    633 template <> 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 
    640 template <> 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 
    648 template <> 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 
    655 template <> 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 
    663 template <> 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 
    689 template <> 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 
    707 template <> 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 
    730 template <> 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 
    763 template <> 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 
    796 template <> 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 
    814 template <> 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 
    832 template <> 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 
    845 template <> 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 
    866 template <> 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 
    887 template <> 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 
    906 template <> 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 
    925 template <> 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 
    944 template <> 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 
    963 template <> 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 
    982 template <> 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 
   1003 template <> 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 
   1021 template <> 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 
   1060 template <> 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 
   1090 template <> 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 
   1116 template <> 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 
   1141 template <> 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 
   1166 template <> 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 
   1205 template <> 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 
   1231 template <> 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 
   1247 template <> 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 
   1256 template <> 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 
   1282 InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
   1283     : InstARM32(Func, InstARM32::Call, 1, Dest) {
   1284   HasSideEffects = true;
   1285   addSource(CallTarget);
   1286 }
   1287 
   1288 InstARM32Label::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 
   1300 namespace {
   1301 // Requirements for Push/Pop:
   1302 //  1) All the Variables have the same type;
   1303 //  2) All the variables have registers assigned to them.
   1304 void 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 
   1322 void InstARM32RegisterStackOp::emit(const Cfg *Func) const {
   1323   if (!BuildDefs::dump())
   1324     return;
   1325   emitUsingForm(Func, Emit_Text);
   1326 }
   1327 
   1328 void InstARM32RegisterStackOp::emitIAS(const Cfg *Func) const {
   1329   emitUsingForm(Func, Emit_Binary);
   1330   assert(!Func->getAssembler<ARM32::AssemblerARM32>()->needsTextFixup());
   1331 }
   1332 
   1333 void 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 
   1346 void 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 
   1360 void 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 
   1379 void 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 
   1390 namespace {
   1391 
   1392 bool 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 
   1401 void 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 
   1467 InstARM32Pop::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 
   1476 InstARM32Push::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 
   1484 InstARM32Ret::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 
   1491 InstARM32Str::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 
   1498 InstARM32Strex::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 
   1505 InstARM32Vstr1::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 
   1513 InstARM32Vdup::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 
   1519 InstARM32Trap::InstARM32Trap(Cfg *Func)
   1520     : InstARM32(Func, InstARM32::Trap, 0, nullptr) {}
   1521 
   1522 InstARM32Umull::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 
   1532 InstARM32Vcvt::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 
   1539 InstARM32Mov::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 
   1561 namespace {
   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.
   1565 Register 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 
   1597 uint32_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 
   1614 uint32_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.
   1622 Register 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 
   1641 void 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 
   1680 void 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 
   1698 namespace {
   1699 Type 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 
   1714 void 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 
   1746 void 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 
   1766 template <InstARM32::InstKindARM32 K>
   1767 void InstARM32CmpLike<K>::emitIAS(const Cfg *Func) const {
   1768   emitUsingTextFixup(Func);
   1769 }
   1770 
   1771 template <> 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 
   1779 template <> 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 
   1787 template <> 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 
   1795 InstARM32Dmb::InstARM32Dmb(Cfg *Func)
   1796     : InstARM32Pred(Func, InstARM32::Dmb, 0, nullptr, CondARM32::AL) {}
   1797 
   1798 InstARM32Nop::InstARM32Nop(Cfg *Func)
   1799     : InstARM32Pred(Func, InstARM32::Nop, 0, nullptr, CondARM32::AL) {}
   1800 
   1801 InstARM32Vcmp::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 
   1809 InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate)
   1810     : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {
   1811   HasSideEffects = true;
   1812 }
   1813 
   1814 InstARM32Vabs::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
   1823 template <> const char *InstARM32Movt::Opcode = "movt";
   1824 // Unary ops
   1825 template <> const char *InstARM32Movw::Opcode = "movw";
   1826 template <> const char *InstARM32Clz::Opcode = "clz";
   1827 template <> const char *InstARM32Mvn::Opcode = "mvn";
   1828 template <> const char *InstARM32Rbit::Opcode = "rbit";
   1829 template <> const char *InstARM32Rev::Opcode = "rev";
   1830 template <> const char *InstARM32Sxt::Opcode = "sxt"; // still requires b/h
   1831 template <> const char *InstARM32Uxt::Opcode = "uxt"; // still requires b/h
   1832 // FP
   1833 template <> const char *InstARM32Vsqrt::Opcode = "vsqrt";
   1834 // Mov-like ops
   1835 template <> const char *InstARM32Ldr::Opcode = "ldr";
   1836 template <> const char *InstARM32Ldrex::Opcode = "ldrex";
   1837 template <> const char *InstARM32Vldr1d::Opcode = "vldr1d";
   1838 template <> const char *InstARM32Vldr1q::Opcode = "vldr1q";
   1839 // Three-addr ops
   1840 template <> const char *InstARM32Adc::Opcode = "adc";
   1841 template <> const char *InstARM32Add::Opcode = "add";
   1842 template <> const char *InstARM32And::Opcode = "and";
   1843 template <> const char *InstARM32Asr::Opcode = "asr";
   1844 template <> const char *InstARM32Bic::Opcode = "bic";
   1845 template <> const char *InstARM32Eor::Opcode = "eor";
   1846 template <> const char *InstARM32Lsl::Opcode = "lsl";
   1847 template <> const char *InstARM32Lsr::Opcode = "lsr";
   1848 template <> const char *InstARM32Mul::Opcode = "mul";
   1849 template <> const char *InstARM32Orr::Opcode = "orr";
   1850 template <> const char *InstARM32Rsb::Opcode = "rsb";
   1851 template <> const char *InstARM32Rsc::Opcode = "rsc";
   1852 template <> const char *InstARM32Sbc::Opcode = "sbc";
   1853 template <> const char *InstARM32Sdiv::Opcode = "sdiv";
   1854 template <> const char *InstARM32Sub::Opcode = "sub";
   1855 template <> const char *InstARM32Udiv::Opcode = "udiv";
   1856 // FP
   1857 template <> const char *InstARM32Vadd::Opcode = "vadd";
   1858 template <> const char *InstARM32Vand::Opcode = "vand";
   1859 template <> const char *InstARM32Vbsl::Opcode = "vbsl";
   1860 template <> const char *InstARM32Vceq::Opcode = "vceq";
   1861 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vcge>::Opcode = "vcge";
   1862 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vcgt>::Opcode = "vcgt";
   1863 template <> const char *InstARM32Vdiv::Opcode = "vdiv";
   1864 template <> const char *InstARM32Veor::Opcode = "veor";
   1865 template <> const char *InstARM32Vmla::Opcode = "vmla";
   1866 template <> const char *InstARM32Vmls::Opcode = "vmls";
   1867 template <> const char *InstARM32Vmul::Opcode = "vmul";
   1868 template <> const char *InstARM32Vmvn::Opcode = "vmvn";
   1869 template <> const char *InstARM32Vmovl::Opcode = "vmovl";
   1870 template <> const char *InstARM32Vmovh::Opcode = "vmovh";
   1871 template <> const char *InstARM32Vmovhl::Opcode = "vmovhl";
   1872 template <> const char *InstARM32Vmovlh::Opcode = "vmovlh";
   1873 template <> const char *InstARM32Vorr::Opcode = "vorr";
   1874 template <> const char *InstARM32UnaryopFP<InstARM32::Vneg>::Opcode = "vneg";
   1875 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshl>::Opcode = "vshl";
   1876 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshr>::Opcode = "vshr";
   1877 template <> const char *InstARM32Vsub::Opcode = "vsub";
   1878 template <>
   1879 const char *InstARM32ThreeAddrFP<InstARM32::Vqadd>::Opcode = "vqadd";
   1880 template <>
   1881 const char *InstARM32ThreeAddrFP<InstARM32::Vqsub>::Opcode = "vqsub";
   1882 template <>
   1883 const char *InstARM32ThreeAddrFP<InstARM32::Vqmovn2>::Opcode = "vqmovn2";
   1884 template <>
   1885 const char *InstARM32ThreeAddrFP<InstARM32::Vmulh>::Opcode = "vmulh";
   1886 template <>
   1887 const char *InstARM32ThreeAddrFP<InstARM32::Vmlap>::Opcode = "vmlap";
   1888 template <> const char *InstARM32ThreeAddrFP<InstARM32::Vzip>::Opcode = "vzip";
   1889 // Four-addr ops
   1890 template <> const char *InstARM32Mla::Opcode = "mla";
   1891 template <> const char *InstARM32Mls::Opcode = "mls";
   1892 // Cmp-like ops
   1893 template <> const char *InstARM32Cmn::Opcode = "cmn";
   1894 template <> const char *InstARM32Cmp::Opcode = "cmp";
   1895 template <> const char *InstARM32Tst::Opcode = "tst";
   1896 
   1897 void 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 
   1905 void 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 
   1926 void 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 
   1948 namespace {
   1949 
   1950 bool isVariableWithoutRegister(const Operand *Op) {
   1951   if (const auto *OpV = llvm::dyn_cast<Variable>(Op)) {
   1952     return !OpV->hasReg();
   1953   }
   1954   return false;
   1955 }
   1956 bool isMemoryAccess(Operand *Op) {
   1957   return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op);
   1958 }
   1959 
   1960 bool 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 
   1969 void 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 
   2010 void 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 
   2027 void 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 
   2149 void 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 
   2168 void 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 
   2191 void 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 
   2208 void 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 
   2233 void 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 
   2258 void 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 
   2277 void 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 
   2289 void 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 
   2300 void 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 
   2310 void InstARM32Label::dump(const Cfg *Func) const {
   2311   if (!BuildDefs::dump())
   2312     return;
   2313   Ostream &Str = Func->getContext()->getStrDump();
   2314   Str << getLabelName() << ":";
   2315 }
   2316 
   2317 template <InstARM32::InstKindARM32 K>
   2318 void InstARM32LoadBase<K>::emitIAS(const Cfg *Func) const {
   2319   emitUsingTextFixup(Func);
   2320 }
   2321 
   2322 template <> 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 
   2350 template <> 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 
   2378 template <> 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 
   2406 template <> 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 
   2439 template <> 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 
   2446 template <> 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 
   2453 template <> 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 
   2469 template <> 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 
   2480 template <InstARM32::InstKindARM32 K>
   2481 void InstARM32TwoAddrGPR<K>::emitIAS(const Cfg *Func) const {
   2482   emitUsingTextFixup(Func);
   2483 }
   2484 
   2485 template <InstARM32::InstKindARM32 K, bool Nws>
   2486 void InstARM32UnaryopGPR<K, Nws>::emitIAS(const Cfg *Func) const {
   2487   emitUsingTextFixup(Func);
   2488 }
   2489 
   2490 template <> 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 
   2498 template <> 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 
   2506 template <> 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 
   2526 template <> 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 
   2534 template <> 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 
   2555 template <> 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 
   2563 template <> 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 
   2571 template <> 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 
   2579 template <> 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 
   2587 template <> 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 
   2595 template <InstARM32::InstKindARM32 K>
   2596 void InstARM32UnaryopFP<K>::emitIAS(const Cfg *Func) const {
   2597   emitUsingTextFixup(Func);
   2598 }
   2599 
   2600 template <InstARM32::InstKindARM32 K>
   2601 void InstARM32UnaryopSignAwareFP<K>::emitIAS(const Cfg *Func) const {
   2602   InstARM32::emitUsingTextFixup(Func);
   2603 }
   2604 
   2605 template <> 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 
   2623 const char *InstARM32Pop::getGPROpcode() const { return "pop"; }
   2624 
   2625 const char *InstARM32Pop::getSRegOpcode() const { return "vpop"; }
   2626 
   2627 Variable *InstARM32Pop::getStackReg(SizeT Index) const { return Dests[Index]; }
   2628 
   2629 SizeT InstARM32Pop::getNumStackRegs() const { return Dests.size(); }
   2630 
   2631 void 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 
   2643 void 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 
   2656 void 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 
   2669 const char *InstARM32Push::getGPROpcode() const { return "push"; }
   2670 
   2671 const char *InstARM32Push::getSRegOpcode() const { return "vpush"; }
   2672 
   2673 Variable *InstARM32Push::getStackReg(SizeT Index) const {
   2674   return llvm::cast<Variable>(getSrc(Index));
   2675 }
   2676 
   2677 SizeT InstARM32Push::getNumStackRegs() const { return getSrcSize(); }
   2678 
   2679 void 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 
   2691 void 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 
   2704 void 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 
   2717 void 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 
   2731 void 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 
   2738 void 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 
   2747 void 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 
   2772 void 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 
   2806 void 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 
   2818 void 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 
   2834 void 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 
   2844 void 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 
   2859 void 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 
   2884 void 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 
   2892 void 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 
   2904 void 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 
   2920 void 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 
   2929 void 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 
   2941 void 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 
   2955 void InstARM32Trap::emitIAS(const Cfg *Func) const {
   2956   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
   2957   Asm->trap();
   2958   assert(!Asm->needsTextFixup());
   2959 }
   2960 
   2961 void InstARM32Trap::dump(const Cfg *Func) const {
   2962   if (!BuildDefs::dump())
   2963     return;
   2964   Ostream &Str = Func->getContext()->getStrDump();
   2965   Str << "trap";
   2966 }
   2967 
   2968 void 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 
   2985 void 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 
   2993 void 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 
   3004 namespace {
   3005 const 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 
   3040 void 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 
   3053 void 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 
   3102 void 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 
   3112 void 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 
   3125 void 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 
   3158 void 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 
   3166 void 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 
   3178 void InstARM32Vmrs::emitIAS(const Cfg *Func) const {
   3179   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
   3180   Asm->vmrsAPSR_nzcv(getPredicate());
   3181   assert(!Asm->needsTextFixup());
   3182 }
   3183 
   3184 void 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 
   3192 void 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 
   3205 void 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 
   3227 void 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 
   3235 void 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 
   3246 void 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 
   3255 void InstARM32Dmb::dump(const Cfg *Func) const {
   3256   if (!BuildDefs::dump())
   3257     return;
   3258   Func->getContext()->getStrDump() << "dmb\t"
   3259                                       "sy";
   3260 }
   3261 
   3262 void 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 
   3270 void InstARM32Nop::emitIAS(const Cfg *Func) const {
   3271   assert(getSrcSize() == 0);
   3272   Func->getAssembler<ARM32::AssemblerARM32>()->nop();
   3273 }
   3274 
   3275 void InstARM32Nop::dump(const Cfg *Func) const {
   3276   if (!BuildDefs::dump())
   3277     return;
   3278   assert(getSrcSize() == 0);
   3279   Func->getContext()->getStrDump() << "nop";
   3280 }
   3281 
   3282 void 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 
   3329 void 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 
   3356 void OperandARM32ShAmtImm::emit(const Cfg *Func) const { ShAmt->emit(Func); }
   3357 
   3358 void OperandARM32ShAmtImm::dump(const Cfg *, Ostream &Str) const {
   3359   ShAmt->dump(Str);
   3360 }
   3361 
   3362 OperandARM32FlexImm *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 
   3377 void 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 
   3386 void 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 
   3394 namespace {
   3395 static constexpr uint32_t a = 0x80;
   3396 static constexpr uint32_t b = 0x40;
   3397 static constexpr uint32_t cdefgh = 0x3F;
   3398 static constexpr uint32_t AllowedBits = a | b | cdefgh;
   3399 static_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?
   3405 float 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 
   3414 void 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 
   3429 void OperandARM32FlexFpImm::dump(const Cfg * /*Func*/, Ostream &Str) const {
   3430   if (!BuildDefs::dump())
   3431     return;
   3432   Str << "#" << materializeFloatImmediate(ModifiedImm) << getFpWidthString(Ty);
   3433 }
   3434 
   3435 void 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 
   3448 void OperandARM32FlexFpZero::dump(const Cfg * /*Func*/, Ostream &Str) const {
   3449   if (!BuildDefs::dump())
   3450     return;
   3451   Str << "#0.0" << getFpWidthString(Ty);
   3452 }
   3453 
   3454 void 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 
   3465 void 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
   3483 template class InstARM32ThreeAddrGPR<InstARM32::Adc>;
   3484 template class InstARM32ThreeAddrGPR<InstARM32::Add>;
   3485 template class InstARM32ThreeAddrGPR<InstARM32::And>;
   3486 template class InstARM32ThreeAddrGPR<InstARM32::Asr>;
   3487 template class InstARM32ThreeAddrGPR<InstARM32::Bic>;
   3488 template class InstARM32ThreeAddrGPR<InstARM32::Eor>;
   3489 template class InstARM32ThreeAddrGPR<InstARM32::Lsl>;
   3490 template class InstARM32ThreeAddrGPR<InstARM32::Lsr>;
   3491 template class InstARM32ThreeAddrGPR<InstARM32::Mul>;
   3492 template class InstARM32ThreeAddrGPR<InstARM32::Orr>;
   3493 template class InstARM32ThreeAddrGPR<InstARM32::Rsb>;
   3494 template class InstARM32ThreeAddrGPR<InstARM32::Rsc>;
   3495 template class InstARM32ThreeAddrGPR<InstARM32::Sbc>;
   3496 template class InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
   3497 template class InstARM32ThreeAddrGPR<InstARM32::Sub>;
   3498 template class InstARM32ThreeAddrGPR<InstARM32::Udiv>;
   3499 
   3500 template class InstARM32ThreeAddrFP<InstARM32::Vadd>;
   3501 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>;
   3502 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>;
   3503 template class InstARM32ThreeAddrFP<InstARM32::Vdiv>;
   3504 template class InstARM32ThreeAddrFP<InstARM32::Veor>;
   3505 template class InstARM32FourAddrFP<InstARM32::Vmla>;
   3506 template class InstARM32FourAddrFP<InstARM32::Vmls>;
   3507 template class InstARM32ThreeAddrFP<InstARM32::Vmul>;
   3508 template class InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
   3509 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
   3510 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
   3511 template class InstARM32ThreeAddrFP<InstARM32::Vsub>;
   3512 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqadd>;
   3513 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqsub>;
   3514 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vqmovn2>;
   3515 template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vmulh>;
   3516 template class InstARM32ThreeAddrFP<InstARM32::Vmlap>;
   3517 
   3518 template class InstARM32LoadBase<InstARM32::Ldr>;
   3519 template class InstARM32LoadBase<InstARM32::Ldrex>;
   3520 template class InstARM32LoadBase<InstARM32::Vldr1d>;
   3521 template class InstARM32LoadBase<InstARM32::Vldr1q>;
   3522 template class InstARM32ThreeAddrFP<InstARM32::Vzip>;
   3523 template class InstARM32TwoAddrGPR<InstARM32::Movt>;
   3524 
   3525 template class InstARM32UnaryopGPR<InstARM32::Movw, false>;
   3526 template class InstARM32UnaryopGPR<InstARM32::Clz, false>;
   3527 template class InstARM32UnaryopGPR<InstARM32::Mvn, false>;
   3528 template class InstARM32UnaryopGPR<InstARM32::Rbit, false>;
   3529 template class InstARM32UnaryopGPR<InstARM32::Rev, false>;
   3530 template class InstARM32UnaryopGPR<InstARM32::Sxt, true>;
   3531 template class InstARM32UnaryopGPR<InstARM32::Uxt, true>;
   3532 template class InstARM32UnaryopFP<InstARM32::Vsqrt>;
   3533 
   3534 template class InstARM32FourAddrGPR<InstARM32::Mla>;
   3535 template class InstARM32FourAddrGPR<InstARM32::Mls>;
   3536 
   3537 template class InstARM32CmpLike<InstARM32::Cmn>;
   3538 template class InstARM32CmpLike<InstARM32::Cmp>;
   3539 template class InstARM32CmpLike<InstARM32::Tst>;
   3540 
   3541 } // end of namespace ARM32
   3542 } // end of namespace Ice
   3543