Home | History | Annotate | Download | only in src
      1 //===- subzero/src/IceAssemblerARM32.h - Assembler for ARM32 ----*- C++ -*-===//
      2 //
      3 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
      4 // for details. All rights reserved. Use of this source code is governed by a
      5 // BSD-style license that can be found in the LICENSE file.
      6 //
      7 // Modified by the Subzero authors.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 //
     11 //                        The Subzero Code Generator
     12 //
     13 // This file is distributed under the University of Illinois Open Source
     14 // License. See LICENSE.TXT for details.
     15 //
     16 //===----------------------------------------------------------------------===//
     17 ///
     18 /// \file
     19 /// \brief Declares the Assembler class for ARM32.
     20 ///
     21 /// Note: All references to ARM "section" documentation refers to the "ARM
     22 /// Architecture Reference Manual, ARMv7-A and ARMv7-R edition". See:
     23 /// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0406c
     24 ///
     25 //===----------------------------------------------------------------------===//
     26 
     27 #ifndef SUBZERO_SRC_ICEASSEMBLERARM32_H
     28 #define SUBZERO_SRC_ICEASSEMBLERARM32_H
     29 
     30 #include "IceAssembler.h"
     31 #include "IceConditionCodesARM32.h"
     32 #include "IceDefs.h"
     33 #include "IceFixups.h"
     34 #include "IceInstARM32.h"
     35 #include "IceRegistersARM32.h"
     36 #include "IceTargetLowering.h"
     37 
     38 namespace Ice {
     39 namespace ARM32 {
     40 
     41 /// Handles encoding of bottom/top 16 bits of an address using movw/movt.
     42 class MoveRelocatableFixup final : public AssemblerFixup {
     43   MoveRelocatableFixup &operator=(const MoveRelocatableFixup &) = delete;
     44   MoveRelocatableFixup(const MoveRelocatableFixup &) = default;
     45 
     46 public:
     47   MoveRelocatableFixup() = default;
     48   size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final;
     49   void emitOffset(Assembler *Asm) const;
     50 };
     51 
     52 /// Handles encoding of branch and link to global location.
     53 class BlRelocatableFixup final : public AssemblerFixup {
     54   BlRelocatableFixup(const BlRelocatableFixup &) = delete;
     55   BlRelocatableFixup &operator=(const BlRelocatableFixup &) = delete;
     56 
     57 public:
     58   BlRelocatableFixup() = default;
     59   size_t emit(GlobalContext *Ctx, const Assembler &Asm) const final;
     60   void emitOffset(Assembler *Asm) const;
     61 };
     62 
     63 class AssemblerARM32 : public Assembler {
     64   AssemblerARM32(const AssemblerARM32 &) = delete;
     65   AssemblerARM32 &operator=(const AssemblerARM32 &) = delete;
     66 
     67 public:
     68   // Rotation values.
     69   enum RotationValue {
     70     kRotateNone, // Omitted
     71     kRotate8,    // ror #8
     72     kRotate16,   // ror #16
     73     kRotate24    // ror #24
     74   };
     75 
     76   // Encoding of the number of D registers in a list of D registers.
     77   enum DRegListSize {
     78     DRegListSize1 = 7,  // 0b0111
     79     DRegListSize2 = 10, // 0b1010
     80     DRegListSIze3 = 6,  // 0b0110
     81     DRegListSize4 = 2   // 0b0010
     82   };
     83 
     84   class TargetInfo {
     85     TargetInfo(const TargetInfo &) = delete;
     86     TargetInfo &operator=(const TargetInfo &) = delete;
     87 
     88   public:
     89     TargetInfo(bool HasFramePointer, RegNumT FrameOrStackReg)
     90         : HasFramePointer(HasFramePointer), FrameOrStackReg(FrameOrStackReg) {}
     91     explicit TargetInfo(const TargetLowering *Target)
     92         : HasFramePointer(Target->hasFramePointer()),
     93           FrameOrStackReg(Target->getFrameOrStackReg()) {}
     94     const bool HasFramePointer;
     95     const RegNumT FrameOrStackReg;
     96   };
     97 
     98   explicit AssemblerARM32(bool IsNonsfi, bool use_far_branches = false)
     99       : Assembler(Asm_ARM32), IsNonsfi(IsNonsfi) {
    100     // TODO(kschimpf): Add mode if needed when branches are handled.
    101     (void)use_far_branches;
    102   }
    103   ~AssemblerARM32() override {
    104     if (BuildDefs::asserts()) {
    105       for (const Label *Label : CfgNodeLabels) {
    106         Label->finalCheck();
    107       }
    108       for (const Label *Label : LocalLabels) {
    109         Label->finalCheck();
    110       }
    111     }
    112   }
    113 
    114   MoveRelocatableFixup *createMoveFixup(bool IsMovW, const Constant *Value);
    115 
    116   BlRelocatableFixup *createBlFixup(const ConstantRelocatable *BlTarget);
    117 
    118   void alignFunction() override {
    119     const SizeT Align = 1 << getBundleAlignLog2Bytes();
    120     SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
    121     constexpr SizeT InstSize = sizeof(IValueT);
    122     assert(BytesNeeded % InstARM32::InstSize == 0);
    123     while (BytesNeeded > 0) {
    124       trap();
    125       BytesNeeded -= InstSize;
    126     }
    127   }
    128 
    129   SizeT getBundleAlignLog2Bytes() const override { return 4; }
    130 
    131   const char *getAlignDirective() const override { return ".p2alignl"; }
    132 
    133   llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override;
    134 
    135   void padWithNop(intptr_t Padding) override;
    136 
    137   Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override {
    138     assert(NodeNumber < CfgNodeLabels.size());
    139     return CfgNodeLabels[NodeNumber];
    140   }
    141 
    142   Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
    143     return getOrCreateLabel(NodeNumber, CfgNodeLabels);
    144   }
    145 
    146   Label *getOrCreateLocalLabel(SizeT Number) {
    147     return getOrCreateLabel(Number, LocalLabels);
    148   }
    149 
    150   void bindLocalLabel(const InstARM32Label *InstL, SizeT Number) {
    151     if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) {
    152       constexpr SizeT InstSize = 0;
    153       emitTextInst(InstL->getLabelName() + ":", InstSize);
    154     }
    155     Label *L = getOrCreateLocalLabel(Number);
    156     if (!getPreliminary())
    157       this->bind(L);
    158   }
    159 
    160   bool fixupIsPCRel(FixupKind Kind) const override {
    161     if (Kind == llvm::ELF::R_ARM_MOVW_PREL_NC)
    162       return true;
    163     if (Kind == llvm::ELF::R_ARM_MOVT_PREL)
    164       return true;
    165     return false;
    166   }
    167 
    168   /// Accessors to keep track of the number of bytes generated inside
    169   /// InstARM32::emit() methods, when run inside of
    170   /// InstARM32::emitUsingTextFixup().
    171   void resetEmitTextSize() { EmitTextSize = 0; }
    172   void incEmitTextSize(size_t Amount) { EmitTextSize += Amount; }
    173   void decEmitTextSize(size_t Amount) { EmitTextSize -= Amount; }
    174   size_t getEmitTextSize() const { return EmitTextSize; }
    175 
    176   void bind(Label *label);
    177 
    178   // List of instructions implemented by integrated assembler.
    179 
    180   void adc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    181            bool SetFlags, CondARM32::Cond Cond);
    182 
    183   void add(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    184            bool SetFlags, CondARM32::Cond Cond);
    185 
    186   void and_(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    187             bool SetFlags, CondARM32::Cond Cond);
    188 
    189   void asr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    190            bool SetFlags, CondARM32::Cond Cond);
    191 
    192   void b(Label *L, CondARM32::Cond Cond);
    193 
    194   void bkpt(uint16_t Imm16);
    195 
    196   void bic(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    197            bool SetFlags, CondARM32::Cond Cond);
    198 
    199   void bl(const ConstantRelocatable *Target);
    200 
    201   void blx(const Operand *Target);
    202 
    203   void bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond = CondARM32::AL);
    204 
    205   void clz(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
    206 
    207   void cmn(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
    208 
    209   void cmp(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
    210 
    211   void dmb(IValueT Option); // Option is a 4-bit value.
    212 
    213   void eor(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    214            bool SetFlags, CondARM32::Cond Cond);
    215 
    216   void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
    217            const TargetInfo &TInfo);
    218 
    219   void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
    220            const TargetLowering *Lowering) {
    221     const TargetInfo TInfo(Lowering);
    222     ldr(OpRt, OpAddress, Cond, TInfo);
    223   }
    224 
    225   void ldrex(const Operand *OpRt, const Operand *OpAddress,
    226              CondARM32::Cond Cond, const TargetInfo &TInfo);
    227 
    228   void ldrex(const Operand *OpRt, const Operand *OpAddress,
    229              CondARM32::Cond Cond, const TargetLowering *Lowering) {
    230     const TargetInfo TInfo(Lowering);
    231     ldrex(OpRt, OpAddress, Cond, TInfo);
    232   }
    233 
    234   void lsl(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    235            bool SetFlags, CondARM32::Cond Cond);
    236 
    237   void lsr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    238            bool SetFlags, CondARM32::Cond Cond);
    239 
    240   void mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
    241 
    242   void movw(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
    243 
    244   void movt(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
    245 
    246   void mla(const Operand *OpRd, const Operand *OpRn, const Operand *OpRm,
    247            const Operand *OpRa, CondARM32::Cond Cond);
    248 
    249   void mls(const Operand *OpRd, const Operand *OpRn, const Operand *OpRm,
    250            const Operand *OpRa, CondARM32::Cond Cond);
    251 
    252   void mul(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    253            bool SetFlags, CondARM32::Cond Cond);
    254 
    255   void mvn(const Operand *OpRd, const Operand *OpScc, CondARM32::Cond Cond);
    256 
    257   void nop();
    258 
    259   void orr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    260            bool SetFlags, CondARM32::Cond Cond);
    261 
    262   void pop(const Variable *OpRt, CondARM32::Cond Cond);
    263 
    264   // Note: Registers is a bitset, where bit n corresponds to register Rn.
    265   void popList(const IValueT Registers, CondARM32::Cond Cond);
    266 
    267   void push(const Operand *OpRt, CondARM32::Cond Cond);
    268 
    269   // Note: Registers is a bitset, where bit n corresponds to register Rn.
    270   void pushList(const IValueT Registers, CondARM32::Cond Cond);
    271 
    272   void rbit(const Operand *OpRd, const Operand *OpRm, CondARM32::Cond Cond);
    273 
    274   void rev(const Operand *OpRd, const Operand *OpRm, CondARM32::Cond Cond);
    275 
    276   void rsb(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    277            bool SetFlags, CondARM32::Cond Cond);
    278 
    279   void rsc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    280            bool SetFlags, CondARM32::Cond Cond);
    281 
    282   void sbc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    283            bool SetFlags, CondARM32::Cond Cond);
    284 
    285   void sdiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    286             CondARM32::Cond Cond);
    287 
    288   void str(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
    289            const TargetInfo &TInfo);
    290 
    291   void str(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond,
    292            const TargetLowering *Lowering) {
    293     const TargetInfo TInfo(Lowering);
    294     str(OpRt, OpAddress, Cond, TInfo);
    295   }
    296 
    297   void strex(const Operand *OpRd, const Operand *OpRt, const Operand *OpAddress,
    298              CondARM32::Cond Cond, const TargetInfo &TInfo);
    299 
    300   void strex(const Operand *OpRd, const Operand *OpRt, const Operand *OpAddress,
    301              CondARM32::Cond Cond, const TargetLowering *Lowering) {
    302     const TargetInfo TInfo(Lowering);
    303     strex(OpRd, OpRt, OpAddress, Cond, TInfo);
    304   }
    305 
    306   void sub(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    307            bool SetFlags, CondARM32::Cond Cond);
    308 
    309   // Implements sxtb/sxth depending on type of OpSrc0.
    310   void sxt(const Operand *OpRd, const Operand *OpSrc0, CondARM32::Cond Cond);
    311 
    312   void trap();
    313 
    314   void tst(const Operand *OpRn, const Operand *OpSrc1, CondARM32::Cond Cond);
    315 
    316   void udiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
    317             CondARM32::Cond Cond);
    318 
    319   void umull(const Operand *OpRdLo, const Operand *OpRdHi, const Operand *OpRn,
    320              const Operand *OpRm, CondARM32::Cond Cond);
    321 
    322   // Implements uxtb/uxth depending on type of OpSrc0.
    323   void uxt(const Operand *OpRd, const Operand *OpSrc0, CondARM32::Cond Cond);
    324 
    325   void vabss(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
    326 
    327   void vabsd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond Cond);
    328 
    329   void vabsq(const Operand *OpQd, const Operand *OpQm);
    330 
    331   void vaddd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
    332              CondARM32::Cond Cond);
    333 
    334   void vadds(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
    335              CondARM32::Cond Cond);
    336 
    337   // Integer vector add.
    338   void vaddqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    339               const Operand *OpQn);
    340 
    341   // Float vector add.
    342   void vaddqf(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
    343 
    344   void vandq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
    345 
    346   void vbslq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
    347 
    348   void vceqqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    349               const Operand *OpQn);
    350 
    351   void vceqqs(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
    352 
    353   void vcgeqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    354               const Operand *OpQn);
    355 
    356   void vcugeqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    357                const Operand *OpQn);
    358 
    359   void vcgeqs(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
    360 
    361   void vcgtqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    362               const Operand *OpQn);
    363 
    364   void vcugtqi(const Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    365                const Operand *OpQn);
    366 
    367   void vcgtqs(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
    368 
    369   void vcmpd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond cond);
    370 
    371   // Second argument of compare is zero (+0.0).
    372   void vcmpdz(const Operand *OpDd, CondARM32::Cond cond);
    373 
    374   void vcmps(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond cond);
    375 
    376   // Second argument of compare is zero (+0.0).
    377   void vcmpsz(const Operand *OpSd, CondARM32::Cond cond);
    378 
    379   void vcvtds(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
    380 
    381   // vcvt<c>.S32.F32
    382   void vcvtis(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
    383 
    384   // vcvt<c>.S32.F64
    385   void vcvtid(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
    386 
    387   // vcvt<c>.F64.S32
    388   void vcvtdi(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
    389 
    390   // vcvt<c>.F64.U32
    391   void vcvtdu(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
    392 
    393   void vcvtsd(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
    394 
    395   // vcvt<c>.F32.S32
    396   void vcvtsi(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
    397 
    398   // vcvt<c>.F32.U32
    399   void vcvtsu(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
    400 
    401   // vcvt<c>.U32.F64
    402   void vcvtud(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
    403 
    404   // vcvt<c>.u32.f32
    405   void vcvtus(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
    406 
    407   void vcvtqsi(const Operand *OpQd, const Operand *OpQm);
    408 
    409   void vcvtqsu(const Operand *OpQd, const Operand *OpQm);
    410 
    411   void vcvtqis(const Operand *OpQd, const Operand *OpQm);
    412 
    413   void vcvtqus(const Operand *OpQd, const Operand *OpQm);
    414 
    415   void vdivd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
    416              CondARM32::Cond Cond);
    417 
    418   void vdivs(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
    419              CondARM32::Cond Cond);
    420 
    421   void veord(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm);
    422 
    423   void veorq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
    424 
    425   void vldrd(const Operand *OpDd, const Operand *OpAddress,
    426              CondARM32::Cond Cond, const TargetInfo &TInfo);
    427 
    428   void vldrd(const Operand *OpDd, const Operand *OpAddress,
    429              CondARM32::Cond Cond, const TargetLowering *Lowering) {
    430     const TargetInfo TInfo(Lowering);
    431     vldrd(OpDd, OpAddress, Cond, TInfo);
    432   }
    433 
    434   void vldrs(const Operand *OpSd, const Operand *OpAddress,
    435              CondARM32::Cond Cond, const TargetInfo &TInfo);
    436 
    437   void vldrs(const Operand *OpSd, const Operand *OpAddress,
    438              CondARM32::Cond Cond, const TargetLowering *Lowering) {
    439     const TargetInfo TInfo(Lowering);
    440     vldrs(OpSd, OpAddress, Cond, TInfo);
    441   }
    442 
    443   // ElmtSize = #bits in vector element.
    444   void vld1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
    445               const TargetInfo &TInfo);
    446 
    447   void vld1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
    448               const TargetLowering *Lowering) {
    449     const TargetInfo TInfo(Lowering);
    450     vld1qr(ElmtSize, OpQd, OpRn, TInfo);
    451   }
    452 
    453   // Qn[i] = Imm for all i in vector. Returns true iff Imm can be defined as an
    454   // Imm8 using AdvSIMDExpandImm().
    455   bool vmovqc(const Operand *OpQd, const ConstantInteger32 *Imm);
    456 
    457   // Dn = FpImm
    458   void vmovd(const Operand *OpDn, const OperandARM32FlexFpImm *OpFpImm,
    459              CondARM32::Cond Cond);
    460 
    461   // Dd = Dm
    462   void vmovdd(const Operand *OpDd, const Variable *OpDm, CondARM32::Cond Cond);
    463 
    464   // Dm = Rt:Rt2
    465   void vmovdrr(const Operand *OpDm, const Operand *OpRt, const Operand *OpRt2,
    466                CondARM32::Cond Cond);
    467 
    468   // Qd[Index] = Rt
    469   void vmovqir(const Operand *OpQd, uint32_t Index, const Operand *OpRt,
    470                CondARM32::Cond Cond);
    471 
    472   // Qd[Index] = Sm
    473   void vmovqis(const Operand *OpQd, uint32_t Indx, const Operand *OpSm,
    474                CondARM32::Cond Cond);
    475 
    476   // Rt = Qm[Index]
    477   void vmovrqi(const Operand *OpRt, const Operand *OpQd, uint32_t Index,
    478                CondARM32::Cond Cond);
    479 
    480   // Rt:Rt2 = Dm
    481   void vmovrrd(const Operand *OpRt, const Operand *OpRt2, const Operand *OpDm,
    482                CondARM32::Cond Cond);
    483 
    484   // Rt = Sn
    485   void vmovrs(const Operand *OpRt, const Operand *OpSn, CondARM32::Cond Cond);
    486 
    487   // Sn = FpImm
    488   void vmovs(const Operand *OpSn, const OperandARM32FlexFpImm *OpFpImm,
    489              CondARM32::Cond Cond);
    490 
    491   // Sd = Sm
    492   void vmovss(const Operand *OpSd, const Variable *OpSm, CondARM32::Cond Cond);
    493 
    494   // Sd = Qm[Index]
    495   void vmovsqi(const Operand *OpSd, const Operand *OpQm, uint32_t Index,
    496                CondARM32::Cond Cond);
    497 
    498   // Sn = Rt
    499   void vmovsr(const Operand *OpSn, const Operand *OpRt, CondARM32::Cond Cond);
    500 
    501   void vmlad(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
    502              CondARM32::Cond Cond);
    503 
    504   void vmlas(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
    505              CondARM32::Cond Cond);
    506 
    507   void vmlsd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
    508              CondARM32::Cond Cond);
    509 
    510   void vmlss(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
    511              CondARM32::Cond Cond);
    512 
    513   // Uses APSR_nzcv as register
    514   void vmrsAPSR_nzcv(CondARM32::Cond Cond);
    515 
    516   void vmuld(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
    517              CondARM32::Cond Cond);
    518 
    519   // Integer vector multiply.
    520   void vmulqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
    521               const Operand *OpQm);
    522 
    523   // Float vector multiply.
    524   void vmulqf(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
    525 
    526   void vmuls(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
    527              CondARM32::Cond Cond);
    528 
    529   void vmvnq(const Operand *OpQd, const Operand *OpQm);
    530 
    531   void vnegqs(const Operand *OpQd, const Operand *OpQm);
    532 
    533   void vnegqs(Type ElmtTy, const Operand *OpQd, const Operand *OpQm);
    534 
    535   void vorrq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
    536 
    537   void vpop(const Variable *OpBaseReg, SizeT NumConsecRegs,
    538             CondARM32::Cond Cond);
    539 
    540   void vpush(const Variable *OpBaseReg, SizeT NumConsecRegs,
    541              CondARM32::Cond Cond);
    542 
    543   void vshlqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    544               const Operand *OpQn);
    545 
    546   void vshlqu(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    547               const Operand *OpQn);
    548 
    549   void vshlqc(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    550               const ConstantInteger32 *OpQn);
    551 
    552   void vshrqic(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    553                const ConstantInteger32 *OpQn);
    554 
    555   void vshrquc(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    556                const ConstantInteger32 *OpQn);
    557 
    558   void vsqrtd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond Cond);
    559 
    560   void vsqrts(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
    561 
    562   void vstrd(const Operand *OpDd, const Operand *OpAddress,
    563              CondARM32::Cond Cond, const TargetInfo &TInfo);
    564 
    565   void vstrd(const Operand *OpDd, const Operand *OpAddress,
    566              CondARM32::Cond Cond, const TargetLowering *Lowering) {
    567     const TargetInfo TInfo(Lowering);
    568     vstrd(OpDd, OpAddress, Cond, TInfo);
    569   }
    570 
    571   void vstrs(const Operand *OpSd, const Operand *OpAddress,
    572              CondARM32::Cond Cond, const TargetInfo &TInfo);
    573 
    574   void vstrs(const Operand *OpSd, const Operand *OpAddress,
    575              CondARM32::Cond Cond, const TargetLowering *Lowering) {
    576     const TargetInfo TInfo(Lowering);
    577     vstrs(OpSd, OpAddress, Cond, TInfo);
    578   }
    579 
    580   // ElmtSize = #bits in vector element.
    581   void vst1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpAddress,
    582               const TargetInfo &TInfo);
    583 
    584   void vst1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
    585               const TargetLowering *Lowering) {
    586     const TargetInfo TInfo(Lowering);
    587     vst1qr(ElmtSize, OpQd, OpRn, TInfo);
    588   }
    589 
    590   void vsubd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
    591              CondARM32::Cond Cond);
    592 
    593   // Integer vector subtract.
    594   void vsubqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    595               const Operand *OpQn);
    596 
    597   // Float vector subtract
    598   void vsubqf(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
    599 
    600   void vsubs(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
    601              CondARM32::Cond Cond);
    602 
    603   static bool classof(const Assembler *Asm) {
    604     return Asm->getKind() == Asm_ARM32;
    605   }
    606 
    607   void emitTextInst(const std::string &Text, SizeT InstSize);
    608 
    609 private:
    610   ENABLE_MAKE_UNIQUE;
    611 
    612   const bool IsNonsfi;
    613 
    614   // A vector of pool-allocated x86 labels for CFG nodes.
    615   using LabelVector = std::vector<Label *>;
    616   LabelVector CfgNodeLabels;
    617   // A vector of pool-allocated x86 labels for Local labels.
    618   LabelVector LocalLabels;
    619   // Number of bytes emitted by InstARM32::emit() methods, when run inside
    620   // InstARM32::emitUsingTextFixup().
    621   size_t EmitTextSize = 0;
    622 
    623   // Load/store multiple addressing mode.
    624   enum BlockAddressMode {
    625     // bit encoding P U W
    626     DA = (0 | 0 | 0) << 21,   // decrement after
    627     IA = (0 | 4 | 0) << 21,   // increment after
    628     DB = (8 | 0 | 0) << 21,   // decrement before
    629     IB = (8 | 4 | 0) << 21,   // increment before
    630     DA_W = (0 | 0 | 1) << 21, // decrement after with writeback to base
    631     IA_W = (0 | 4 | 1) << 21, // increment after with writeback to base
    632     DB_W = (8 | 0 | 1) << 21, // decrement before with writeback to base
    633     IB_W = (8 | 4 | 1) << 21  // increment before with writeback to base
    634   };
    635 
    636   Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
    637 
    638   void bindCfgNodeLabel(const CfgNode *Node) override;
    639 
    640   // SIMD encoding for the vector ElmtTy.
    641   static IValueT encodeElmtType(Type ElmtTy);
    642 
    643   void emitInst(IValueT Value) {
    644     AssemblerBuffer::EnsureCapacity _(&Buffer);
    645     Buffer.emit<IValueT>(Value);
    646   }
    647 
    648   // List of possible checks to apply when calling emitType01() (below).
    649   enum EmitChecks { NoChecks, RdIsPcAndSetFlags };
    650 
    651   // Pattern cccctttoooosnnnnddddiiiiiiiiiiii where cccc=Cond, ttt=InstType,
    652   // s=SetFlags, oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM
    653   // section A5.2.3).
    654   void emitType01(CondARM32::Cond Cond, IValueT InstType, IValueT Opcode,
    655                   bool SetFlags, IValueT Rn, IValueT Rd, IValueT imm12,
    656                   EmitChecks RuleChecks, const char *InstName);
    657 
    658   // Converts appropriate representation on a data operation, and then calls
    659   // emitType01 above.
    660   void emitType01(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRd,
    661                   const Operand *OpRn, const Operand *OpSrc1, bool SetFlags,
    662                   EmitChecks RuleChecks, const char *InstName);
    663 
    664   // Same as above, but the value for Rd and Rn have already been converted
    665   // into instruction values.
    666   void emitType01(CondARM32::Cond Cond, IValueT Opcode, IValueT OpRd,
    667                   IValueT OpRn, const Operand *OpSrc1, bool SetFlags,
    668                   EmitChecks RuleChecks, const char *InstName);
    669 
    670   void emitType05(CondARM32::Cond Cond, int32_t Offset, bool Link);
    671 
    672   // Emit ccccoooaabalnnnnttttaaaaaaaaaaaa where cccc=Cond,
    673   // ooo=InstType, l=isLoad, b=isByte, and
    674   // aaa0a0aaaa0000aaaaaaaaaaaa=Address. Note that Address is assumed to be
    675   // defined by decodeAddress() in IceAssemblerARM32.cpp.
    676   void emitMemOp(CondARM32::Cond Cond, IValueT InstType, bool IsLoad,
    677                  bool IsByte, IValueT Rt, IValueT Address);
    678 
    679   // Emit ccccxxxxxxxxxxxxddddxxxxxxxxmmmm where cccc=Cond,
    680   // xxxxxxxxxxxx0000xxxxxxxx0000=Opcode, dddd=Rd, and mmmm=Rm.
    681   void emitRdRm(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRd,
    682                 const Operand *OpRm, const char *InstName);
    683 
    684   // Emit ldr/ldrb/str/strb instruction with given address.
    685   void emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, IValueT Rt,
    686                  const Operand *OpAddress, const TargetInfo &TInfo,
    687                  const char *InstName);
    688 
    689   // Emit ldrh/ldrd/strh/strd instruction with given address using encoding 3.
    690   void emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, IValueT Rt,
    691                      const Operand *OpAddress, const TargetInfo &TInfo,
    692                      const char *InstName);
    693 
    694   // Emit cccc00011xxlnnnndddd11111001tttt where cccc=Cond, xx encodes type
    695   // size, l=IsLoad, nnnn=Rn (as defined by OpAddress), and tttt=Rt.
    696   void emitMemExOp(CondARM32::Cond, Type Ty, bool IsLoad, const Operand *OpRd,
    697                    IValueT Rt, const Operand *OpAddress,
    698                    const TargetInfo &TInfo, const char *InstName);
    699 
    700   // Pattern cccc100aaaalnnnnrrrrrrrrrrrrrrrr where cccc=Cond,
    701   // aaaa<<21=AddressMode, l=IsLoad, nnnn=BaseReg, and
    702   // rrrrrrrrrrrrrrrr is bitset of Registers.
    703   void emitMultiMemOp(CondARM32::Cond Cond, BlockAddressMode AddressMode,
    704                       bool IsLoad, IValueT BaseReg, IValueT Registers);
    705 
    706   // Pattern ccccxxxxxDxxxxxxddddxxxxiiiiiiii where cccc=Cond, ddddD=BaseReg,
    707   // iiiiiiii=NumConsecRegs, and xxxxx0xxxxxx0000xxxx00000000=Opcode.
    708   void emitVStackOp(CondARM32::Cond Cond, IValueT Opcode,
    709                     const Variable *OpBaseReg, SizeT NumConsecRegs);
    710 
    711   // Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, ddddD=Sd,
    712   // Mmmmm=Dm, and xx0xxxxxxdddd000xxx0x0000=Opcode.
    713   void emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, IValueT Dm);
    714 
    715   // Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, Ddddd=Dd,
    716   // mmmmM=Sm, and xx0xxxxxxdddd000xxx0x0000=Opcode.
    717   void emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, IValueT Sm);
    718 
    719   // Pattern 111100000D00nnnnddddttttssaammmm | Opcode where Ddddd=Dd, nnnn=Rn,
    720   // mmmmm=Rm, tttt=NumDRegs, ElmtSize in {8, 16, 32, 64) and defines ss, and
    721   // aa=Align.
    722   void emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn, IValueT Rm,
    723                    DRegListSize NumDRegs, size_t ElmtSize, IValueT Align,
    724                    const char *InstName);
    725 
    726   // Pattern cccc011100x1dddd1111mmmm0001nnn where cccc=Cond,
    727   // x=Opcode, dddd=Rd, nnnn=Rn, mmmm=Rm.
    728   void emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
    729                  IValueT Rm);
    730 
    731   // cccc1110iiiennnntttt1011Njj10000 where cccc=Cond, tttt=Rt, Ndddd=2*Qn=Dn,
    732   // iii=Opcode1, jj=Opcode2, Opcode1Opcode2 encodes Index and the
    733   // corresponding element size of the vector element, and e=IsExtract.
    734   void emitInsertExtractInt(CondARM32::Cond Cond, const Operand *OpQn,
    735                             uint32_t Index, const Operand *OpRt, bool IsExtract,
    736                             const char *InstName);
    737 
    738   // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
    739   // Assigns Sd the value of Sm.
    740   void emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm);
    741 
    742   // Pattern ccccxxxxxxxfnnnnddddssss1001mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
    743   // mmmm=Rm, ssss=Rs, f=SetFlags and xxxxxxx=Opcode.
    744   void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
    745                  IValueT Rm, IValueT Rs, bool SetFlags);
    746 
    747   // Pattern cccc0001101s0000ddddxxxxxtt0mmmm where cccc=Cond, s=SetFlags,
    748   // dddd=Rd, mmmm=Rm, tt=Shift, and xxxxx is defined by OpSrc1. OpSrc1 defines
    749   // either xxxxx=Imm5, or xxxxx=ssss0 where ssss=Rs.
    750   void emitShift(const CondARM32::Cond Cond,
    751                  const OperandARM32::ShiftKind Shift, const Operand *OpRd,
    752                  const Operand *OpRm, const Operand *OpSrc1,
    753                  const bool SetFlags, const char *InstName);
    754 
    755   // Implements various forms of signed/unsigned extend value, using pattern
    756   // ccccxxxxxxxxnnnnddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode,
    757   // nnnn=Rn, dddd=Rd, rr=Rotation, and mmmm=Rm.
    758   void emitSignExtend(CondARM32::Cond, IValueT Opcode, const Operand *OpRd,
    759                       const Operand *OpSrc0, const char *InstName);
    760 
    761   // Implements various forms of vector (SIMD) operations.  Implements pattern
    762   // 111100100D00nnnndddn00F0NQM0mmmm where Dddd=Dd, Nnnn=Dn, Mmmm=Dm,
    763   // Q=UseQRegs, F=IsFloatTy, and Opcode is unioned into the pattern.
    764   void emitSIMDBase(IValueT Opcode, IValueT Dd, IValueT Dn, IValueT Dm,
    765                     bool UseQRegs, bool IsFloatTy);
    766 
    767   // Same as emitSIMDBase above, except ElmtShift=20 and ElmtSize is computed
    768   // from ElmtTy.
    769   void emitSIMD(IValueT Opcode, Type ElmtTy, IValueT Dd, IValueT Dn, IValueT Dm,
    770                 bool UseQRegs);
    771 
    772   // Implements various integer forms of vector (SIMD) operations using Q
    773   // registers. Implements pattern 111100100D00nnn0ddd000F0N1M0mmm0 where
    774   // Dddd=Qd, Nnnn=Qn, Mmmm=Qm, F=IsFloatTy, and Opcode is unioned into the
    775   // pattern.
    776   void emitSIMDqqqBase(IValueT Opcode, const Operand *OpQd, const Operand *OpQn,
    777                        const Operand *OpQm, bool IsFloatTy,
    778                        const char *OpcodeName);
    779 
    780   // Same as emitSIMD above, except ElmtShift=20 and ElmtSize is computed from
    781   // ElmtTy.
    782   void emitSIMDqqq(IValueT Opcode, Type ElmtTy, const Operand *OpQd,
    783                    const Operand *OpQn, const Operand *OpQm,
    784                    const char *OpcodeName);
    785 
    786   // Implements various forms of vector (SIMD) shifts using Q registers.
    787   // Implements pattern 111100101Diiiiiidddd010101M1mmmm where Dddd=Qd, Mmmm=Qm,
    788   // iiiiii=Imm6, and Opcode is unioned into the pattern.
    789   void emitSIMDShiftqqc(IValueT Opcode, const Operand *OpQd,
    790                         const Operand *OpQm, const IValueT Imm6,
    791                         const char *OpcodeName);
    792 
    793   // Implements various forms of vector (SIMD) casts between (signed and
    794   // unsigned) integer and floating point types (f32). Implements pattern
    795   // 111100111D11ss11dddd011ooQM0mmmm where Dddd=Qd, Mmmm=Qm, 10=ss, op=00, 1=Q,
    796   // and Opcode is unioned into the pattern.
    797   void emitSIMDCvtqq(IValueT Opcode, const Operand *OpQd, const Operand *OpQm,
    798                      const char *CvtName);
    799 
    800   // Pattern cccctttxxxxnnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn,
    801   // ttt=Instruction type (derived from OpSrc1), iiiiiiiiiiii is derived from
    802   // OpSrc1, and xxxx=Opcode.
    803   void emitCompareOp(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRn,
    804                      const Operand *OpSrc1, const char *CmpName);
    805 
    806   void emitBranch(Label *L, CondARM32::Cond, bool Link);
    807 
    808   // Returns the offset encoded in the branch instruction Inst.
    809   static IOffsetT decodeBranchOffset(IValueT Inst);
    810 
    811   // Implements movw/movt, generating pattern ccccxxxxxxxsiiiiddddiiiiiiiiiiii
    812   // where cccc=Cond, xxxxxxx<<21=Opcode, dddd=Rd, s=SetFlags, and
    813   // iiiiiiiiiiiiiiii=Imm16.
    814   void emitMovwt(CondARM32::Cond Cond, bool IsMovw, const Operand *OpRd,
    815                  const Operand *OpSrc, const char *MovName);
    816 
    817   // Emit VFP instruction with 3 D registers.
    818   void emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpDd,
    819                   const Operand *OpDn, const Operand *OpDm,
    820                   const char *InstName);
    821 
    822   void emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, IValueT Dn,
    823                   IValueT Dm);
    824 
    825   // Emit VFP instruction with 3 S registers.
    826   void emitVFPsss(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, IValueT Sn,
    827                   IValueT Sm);
    828 
    829   void emitVFPsss(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpSd,
    830                   const Operand *OpSn, const Operand *OpSm,
    831                   const char *InstName);
    832 };
    833 
    834 } // end of namespace ARM32
    835 } // end of namespace Ice
    836 
    837 #endif // SUBZERO_SRC_ICEASSEMBLERARM32_H
    838