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