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   void vldrq(const Operand *OpQd, const Operand *OpAddress,
    444              CondARM32::Cond Cond, const TargetInfo &TInfo);
    445 
    446   void vldrq(const Operand *OpQd, const Operand *OpAddress,
    447              CondARM32::Cond Cond, const TargetLowering *Lowering) {
    448     const TargetInfo TInfo(Lowering);
    449     vldrq(OpQd, OpAddress, Cond, TInfo);
    450   }
    451 
    452   // ElmtSize = #bits in vector element.
    453   void vld1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
    454               const TargetInfo &TInfo);
    455 
    456   void vld1(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
    457             const TargetInfo &TInfo);
    458 
    459   void vld1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
    460               const TargetLowering *Lowering) {
    461     const TargetInfo TInfo(Lowering);
    462     vld1qr(ElmtSize, OpQd, OpRn, TInfo);
    463   }
    464 
    465   void vld1(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
    466             const TargetLowering *Lowering) {
    467     const TargetInfo TInfo(Lowering);
    468     vld1(ElmtSize, OpQd, OpRn, TInfo);
    469   }
    470 
    471   // Qn[i] = Imm for all i in vector. Returns true iff Imm can be defined as an
    472   // Imm8 using AdvSIMDExpandImm().
    473   bool vmovqc(const Operand *OpQd, const ConstantInteger32 *Imm);
    474 
    475   // Dn = FpImm
    476   void vmovd(const Operand *OpDn, const OperandARM32FlexFpImm *OpFpImm,
    477              CondARM32::Cond Cond);
    478 
    479   // Dd = Dm
    480   void vmovdd(const Operand *OpDd, const Variable *OpDm, CondARM32::Cond Cond);
    481 
    482   // Dm = Rt:Rt2
    483   void vmovdrr(const Operand *OpDm, const Operand *OpRt, const Operand *OpRt2,
    484                CondARM32::Cond Cond);
    485 
    486   // Qd[Index] = Rt
    487   void vmovqir(const Operand *OpQd, uint32_t Index, const Operand *OpRt,
    488                CondARM32::Cond Cond);
    489 
    490   // Qd[Index] = Sm
    491   void vmovqis(const Operand *OpQd, uint32_t Indx, const Operand *OpSm,
    492                CondARM32::Cond Cond);
    493 
    494   // Rt = Qm[Index]
    495   void vmovrqi(const Operand *OpRt, const Operand *OpQd, uint32_t Index,
    496                CondARM32::Cond Cond);
    497 
    498   // Rt:Rt2 = Dm
    499   void vmovrrd(const Operand *OpRt, const Operand *OpRt2, const Operand *OpDm,
    500                CondARM32::Cond Cond);
    501 
    502   // Rt = Sn
    503   void vmovrs(const Operand *OpRt, const Operand *OpSn, CondARM32::Cond Cond);
    504 
    505   // Sn = FpImm
    506   void vmovs(const Operand *OpSn, const OperandARM32FlexFpImm *OpFpImm,
    507              CondARM32::Cond Cond);
    508 
    509   // Sd = Sm
    510   void vmovss(const Operand *OpSd, const Variable *OpSm, CondARM32::Cond Cond);
    511 
    512   // Sd = Qm[Index]
    513   void vmovsqi(const Operand *OpSd, const Operand *OpQm, uint32_t Index,
    514                CondARM32::Cond Cond);
    515 
    516   // Sn = Rt
    517   void vmovsr(const Operand *OpSn, const Operand *OpRt, CondARM32::Cond Cond);
    518 
    519   void vmlad(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
    520              CondARM32::Cond Cond);
    521 
    522   void vmlas(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
    523              CondARM32::Cond Cond);
    524 
    525   void vmlsd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
    526              CondARM32::Cond Cond);
    527 
    528   void vmlss(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
    529              CondARM32::Cond Cond);
    530 
    531   // Uses APSR_nzcv as register
    532   void vmrsAPSR_nzcv(CondARM32::Cond Cond);
    533 
    534   void vmuld(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
    535              CondARM32::Cond Cond);
    536 
    537   // Integer vector multiply.
    538   void vmulqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
    539               const Operand *OpQm);
    540 
    541   // Integer vector multiply high.
    542   void vmulh(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
    543              const Operand *OpQm, bool Unsigned);
    544 
    545   // Integer vector multiply add pairwise.
    546   void vmlap(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
    547              const Operand *OpQm);
    548 
    549   // Vector element replication.
    550   void vdup(Type ElmtTy, const Operand *OpQd, const Operand *OpQn, IValueT Idx);
    551 
    552   // Vector interleave lower halves.
    553   void vzip(Type ElmtTy, const Operand *OpQd, const Operand *OpQn,
    554             const Operand *OpQm);
    555 
    556   // Float vector multiply.
    557   void vmulqf(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
    558 
    559   void vmuls(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
    560              CondARM32::Cond Cond);
    561 
    562   void vmvnq(const Operand *OpQd, const Operand *OpQm);
    563 
    564   void vmovlq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
    565   void vmovhq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
    566   void vmovhlq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
    567   void vmovlhq(const Operand *OpQd, const Operand *OpQn, const Operand *OpQm);
    568 
    569   void vnegqs(const Operand *OpQd, const Operand *OpQm);
    570 
    571   void vnegqs(Type ElmtTy, const Operand *OpQd, const Operand *OpQm);
    572 
    573   void vorrq(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
    574 
    575   void vpop(const Variable *OpBaseReg, SizeT NumConsecRegs,
    576             CondARM32::Cond Cond);
    577 
    578   void vpush(const Variable *OpBaseReg, SizeT NumConsecRegs,
    579              CondARM32::Cond Cond);
    580 
    581   void vshlqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    582               const Operand *OpQn);
    583 
    584   void vshlqu(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    585               const Operand *OpQn);
    586 
    587   void vshlqc(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    588               const ConstantInteger32 *OpQn);
    589 
    590   void vshrqc(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    591               const ConstantInteger32 *OpQn, InstARM32::FPSign Sign);
    592 
    593   void vsqrtd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond Cond);
    594 
    595   void vsqrts(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
    596 
    597   void vstrd(const Operand *OpDd, const Operand *OpAddress,
    598              CondARM32::Cond Cond, const TargetInfo &TInfo);
    599 
    600   void vstrd(const Operand *OpDd, const Operand *OpAddress,
    601              CondARM32::Cond Cond, const TargetLowering *Lowering) {
    602     const TargetInfo TInfo(Lowering);
    603     vstrd(OpDd, OpAddress, Cond, TInfo);
    604   }
    605 
    606   void vstrs(const Operand *OpSd, const Operand *OpAddress,
    607              CondARM32::Cond Cond, const TargetInfo &TInfo);
    608 
    609   void vstrs(const Operand *OpSd, const Operand *OpAddress,
    610              CondARM32::Cond Cond, const TargetLowering *Lowering) {
    611     const TargetInfo TInfo(Lowering);
    612     vstrs(OpSd, OpAddress, Cond, TInfo);
    613   }
    614 
    615   void vstrq(const Operand *OpQd, const Operand *OpAddress,
    616              CondARM32::Cond Cond, const TargetInfo &TInfo);
    617 
    618   void vstrq(const Operand *OpQd, const Operand *OpAddress,
    619              CondARM32::Cond Cond, const TargetLowering *Lowering) {
    620     const TargetInfo TInfo(Lowering);
    621     vstrq(OpQd, OpAddress, Cond, TInfo);
    622   }
    623 
    624   // ElmtSize = #bits in vector element.
    625   void vst1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpAddress,
    626               const TargetInfo &TInfo);
    627 
    628   void vst1qr(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
    629               const TargetLowering *Lowering) {
    630     const TargetInfo TInfo(Lowering);
    631     vst1qr(ElmtSize, OpQd, OpRn, TInfo);
    632   }
    633 
    634   void vst1(size_t ElmtSize, const Operand *OpQd, const Operand *OpAddress,
    635             const TargetInfo &TInfo);
    636 
    637   void vst1(size_t ElmtSize, const Operand *OpQd, const Operand *OpRn,
    638             const TargetLowering *Lowering) {
    639     const TargetInfo TInfo(Lowering);
    640     vst1(ElmtSize, OpQd, OpRn, TInfo);
    641   }
    642 
    643   void vsubd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
    644              CondARM32::Cond Cond);
    645 
    646   // Integer vector subtract.
    647   void vsubqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    648               const Operand *OpQn);
    649 
    650   // Integer vector saturating subtract.
    651   void vqsubqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    652                const Operand *OpQn);
    653   void vqsubqu(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    654                const Operand *OpQn);
    655 
    656   // Integer vector saturating add.
    657   void vqaddqi(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    658                const Operand *OpQn);
    659   void vqaddqu(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    660                const Operand *OpQn);
    661 
    662   // Integer vector packing with optional saturation.
    663   void vqmovn2(Type ElmtTy, const Operand *OpQd, const Operand *OpQm,
    664                const Operand *OpQn, bool Unsigned, bool Saturating);
    665 
    666   // Float vector subtract
    667   void vsubqf(const Operand *OpQd, const Operand *OpQm, const Operand *OpQn);
    668 
    669   void vsubs(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
    670              CondARM32::Cond Cond);
    671 
    672   static bool classof(const Assembler *Asm) {
    673     return Asm->getKind() == Asm_ARM32;
    674   }
    675 
    676   void emitTextInst(const std::string &Text, SizeT InstSize);
    677 
    678 private:
    679   ENABLE_MAKE_UNIQUE;
    680 
    681   const bool IsNonsfi;
    682 
    683   // A vector of pool-allocated x86 labels for CFG nodes.
    684   using LabelVector = std::vector<Label *>;
    685   LabelVector CfgNodeLabels;
    686   // A vector of pool-allocated x86 labels for Local labels.
    687   LabelVector LocalLabels;
    688   // Number of bytes emitted by InstARM32::emit() methods, when run inside
    689   // InstARM32::emitUsingTextFixup().
    690   size_t EmitTextSize = 0;
    691 
    692   // Load/store multiple addressing mode.
    693   enum BlockAddressMode {
    694     // bit encoding P U W
    695     DA = (0 | 0 | 0) << 21,   // decrement after
    696     IA = (0 | 4 | 0) << 21,   // increment after
    697     DB = (8 | 0 | 0) << 21,   // decrement before
    698     IB = (8 | 4 | 0) << 21,   // increment before
    699     DA_W = (0 | 0 | 1) << 21, // decrement after with writeback to base
    700     IA_W = (0 | 4 | 1) << 21, // increment after with writeback to base
    701     DB_W = (8 | 0 | 1) << 21, // decrement before with writeback to base
    702     IB_W = (8 | 4 | 1) << 21  // increment before with writeback to base
    703   };
    704 
    705   Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
    706 
    707   void bindCfgNodeLabel(const CfgNode *Node) override;
    708 
    709   // SIMD encoding for the vector ElmtTy.
    710   static IValueT encodeElmtType(Type ElmtTy);
    711 
    712   void emitInst(IValueT Value) {
    713     AssemblerBuffer::EnsureCapacity _(&Buffer);
    714     Buffer.emit<IValueT>(Value);
    715   }
    716 
    717   // List of possible checks to apply when calling emitType01() (below).
    718   enum EmitChecks { NoChecks, RdIsPcAndSetFlags };
    719 
    720   // Pattern cccctttoooosnnnnddddiiiiiiiiiiii where cccc=Cond, ttt=InstType,
    721   // s=SetFlags, oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM
    722   // section A5.2.3).
    723   void emitType01(CondARM32::Cond Cond, IValueT InstType, IValueT Opcode,
    724                   bool SetFlags, IValueT Rn, IValueT Rd, IValueT imm12,
    725                   EmitChecks RuleChecks, const char *InstName);
    726 
    727   // Converts appropriate representation on a data operation, and then calls
    728   // emitType01 above.
    729   void emitType01(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRd,
    730                   const Operand *OpRn, const Operand *OpSrc1, bool SetFlags,
    731                   EmitChecks RuleChecks, const char *InstName);
    732 
    733   // Same as above, but the value for Rd and Rn have already been converted
    734   // into instruction values.
    735   void emitType01(CondARM32::Cond Cond, IValueT Opcode, IValueT OpRd,
    736                   IValueT OpRn, const Operand *OpSrc1, bool SetFlags,
    737                   EmitChecks RuleChecks, const char *InstName);
    738 
    739   void emitType05(CondARM32::Cond Cond, int32_t Offset, bool Link);
    740 
    741   // Emit ccccoooaabalnnnnttttaaaaaaaaaaaa where cccc=Cond,
    742   // ooo=InstType, l=isLoad, b=isByte, and
    743   // aaa0a0aaaa0000aaaaaaaaaaaa=Address. Note that Address is assumed to be
    744   // defined by decodeAddress() in IceAssemblerARM32.cpp.
    745   void emitMemOp(CondARM32::Cond Cond, IValueT InstType, bool IsLoad,
    746                  bool IsByte, IValueT Rt, IValueT Address);
    747 
    748   // Emit ccccxxxxxxxxxxxxddddxxxxxxxxmmmm where cccc=Cond,
    749   // xxxxxxxxxxxx0000xxxxxxxx0000=Opcode, dddd=Rd, and mmmm=Rm.
    750   void emitRdRm(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRd,
    751                 const Operand *OpRm, const char *InstName);
    752 
    753   // Emit ldr/ldrb/str/strb instruction with given address.
    754   void emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, IValueT Rt,
    755                  const Operand *OpAddress, const TargetInfo &TInfo,
    756                  const char *InstName);
    757 
    758   // Emit ldrh/ldrd/strh/strd instruction with given address using encoding 3.
    759   void emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, IValueT Rt,
    760                      const Operand *OpAddress, const TargetInfo &TInfo,
    761                      const char *InstName);
    762 
    763   // Emit cccc00011xxlnnnndddd11111001tttt where cccc=Cond, xx encodes type
    764   // size, l=IsLoad, nnnn=Rn (as defined by OpAddress), and tttt=Rt.
    765   void emitMemExOp(CondARM32::Cond, Type Ty, bool IsLoad, const Operand *OpRd,
    766                    IValueT Rt, const Operand *OpAddress,
    767                    const TargetInfo &TInfo, const char *InstName);
    768 
    769   // Pattern cccc100aaaalnnnnrrrrrrrrrrrrrrrr where cccc=Cond,
    770   // aaaa<<21=AddressMode, l=IsLoad, nnnn=BaseReg, and
    771   // rrrrrrrrrrrrrrrr is bitset of Registers.
    772   void emitMultiMemOp(CondARM32::Cond Cond, BlockAddressMode AddressMode,
    773                       bool IsLoad, IValueT BaseReg, IValueT Registers);
    774 
    775   // Pattern ccccxxxxxDxxxxxxddddxxxxiiiiiiii where cccc=Cond, ddddD=BaseReg,
    776   // iiiiiiii=NumConsecRegs, and xxxxx0xxxxxx0000xxxx00000000=Opcode.
    777   void emitVStackOp(CondARM32::Cond Cond, IValueT Opcode,
    778                     const Variable *OpBaseReg, SizeT NumConsecRegs);
    779 
    780   // Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, ddddD=Sd,
    781   // Mmmmm=Dm, and xx0xxxxxxdddd000xxx0x0000=Opcode.
    782   void emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, IValueT Dm);
    783 
    784   // Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, Ddddd=Dd,
    785   // mmmmM=Sm, and xx0xxxxxxdddd000xxx0x0000=Opcode.
    786   void emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, IValueT Sm);
    787 
    788   // Pattern 111100000D00nnnnddddttttssaammmm | Opcode where Ddddd=Dd, nnnn=Rn,
    789   // mmmmm=Rm, tttt=NumDRegs, ElmtSize in {8, 16, 32, 64) and defines ss, and
    790   // aa=Align.
    791   void emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn, IValueT Rm,
    792                    DRegListSize NumDRegs, size_t ElmtSize, IValueT Align,
    793                    const char *InstName);
    794 
    795   // Pattern 111100000D00nnnnddddss00aaaammmm | Opcode where Ddddd=Dd, nnnn=Rn,
    796   // mmmmm=Rm, ElmtSize in {8, 16, 32) and defines ss, and aa=Align.
    797   void emitVMem1Op(IValueT Opcode, IValueT Dd, IValueT Rn, IValueT Rm,
    798                    size_t ElmtSize, IValueT Align, const char *InstName);
    799 
    800   // Pattern cccc011100x1dddd1111mmmm0001nnn where cccc=Cond,
    801   // x=Opcode, dddd=Rd, nnnn=Rn, mmmm=Rm.
    802   void emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
    803                  IValueT Rm);
    804 
    805   // cccc1110iiiennnntttt1011Njj10000 where cccc=Cond, tttt=Rt, Ndddd=2*Qn=Dn,
    806   // iii=Opcode1, jj=Opcode2, Opcode1Opcode2 encodes Index and the
    807   // corresponding element size of the vector element, and e=IsExtract.
    808   void emitInsertExtractInt(CondARM32::Cond Cond, const Operand *OpQn,
    809                             uint32_t Index, const Operand *OpRt, bool IsExtract,
    810                             const char *InstName);
    811 
    812   // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
    813   // Assigns Sd the value of Sm.
    814   void emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm);
    815 
    816   // Pattern ccccxxxxxxxfnnnnddddssss1001mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
    817   // mmmm=Rm, ssss=Rs, f=SetFlags and xxxxxxx=Opcode.
    818   void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
    819                  IValueT Rm, IValueT Rs, bool SetFlags);
    820 
    821   // Pattern cccc0001101s0000ddddxxxxxtt0mmmm where cccc=Cond, s=SetFlags,
    822   // dddd=Rd, mmmm=Rm, tt=Shift, and xxxxx is defined by OpSrc1. OpSrc1 defines
    823   // either xxxxx=Imm5, or xxxxx=ssss0 where ssss=Rs.
    824   void emitShift(const CondARM32::Cond Cond,
    825                  const OperandARM32::ShiftKind Shift, const Operand *OpRd,
    826                  const Operand *OpRm, const Operand *OpSrc1,
    827                  const bool SetFlags, const char *InstName);
    828 
    829   // Implements various forms of signed/unsigned extend value, using pattern
    830   // ccccxxxxxxxxnnnnddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode,
    831   // nnnn=Rn, dddd=Rd, rr=Rotation, and mmmm=Rm.
    832   void emitSignExtend(CondARM32::Cond, IValueT Opcode, const Operand *OpRd,
    833                       const Operand *OpSrc0, const char *InstName);
    834 
    835   // Implements various forms of vector (SIMD) operations.  Implements pattern
    836   // 111100100D00nnnndddn00F0NQM0mmmm where Dddd=Dd, Nnnn=Dn, Mmmm=Dm,
    837   // Q=UseQRegs, F=IsFloatTy, and Opcode is unioned into the pattern.
    838   void emitSIMDBase(IValueT Opcode, IValueT Dd, IValueT Dn, IValueT Dm,
    839                     bool UseQRegs, bool IsFloatTy);
    840 
    841   // Same as emitSIMDBase above, except ElmtShift=20 and ElmtSize is computed
    842   // from ElmtTy.
    843   void emitSIMD(IValueT Opcode, Type ElmtTy, IValueT Dd, IValueT Dn, IValueT Dm,
    844                 bool UseQRegs);
    845 
    846   // Implements various integer forms of vector (SIMD) operations using Q
    847   // registers. Implements pattern 111100100D00nnn0ddd000F0N1M0mmm0 where
    848   // Dddd=Qd, Nnnn=Qn, Mmmm=Qm, F=IsFloatTy, and Opcode is unioned into the
    849   // pattern.
    850   void emitSIMDqqqBase(IValueT Opcode, const Operand *OpQd, const Operand *OpQn,
    851                        const Operand *OpQm, bool IsFloatTy,
    852                        const char *OpcodeName);
    853 
    854   // Same as emitSIMD above, except ElmtShift=20 and ElmtSize is computed from
    855   // ElmtTy.
    856   void emitSIMDqqq(IValueT Opcode, Type ElmtTy, const Operand *OpQd,
    857                    const Operand *OpQn, const Operand *OpQm,
    858                    const char *OpcodeName);
    859 
    860   // Implements various forms of vector (SIMD) shifts using Q registers.
    861   // Implements pattern 111100101Diiiiiidddd010101M1mmmm where Dddd=Qd, Mmmm=Qm,
    862   // iiiiii=Imm6, and Opcode is unioned into the pattern.
    863   void emitSIMDShiftqqc(IValueT Opcode, const Operand *OpQd,
    864                         const Operand *OpQm, const IValueT Imm6,
    865                         const char *OpcodeName);
    866 
    867   // Implements various forms of vector (SIMD) casts between (signed and
    868   // unsigned) integer and floating point types (f32). Implements pattern
    869   // 111100111D11ss11dddd011ooQM0mmmm where Dddd=Qd, Mmmm=Qm, 10=ss, op=00, 1=Q,
    870   // and Opcode is unioned into the pattern.
    871   void emitSIMDCvtqq(IValueT Opcode, const Operand *OpQd, const Operand *OpQm,
    872                      const char *CvtName);
    873 
    874   // Pattern cccctttxxxxnnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn,
    875   // ttt=Instruction type (derived from OpSrc1), iiiiiiiiiiii is derived from
    876   // OpSrc1, and xxxx=Opcode.
    877   void emitCompareOp(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpRn,
    878                      const Operand *OpSrc1, const char *CmpName);
    879 
    880   void emitBranch(Label *L, CondARM32::Cond, bool Link);
    881 
    882   // Returns the offset encoded in the branch instruction Inst.
    883   static IOffsetT decodeBranchOffset(IValueT Inst);
    884 
    885   // Implements movw/movt, generating pattern ccccxxxxxxxsiiiiddddiiiiiiiiiiii
    886   // where cccc=Cond, xxxxxxx<<21=Opcode, dddd=Rd, s=SetFlags, and
    887   // iiiiiiiiiiiiiiii=Imm16.
    888   void emitMovwt(CondARM32::Cond Cond, bool IsMovw, const Operand *OpRd,
    889                  const Operand *OpSrc, const char *MovName);
    890 
    891   // Emit VFP instruction with 3 D registers.
    892   void emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpDd,
    893                   const Operand *OpDn, const Operand *OpDm,
    894                   const char *InstName);
    895 
    896   void emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, IValueT Dn,
    897                   IValueT Dm);
    898 
    899   // Emit VFP instruction with 3 S registers.
    900   void emitVFPsss(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, IValueT Sn,
    901                   IValueT Sm);
    902 
    903   void emitVFPsss(CondARM32::Cond Cond, IValueT Opcode, const Operand *OpSd,
    904                   const Operand *OpSn, const Operand *OpSm,
    905                   const char *InstName);
    906 };
    907 
    908 } // end of namespace ARM32
    909 } // end of namespace Ice
    910 
    911 #endif // SUBZERO_SRC_ICEASSEMBLERARM32_H
    912