• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Declares the InstARM32 and OperandARM32 classes and their subclasses.
12 ///
13 /// This represents the machine instructions and operands used for ARM32 code
14 /// selection.
15 ///
16 //===----------------------------------------------------------------------===//
17 
18 #ifndef SUBZERO_SRC_ICEINSTARM32_H
19 #define SUBZERO_SRC_ICEINSTARM32_H
20 
21 #include "IceConditionCodesARM32.h"
22 #include "IceDefs.h"
23 #include "IceInst.h"
24 #include "IceInstARM32.def"
25 #include "IceOperand.h"
26 #include "IceRegistersARM32.h"
27 
28 namespace Ice {
29 namespace ARM32 {
30 
31 /// Encoding of an ARM 32-bit instruction.
32 using IValueT = uint32_t;
33 
34 /// An Offset value (+/-) used in an ARM 32-bit instruction.
35 using IOffsetT = int32_t;
36 
37 class TargetARM32;
38 
39 /// OperandARM32 extends the Operand hierarchy. Its subclasses are
40 /// OperandARM32Mem and OperandARM32Flex.
41 class OperandARM32 : public Operand {
42   OperandARM32() = delete;
43   OperandARM32(const OperandARM32 &) = delete;
44   OperandARM32 &operator=(const OperandARM32 &) = delete;
45 
46 public:
47   enum OperandKindARM32 {
48     k__Start = Operand::kTarget,
49     kMem,
50     kShAmtImm,
51     kFlexStart,
52     kFlexImm = kFlexStart,
53     kFlexFpImm,
54     kFlexFpZero,
55     kFlexReg,
56     kFlexEnd = kFlexReg
57   };
58 
59   enum ShiftKind {
60     kNoShift = -1,
61 #define X(enum, emit) enum,
62     ICEINSTARM32SHIFT_TABLE
63 #undef X
64   };
65 
66   using Operand::dump;
dump(const Cfg *,Ostream & Str)67   void dump(const Cfg *, Ostream &Str) const override {
68     if (BuildDefs::dump())
69       Str << "<OperandARM32>";
70   }
71 
72 protected:
OperandARM32(OperandKindARM32 Kind,Type Ty)73   OperandARM32(OperandKindARM32 Kind, Type Ty)
74       : Operand(static_cast<OperandKind>(Kind), Ty) {}
75 };
76 
77 /// OperandARM32Mem represents a memory operand in any of the various ARM32
78 /// addressing modes.
79 class OperandARM32Mem : public OperandARM32 {
80   OperandARM32Mem() = delete;
81   OperandARM32Mem(const OperandARM32Mem &) = delete;
82   OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;
83 
84 public:
85   /// Memory operand addressing mode.
86   /// The enum value also carries the encoding.
87   // TODO(jvoung): unify with the assembler.
88   enum AddrMode {
89     // bit encoding P U 0 W
90     Offset = (8 | 4 | 0) << 21,      // offset (w/o writeback to base)
91     PreIndex = (8 | 4 | 1) << 21,    // pre-indexed addressing with writeback
92     PostIndex = (0 | 4 | 0) << 21,   // post-indexed addressing with writeback
93     NegOffset = (8 | 0 | 0) << 21,   // negative offset (w/o writeback to base)
94     NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback
95     NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback
96   };
97 
98   /// Provide two constructors.
99   /// NOTE: The Variable-typed operands have to be registers.
100   ///
101   /// (1) Reg + Imm. The Immediate actually has a limited number of bits
102   /// for encoding, so check canHoldOffset first. It cannot handle general
103   /// Constant operands like ConstantRelocatable, since a relocatable can
104   /// potentially take up too many bits.
105   static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
106                                  ConstantInteger32 *ImmOffset,
107                                  AddrMode Mode = Offset) {
108     return new (Func->allocate<OperandARM32Mem>())
109         OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
110   }
111   /// (2) Reg +/- Reg with an optional shift of some kind and amount. Note that
112   /// this mode is disallowed in the NaCl sandbox.
113   static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
114                                  Variable *Index, ShiftKind ShiftOp = kNoShift,
115                                  uint16_t ShiftAmt = 0,
116                                  AddrMode Mode = Offset) {
117     return new (Func->allocate<OperandARM32Mem>())
118         OperandARM32Mem(Func, Ty, Base, Index, ShiftOp, ShiftAmt, Mode);
119   }
getBase()120   Variable *getBase() const { return Base; }
getOffset()121   ConstantInteger32 *getOffset() const { return ImmOffset; }
getIndex()122   Variable *getIndex() const { return Index; }
getShiftOp()123   ShiftKind getShiftOp() const { return ShiftOp; }
getShiftAmt()124   uint16_t getShiftAmt() const { return ShiftAmt; }
getAddrMode()125   AddrMode getAddrMode() const { return Mode; }
126 
isRegReg()127   bool isRegReg() const { return Index != nullptr; }
isNegAddrMode()128   bool isNegAddrMode() const {
129     // Positive address modes have the "U" bit set, and negative modes don't.
130     static_assert((PreIndex & (4 << 21)) != 0,
131                   "Positive addr modes should have U bit set.");
132     static_assert((NegPreIndex & (4 << 21)) == 0,
133                   "Negative addr modes should have U bit clear.");
134     return (Mode & (4 << 21)) == 0;
135   }
136 
137   void emit(const Cfg *Func) const override;
138   using OperandARM32::dump;
139   void dump(const Cfg *Func, Ostream &Str) const override;
140 
classof(const Operand * Operand)141   static bool classof(const Operand *Operand) {
142     return Operand->getKind() == static_cast<OperandKind>(kMem);
143   }
144 
145   /// Return true if a load/store instruction for an element of type Ty can
146   /// encode the Offset directly in the immediate field of the 32-bit ARM
147   /// instruction. For some types, if the load is Sign extending, then the range
148   /// is reduced.
149   static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
150 
151 private:
152   OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
153                   ConstantInteger32 *ImmOffset, AddrMode Mode);
154   OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base, Variable *Index,
155                   ShiftKind ShiftOp, uint16_t ShiftAmt, AddrMode Mode);
156 
157   Variable *Base;
158   ConstantInteger32 *ImmOffset;
159   Variable *Index;
160   ShiftKind ShiftOp;
161   uint16_t ShiftAmt;
162   AddrMode Mode;
163 };
164 
165 /// OperandARM32ShAmtImm represents an Immediate that is used in one of the
166 /// shift-by-immediate instructions (lsl, lsr, and asr), and shift-by-immediate
167 /// shifted registers.
168 class OperandARM32ShAmtImm : public OperandARM32 {
169   OperandARM32ShAmtImm() = delete;
170   OperandARM32ShAmtImm(const OperandARM32ShAmtImm &) = delete;
171   OperandARM32ShAmtImm &operator=(const OperandARM32ShAmtImm &) = delete;
172 
173 public:
create(Cfg * Func,ConstantInteger32 * ShAmt)174   static OperandARM32ShAmtImm *create(Cfg *Func, ConstantInteger32 *ShAmt) {
175     return new (Func->allocate<OperandARM32ShAmtImm>())
176         OperandARM32ShAmtImm(ShAmt);
177   }
178 
classof(const Operand * Operand)179   static bool classof(const Operand *Operand) {
180     return Operand->getKind() == static_cast<OperandKind>(kShAmtImm);
181   }
182 
183   void emit(const Cfg *Func) const override;
184   using OperandARM32::dump;
185   void dump(const Cfg *Func, Ostream &Str) const override;
186 
getShAmtImm()187   uint32_t getShAmtImm() const { return ShAmt->getValue(); }
188 
189 private:
190   explicit OperandARM32ShAmtImm(ConstantInteger32 *SA);
191 
192   const ConstantInteger32 *const ShAmt;
193 };
194 
195 /// OperandARM32Flex represent the "flexible second operand" for data-processing
196 /// instructions. It can be a rotatable 8-bit constant, or a register with an
197 /// optional shift operand. The shift amount can even be a third register.
198 class OperandARM32Flex : public OperandARM32 {
199   OperandARM32Flex() = delete;
200   OperandARM32Flex(const OperandARM32Flex &) = delete;
201   OperandARM32Flex &operator=(const OperandARM32Flex &) = delete;
202 
203 public:
classof(const Operand * Operand)204   static bool classof(const Operand *Operand) {
205     return static_cast<OperandKind>(kFlexStart) <= Operand->getKind() &&
206            Operand->getKind() <= static_cast<OperandKind>(kFlexEnd);
207   }
208 
209 protected:
OperandARM32Flex(OperandKindARM32 Kind,Type Ty)210   OperandARM32Flex(OperandKindARM32 Kind, Type Ty) : OperandARM32(Kind, Ty) {}
211 };
212 
213 /// Rotated immediate variant.
214 class OperandARM32FlexImm : public OperandARM32Flex {
215   OperandARM32FlexImm() = delete;
216   OperandARM32FlexImm(const OperandARM32FlexImm &) = delete;
217   OperandARM32FlexImm &operator=(const OperandARM32FlexImm &) = delete;
218 
219 public:
220   /// Immed_8 rotated by an even number of bits (2 * RotateAmt).
221   static OperandARM32FlexImm *create(Cfg *Func, Type Ty, uint32_t Imm,
222                                      uint32_t RotateAmt);
223 
224   void emit(const Cfg *Func) const override;
225   using OperandARM32::dump;
226   void dump(const Cfg *Func, Ostream &Str) const override;
227 
classof(const Operand * Operand)228   static bool classof(const Operand *Operand) {
229     return Operand->getKind() == static_cast<OperandKind>(kFlexImm);
230   }
231 
232   /// Return true if the Immediate can fit in the ARM flexible operand. Fills in
233   /// the out-params RotateAmt and Immed_8 if Immediate fits.
234   static bool canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
235                          uint32_t *Immed_8);
236 
getImm()237   uint32_t getImm() const { return Imm; }
getRotateAmt()238   uint32_t getRotateAmt() const { return RotateAmt; }
239 
240 private:
241   OperandARM32FlexImm(Cfg *Func, Type Ty, uint32_t Imm, uint32_t RotateAmt);
242 
243   uint32_t Imm;
244   uint32_t RotateAmt;
245 };
246 
247 /// Modified Floating-point constant.
248 class OperandARM32FlexFpImm : public OperandARM32Flex {
249   OperandARM32FlexFpImm() = delete;
250   OperandARM32FlexFpImm(const OperandARM32FlexFpImm &) = delete;
251   OperandARM32FlexFpImm &operator=(const OperandARM32FlexFpImm &) = delete;
252 
253 public:
create(Cfg * Func,Type Ty,uint32_t ModifiedImm)254   static OperandARM32FlexFpImm *create(Cfg *Func, Type Ty,
255                                        uint32_t ModifiedImm) {
256     return new (Func->allocate<OperandARM32FlexFpImm>())
257         OperandARM32FlexFpImm(Func, Ty, ModifiedImm);
258   }
259 
260   void emit(const Cfg *Func) const override;
261   using OperandARM32::dump;
262   void dump(const Cfg *Func, Ostream &Str) const override;
263 
classof(const Operand * Operand)264   static bool classof(const Operand *Operand) {
265     return Operand->getKind() == static_cast<OperandKind>(kFlexFpImm);
266   }
267 
268   static bool canHoldImm(const Operand *C, uint32_t *ModifiedImm);
269 
getModifiedImm()270   uint32_t getModifiedImm() const { return ModifiedImm; }
271 
272 private:
273   OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm);
274 
275   const uint32_t ModifiedImm;
276 };
277 
278 /// An operand for representing the 0.0 immediate in vcmp.
279 class OperandARM32FlexFpZero : public OperandARM32Flex {
280   OperandARM32FlexFpZero() = delete;
281   OperandARM32FlexFpZero(const OperandARM32FlexFpZero &) = delete;
282   OperandARM32FlexFpZero &operator=(const OperandARM32FlexFpZero &) = delete;
283 
284 public:
create(Cfg * Func,Type Ty)285   static OperandARM32FlexFpZero *create(Cfg *Func, Type Ty) {
286     return new (Func->allocate<OperandARM32FlexFpZero>())
287         OperandARM32FlexFpZero(Func, Ty);
288   }
289 
290   void emit(const Cfg *Func) const override;
291   using OperandARM32::dump;
292   void dump(const Cfg *Func, Ostream &Str) const override;
293 
classof(const Operand * Operand)294   static bool classof(const Operand *Operand) {
295     return Operand->getKind() == static_cast<OperandKind>(kFlexFpZero);
296   }
297 
298 private:
299   OperandARM32FlexFpZero(Cfg *Func, Type Ty);
300 };
301 
302 /// Shifted register variant.
303 class OperandARM32FlexReg : public OperandARM32Flex {
304   OperandARM32FlexReg() = delete;
305   OperandARM32FlexReg(const OperandARM32FlexReg &) = delete;
306   OperandARM32FlexReg &operator=(const OperandARM32FlexReg &) = delete;
307 
308 public:
309   /// Register with immediate/reg shift amount and shift operation.
create(Cfg * Func,Type Ty,Variable * Reg,ShiftKind ShiftOp,Operand * ShiftAmt)310   static OperandARM32FlexReg *create(Cfg *Func, Type Ty, Variable *Reg,
311                                      ShiftKind ShiftOp, Operand *ShiftAmt) {
312     return new (Func->allocate<OperandARM32FlexReg>())
313         OperandARM32FlexReg(Func, Ty, Reg, ShiftOp, ShiftAmt);
314   }
315 
316   void emit(const Cfg *Func) const override;
317   using OperandARM32::dump;
318   void dump(const Cfg *Func, Ostream &Str) const override;
319 
classof(const Operand * Operand)320   static bool classof(const Operand *Operand) {
321     return Operand->getKind() == static_cast<OperandKind>(kFlexReg);
322   }
323 
getReg()324   Variable *getReg() const { return Reg; }
getShiftOp()325   ShiftKind getShiftOp() const { return ShiftOp; }
326   /// ShiftAmt can represent an immediate or a register.
getShiftAmt()327   Operand *getShiftAmt() const { return ShiftAmt; }
328 
329 private:
330   OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp,
331                       Operand *ShiftAmt);
332 
333   Variable *Reg;
334   ShiftKind ShiftOp;
335   Operand *ShiftAmt;
336 };
337 
338 /// StackVariable represents a Var that isn't assigned a register (stack-only).
339 /// It is assigned a stack slot, but the slot's offset may be too large to
340 /// represent in the native addressing mode, and so it has a separate base
341 /// register from SP/FP, where the offset from that base register is then in
342 /// range.
343 class StackVariable final : public Variable {
344   StackVariable() = delete;
345   StackVariable(const StackVariable &) = delete;
346   StackVariable &operator=(const StackVariable &) = delete;
347 
348 public:
create(Cfg * Func,Type Ty,SizeT Index)349   static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) {
350     return new (Func->allocate<StackVariable>()) StackVariable(Func, Ty, Index);
351   }
352   constexpr static auto StackVariableKind =
353       static_cast<OperandKind>(kVariable_Target);
classof(const Operand * Operand)354   static bool classof(const Operand *Operand) {
355     return Operand->getKind() == StackVariableKind;
356   }
setBaseRegNum(RegNumT RegNum)357   void setBaseRegNum(RegNumT RegNum) { BaseRegNum = RegNum; }
getBaseRegNum()358   RegNumT getBaseRegNum() const override { return BaseRegNum; }
359   // Inherit dump() and emit() from Variable.
360 
361 private:
StackVariable(const Cfg * Func,Type Ty,SizeT Index)362   StackVariable(const Cfg *Func, Type Ty, SizeT Index)
363       : Variable(Func, StackVariableKind, Ty, Index) {}
364   RegNumT BaseRegNum;
365 };
366 
367 /// Base class for ARM instructions. While most ARM instructions can be
368 /// conditionally executed, a few of them are not predicable (halt, memory
369 /// barriers, etc.).
370 class InstARM32 : public InstTarget {
371   InstARM32() = delete;
372   InstARM32(const InstARM32 &) = delete;
373   InstARM32 &operator=(const InstARM32 &) = delete;
374 
375 public:
376   // Defines form that assembly instruction should be synthesized.
377   enum EmitForm { Emit_Text, Emit_Binary };
378 
379   enum InstKindARM32 {
380     k__Start = Inst::Target,
381     Adc,
382     Add,
383     And,
384     Asr,
385     Bic,
386     Br,
387     Call,
388     Clz,
389     Cmn,
390     Cmp,
391     Dmb,
392     Eor,
393     Extract,
394     Insert,
395     Label,
396     Ldr,
397     Ldrex,
398     Lsl,
399     Lsr,
400     Nop,
401     Mla,
402     Mls,
403     Mov,
404     Movt,
405     Movw,
406     Mul,
407     Mvn,
408     Orr,
409     Pop,
410     Push,
411     Rbit,
412     Ret,
413     Rev,
414     Rsb,
415     Rsc,
416     Sbc,
417     Sdiv,
418     Str,
419     Strex,
420     Sub,
421     Sxt,
422     Trap,
423     Tst,
424     Udiv,
425     Umull,
426     Uxt,
427     Vabs,
428     Vadd,
429     Vand,
430     Vbsl,
431     Vceq,
432     Vcge,
433     Vcgt,
434     Vcmp,
435     Vcvt,
436     Vdiv,
437     Veor,
438     Vmla,
439     Vmls,
440     Vmrs,
441     Vmul,
442     Vmvn,
443     Vneg,
444     Vorr,
445     Vshl,
446     Vshr,
447     Vsqrt,
448     Vsub
449   };
450 
451   static constexpr size_t InstSize = sizeof(uint32_t);
452 
453   static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond);
454 
455   /// Called inside derived methods emit() to communicate that multiple
456   /// instructions are being generated. Used by emitIAS() methods to
457   /// generate textual fixups for instructions that are not yet
458   /// implemented.
459   void startNextInst(const Cfg *Func) const;
460 
461   /// FPSign is used for certain vector instructions (particularly, right
462   /// shifts) that require an operand sign specification.
463   enum FPSign {
464     FS_None,
465     FS_Signed,
466     FS_Unsigned,
467   };
468   /// Shared emit routines for common forms of instructions.
469   /// @{
470   static void emitThreeAddrFP(const char *Opcode, FPSign Sign,
471                               const InstARM32 *Instr, const Cfg *Func,
472                               Type OpType);
473   static void emitFourAddrFP(const char *Opcode, FPSign Sign,
474                              const InstARM32 *Instr, const Cfg *Func);
475   /// @}
476 
477   void dump(const Cfg *Func) const override;
478 
479   void emitIAS(const Cfg *Func) const override;
480 
481 protected:
InstARM32(Cfg * Func,InstKindARM32 Kind,SizeT Maxsrcs,Variable * Dest)482   InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
483       : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
484 
isClassof(const Inst * Instr,InstKindARM32 MyKind)485   static bool isClassof(const Inst *Instr, InstKindARM32 MyKind) {
486     return Instr->getKind() == static_cast<InstKind>(MyKind);
487   }
488 
489   // Generates text of assembly instruction using method emit(), and then adds
490   // to the assembly buffer as a Fixup.
491   void emitUsingTextFixup(const Cfg *Func) const;
492 };
493 
494 /// A predicable ARM instruction.
495 class InstARM32Pred : public InstARM32 {
496   InstARM32Pred() = delete;
497   InstARM32Pred(const InstARM32Pred &) = delete;
498   InstARM32Pred &operator=(const InstARM32Pred &) = delete;
499 
500 public:
InstARM32Pred(Cfg * Func,InstKindARM32 Kind,SizeT Maxsrcs,Variable * Dest,CondARM32::Cond Predicate)501   InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest,
502                 CondARM32::Cond Predicate)
503       : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {}
504 
getPredicate()505   CondARM32::Cond getPredicate() const { return Predicate; }
setPredicate(CondARM32::Cond Pred)506   void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; }
507 
508   static const char *predString(CondARM32::Cond Predicate);
509   void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;
510 
511   /// Shared emit routines for common forms of instructions.
512   static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Instr,
513                              const Cfg *Func, bool NeedsWidthSuffix);
514   static void emitUnaryopFP(const char *Opcode, FPSign Sign,
515                             const InstARM32Pred *Instr, const Cfg *Func);
516   static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr,
517                           const Cfg *Func);
518   static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Instr,
519                             const Cfg *Func, bool SetFlags);
520   static void emitFourAddr(const char *Opcode, const InstARM32Pred *Instr,
521                            const Cfg *Func);
522   static void emitCmpLike(const char *Opcode, const InstARM32Pred *Instr,
523                           const Cfg *Func);
524 
525 protected:
526   CondARM32::Cond Predicate;
527 };
528 
529 template <typename StreamType>
530 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) {
531   Stream << InstARM32Pred::predString(Predicate);
532   return Stream;
533 }
534 
535 /// Instructions of the form x := op(y).
536 template <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix>
537 class InstARM32UnaryopGPR : public InstARM32Pred {
538   InstARM32UnaryopGPR() = delete;
539   InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
540   InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;
541 
542 public:
create(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)543   static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
544                                      CondARM32::Cond Predicate) {
545     return new (Func->allocate<InstARM32UnaryopGPR>())
546         InstARM32UnaryopGPR(Func, Dest, Src, Predicate);
547   }
emit(const Cfg * Func)548   void emit(const Cfg *Func) const override {
549     if (!BuildDefs::dump())
550       return;
551     emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix);
552   }
553   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)554   void dump(const Cfg *Func) const override {
555     if (!BuildDefs::dump())
556       return;
557     Ostream &Str = Func->getContext()->getStrDump();
558     dumpDest(Func);
559     Str << " = ";
560     dumpOpcodePred(Str, Opcode, getDest()->getType());
561     Str << " ";
562     dumpSources(Func);
563   }
classof(const Inst * Instr)564   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
565 
566 private:
InstARM32UnaryopGPR(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)567   InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
568                       CondARM32::Cond Predicate)
569       : InstARM32Pred(Func, K, 1, Dest, Predicate) {
570     addSource(Src);
571   }
572 
573   static const char *Opcode;
574 };
575 
576 /// Instructions of the form x := op(y), for vector/FP.
577 template <InstARM32::InstKindARM32 K>
578 class InstARM32UnaryopFP : public InstARM32Pred {
579   InstARM32UnaryopFP() = delete;
580   InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete;
581   InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete;
582 
583 public:
create(Cfg * Func,Variable * Dest,Variable * Src,CondARM32::Cond Predicate)584   static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src,
585                                     CondARM32::Cond Predicate) {
586     return new (Func->allocate<InstARM32UnaryopFP>())
587         InstARM32UnaryopFP(Func, Dest, Src, Predicate);
588   }
emit(const Cfg * Func)589   void emit(const Cfg *Func) const override {
590     if (!BuildDefs::dump())
591       return;
592     emitUnaryopFP(Opcode, Sign, this, Func);
593   }
594   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)595   void dump(const Cfg *Func) const override {
596     if (!BuildDefs::dump())
597       return;
598     Ostream &Str = Func->getContext()->getStrDump();
599     dumpDest(Func);
600     Str << " = ";
601     dumpOpcodePred(Str, Opcode, getDest()->getType());
602     Str << " ";
603     dumpSources(Func);
604   }
classof(const Inst * Instr)605   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
606 
607 protected:
InstARM32UnaryopFP(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)608   InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src,
609                      CondARM32::Cond Predicate)
610       : InstARM32Pred(Func, K, 1, Dest, Predicate) {
611     addSource(Src);
612   }
613 
614   FPSign Sign = FS_None;
615   static const char *Opcode;
616 };
617 
618 template <InstARM32::InstKindARM32 K>
619 class InstARM32UnaryopSignAwareFP : public InstARM32UnaryopFP<K> {
620   InstARM32UnaryopSignAwareFP() = delete;
621   InstARM32UnaryopSignAwareFP(const InstARM32UnaryopSignAwareFP &) = delete;
622   InstARM32UnaryopSignAwareFP &
623   operator=(const InstARM32UnaryopSignAwareFP &) = delete;
624 
625 public:
626   static InstARM32UnaryopSignAwareFP *
create(Cfg * Func,Variable * Dest,Variable * Src,CondARM32::Cond Predicate)627   create(Cfg *Func, Variable *Dest, Variable *Src, CondARM32::Cond Predicate) {
628     return new (Func->allocate<InstARM32UnaryopSignAwareFP>())
629         InstARM32UnaryopSignAwareFP(Func, Dest, Src, Predicate);
630   }
631   void emitIAS(const Cfg *Func) const override;
setSignType(InstARM32::FPSign SignType)632   void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; }
633 
634 private:
InstARM32UnaryopSignAwareFP(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)635   InstARM32UnaryopSignAwareFP(Cfg *Func, Variable *Dest, Operand *Src,
636                               CondARM32::Cond Predicate)
637       : InstARM32UnaryopFP<K>(Func, Dest, Src, Predicate) {}
638 };
639 
640 /// Instructions of the form x := x op y.
641 template <InstARM32::InstKindARM32 K>
642 class InstARM32TwoAddrGPR : public InstARM32Pred {
643   InstARM32TwoAddrGPR() = delete;
644   InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
645   InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
646 
647 public:
648   /// Dest must be a register.
create(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)649   static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
650                                      CondARM32::Cond Predicate) {
651     return new (Func->allocate<InstARM32TwoAddrGPR>())
652         InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
653   }
emit(const Cfg * Func)654   void emit(const Cfg *Func) const override {
655     if (!BuildDefs::dump())
656       return;
657     emitTwoAddr(Opcode, this, Func);
658   }
659   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)660   void dump(const Cfg *Func) const override {
661     if (!BuildDefs::dump())
662       return;
663     Ostream &Str = Func->getContext()->getStrDump();
664     dumpDest(Func);
665     Str << " = ";
666     dumpOpcodePred(Str, Opcode, getDest()->getType());
667     Str << " ";
668     dumpSources(Func);
669   }
classof(const Inst * Instr)670   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
671 
672 private:
InstARM32TwoAddrGPR(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)673   InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
674                       CondARM32::Cond Predicate)
675       : InstARM32Pred(Func, K, 2, Dest, Predicate) {
676     addSource(Dest);
677     addSource(Src);
678   }
679 
680   static const char *Opcode;
681 };
682 
683 /// Base class for load instructions.
684 template <InstARM32::InstKindARM32 K>
685 class InstARM32LoadBase : public InstARM32Pred {
686   InstARM32LoadBase() = delete;
687   InstARM32LoadBase(const InstARM32LoadBase &) = delete;
688   InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete;
689 
690 public:
create(Cfg * Func,Variable * Dest,Operand * Source,CondARM32::Cond Predicate)691   static InstARM32LoadBase *create(Cfg *Func, Variable *Dest, Operand *Source,
692                                    CondARM32::Cond Predicate) {
693     return new (Func->allocate<InstARM32LoadBase>())
694         InstARM32LoadBase(Func, Dest, Source, Predicate);
695   }
696   void emit(const Cfg *Func) const override;
697   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)698   void dump(const Cfg *Func) const override {
699     if (!BuildDefs::dump())
700       return;
701     Ostream &Str = Func->getContext()->getStrDump();
702     dumpOpcodePred(Str, Opcode, getDest()->getType());
703     Str << " ";
704     dumpDest(Func);
705     Str << ", ";
706     dumpSources(Func);
707   }
classof(const Inst * Instr)708   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
709 
710 private:
InstARM32LoadBase(Cfg * Func,Variable * Dest,Operand * Source,CondARM32::Cond Predicate)711   InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source,
712                     CondARM32::Cond Predicate)
713       : InstARM32Pred(Func, K, 1, Dest, Predicate) {
714     addSource(Source);
715   }
716 
717   static const char *Opcode;
718 };
719 
720 /// Instructions of the form x := y op z. May have the side-effect of setting
721 /// status flags.
722 template <InstARM32::InstKindARM32 K>
723 class InstARM32ThreeAddrGPR : public InstARM32Pred {
724   InstARM32ThreeAddrGPR() = delete;
725   InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
726   InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
727 
728 public:
729   /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
730   /// must be registers.
731   static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
732                                        Variable *Src0, Operand *Src1,
733                                        CondARM32::Cond Predicate,
734                                        bool SetFlags = false) {
735     return new (Func->allocate<InstARM32ThreeAddrGPR>())
736         InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
737   }
emit(const Cfg * Func)738   void emit(const Cfg *Func) const override {
739     if (!BuildDefs::dump())
740       return;
741     emitThreeAddr(Opcode, this, Func, SetFlags);
742   }
743   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)744   void dump(const Cfg *Func) const override {
745     if (!BuildDefs::dump())
746       return;
747     Ostream &Str = Func->getContext()->getStrDump();
748     dumpDest(Func);
749     Str << " = ";
750     dumpOpcodePred(Str, Opcode, getDest()->getType());
751     Str << (SetFlags ? ".s " : " ");
752     dumpSources(Func);
753   }
classof(const Inst * Instr)754   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
755 
756 private:
InstARM32ThreeAddrGPR(Cfg * Func,Variable * Dest,Variable * Src0,Operand * Src1,CondARM32::Cond Predicate,bool SetFlags)757   InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
758                         Operand *Src1, CondARM32::Cond Predicate, bool SetFlags)
759       : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) {
760     HasSideEffects = SetFlags;
761     addSource(Src0);
762     addSource(Src1);
763   }
764 
765   static const char *Opcode;
766   bool SetFlags;
767 };
768 
769 /// Instructions of the form x := y op z, for vector/FP. We leave these as
770 /// unconditional: "ARM deprecates the conditional execution of any instruction
771 /// encoding provided by the Advanced SIMD Extension that is not also provided
772 /// by the floating-point (VFP) extension". They do not set flags.
773 template <InstARM32::InstKindARM32 K>
774 class InstARM32ThreeAddrFP : public InstARM32 {
775   InstARM32ThreeAddrFP() = delete;
776   InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
777   InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;
778 
779 public:
780   /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
781   /// must be a register.
create(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)782   static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
783                                       Variable *Src1) {
784     return new (Func->allocate<InstARM32ThreeAddrFP>())
785         InstARM32ThreeAddrFP(Func, Dest, Src0, Src1);
786   }
emit(const Cfg * Func)787   void emit(const Cfg *Func) const override {
788     if (!BuildDefs::dump())
789       return;
790     const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
791     emitThreeAddrFP(Opcode, Sign, this, Func, OpType);
792   }
793   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)794   void dump(const Cfg *Func) const override {
795     if (!BuildDefs::dump())
796       return;
797     Ostream &Str = Func->getContext()->getStrDump();
798     dumpDest(Func);
799     const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
800     Str << " = " << Opcode << "." << OpType << " ";
801     dumpSources(Func);
802   }
classof(const Inst * Instr)803   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
804 
805 protected:
806   FPSign Sign = FS_None;
807 
InstARM32ThreeAddrFP(Cfg * Func,Variable * Dest,Variable * Src0,Operand * Src1)808   InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Operand *Src1)
809       : InstARM32(Func, K, 2, Dest) {
810     addSource(Src0);
811     addSource(Src1);
812   }
813 
814   static const char *Opcode;
815 
816 private:
isVectorCompare()817   static constexpr bool isVectorCompare() {
818     return K == InstARM32::Vceq || K == InstARM32::Vcgt || K == InstARM32::Vcge;
819   }
820 };
821 
822 template <InstARM32::InstKindARM32 K>
823 class InstARM32ThreeAddrSignAwareFP : public InstARM32ThreeAddrFP<K> {
824   InstARM32ThreeAddrSignAwareFP() = delete;
825   InstARM32ThreeAddrSignAwareFP(const InstARM32ThreeAddrSignAwareFP &) = delete;
826   InstARM32ThreeAddrSignAwareFP &
827   operator=(const InstARM32ThreeAddrSignAwareFP &) = delete;
828 
829 public:
830   /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
831   /// must be a register.
create(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)832   static InstARM32ThreeAddrSignAwareFP *create(Cfg *Func, Variable *Dest,
833                                                Variable *Src0, Variable *Src1) {
834     return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>())
835         InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1);
836   }
837 
838   static InstARM32ThreeAddrSignAwareFP *
create(Cfg * Func,Variable * Dest,Variable * Src0,ConstantInteger32 * Src1)839   create(Cfg *Func, Variable *Dest, Variable *Src0, ConstantInteger32 *Src1) {
840     return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>())
841         InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1);
842   }
843 
844   void emitIAS(const Cfg *Func) const override;
setSignType(InstARM32::FPSign SignType)845   void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; }
846 
847 private:
InstARM32ThreeAddrSignAwareFP(Cfg * Func,Variable * Dest,Variable * Src0,Operand * Src1)848   InstARM32ThreeAddrSignAwareFP(Cfg *Func, Variable *Dest, Variable *Src0,
849                                 Operand *Src1)
850       : InstARM32ThreeAddrFP<K>(Func, Dest, Src0, Src1) {}
851 };
852 
853 /// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
854 template <InstARM32::InstKindARM32 K>
855 class InstARM32FourAddrGPR : public InstARM32Pred {
856   InstARM32FourAddrGPR() = delete;
857   InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete;
858   InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete;
859 
860 public:
861   // Every operand must be a register.
create(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1,Variable * Src2,CondARM32::Cond Predicate)862   static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0,
863                                       Variable *Src1, Variable *Src2,
864                                       CondARM32::Cond Predicate) {
865     return new (Func->allocate<InstARM32FourAddrGPR>())
866         InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate);
867   }
emit(const Cfg * Func)868   void emit(const Cfg *Func) const override {
869     if (!BuildDefs::dump())
870       return;
871     emitFourAddr(Opcode, this, Func);
872   }
873   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)874   void dump(const Cfg *Func) const override {
875     if (!BuildDefs::dump())
876       return;
877     Ostream &Str = Func->getContext()->getStrDump();
878     dumpDest(Func);
879     Str << " = ";
880     dumpOpcodePred(Str, Opcode, getDest()->getType());
881     Str << " ";
882     dumpSources(Func);
883   }
classof(const Inst * Instr)884   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
885 
886 private:
InstARM32FourAddrGPR(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1,Variable * Src2,CondARM32::Cond Predicate)887   InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
888                        Variable *Src1, Variable *Src2,
889                        CondARM32::Cond Predicate)
890       : InstARM32Pred(Func, K, 3, Dest, Predicate) {
891     addSource(Src0);
892     addSource(Src1);
893     addSource(Src2);
894   }
895 
896   static const char *Opcode;
897 };
898 
899 /// Instructions of the form x := x op1 (y op2 z). E.g., multiply accumulate.
900 /// We leave these as unconditional: "ARM deprecates the conditional execution
901 /// of any instruction encoding provided by the Advanced SIMD Extension that is
902 /// not also provided by the floating-point (VFP) extension". They do not set
903 /// flags.
904 template <InstARM32::InstKindARM32 K>
905 class InstARM32FourAddrFP : public InstARM32 {
906   InstARM32FourAddrFP() = delete;
907   InstARM32FourAddrFP(const InstARM32FourAddrFP &) = delete;
908   InstARM32FourAddrFP &operator=(const InstARM32FourAddrFP &) = delete;
909 
910 public:
911   // Every operand must be a register.
create(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)912   static InstARM32FourAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
913                                      Variable *Src1) {
914     return new (Func->allocate<InstARM32FourAddrFP>())
915         InstARM32FourAddrFP(Func, Dest, Src0, Src1);
916   }
emit(const Cfg * Func)917   void emit(const Cfg *Func) const override {
918     if (!BuildDefs::dump())
919       return;
920     emitFourAddrFP(Opcode, Sign, this, Func);
921   }
922   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)923   void dump(const Cfg *Func) const override {
924     if (!BuildDefs::dump())
925       return;
926     Ostream &Str = Func->getContext()->getStrDump();
927     dumpDest(Func);
928     Str << " = ";
929     Str << Opcode << "." << getDest()->getType() << " ";
930     dumpDest(Func);
931     Str << ", ";
932     dumpSources(Func);
933   }
classof(const Inst * Instr)934   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
935 
936 private:
InstARM32FourAddrFP(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)937   InstARM32FourAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1)
938       : InstARM32(Func, K, 3, Dest) {
939     addSource(Dest);
940     addSource(Src0);
941     addSource(Src1);
942   }
943 
944   FPSign Sign = FS_None;
945   static const char *Opcode;
946 };
947 
948 /// Instructions of the form x cmpop y (setting flags).
949 template <InstARM32::InstKindARM32 K>
950 class InstARM32CmpLike : public InstARM32Pred {
951   InstARM32CmpLike() = delete;
952   InstARM32CmpLike(const InstARM32CmpLike &) = delete;
953   InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete;
954 
955 public:
create(Cfg * Func,Variable * Src0,Operand * Src1,CondARM32::Cond Predicate)956   static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1,
957                                   CondARM32::Cond Predicate) {
958     return new (Func->allocate<InstARM32CmpLike>())
959         InstARM32CmpLike(Func, Src0, Src1, Predicate);
960   }
emit(const Cfg * Func)961   void emit(const Cfg *Func) const override {
962     if (!BuildDefs::dump())
963       return;
964     emitCmpLike(Opcode, this, Func);
965   }
966   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)967   void dump(const Cfg *Func) const override {
968     if (!BuildDefs::dump())
969       return;
970     Ostream &Str = Func->getContext()->getStrDump();
971     dumpOpcodePred(Str, Opcode, getSrc(0)->getType());
972     Str << " ";
973     dumpSources(Func);
974   }
classof(const Inst * Instr)975   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
976 
977 private:
InstARM32CmpLike(Cfg * Func,Variable * Src0,Operand * Src1,CondARM32::Cond Predicate)978   InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1,
979                    CondARM32::Cond Predicate)
980       : InstARM32Pred(Func, K, 2, nullptr, Predicate) {
981     HasSideEffects = true;
982     addSource(Src0);
983     addSource(Src1);
984   }
985 
986   static const char *Opcode;
987 };
988 
989 using InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>;
990 using InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>;
991 using InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>;
992 using InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>;
993 using InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>;
994 using InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>;
995 using InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>;
996 using InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>;
997 using InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>;
998 using InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>;
999 using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>;
1000 using InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>;
1001 using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>;
1002 using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
1003 using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>;
1004 using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>;
1005 using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>;
1006 using InstARM32Vand = InstARM32ThreeAddrFP<InstARM32::Vand>;
1007 using InstARM32Vbsl = InstARM32ThreeAddrFP<InstARM32::Vbsl>;
1008 using InstARM32Vceq = InstARM32ThreeAddrFP<InstARM32::Vceq>;
1009 using InstARM32Vcge = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>;
1010 using InstARM32Vcgt = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>;
1011 using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>;
1012 using InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>;
1013 using InstARM32Vmla = InstARM32FourAddrFP<InstARM32::Vmla>;
1014 using InstARM32Vmls = InstARM32FourAddrFP<InstARM32::Vmls>;
1015 using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>;
1016 using InstARM32Vmvn = InstARM32UnaryopFP<InstARM32::Vmvn>;
1017 using InstARM32Vneg = InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
1018 using InstARM32Vorr = InstARM32ThreeAddrFP<InstARM32::Vorr>;
1019 using InstARM32Vshl = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
1020 using InstARM32Vshr = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
1021 using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>;
1022 using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>;
1023 using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>;
1024 /// MovT leaves the bottom bits alone so dest is also a source. This helps
1025 /// indicate that a previous MovW setting dest is not dead code.
1026 using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>;
1027 using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>;
1028 using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>;
1029 using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>;
1030 using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>;
1031 using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>;
1032 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand
1033 // as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't
1034 // using that for now, so just model as a Unaryop.
1035 using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>;
1036 using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>;
1037 using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>;
1038 using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>;
1039 using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>;
1040 using InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>;
1041 using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
1042 using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;
1043 
1044 // InstARM32Label represents an intra-block label that is the target of an
1045 // intra-block branch. The offset between the label and the branch must be fit
1046 // in the instruction immediate (considered "near").
1047 class InstARM32Label : public InstARM32 {
1048   InstARM32Label() = delete;
1049   InstARM32Label(const InstARM32Label &) = delete;
1050   InstARM32Label &operator=(const InstARM32Label &) = delete;
1051 
1052 public:
create(Cfg * Func,TargetARM32 * Target)1053   static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
1054     return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
1055   }
getEmitInstCount()1056   uint32_t getEmitInstCount() const override { return 0; }
getLabelName()1057   GlobalString getLabelName() const { return Name; }
getNumber()1058   SizeT getNumber() const { return Number; }
1059   void emit(const Cfg *Func) const override;
1060   void emitIAS(const Cfg *Func) const override;
1061   void dump(const Cfg *Func) const override;
setRelocOffset(RelocOffset * Value)1062   void setRelocOffset(RelocOffset *Value) { OffsetReloc = Value; }
1063 
1064 private:
1065   InstARM32Label(Cfg *Func, TargetARM32 *Target);
1066 
1067   RelocOffset *OffsetReloc = nullptr;
1068   SizeT Number; // used for unique label generation.
1069   GlobalString Name;
1070 };
1071 
1072 /// Direct branch instruction.
1073 class InstARM32Br : public InstARM32Pred {
1074   InstARM32Br() = delete;
1075   InstARM32Br(const InstARM32Br &) = delete;
1076   InstARM32Br &operator=(const InstARM32Br &) = delete;
1077 
1078 public:
1079   /// Create a conditional branch to one of two nodes.
create(Cfg * Func,CfgNode * TargetTrue,CfgNode * TargetFalse,CondARM32::Cond Predicate)1080   static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
1081                              CfgNode *TargetFalse, CondARM32::Cond Predicate) {
1082     assert(Predicate != CondARM32::AL);
1083     constexpr InstARM32Label *NoLabel = nullptr;
1084     return new (Func->allocate<InstARM32Br>())
1085         InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
1086   }
1087   /// Create an unconditional branch to a node.
create(Cfg * Func,CfgNode * Target)1088   static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
1089     constexpr CfgNode *NoCondTarget = nullptr;
1090     constexpr InstARM32Label *NoLabel = nullptr;
1091     return new (Func->allocate<InstARM32Br>())
1092         InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
1093   }
1094   /// Create a non-terminator conditional branch to a node, with a fallthrough
1095   /// to the next instruction in the current node. This is used for switch
1096   /// lowering.
create(Cfg * Func,CfgNode * Target,CondARM32::Cond Predicate)1097   static InstARM32Br *create(Cfg *Func, CfgNode *Target,
1098                              CondARM32::Cond Predicate) {
1099     assert(Predicate != CondARM32::AL);
1100     constexpr CfgNode *NoUncondTarget = nullptr;
1101     constexpr InstARM32Label *NoLabel = nullptr;
1102     return new (Func->allocate<InstARM32Br>())
1103         InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
1104   }
1105   // Create a conditional intra-block branch (or unconditional, if
1106   // Condition==AL) to a label in the current block.
create(Cfg * Func,InstARM32Label * Label,CondARM32::Cond Predicate)1107   static InstARM32Br *create(Cfg *Func, InstARM32Label *Label,
1108                              CondARM32::Cond Predicate) {
1109     constexpr CfgNode *NoCondTarget = nullptr;
1110     constexpr CfgNode *NoUncondTarget = nullptr;
1111     return new (Func->allocate<InstARM32Br>())
1112         InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate);
1113   }
getTargetTrue()1114   const CfgNode *getTargetTrue() const { return TargetTrue; }
getTargetFalse()1115   const CfgNode *getTargetFalse() const { return TargetFalse; }
1116   bool optimizeBranch(const CfgNode *NextNode);
getEmitInstCount()1117   uint32_t getEmitInstCount() const override {
1118     uint32_t Sum = 0;
1119     if (Label)
1120       ++Sum;
1121     if (getTargetTrue())
1122       ++Sum;
1123     if (getTargetFalse())
1124       ++Sum;
1125     return Sum;
1126   }
isUnconditionalBranch()1127   bool isUnconditionalBranch() const override {
1128     return getPredicate() == CondARM32::AL;
1129   }
1130   bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
1131   void emit(const Cfg *Func) const override;
1132   void emitIAS(const Cfg *Func) const override;
1133   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1134   static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
1135 
1136 private:
1137   InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
1138               const InstARM32Label *Label, CondARM32::Cond Predicate);
1139 
1140   const CfgNode *TargetTrue;
1141   const CfgNode *TargetFalse;
1142   const InstARM32Label *Label; // Intra-block branch target
1143 };
1144 
1145 /// Call instruction (bl/blx). Arguments should have already been pushed.
1146 /// Technically bl and the register form of blx can be predicated, but we'll
1147 /// leave that out until needed.
1148 class InstARM32Call : public InstARM32 {
1149   InstARM32Call() = delete;
1150   InstARM32Call(const InstARM32Call &) = delete;
1151   InstARM32Call &operator=(const InstARM32Call &) = delete;
1152 
1153 public:
create(Cfg * Func,Variable * Dest,Operand * CallTarget)1154   static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
1155     return new (Func->allocate<InstARM32Call>())
1156         InstARM32Call(Func, Dest, CallTarget);
1157   }
getCallTarget()1158   Operand *getCallTarget() const { return getSrc(0); }
1159   void emit(const Cfg *Func) const override;
1160   void emitIAS(const Cfg *Func) const override;
1161   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1162   static bool classof(const Inst *Instr) { return isClassof(Instr, Call); }
1163 
1164 private:
1165   InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
1166 };
1167 
1168 class InstARM32RegisterStackOp : public InstARM32 {
1169   InstARM32RegisterStackOp() = delete;
1170   InstARM32RegisterStackOp(const InstARM32RegisterStackOp &) = delete;
1171   InstARM32RegisterStackOp &
1172   operator=(const InstARM32RegisterStackOp &) = delete;
1173 
1174 public:
1175   void emit(const Cfg *Func) const override;
1176   void emitIAS(const Cfg *Func) const override;
1177   void dump(const Cfg *Func) const override;
1178 
1179 protected:
InstARM32RegisterStackOp(Cfg * Func,InstKindARM32 Kind,SizeT Maxsrcs,Variable * Dest)1180   InstARM32RegisterStackOp(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs,
1181                            Variable *Dest)
1182       : InstARM32(Func, Kind, Maxsrcs, Dest) {}
1183   void emitUsingForm(const Cfg *Func, const EmitForm Form) const;
1184   void emitGPRsAsText(const Cfg *Func) const;
1185   void emitSRegsAsText(const Cfg *Func, const Variable *BaseReg,
1186                        SizeT Regcount) const;
1187   void emitSRegsOp(const Cfg *Func, const EmitForm, const Variable *BaseReg,
1188                    SizeT RegCount, SizeT InstIndex) const;
getDumpOpcode()1189   virtual const char *getDumpOpcode() const { return getGPROpcode(); }
1190   virtual const char *getGPROpcode() const = 0;
1191   virtual const char *getSRegOpcode() const = 0;
1192   virtual Variable *getStackReg(SizeT Index) const = 0;
1193   virtual SizeT getNumStackRegs() const = 0;
1194   virtual void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1195                              const Variable *Reg) const = 0;
1196   virtual void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1197                                 IValueT Registers) const = 0;
1198   virtual void emitSRegs(const Cfg *Func, const EmitForm Form,
1199                          const Variable *BaseReg, SizeT RegCount) const = 0;
1200 };
1201 
1202 /// Pops a list of registers. It may be a list of GPRs, or a list of VFP "s"
1203 /// regs, but not both. In any case, the list must be sorted.
1204 class InstARM32Pop final : public InstARM32RegisterStackOp {
1205   InstARM32Pop() = delete;
1206   InstARM32Pop(const InstARM32Pop &) = delete;
1207   InstARM32Pop &operator=(const InstARM32Pop &) = delete;
1208 
1209 public:
create(Cfg * Func,const VarList & Dests)1210   static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
1211     return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
1212   }
classof(const Inst * Instr)1213   static bool classof(const Inst *Instr) { return isClassof(Instr, Pop); }
1214 
1215 private:
1216   InstARM32Pop(Cfg *Func, const VarList &Dests);
1217   virtual const char *getGPROpcode() const final;
1218   virtual const char *getSRegOpcode() const final;
1219   Variable *getStackReg(SizeT Index) const final;
1220   SizeT getNumStackRegs() const final;
1221   void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1222                      const Variable *Reg) const final;
1223   void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1224                         IValueT Registers) const final;
1225   void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1226                  SizeT RegCount) const final;
1227   VarList Dests;
1228 };
1229 
1230 /// Pushes a list of registers. Just like Pop (see above), the list may be of
1231 /// GPRs, or VFP "s" registers, but not both.
1232 class InstARM32Push final : public InstARM32RegisterStackOp {
1233   InstARM32Push() = delete;
1234   InstARM32Push(const InstARM32Push &) = delete;
1235   InstARM32Push &operator=(const InstARM32Push &) = delete;
1236 
1237 public:
create(Cfg * Func,const VarList & Srcs)1238   static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
1239     return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
1240   }
classof(const Inst * Instr)1241   static bool classof(const Inst *Instr) { return isClassof(Instr, Push); }
1242 
1243 private:
1244   InstARM32Push(Cfg *Func, const VarList &Srcs);
1245   const char *getGPROpcode() const final;
1246   const char *getSRegOpcode() const final;
1247   Variable *getStackReg(SizeT Index) const final;
1248   SizeT getNumStackRegs() const final;
1249   void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1250                      const Variable *Reg) const final;
1251   void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1252                         IValueT Registers) const final;
1253   void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1254                  SizeT RegCount) const final;
1255 };
1256 
1257 /// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
1258 /// register operand, but epilogue lowering will search for a Ret instead of a
1259 /// generic "bx". This instruction also takes a Source operand (for non-void
1260 /// returning functions) for liveness analysis, though a FakeUse before the ret
1261 /// would do just as well.
1262 ///
1263 /// NOTE: Even though "bx" can be predicated, for now leave out the predication
1264 /// since it's not yet known to be useful for Ret. That may complicate finding
1265 /// the terminator instruction if it's not guaranteed to be executed.
1266 class InstARM32Ret : public InstARM32 {
1267   InstARM32Ret() = delete;
1268   InstARM32Ret(const InstARM32Ret &) = delete;
1269   InstARM32Ret &operator=(const InstARM32Ret &) = delete;
1270 
1271 public:
1272   static InstARM32Ret *create(Cfg *Func, Variable *LR,
1273                               Variable *Source = nullptr) {
1274     return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
1275   }
1276   void emit(const Cfg *Func) const override;
1277   void emitIAS(const Cfg *Func) const override;
1278   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1279   static bool classof(const Inst *Instr) { return isClassof(Instr, Ret); }
1280 
1281 private:
1282   InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
1283 };
1284 
1285 /// Store instruction. It's important for liveness that there is no Dest operand
1286 /// (OperandARM32Mem instead of Dest Variable).
1287 class InstARM32Str final : public InstARM32Pred {
1288   InstARM32Str() = delete;
1289   InstARM32Str(const InstARM32Str &) = delete;
1290   InstARM32Str &operator=(const InstARM32Str &) = delete;
1291 
1292 public:
1293   /// Value must be a register.
create(Cfg * Func,Variable * Value,OperandARM32Mem * Mem,CondARM32::Cond Predicate)1294   static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1295                               CondARM32::Cond Predicate) {
1296     return new (Func->allocate<InstARM32Str>())
1297         InstARM32Str(Func, Value, Mem, Predicate);
1298   }
1299   void emit(const Cfg *Func) const override;
1300   void emitIAS(const Cfg *Func) const override;
1301   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1302   static bool classof(const Inst *Instr) { return isClassof(Instr, Str); }
1303 
1304 private:
1305   InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1306                CondARM32::Cond Predicate);
1307 };
1308 
1309 /// Exclusive Store instruction. Like its non-exclusive sibling, it's important
1310 /// for liveness that there is no Dest operand (OperandARM32Mem instead of Dest
1311 /// Variable).
1312 class InstARM32Strex final : public InstARM32Pred {
1313   InstARM32Strex() = delete;
1314   InstARM32Strex(const InstARM32Strex &) = delete;
1315   InstARM32Strex &operator=(const InstARM32Strex &) = delete;
1316 
1317 public:
1318   /// Value must be a register.
create(Cfg * Func,Variable * Dest,Variable * Value,OperandARM32Mem * Mem,CondARM32::Cond Predicate)1319   static InstARM32Strex *create(Cfg *Func, Variable *Dest, Variable *Value,
1320                                 OperandARM32Mem *Mem,
1321                                 CondARM32::Cond Predicate) {
1322     return new (Func->allocate<InstARM32Strex>())
1323         InstARM32Strex(Func, Dest, Value, Mem, Predicate);
1324   }
1325   void emit(const Cfg *Func) const override;
1326   void emitIAS(const Cfg *Func) const override;
1327   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1328   static bool classof(const Inst *Instr) { return isClassof(Instr, Strex); }
1329 
1330 private:
1331   InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
1332                  OperandARM32Mem *Mem, CondARM32::Cond Predicate);
1333 };
1334 
1335 class InstARM32Trap : public InstARM32 {
1336   InstARM32Trap() = delete;
1337   InstARM32Trap(const InstARM32Trap &) = delete;
1338   InstARM32Trap &operator=(const InstARM32Trap &) = delete;
1339 
1340 public:
create(Cfg * Func)1341   static InstARM32Trap *create(Cfg *Func) {
1342     return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func);
1343   }
1344   void emit(const Cfg *Func) const override;
1345   void emitIAS(const Cfg *Func) const override;
1346   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1347   static bool classof(const Inst *Instr) { return isClassof(Instr, Trap); }
1348 
1349 private:
1350   explicit InstARM32Trap(Cfg *Func);
1351 };
1352 
1353 /// Unsigned Multiply Long: d.lo, d.hi := x * y
1354 class InstARM32Umull : public InstARM32Pred {
1355   InstARM32Umull() = delete;
1356   InstARM32Umull(const InstARM32Umull &) = delete;
1357   InstARM32Umull &operator=(const InstARM32Umull &) = delete;
1358 
1359 public:
1360   /// Everything must be a register.
create(Cfg * Func,Variable * DestLo,Variable * DestHi,Variable * Src0,Variable * Src1,CondARM32::Cond Predicate)1361   static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
1362                                 Variable *Src0, Variable *Src1,
1363                                 CondARM32::Cond Predicate) {
1364     return new (Func->allocate<InstARM32Umull>())
1365         InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
1366   }
1367   void emit(const Cfg *Func) const override;
1368   void emitIAS(const Cfg *Func) const override;
1369   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1370   static bool classof(const Inst *Instr) { return isClassof(Instr, Umull); }
1371 
1372 private:
1373   InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
1374                  Variable *Src1, CondARM32::Cond Predicate);
1375 
1376   Variable *DestHi;
1377 };
1378 
1379 /// Handles fp2int, int2fp, and fp2fp conversions.
1380 class InstARM32Vcvt final : public InstARM32Pred {
1381   InstARM32Vcvt() = delete;
1382   InstARM32Vcvt(const InstARM32Vcvt &) = delete;
1383   InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete;
1384 
1385 public:
1386   enum VcvtVariant {
1387     S2si,
1388     S2ui,
1389     Si2s,
1390     Ui2s,
1391     D2si,
1392     D2ui,
1393     Si2d,
1394     Ui2d,
1395     S2d,
1396     D2s,
1397     Vs2si,
1398     Vs2ui,
1399     Vsi2s,
1400     Vui2s,
1401   };
create(Cfg * Func,Variable * Dest,Variable * Src,VcvtVariant Variant,CondARM32::Cond Predicate)1402   static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src,
1403                                VcvtVariant Variant, CondARM32::Cond Predicate) {
1404     return new (Func->allocate<InstARM32Vcvt>())
1405         InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
1406   }
1407   void emit(const Cfg *Func) const override;
1408   void emitIAS(const Cfg *Func) const override;
1409   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1410   static bool classof(const Inst *Instr) { return isClassof(Instr, Vcvt); }
1411 
1412 private:
1413   InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
1414                 CondARM32::Cond Predicate);
1415 
1416   const VcvtVariant Variant;
1417 };
1418 
1419 /// Handles (some of) vmov's various formats.
1420 class InstARM32Mov final : public InstARM32Pred {
1421   InstARM32Mov() = delete;
1422   InstARM32Mov(const InstARM32Mov &) = delete;
1423   InstARM32Mov &operator=(const InstARM32Mov &) = delete;
1424 
1425 public:
create(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)1426   static InstARM32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
1427                               CondARM32::Cond Predicate) {
1428     return new (Func->allocate<InstARM32Mov>())
1429         InstARM32Mov(Func, Dest, Src, Predicate);
1430   }
isRedundantAssign()1431   bool isRedundantAssign() const override {
1432     return !isMultiDest() && !isMultiSource() &&
1433            getPredicate() == CondARM32::AL &&
1434            checkForRedundantAssign(getDest(), getSrc(0));
1435   }
isVarAssign()1436   bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); }
1437   void emit(const Cfg *Func) const override;
1438   void emitIAS(const Cfg *Func) const override;
1439   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1440   static bool classof(const Inst *Instr) { return isClassof(Instr, Mov); }
1441 
isMultiDest()1442   bool isMultiDest() const { return DestHi != nullptr; }
1443 
isMultiSource()1444   bool isMultiSource() const {
1445     assert(getSrcSize() == 1 || getSrcSize() == 2);
1446     return getSrcSize() == 2;
1447   }
1448 
getDestHi()1449   Variable *getDestHi() const { return DestHi; }
1450 
1451 private:
1452   InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
1453                CondARM32::Cond Predicate);
1454   void emitMultiDestSingleSource(const Cfg *Func) const;
1455   void emitSingleDestMultiSource(const Cfg *Func) const;
1456   void emitSingleDestSingleSource(const Cfg *Func) const;
1457 
1458   Variable *DestHi = nullptr;
1459 };
1460 
1461 /// Generates vmov Rd, Dn[x] instructions, and their related floating point
1462 /// versions.
1463 class InstARM32Extract final : public InstARM32Pred {
1464   InstARM32Extract() = delete;
1465   InstARM32Extract(const InstARM32Extract &) = delete;
1466   InstARM32Extract &operator=(const InstARM32Extract &) = delete;
1467 
1468 public:
create(Cfg * Func,Variable * Dest,Variable * Src0,uint32_t Index,CondARM32::Cond Predicate)1469   static InstARM32Extract *create(Cfg *Func, Variable *Dest, Variable *Src0,
1470                                   uint32_t Index, CondARM32::Cond Predicate) {
1471     return new (Func->allocate<InstARM32Extract>())
1472         InstARM32Extract(Func, Dest, Src0, Index, Predicate);
1473   }
1474   void emit(const Cfg *Func) const override;
1475   void emitIAS(const Cfg *Func) const override;
classof(const Inst * Inst)1476   static bool classof(const Inst *Inst) { return isClassof(Inst, Extract); }
1477 
1478 private:
InstARM32Extract(Cfg * Func,Variable * Dest,Variable * Src0,uint32_t Index,CondARM32::Cond Predicate)1479   InstARM32Extract(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index,
1480                    CondARM32::Cond Predicate)
1481       : InstARM32Pred(Func, InstARM32::Extract, 1, Dest, Predicate),
1482         Index(Index) {
1483     assert(Index < typeNumElements(Src0->getType()));
1484     addSource(Src0);
1485   }
1486 
1487   const uint32_t Index;
1488 };
1489 
1490 /// Generates vmov Dn[x], Rd instructions, and their related floating point
1491 /// versions.
1492 class InstARM32Insert final : public InstARM32Pred {
1493   InstARM32Insert() = delete;
1494   InstARM32Insert(const InstARM32Insert &) = delete;
1495   InstARM32Insert &operator=(const InstARM32Insert &) = delete;
1496 
1497 public:
create(Cfg * Func,Variable * Dest,Variable * Src0,uint32_t Index,CondARM32::Cond Predicate)1498   static InstARM32Insert *create(Cfg *Func, Variable *Dest, Variable *Src0,
1499                                  uint32_t Index, CondARM32::Cond Predicate) {
1500     return new (Func->allocate<InstARM32Insert>())
1501         InstARM32Insert(Func, Dest, Src0, Index, Predicate);
1502   }
1503   void emit(const Cfg *Func) const override;
1504   void emitIAS(const Cfg *Func) const override;
classof(const Inst * Inst)1505   static bool classof(const Inst *Inst) { return isClassof(Inst, Insert); }
1506 
1507 private:
InstARM32Insert(Cfg * Func,Variable * Dest,Variable * Src0,uint32_t Index,CondARM32::Cond Predicate)1508   InstARM32Insert(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index,
1509                   CondARM32::Cond Predicate)
1510       : InstARM32Pred(Func, InstARM32::Insert, 1, Dest, Predicate),
1511         Index(Index) {
1512     assert(Index < typeNumElements(Dest->getType()));
1513     addSource(Src0);
1514   }
1515 
1516   const uint32_t Index;
1517 };
1518 
1519 class InstARM32Vcmp final : public InstARM32Pred {
1520   InstARM32Vcmp() = delete;
1521   InstARM32Vcmp(const InstARM32Vcmp &) = delete;
1522   InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete;
1523 
1524 public:
create(Cfg * Func,Variable * Src0,Variable * Src1,CondARM32::Cond Predicate)1525   static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1,
1526                                CondARM32::Cond Predicate) {
1527     return new (Func->allocate<InstARM32Vcmp>())
1528         InstARM32Vcmp(Func, Src0, Src1, Predicate);
1529   }
create(Cfg * Func,Variable * Src0,OperandARM32FlexFpZero * Src1,CondARM32::Cond Predicate)1530   static InstARM32Vcmp *create(Cfg *Func, Variable *Src0,
1531                                OperandARM32FlexFpZero *Src1,
1532                                CondARM32::Cond Predicate) {
1533     return new (Func->allocate<InstARM32Vcmp>())
1534         InstARM32Vcmp(Func, Src0, Src1, Predicate);
1535   }
1536   void emit(const Cfg *Func) const override;
1537   void emitIAS(const Cfg *Func) const override;
1538   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1539   static bool classof(const Inst *Instr) { return isClassof(Instr, Vcmp); }
1540 
1541 private:
1542   InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
1543                 CondARM32::Cond Predicate);
1544 };
1545 
1546 /// Copies the FP Status and Control Register the core flags.
1547 class InstARM32Vmrs final : public InstARM32Pred {
1548   InstARM32Vmrs() = delete;
1549   InstARM32Vmrs(const InstARM32Vmrs &) = delete;
1550   InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete;
1551 
1552 public:
create(Cfg * Func,CondARM32::Cond Predicate)1553   static InstARM32Vmrs *create(Cfg *Func, CondARM32::Cond Predicate) {
1554     return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate);
1555   }
1556   void emit(const Cfg *Func) const override;
1557   void emitIAS(const Cfg *Func) const override;
1558   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1559   static bool classof(const Inst *Instr) { return isClassof(Instr, Vmrs); }
1560 
1561 private:
1562   InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate);
1563 };
1564 
1565 class InstARM32Vabs final : public InstARM32Pred {
1566   InstARM32Vabs() = delete;
1567   InstARM32Vabs(const InstARM32Vabs &) = delete;
1568   InstARM32Vabs &operator=(const InstARM32Vabs &) = delete;
1569 
1570 public:
create(Cfg * Func,Variable * Dest,Variable * Src,CondARM32::Cond Predicate)1571   static InstARM32Vabs *create(Cfg *Func, Variable *Dest, Variable *Src,
1572                                CondARM32::Cond Predicate) {
1573     return new (Func->allocate<InstARM32Vabs>())
1574         InstARM32Vabs(Func, Dest, Src, Predicate);
1575   }
1576   void emit(const Cfg *Func) const override;
1577   void emitIAS(const Cfg *Func) const override;
1578   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1579   static bool classof(const Inst *Instr) { return isClassof(Instr, Vabs); }
1580 
1581 private:
1582   InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
1583                 CondARM32::Cond Predicate);
1584 };
1585 
1586 class InstARM32Dmb final : public InstARM32Pred {
1587   InstARM32Dmb() = delete;
1588   InstARM32Dmb(const InstARM32Dmb &) = delete;
1589   InstARM32Dmb &operator=(const InstARM32Dmb &) = delete;
1590 
1591 public:
create(Cfg * Func)1592   static InstARM32Dmb *create(Cfg *Func) {
1593     return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func);
1594   }
1595   void emit(const Cfg *Func) const override;
1596   void emitIAS(const Cfg *Func) const override;
1597   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1598   static bool classof(const Inst *Instr) { return isClassof(Instr, Dmb); }
1599 
1600 private:
1601   explicit InstARM32Dmb(Cfg *Func);
1602 };
1603 
1604 class InstARM32Nop final : public InstARM32Pred {
1605   InstARM32Nop() = delete;
1606   InstARM32Nop(const InstARM32Nop &) = delete;
1607   InstARM32Nop &operator=(const InstARM32Nop &) = delete;
1608 
1609 public:
create(Cfg * Func)1610   static InstARM32Nop *create(Cfg *Func) {
1611     return new (Func->allocate<InstARM32Nop>()) InstARM32Nop(Func);
1612   }
1613   void emit(const Cfg *Func) const override;
1614   void emitIAS(const Cfg *Func) const override;
1615   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1616   static bool classof(const Inst *Instr) { return isClassof(Instr, Nop); }
1617 
1618 private:
1619   explicit InstARM32Nop(Cfg *Func);
1620 };
1621 
1622 // Declare partial template specializations of emit() methods that already have
1623 // default implementations. Without this, there is the possibility of ODR
1624 // violations and link errors.
1625 
1626 template <> void InstARM32Ldr::emit(const Cfg *Func) const;
1627 template <> void InstARM32Movw::emit(const Cfg *Func) const;
1628 template <> void InstARM32Movt::emit(const Cfg *Func) const;
1629 
1630 } // end of namespace ARM32
1631 } // end of namespace Ice
1632 
1633 #endif // SUBZERO_SRC_ICEINSTARM32_H
1634