• 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     Vdup,
438     Veor,
439     Vldr1d,
440     Vldr1q,
441     Vmla,
442     Vmlap,
443     Vmls,
444     Vmovl,
445     Vmovh,
446     Vmovhl,
447     Vmovlh,
448     Vmrs,
449     Vmul,
450     Vmulh,
451     Vmvn,
452     Vneg,
453     Vorr,
454     Vqadd,
455     Vqmovn2,
456     Vqsub,
457     Vshl,
458     Vshr,
459     Vsqrt,
460     Vstr1,
461     Vsub,
462     Vzip
463   };
464 
465   static constexpr size_t InstSize = sizeof(uint32_t);
466 
467   static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond);
468 
469   /// Called inside derived methods emit() to communicate that multiple
470   /// instructions are being generated. Used by emitIAS() methods to
471   /// generate textual fixups for instructions that are not yet
472   /// implemented.
473   void startNextInst(const Cfg *Func) const;
474 
475   /// FPSign is used for certain vector instructions (particularly, right
476   /// shifts) that require an operand sign specification.
477   enum FPSign {
478     FS_None,
479     FS_Signed,
480     FS_Unsigned,
481   };
482   /// Shared emit routines for common forms of instructions.
483   /// @{
484   static void emitThreeAddrFP(const char *Opcode, FPSign Sign,
485                               const InstARM32 *Instr, const Cfg *Func,
486                               Type OpType);
487   static void emitFourAddrFP(const char *Opcode, FPSign Sign,
488                              const InstARM32 *Instr, const Cfg *Func);
489   /// @}
490 
491   void dump(const Cfg *Func) const override;
492 
493   void emitIAS(const Cfg *Func) const override;
494 
495 protected:
InstARM32(Cfg * Func,InstKindARM32 Kind,SizeT Maxsrcs,Variable * Dest)496   InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
497       : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
498 
isClassof(const Inst * Instr,InstKindARM32 MyKind)499   static bool isClassof(const Inst *Instr, InstKindARM32 MyKind) {
500     return Instr->getKind() == static_cast<InstKind>(MyKind);
501   }
502 
503   // Generates text of assembly instruction using method emit(), and then adds
504   // to the assembly buffer as a Fixup.
505   void emitUsingTextFixup(const Cfg *Func) const;
506 };
507 
508 /// A predicable ARM instruction.
509 class InstARM32Pred : public InstARM32 {
510   InstARM32Pred() = delete;
511   InstARM32Pred(const InstARM32Pred &) = delete;
512   InstARM32Pred &operator=(const InstARM32Pred &) = delete;
513 
514 public:
InstARM32Pred(Cfg * Func,InstKindARM32 Kind,SizeT Maxsrcs,Variable * Dest,CondARM32::Cond Predicate)515   InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest,
516                 CondARM32::Cond Predicate)
517       : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {}
518 
getPredicate()519   CondARM32::Cond getPredicate() const { return Predicate; }
setPredicate(CondARM32::Cond Pred)520   void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; }
521 
522   static const char *predString(CondARM32::Cond Predicate);
523   void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;
524 
525   /// Shared emit routines for common forms of instructions.
526   static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Instr,
527                              const Cfg *Func, bool NeedsWidthSuffix);
528   static void emitUnaryopFP(const char *Opcode, FPSign Sign,
529                             const InstARM32Pred *Instr, const Cfg *Func);
530   static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr,
531                           const Cfg *Func);
532   static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Instr,
533                             const Cfg *Func, bool SetFlags);
534   static void emitFourAddr(const char *Opcode, const InstARM32Pred *Instr,
535                            const Cfg *Func);
536   static void emitCmpLike(const char *Opcode, const InstARM32Pred *Instr,
537                           const Cfg *Func);
538 
539 protected:
540   CondARM32::Cond Predicate;
541 };
542 
543 template <typename StreamType>
544 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) {
545   Stream << InstARM32Pred::predString(Predicate);
546   return Stream;
547 }
548 
549 /// Instructions of the form x := op(y).
550 template <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix>
551 class InstARM32UnaryopGPR : public InstARM32Pred {
552   InstARM32UnaryopGPR() = delete;
553   InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
554   InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;
555 
556 public:
create(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)557   static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
558                                      CondARM32::Cond Predicate) {
559     return new (Func->allocate<InstARM32UnaryopGPR>())
560         InstARM32UnaryopGPR(Func, Dest, Src, Predicate);
561   }
emit(const Cfg * Func)562   void emit(const Cfg *Func) const override {
563     if (!BuildDefs::dump())
564       return;
565     emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix);
566   }
567   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)568   void dump(const Cfg *Func) const override {
569     if (!BuildDefs::dump())
570       return;
571     Ostream &Str = Func->getContext()->getStrDump();
572     dumpDest(Func);
573     Str << " = ";
574     dumpOpcodePred(Str, Opcode, getDest()->getType());
575     Str << " ";
576     dumpSources(Func);
577   }
classof(const Inst * Instr)578   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
579 
580 private:
InstARM32UnaryopGPR(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)581   InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
582                       CondARM32::Cond Predicate)
583       : InstARM32Pred(Func, K, 1, Dest, Predicate) {
584     addSource(Src);
585   }
586 
587   static const char *Opcode;
588 };
589 
590 /// Instructions of the form x := op(y), for vector/FP.
591 template <InstARM32::InstKindARM32 K>
592 class InstARM32UnaryopFP : public InstARM32Pred {
593   InstARM32UnaryopFP() = delete;
594   InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete;
595   InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete;
596 
597 public:
create(Cfg * Func,Variable * Dest,Variable * Src,CondARM32::Cond Predicate)598   static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src,
599                                     CondARM32::Cond Predicate) {
600     return new (Func->allocate<InstARM32UnaryopFP>())
601         InstARM32UnaryopFP(Func, Dest, Src, Predicate);
602   }
emit(const Cfg * Func)603   void emit(const Cfg *Func) const override {
604     if (!BuildDefs::dump())
605       return;
606     emitUnaryopFP(Opcode, Sign, this, Func);
607   }
608   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)609   void dump(const Cfg *Func) const override {
610     if (!BuildDefs::dump())
611       return;
612     Ostream &Str = Func->getContext()->getStrDump();
613     dumpDest(Func);
614     Str << " = ";
615     dumpOpcodePred(Str, Opcode, getDest()->getType());
616     Str << " ";
617     dumpSources(Func);
618   }
classof(const Inst * Instr)619   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
620 
621 protected:
InstARM32UnaryopFP(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)622   InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src,
623                      CondARM32::Cond Predicate)
624       : InstARM32Pred(Func, K, 1, Dest, Predicate) {
625     addSource(Src);
626   }
627 
628   FPSign Sign = FS_None;
629   static const char *Opcode;
630 };
631 
632 template <InstARM32::InstKindARM32 K>
633 class InstARM32UnaryopSignAwareFP : public InstARM32UnaryopFP<K> {
634   InstARM32UnaryopSignAwareFP() = delete;
635   InstARM32UnaryopSignAwareFP(const InstARM32UnaryopSignAwareFP &) = delete;
636   InstARM32UnaryopSignAwareFP &
637   operator=(const InstARM32UnaryopSignAwareFP &) = delete;
638 
639 public:
640   static InstARM32UnaryopSignAwareFP *
create(Cfg * Func,Variable * Dest,Variable * Src,CondARM32::Cond Predicate)641   create(Cfg *Func, Variable *Dest, Variable *Src, CondARM32::Cond Predicate) {
642     return new (Func->allocate<InstARM32UnaryopSignAwareFP>())
643         InstARM32UnaryopSignAwareFP(Func, Dest, Src, Predicate);
644   }
645   void emitIAS(const Cfg *Func) const override;
setSignType(InstARM32::FPSign SignType)646   void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; }
647 
648 private:
InstARM32UnaryopSignAwareFP(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)649   InstARM32UnaryopSignAwareFP(Cfg *Func, Variable *Dest, Operand *Src,
650                               CondARM32::Cond Predicate)
651       : InstARM32UnaryopFP<K>(Func, Dest, Src, Predicate) {}
652 };
653 
654 /// Instructions of the form x := x op y.
655 template <InstARM32::InstKindARM32 K>
656 class InstARM32TwoAddrGPR : public InstARM32Pred {
657   InstARM32TwoAddrGPR() = delete;
658   InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
659   InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
660 
661 public:
662   /// Dest must be a register.
create(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)663   static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
664                                      CondARM32::Cond Predicate) {
665     return new (Func->allocate<InstARM32TwoAddrGPR>())
666         InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
667   }
emit(const Cfg * Func)668   void emit(const Cfg *Func) const override {
669     if (!BuildDefs::dump())
670       return;
671     emitTwoAddr(Opcode, this, Func);
672   }
673   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)674   void dump(const Cfg *Func) const override {
675     if (!BuildDefs::dump())
676       return;
677     Ostream &Str = Func->getContext()->getStrDump();
678     dumpDest(Func);
679     Str << " = ";
680     dumpOpcodePred(Str, Opcode, getDest()->getType());
681     Str << " ";
682     dumpSources(Func);
683   }
classof(const Inst * Instr)684   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
685 
686 private:
InstARM32TwoAddrGPR(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)687   InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
688                       CondARM32::Cond Predicate)
689       : InstARM32Pred(Func, K, 2, Dest, Predicate) {
690     addSource(Dest);
691     addSource(Src);
692   }
693 
694   static const char *Opcode;
695 };
696 
697 /// Base class for load instructions.
698 template <InstARM32::InstKindARM32 K>
699 class InstARM32LoadBase : public InstARM32Pred {
700   InstARM32LoadBase() = delete;
701   InstARM32LoadBase(const InstARM32LoadBase &) = delete;
702   InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete;
703 
704 public:
create(Cfg * Func,Variable * Dest,Operand * Source,CondARM32::Cond Predicate)705   static InstARM32LoadBase *create(Cfg *Func, Variable *Dest, Operand *Source,
706                                    CondARM32::Cond Predicate) {
707     return new (Func->allocate<InstARM32LoadBase>())
708         InstARM32LoadBase(Func, Dest, Source, Predicate);
709   }
710   void emit(const Cfg *Func) const override;
711   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)712   void dump(const Cfg *Func) const override {
713     if (!BuildDefs::dump())
714       return;
715     Ostream &Str = Func->getContext()->getStrDump();
716     dumpOpcodePred(Str, Opcode, getDest()->getType());
717     Str << " ";
718     dumpDest(Func);
719     Str << ", ";
720     dumpSources(Func);
721   }
classof(const Inst * Instr)722   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
723 
724 private:
InstARM32LoadBase(Cfg * Func,Variable * Dest,Operand * Source,CondARM32::Cond Predicate)725   InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source,
726                     CondARM32::Cond Predicate)
727       : InstARM32Pred(Func, K, 1, Dest, Predicate) {
728     addSource(Source);
729   }
730 
731   static const char *Opcode;
732 };
733 
734 /// Instructions of the form x := y op z. May have the side-effect of setting
735 /// status flags.
736 template <InstARM32::InstKindARM32 K>
737 class InstARM32ThreeAddrGPR : public InstARM32Pred {
738   InstARM32ThreeAddrGPR() = delete;
739   InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
740   InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
741 
742 public:
743   /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
744   /// must be registers.
745   static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
746                                        Variable *Src0, Operand *Src1,
747                                        CondARM32::Cond Predicate,
748                                        bool SetFlags = false) {
749     return new (Func->allocate<InstARM32ThreeAddrGPR>())
750         InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
751   }
emit(const Cfg * Func)752   void emit(const Cfg *Func) const override {
753     if (!BuildDefs::dump())
754       return;
755     emitThreeAddr(Opcode, this, Func, SetFlags);
756   }
757   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)758   void dump(const Cfg *Func) const override {
759     if (!BuildDefs::dump())
760       return;
761     Ostream &Str = Func->getContext()->getStrDump();
762     dumpDest(Func);
763     Str << " = ";
764     dumpOpcodePred(Str, Opcode, getDest()->getType());
765     Str << (SetFlags ? ".s " : " ");
766     dumpSources(Func);
767   }
classof(const Inst * Instr)768   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
769 
770 private:
InstARM32ThreeAddrGPR(Cfg * Func,Variable * Dest,Variable * Src0,Operand * Src1,CondARM32::Cond Predicate,bool SetFlags)771   InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
772                         Operand *Src1, CondARM32::Cond Predicate, bool SetFlags)
773       : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) {
774     HasSideEffects = SetFlags;
775     addSource(Src0);
776     addSource(Src1);
777   }
778 
779   static const char *Opcode;
780   bool SetFlags;
781 };
782 
783 /// Instructions of the form x := y op z, for vector/FP. We leave these as
784 /// unconditional: "ARM deprecates the conditional execution of any instruction
785 /// encoding provided by the Advanced SIMD Extension that is not also provided
786 /// by the floating-point (VFP) extension". They do not set flags.
787 template <InstARM32::InstKindARM32 K>
788 class InstARM32ThreeAddrFP : public InstARM32 {
789   InstARM32ThreeAddrFP() = delete;
790   InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
791   InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;
792 
793 public:
794   /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
795   /// must be a register.
create(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)796   static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
797                                       Variable *Src1) {
798     return new (Func->allocate<InstARM32ThreeAddrFP>())
799         InstARM32ThreeAddrFP(Func, Dest, Src0, Src1);
800   }
emit(const Cfg * Func)801   void emit(const Cfg *Func) const override {
802     if (!BuildDefs::dump())
803       return;
804     const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
805     emitThreeAddrFP(Opcode, Sign, this, Func, OpType);
806   }
807   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)808   void dump(const Cfg *Func) const override {
809     if (!BuildDefs::dump())
810       return;
811     Ostream &Str = Func->getContext()->getStrDump();
812     dumpDest(Func);
813     const Type OpType = (isVectorCompare() ? getSrc(0) : getDest())->getType();
814     Str << " = " << Opcode << "." << OpType << " ";
815     dumpSources(Func);
816   }
classof(const Inst * Instr)817   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
818 
819 protected:
820   FPSign Sign = FS_None;
821 
InstARM32ThreeAddrFP(Cfg * Func,Variable * Dest,Variable * Src0,Operand * Src1)822   InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Operand *Src1)
823       : InstARM32(Func, K, 2, Dest) {
824     addSource(Src0);
825     addSource(Src1);
826   }
827 
828   static const char *Opcode;
829 
830 private:
isVectorCompare()831   static constexpr bool isVectorCompare() {
832     return K == InstARM32::Vceq || K == InstARM32::Vcgt || K == InstARM32::Vcge;
833   }
834 };
835 
836 template <InstARM32::InstKindARM32 K>
837 class InstARM32ThreeAddrSignAwareFP : public InstARM32ThreeAddrFP<K> {
838   InstARM32ThreeAddrSignAwareFP() = delete;
839   InstARM32ThreeAddrSignAwareFP(const InstARM32ThreeAddrSignAwareFP &) = delete;
840   InstARM32ThreeAddrSignAwareFP &
841   operator=(const InstARM32ThreeAddrSignAwareFP &) = delete;
842 
843 public:
844   /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
845   /// must be a register.
create(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)846   static InstARM32ThreeAddrSignAwareFP *create(Cfg *Func, Variable *Dest,
847                                                Variable *Src0, Variable *Src1) {
848     return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>())
849         InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1);
850   }
851 
852   static InstARM32ThreeAddrSignAwareFP *
create(Cfg * Func,Variable * Dest,Variable * Src0,ConstantInteger32 * Src1)853   create(Cfg *Func, Variable *Dest, Variable *Src0, ConstantInteger32 *Src1) {
854     return new (Func->allocate<InstARM32ThreeAddrSignAwareFP>())
855         InstARM32ThreeAddrSignAwareFP(Func, Dest, Src0, Src1);
856   }
857 
858   void emitIAS(const Cfg *Func) const override;
setSignType(InstARM32::FPSign SignType)859   void setSignType(InstARM32::FPSign SignType) { this->Sign = SignType; }
860 
861 private:
InstARM32ThreeAddrSignAwareFP(Cfg * Func,Variable * Dest,Variable * Src0,Operand * Src1)862   InstARM32ThreeAddrSignAwareFP(Cfg *Func, Variable *Dest, Variable *Src0,
863                                 Operand *Src1)
864       : InstARM32ThreeAddrFP<K>(Func, Dest, Src0, Src1) {}
865 };
866 
867 /// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
868 template <InstARM32::InstKindARM32 K>
869 class InstARM32FourAddrGPR : public InstARM32Pred {
870   InstARM32FourAddrGPR() = delete;
871   InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete;
872   InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete;
873 
874 public:
875   // Every operand must be a register.
create(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1,Variable * Src2,CondARM32::Cond Predicate)876   static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0,
877                                       Variable *Src1, Variable *Src2,
878                                       CondARM32::Cond Predicate) {
879     return new (Func->allocate<InstARM32FourAddrGPR>())
880         InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate);
881   }
emit(const Cfg * Func)882   void emit(const Cfg *Func) const override {
883     if (!BuildDefs::dump())
884       return;
885     emitFourAddr(Opcode, this, Func);
886   }
887   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)888   void dump(const Cfg *Func) const override {
889     if (!BuildDefs::dump())
890       return;
891     Ostream &Str = Func->getContext()->getStrDump();
892     dumpDest(Func);
893     Str << " = ";
894     dumpOpcodePred(Str, Opcode, getDest()->getType());
895     Str << " ";
896     dumpSources(Func);
897   }
classof(const Inst * Instr)898   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
899 
900 private:
InstARM32FourAddrGPR(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1,Variable * Src2,CondARM32::Cond Predicate)901   InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
902                        Variable *Src1, Variable *Src2,
903                        CondARM32::Cond Predicate)
904       : InstARM32Pred(Func, K, 3, Dest, Predicate) {
905     addSource(Src0);
906     addSource(Src1);
907     addSource(Src2);
908   }
909 
910   static const char *Opcode;
911 };
912 
913 /// Instructions of the form x := x op1 (y op2 z). E.g., multiply accumulate.
914 /// We leave these as unconditional: "ARM deprecates the conditional execution
915 /// of any instruction encoding provided by the Advanced SIMD Extension that is
916 /// not also provided by the floating-point (VFP) extension". They do not set
917 /// flags.
918 template <InstARM32::InstKindARM32 K>
919 class InstARM32FourAddrFP : public InstARM32 {
920   InstARM32FourAddrFP() = delete;
921   InstARM32FourAddrFP(const InstARM32FourAddrFP &) = delete;
922   InstARM32FourAddrFP &operator=(const InstARM32FourAddrFP &) = delete;
923 
924 public:
925   // Every operand must be a register.
create(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)926   static InstARM32FourAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
927                                      Variable *Src1) {
928     return new (Func->allocate<InstARM32FourAddrFP>())
929         InstARM32FourAddrFP(Func, Dest, Src0, Src1);
930   }
emit(const Cfg * Func)931   void emit(const Cfg *Func) const override {
932     if (!BuildDefs::dump())
933       return;
934     emitFourAddrFP(Opcode, Sign, this, Func);
935   }
936   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)937   void dump(const Cfg *Func) const override {
938     if (!BuildDefs::dump())
939       return;
940     Ostream &Str = Func->getContext()->getStrDump();
941     dumpDest(Func);
942     Str << " = ";
943     Str << Opcode << "." << getDest()->getType() << " ";
944     dumpDest(Func);
945     Str << ", ";
946     dumpSources(Func);
947   }
classof(const Inst * Instr)948   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
949 
950 private:
InstARM32FourAddrFP(Cfg * Func,Variable * Dest,Variable * Src0,Variable * Src1)951   InstARM32FourAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1)
952       : InstARM32(Func, K, 3, Dest) {
953     addSource(Dest);
954     addSource(Src0);
955     addSource(Src1);
956   }
957 
958   FPSign Sign = FS_None;
959   static const char *Opcode;
960 };
961 
962 /// Instructions of the form x cmpop y (setting flags).
963 template <InstARM32::InstKindARM32 K>
964 class InstARM32CmpLike : public InstARM32Pred {
965   InstARM32CmpLike() = delete;
966   InstARM32CmpLike(const InstARM32CmpLike &) = delete;
967   InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete;
968 
969 public:
create(Cfg * Func,Variable * Src0,Operand * Src1,CondARM32::Cond Predicate)970   static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1,
971                                   CondARM32::Cond Predicate) {
972     return new (Func->allocate<InstARM32CmpLike>())
973         InstARM32CmpLike(Func, Src0, Src1, Predicate);
974   }
emit(const Cfg * Func)975   void emit(const Cfg *Func) const override {
976     if (!BuildDefs::dump())
977       return;
978     emitCmpLike(Opcode, this, Func);
979   }
980   void emitIAS(const Cfg *Func) const override;
dump(const Cfg * Func)981   void dump(const Cfg *Func) const override {
982     if (!BuildDefs::dump())
983       return;
984     Ostream &Str = Func->getContext()->getStrDump();
985     dumpOpcodePred(Str, Opcode, getSrc(0)->getType());
986     Str << " ";
987     dumpSources(Func);
988   }
classof(const Inst * Instr)989   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
990 
991 private:
InstARM32CmpLike(Cfg * Func,Variable * Src0,Operand * Src1,CondARM32::Cond Predicate)992   InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1,
993                    CondARM32::Cond Predicate)
994       : InstARM32Pred(Func, K, 2, nullptr, Predicate) {
995     HasSideEffects = true;
996     addSource(Src0);
997     addSource(Src1);
998   }
999 
1000   static const char *Opcode;
1001 };
1002 
1003 using InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>;
1004 using InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>;
1005 using InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>;
1006 using InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>;
1007 using InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>;
1008 using InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>;
1009 using InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>;
1010 using InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>;
1011 using InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>;
1012 using InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>;
1013 using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>;
1014 using InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>;
1015 using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>;
1016 using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
1017 using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>;
1018 using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>;
1019 using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>;
1020 using InstARM32Vand = InstARM32ThreeAddrFP<InstARM32::Vand>;
1021 using InstARM32Vbsl = InstARM32ThreeAddrFP<InstARM32::Vbsl>;
1022 using InstARM32Vceq = InstARM32ThreeAddrFP<InstARM32::Vceq>;
1023 using InstARM32Vcge = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcge>;
1024 using InstARM32Vcgt = InstARM32ThreeAddrSignAwareFP<InstARM32::Vcgt>;
1025 using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>;
1026 using InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>;
1027 using InstARM32Vmla = InstARM32FourAddrFP<InstARM32::Vmla>;
1028 using InstARM32Vmls = InstARM32FourAddrFP<InstARM32::Vmls>;
1029 using InstARM32Vmovl = InstARM32ThreeAddrFP<InstARM32::Vmovl>;
1030 using InstARM32Vmovh = InstARM32ThreeAddrFP<InstARM32::Vmovh>;
1031 using InstARM32Vmovhl = InstARM32ThreeAddrFP<InstARM32::Vmovhl>;
1032 using InstARM32Vmovlh = InstARM32ThreeAddrFP<InstARM32::Vmovlh>;
1033 using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>;
1034 using InstARM32Vmvn = InstARM32UnaryopFP<InstARM32::Vmvn>;
1035 using InstARM32Vneg = InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
1036 using InstARM32Vorr = InstARM32ThreeAddrFP<InstARM32::Vorr>;
1037 using InstARM32Vqadd = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqadd>;
1038 using InstARM32Vqsub = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqsub>;
1039 using InstARM32Vqmovn2 = InstARM32ThreeAddrSignAwareFP<InstARM32::Vqmovn2>;
1040 using InstARM32Vmulh = InstARM32ThreeAddrSignAwareFP<InstARM32::Vmulh>;
1041 using InstARM32Vmlap = InstARM32ThreeAddrFP<InstARM32::Vmlap>;
1042 using InstARM32Vshl = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
1043 using InstARM32Vshr = InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
1044 using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>;
1045 using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>;
1046 using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>;
1047 using InstARM32Vldr1d = InstARM32LoadBase<InstARM32::Vldr1d>;
1048 using InstARM32Vldr1q = InstARM32LoadBase<InstARM32::Vldr1q>;
1049 using InstARM32Vzip = InstARM32ThreeAddrFP<InstARM32::Vzip>;
1050 /// MovT leaves the bottom bits alone so dest is also a source. This helps
1051 /// indicate that a previous MovW setting dest is not dead code.
1052 using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>;
1053 using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>;
1054 using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>;
1055 using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>;
1056 using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>;
1057 using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>;
1058 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand
1059 // as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't
1060 // using that for now, so just model as a Unaryop.
1061 using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>;
1062 using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>;
1063 using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>;
1064 using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>;
1065 using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>;
1066 using InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>;
1067 using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
1068 using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;
1069 
1070 // InstARM32Label represents an intra-block label that is the target of an
1071 // intra-block branch. The offset between the label and the branch must be fit
1072 // in the instruction immediate (considered "near").
1073 class InstARM32Label : public InstARM32 {
1074   InstARM32Label() = delete;
1075   InstARM32Label(const InstARM32Label &) = delete;
1076   InstARM32Label &operator=(const InstARM32Label &) = delete;
1077 
1078 public:
create(Cfg * Func,TargetARM32 * Target)1079   static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
1080     return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
1081   }
getEmitInstCount()1082   uint32_t getEmitInstCount() const override { return 0; }
getLabelName()1083   GlobalString getLabelName() const { return Name; }
getNumber()1084   SizeT getNumber() const { return Number; }
1085   void emit(const Cfg *Func) const override;
1086   void emitIAS(const Cfg *Func) const override;
1087   void dump(const Cfg *Func) const override;
setRelocOffset(RelocOffset * Value)1088   void setRelocOffset(RelocOffset *Value) { OffsetReloc = Value; }
1089 
1090 private:
1091   InstARM32Label(Cfg *Func, TargetARM32 *Target);
1092 
1093   RelocOffset *OffsetReloc = nullptr;
1094   SizeT Number; // used for unique label generation.
1095   GlobalString Name;
1096 };
1097 
1098 /// Direct branch instruction.
1099 class InstARM32Br : public InstARM32Pred {
1100   InstARM32Br() = delete;
1101   InstARM32Br(const InstARM32Br &) = delete;
1102   InstARM32Br &operator=(const InstARM32Br &) = delete;
1103 
1104 public:
1105   /// Create a conditional branch to one of two nodes.
create(Cfg * Func,CfgNode * TargetTrue,CfgNode * TargetFalse,CondARM32::Cond Predicate)1106   static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
1107                              CfgNode *TargetFalse, CondARM32::Cond Predicate) {
1108     assert(Predicate != CondARM32::AL);
1109     constexpr InstARM32Label *NoLabel = nullptr;
1110     return new (Func->allocate<InstARM32Br>())
1111         InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
1112   }
1113   /// Create an unconditional branch to a node.
create(Cfg * Func,CfgNode * Target)1114   static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
1115     constexpr CfgNode *NoCondTarget = nullptr;
1116     constexpr InstARM32Label *NoLabel = nullptr;
1117     return new (Func->allocate<InstARM32Br>())
1118         InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
1119   }
1120   /// Create a non-terminator conditional branch to a node, with a fallthrough
1121   /// to the next instruction in the current node. This is used for switch
1122   /// lowering.
create(Cfg * Func,CfgNode * Target,CondARM32::Cond Predicate)1123   static InstARM32Br *create(Cfg *Func, CfgNode *Target,
1124                              CondARM32::Cond Predicate) {
1125     assert(Predicate != CondARM32::AL);
1126     constexpr CfgNode *NoUncondTarget = nullptr;
1127     constexpr InstARM32Label *NoLabel = nullptr;
1128     return new (Func->allocate<InstARM32Br>())
1129         InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
1130   }
1131   // Create a conditional intra-block branch (or unconditional, if
1132   // Condition==AL) to a label in the current block.
create(Cfg * Func,InstARM32Label * Label,CondARM32::Cond Predicate)1133   static InstARM32Br *create(Cfg *Func, InstARM32Label *Label,
1134                              CondARM32::Cond Predicate) {
1135     constexpr CfgNode *NoCondTarget = nullptr;
1136     constexpr CfgNode *NoUncondTarget = nullptr;
1137     return new (Func->allocate<InstARM32Br>())
1138         InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate);
1139   }
getTargetTrue()1140   const CfgNode *getTargetTrue() const { return TargetTrue; }
getTargetFalse()1141   const CfgNode *getTargetFalse() const { return TargetFalse; }
1142   bool optimizeBranch(const CfgNode *NextNode);
getEmitInstCount()1143   uint32_t getEmitInstCount() const override {
1144     uint32_t Sum = 0;
1145     if (Label)
1146       ++Sum;
1147     if (getTargetTrue())
1148       ++Sum;
1149     if (getTargetFalse())
1150       ++Sum;
1151     return Sum;
1152   }
isUnconditionalBranch()1153   bool isUnconditionalBranch() const override {
1154     return getPredicate() == CondARM32::AL;
1155   }
1156   bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
1157   void emit(const Cfg *Func) const override;
1158   void emitIAS(const Cfg *Func) const override;
1159   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1160   static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
1161 
1162 private:
1163   InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
1164               const InstARM32Label *Label, CondARM32::Cond Predicate);
1165 
1166   const CfgNode *TargetTrue;
1167   const CfgNode *TargetFalse;
1168   const InstARM32Label *Label; // Intra-block branch target
1169 };
1170 
1171 /// Call instruction (bl/blx). Arguments should have already been pushed.
1172 /// Technically bl and the register form of blx can be predicated, but we'll
1173 /// leave that out until needed.
1174 class InstARM32Call : public InstARM32 {
1175   InstARM32Call() = delete;
1176   InstARM32Call(const InstARM32Call &) = delete;
1177   InstARM32Call &operator=(const InstARM32Call &) = delete;
1178 
1179 public:
create(Cfg * Func,Variable * Dest,Operand * CallTarget)1180   static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
1181     return new (Func->allocate<InstARM32Call>())
1182         InstARM32Call(Func, Dest, CallTarget);
1183   }
getCallTarget()1184   Operand *getCallTarget() const { return getSrc(0); }
1185   void emit(const Cfg *Func) const override;
1186   void emitIAS(const Cfg *Func) const override;
1187   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1188   static bool classof(const Inst *Instr) { return isClassof(Instr, Call); }
1189 
1190 private:
1191   InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
1192 };
1193 
1194 class InstARM32RegisterStackOp : public InstARM32 {
1195   InstARM32RegisterStackOp() = delete;
1196   InstARM32RegisterStackOp(const InstARM32RegisterStackOp &) = delete;
1197   InstARM32RegisterStackOp &
1198   operator=(const InstARM32RegisterStackOp &) = delete;
1199 
1200 public:
1201   void emit(const Cfg *Func) const override;
1202   void emitIAS(const Cfg *Func) const override;
1203   void dump(const Cfg *Func) const override;
1204 
1205 protected:
InstARM32RegisterStackOp(Cfg * Func,InstKindARM32 Kind,SizeT Maxsrcs,Variable * Dest)1206   InstARM32RegisterStackOp(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs,
1207                            Variable *Dest)
1208       : InstARM32(Func, Kind, Maxsrcs, Dest) {}
1209   void emitUsingForm(const Cfg *Func, const EmitForm Form) const;
1210   void emitGPRsAsText(const Cfg *Func) const;
1211   void emitSRegsAsText(const Cfg *Func, const Variable *BaseReg,
1212                        SizeT Regcount) const;
1213   void emitSRegsOp(const Cfg *Func, const EmitForm, const Variable *BaseReg,
1214                    SizeT RegCount, SizeT InstIndex) const;
getDumpOpcode()1215   virtual const char *getDumpOpcode() const { return getGPROpcode(); }
1216   virtual const char *getGPROpcode() const = 0;
1217   virtual const char *getSRegOpcode() const = 0;
1218   virtual Variable *getStackReg(SizeT Index) const = 0;
1219   virtual SizeT getNumStackRegs() const = 0;
1220   virtual void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1221                              const Variable *Reg) const = 0;
1222   virtual void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1223                                 IValueT Registers) const = 0;
1224   virtual void emitSRegs(const Cfg *Func, const EmitForm Form,
1225                          const Variable *BaseReg, SizeT RegCount) const = 0;
1226 };
1227 
1228 /// Pops a list of registers. It may be a list of GPRs, or a list of VFP "s"
1229 /// regs, but not both. In any case, the list must be sorted.
1230 class InstARM32Pop final : public InstARM32RegisterStackOp {
1231   InstARM32Pop() = delete;
1232   InstARM32Pop(const InstARM32Pop &) = delete;
1233   InstARM32Pop &operator=(const InstARM32Pop &) = delete;
1234 
1235 public:
create(Cfg * Func,const VarList & Dests)1236   static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
1237     return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
1238   }
classof(const Inst * Instr)1239   static bool classof(const Inst *Instr) { return isClassof(Instr, Pop); }
1240 
1241 private:
1242   InstARM32Pop(Cfg *Func, const VarList &Dests);
1243   virtual const char *getGPROpcode() const final;
1244   virtual const char *getSRegOpcode() const final;
1245   Variable *getStackReg(SizeT Index) const final;
1246   SizeT getNumStackRegs() const final;
1247   void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1248                      const Variable *Reg) const final;
1249   void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1250                         IValueT Registers) const final;
1251   void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1252                  SizeT RegCount) const final;
1253   VarList Dests;
1254 };
1255 
1256 /// Pushes a list of registers. Just like Pop (see above), the list may be of
1257 /// GPRs, or VFP "s" registers, but not both.
1258 class InstARM32Push final : public InstARM32RegisterStackOp {
1259   InstARM32Push() = delete;
1260   InstARM32Push(const InstARM32Push &) = delete;
1261   InstARM32Push &operator=(const InstARM32Push &) = delete;
1262 
1263 public:
create(Cfg * Func,const VarList & Srcs)1264   static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
1265     return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
1266   }
classof(const Inst * Instr)1267   static bool classof(const Inst *Instr) { return isClassof(Instr, Push); }
1268 
1269 private:
1270   InstARM32Push(Cfg *Func, const VarList &Srcs);
1271   const char *getGPROpcode() const final;
1272   const char *getSRegOpcode() const final;
1273   Variable *getStackReg(SizeT Index) const final;
1274   SizeT getNumStackRegs() const final;
1275   void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1276                      const Variable *Reg) const final;
1277   void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1278                         IValueT Registers) const final;
1279   void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1280                  SizeT RegCount) const final;
1281 };
1282 
1283 /// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
1284 /// register operand, but epilogue lowering will search for a Ret instead of a
1285 /// generic "bx". This instruction also takes a Source operand (for non-void
1286 /// returning functions) for liveness analysis, though a FakeUse before the ret
1287 /// would do just as well.
1288 ///
1289 /// NOTE: Even though "bx" can be predicated, for now leave out the predication
1290 /// since it's not yet known to be useful for Ret. That may complicate finding
1291 /// the terminator instruction if it's not guaranteed to be executed.
1292 class InstARM32Ret : public InstARM32 {
1293   InstARM32Ret() = delete;
1294   InstARM32Ret(const InstARM32Ret &) = delete;
1295   InstARM32Ret &operator=(const InstARM32Ret &) = delete;
1296 
1297 public:
1298   static InstARM32Ret *create(Cfg *Func, Variable *LR,
1299                               Variable *Source = nullptr) {
1300     return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
1301   }
1302   void emit(const Cfg *Func) const override;
1303   void emitIAS(const Cfg *Func) const override;
1304   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1305   static bool classof(const Inst *Instr) { return isClassof(Instr, Ret); }
1306 
1307 private:
1308   InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
1309 };
1310 
1311 /// Store instruction. It's important for liveness that there is no Dest operand
1312 /// (OperandARM32Mem instead of Dest Variable).
1313 class InstARM32Str final : public InstARM32Pred {
1314   InstARM32Str() = delete;
1315   InstARM32Str(const InstARM32Str &) = delete;
1316   InstARM32Str &operator=(const InstARM32Str &) = delete;
1317 
1318 public:
1319   /// Value must be a register.
create(Cfg * Func,Variable * Value,OperandARM32Mem * Mem,CondARM32::Cond Predicate)1320   static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1321                               CondARM32::Cond Predicate) {
1322     return new (Func->allocate<InstARM32Str>())
1323         InstARM32Str(Func, 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, Str); }
1329 
1330 private:
1331   InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1332                CondARM32::Cond Predicate);
1333 };
1334 
1335 /// Exclusive Store instruction. Like its non-exclusive sibling, it's important
1336 /// for liveness that there is no Dest operand (OperandARM32Mem instead of Dest
1337 /// Variable).
1338 class InstARM32Strex final : public InstARM32Pred {
1339   InstARM32Strex() = delete;
1340   InstARM32Strex(const InstARM32Strex &) = delete;
1341   InstARM32Strex &operator=(const InstARM32Strex &) = delete;
1342 
1343 public:
1344   /// Value must be a register.
create(Cfg * Func,Variable * Dest,Variable * Value,OperandARM32Mem * Mem,CondARM32::Cond Predicate)1345   static InstARM32Strex *create(Cfg *Func, Variable *Dest, Variable *Value,
1346                                 OperandARM32Mem *Mem,
1347                                 CondARM32::Cond Predicate) {
1348     return new (Func->allocate<InstARM32Strex>())
1349         InstARM32Strex(Func, Dest, Value, Mem, Predicate);
1350   }
1351   void emit(const Cfg *Func) const override;
1352   void emitIAS(const Cfg *Func) const override;
1353   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1354   static bool classof(const Inst *Instr) { return isClassof(Instr, Strex); }
1355 
1356 private:
1357   InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
1358                  OperandARM32Mem *Mem, CondARM32::Cond Predicate);
1359 };
1360 
1361 /// Sub-vector store instruction. It's important for liveness that there is no
1362 ///  Dest operand (OperandARM32Mem instead of Dest Variable).
1363 class InstARM32Vstr1 final : public InstARM32Pred {
1364   InstARM32Vstr1() = delete;
1365   InstARM32Vstr1(const InstARM32Vstr1 &) = delete;
1366   InstARM32Vstr1 &operator=(const InstARM32Vstr1 &) = delete;
1367 
1368 public:
1369   /// Value must be a register.
create(Cfg * Func,Variable * Value,OperandARM32Mem * Mem,CondARM32::Cond Predicate,SizeT Size)1370   static InstARM32Vstr1 *create(Cfg *Func, Variable *Value,
1371                                 OperandARM32Mem *Mem, CondARM32::Cond Predicate,
1372                                 SizeT Size) {
1373     return new (Func->allocate<InstARM32Vstr1>())
1374         InstARM32Vstr1(Func, Value, Mem, Predicate, Size);
1375   }
1376   void emit(const Cfg *Func) const override;
1377   void emitIAS(const Cfg *Func) const override;
1378   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1379   static bool classof(const Inst *Instr) { return isClassof(Instr, Vstr1); }
1380 
1381 private:
1382   InstARM32Vstr1(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1383                  CondARM32::Cond Predicate, SizeT Size);
1384 
1385   SizeT Size;
1386 };
1387 
1388 /// Vector element duplication/replication instruction.
1389 class InstARM32Vdup final : public InstARM32Pred {
1390   InstARM32Vdup() = delete;
1391   InstARM32Vdup(const InstARM32Vdup &) = delete;
1392   InstARM32Vdup &operator=(const InstARM32Vdup &) = delete;
1393 
1394 public:
1395   /// Value must be a register.
create(Cfg * Func,Variable * Dest,Variable * Src,IValueT Idx)1396   static InstARM32Vdup *create(Cfg *Func, Variable *Dest, Variable *Src,
1397                                IValueT Idx) {
1398     return new (Func->allocate<InstARM32Vdup>())
1399         InstARM32Vdup(Func, Dest, Src, Idx);
1400   }
1401   void emit(const Cfg *Func) const override;
1402   void emitIAS(const Cfg *Func) const override;
1403   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1404   static bool classof(const Inst *Instr) { return isClassof(Instr, Vdup); }
1405 
1406 private:
1407   InstARM32Vdup(Cfg *Func, Variable *Dest, Variable *Src, IValueT Idx);
1408 
1409   const IValueT Idx;
1410 };
1411 
1412 class InstARM32Trap : public InstARM32 {
1413   InstARM32Trap() = delete;
1414   InstARM32Trap(const InstARM32Trap &) = delete;
1415   InstARM32Trap &operator=(const InstARM32Trap &) = delete;
1416 
1417 public:
create(Cfg * Func)1418   static InstARM32Trap *create(Cfg *Func) {
1419     return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func);
1420   }
1421   void emit(const Cfg *Func) const override;
1422   void emitIAS(const Cfg *Func) const override;
1423   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1424   static bool classof(const Inst *Instr) { return isClassof(Instr, Trap); }
1425 
1426 private:
1427   explicit InstARM32Trap(Cfg *Func);
1428 };
1429 
1430 /// Unsigned Multiply Long: d.lo, d.hi := x * y
1431 class InstARM32Umull : public InstARM32Pred {
1432   InstARM32Umull() = delete;
1433   InstARM32Umull(const InstARM32Umull &) = delete;
1434   InstARM32Umull &operator=(const InstARM32Umull &) = delete;
1435 
1436 public:
1437   /// Everything must be a register.
create(Cfg * Func,Variable * DestLo,Variable * DestHi,Variable * Src0,Variable * Src1,CondARM32::Cond Predicate)1438   static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
1439                                 Variable *Src0, Variable *Src1,
1440                                 CondARM32::Cond Predicate) {
1441     return new (Func->allocate<InstARM32Umull>())
1442         InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
1443   }
1444   void emit(const Cfg *Func) const override;
1445   void emitIAS(const Cfg *Func) const override;
1446   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1447   static bool classof(const Inst *Instr) { return isClassof(Instr, Umull); }
1448 
1449 private:
1450   InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
1451                  Variable *Src1, CondARM32::Cond Predicate);
1452 
1453   Variable *DestHi;
1454 };
1455 
1456 /// Handles fp2int, int2fp, and fp2fp conversions.
1457 class InstARM32Vcvt final : public InstARM32Pred {
1458   InstARM32Vcvt() = delete;
1459   InstARM32Vcvt(const InstARM32Vcvt &) = delete;
1460   InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete;
1461 
1462 public:
1463   enum VcvtVariant {
1464     S2si,
1465     S2ui,
1466     Si2s,
1467     Ui2s,
1468     D2si,
1469     D2ui,
1470     Si2d,
1471     Ui2d,
1472     S2d,
1473     D2s,
1474     Vs2si,
1475     Vs2ui,
1476     Vsi2s,
1477     Vui2s,
1478   };
create(Cfg * Func,Variable * Dest,Variable * Src,VcvtVariant Variant,CondARM32::Cond Predicate)1479   static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src,
1480                                VcvtVariant Variant, CondARM32::Cond Predicate) {
1481     return new (Func->allocate<InstARM32Vcvt>())
1482         InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
1483   }
1484   void emit(const Cfg *Func) const override;
1485   void emitIAS(const Cfg *Func) const override;
1486   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1487   static bool classof(const Inst *Instr) { return isClassof(Instr, Vcvt); }
1488 
1489 private:
1490   InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
1491                 CondARM32::Cond Predicate);
1492 
1493   const VcvtVariant Variant;
1494 };
1495 
1496 /// Handles (some of) vmov's various formats.
1497 class InstARM32Mov final : public InstARM32Pred {
1498   InstARM32Mov() = delete;
1499   InstARM32Mov(const InstARM32Mov &) = delete;
1500   InstARM32Mov &operator=(const InstARM32Mov &) = delete;
1501 
1502 public:
create(Cfg * Func,Variable * Dest,Operand * Src,CondARM32::Cond Predicate)1503   static InstARM32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
1504                               CondARM32::Cond Predicate) {
1505     return new (Func->allocate<InstARM32Mov>())
1506         InstARM32Mov(Func, Dest, Src, Predicate);
1507   }
isRedundantAssign()1508   bool isRedundantAssign() const override {
1509     return !isMultiDest() && !isMultiSource() &&
1510            getPredicate() == CondARM32::AL &&
1511            checkForRedundantAssign(getDest(), getSrc(0));
1512   }
isVarAssign()1513   bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); }
1514   void emit(const Cfg *Func) const override;
1515   void emitIAS(const Cfg *Func) const override;
1516   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1517   static bool classof(const Inst *Instr) { return isClassof(Instr, Mov); }
1518 
isMultiDest()1519   bool isMultiDest() const { return DestHi != nullptr; }
1520 
isMultiSource()1521   bool isMultiSource() const {
1522     assert(getSrcSize() == 1 || getSrcSize() == 2);
1523     return getSrcSize() == 2;
1524   }
1525 
getDestHi()1526   Variable *getDestHi() const { return DestHi; }
1527 
1528 private:
1529   InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
1530                CondARM32::Cond Predicate);
1531   void emitMultiDestSingleSource(const Cfg *Func) const;
1532   void emitSingleDestMultiSource(const Cfg *Func) const;
1533   void emitSingleDestSingleSource(const Cfg *Func) const;
1534 
1535   Variable *DestHi = nullptr;
1536 };
1537 
1538 /// Generates vmov Rd, Dn[x] instructions, and their related floating point
1539 /// versions.
1540 class InstARM32Extract final : public InstARM32Pred {
1541   InstARM32Extract() = delete;
1542   InstARM32Extract(const InstARM32Extract &) = delete;
1543   InstARM32Extract &operator=(const InstARM32Extract &) = delete;
1544 
1545 public:
create(Cfg * Func,Variable * Dest,Variable * Src0,uint32_t Index,CondARM32::Cond Predicate)1546   static InstARM32Extract *create(Cfg *Func, Variable *Dest, Variable *Src0,
1547                                   uint32_t Index, CondARM32::Cond Predicate) {
1548     return new (Func->allocate<InstARM32Extract>())
1549         InstARM32Extract(Func, Dest, Src0, Index, Predicate);
1550   }
1551   void emit(const Cfg *Func) const override;
1552   void emitIAS(const Cfg *Func) const override;
classof(const Inst * Inst)1553   static bool classof(const Inst *Inst) { return isClassof(Inst, Extract); }
1554 
1555 private:
InstARM32Extract(Cfg * Func,Variable * Dest,Variable * Src0,uint32_t Index,CondARM32::Cond Predicate)1556   InstARM32Extract(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index,
1557                    CondARM32::Cond Predicate)
1558       : InstARM32Pred(Func, InstARM32::Extract, 1, Dest, Predicate),
1559         Index(Index) {
1560     assert(Index < typeNumElements(Src0->getType()));
1561     addSource(Src0);
1562   }
1563 
1564   const uint32_t Index;
1565 };
1566 
1567 /// Generates vmov Dn[x], Rd instructions, and their related floating point
1568 /// versions.
1569 class InstARM32Insert final : public InstARM32Pred {
1570   InstARM32Insert() = delete;
1571   InstARM32Insert(const InstARM32Insert &) = delete;
1572   InstARM32Insert &operator=(const InstARM32Insert &) = delete;
1573 
1574 public:
create(Cfg * Func,Variable * Dest,Variable * Src0,uint32_t Index,CondARM32::Cond Predicate)1575   static InstARM32Insert *create(Cfg *Func, Variable *Dest, Variable *Src0,
1576                                  uint32_t Index, CondARM32::Cond Predicate) {
1577     return new (Func->allocate<InstARM32Insert>())
1578         InstARM32Insert(Func, Dest, Src0, Index, Predicate);
1579   }
1580   void emit(const Cfg *Func) const override;
1581   void emitIAS(const Cfg *Func) const override;
classof(const Inst * Inst)1582   static bool classof(const Inst *Inst) { return isClassof(Inst, Insert); }
1583 
1584 private:
InstARM32Insert(Cfg * Func,Variable * Dest,Variable * Src0,uint32_t Index,CondARM32::Cond Predicate)1585   InstARM32Insert(Cfg *Func, Variable *Dest, Variable *Src0, uint32_t Index,
1586                   CondARM32::Cond Predicate)
1587       : InstARM32Pred(Func, InstARM32::Insert, 1, Dest, Predicate),
1588         Index(Index) {
1589     assert(Index < typeNumElements(Dest->getType()));
1590     addSource(Src0);
1591   }
1592 
1593   const uint32_t Index;
1594 };
1595 
1596 class InstARM32Vcmp final : public InstARM32Pred {
1597   InstARM32Vcmp() = delete;
1598   InstARM32Vcmp(const InstARM32Vcmp &) = delete;
1599   InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete;
1600 
1601 public:
create(Cfg * Func,Variable * Src0,Variable * Src1,CondARM32::Cond Predicate)1602   static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1,
1603                                CondARM32::Cond Predicate) {
1604     return new (Func->allocate<InstARM32Vcmp>())
1605         InstARM32Vcmp(Func, Src0, Src1, Predicate);
1606   }
create(Cfg * Func,Variable * Src0,OperandARM32FlexFpZero * Src1,CondARM32::Cond Predicate)1607   static InstARM32Vcmp *create(Cfg *Func, Variable *Src0,
1608                                OperandARM32FlexFpZero *Src1,
1609                                CondARM32::Cond Predicate) {
1610     return new (Func->allocate<InstARM32Vcmp>())
1611         InstARM32Vcmp(Func, Src0, Src1, Predicate);
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, Vcmp); }
1617 
1618 private:
1619   InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
1620                 CondARM32::Cond Predicate);
1621 };
1622 
1623 /// Copies the FP Status and Control Register the core flags.
1624 class InstARM32Vmrs final : public InstARM32Pred {
1625   InstARM32Vmrs() = delete;
1626   InstARM32Vmrs(const InstARM32Vmrs &) = delete;
1627   InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete;
1628 
1629 public:
create(Cfg * Func,CondARM32::Cond Predicate)1630   static InstARM32Vmrs *create(Cfg *Func, CondARM32::Cond Predicate) {
1631     return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate);
1632   }
1633   void emit(const Cfg *Func) const override;
1634   void emitIAS(const Cfg *Func) const override;
1635   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1636   static bool classof(const Inst *Instr) { return isClassof(Instr, Vmrs); }
1637 
1638 private:
1639   InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate);
1640 };
1641 
1642 class InstARM32Vabs final : public InstARM32Pred {
1643   InstARM32Vabs() = delete;
1644   InstARM32Vabs(const InstARM32Vabs &) = delete;
1645   InstARM32Vabs &operator=(const InstARM32Vabs &) = delete;
1646 
1647 public:
create(Cfg * Func,Variable * Dest,Variable * Src,CondARM32::Cond Predicate)1648   static InstARM32Vabs *create(Cfg *Func, Variable *Dest, Variable *Src,
1649                                CondARM32::Cond Predicate) {
1650     return new (Func->allocate<InstARM32Vabs>())
1651         InstARM32Vabs(Func, Dest, Src, Predicate);
1652   }
1653   void emit(const Cfg *Func) const override;
1654   void emitIAS(const Cfg *Func) const override;
1655   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1656   static bool classof(const Inst *Instr) { return isClassof(Instr, Vabs); }
1657 
1658 private:
1659   InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
1660                 CondARM32::Cond Predicate);
1661 };
1662 
1663 class InstARM32Dmb final : public InstARM32Pred {
1664   InstARM32Dmb() = delete;
1665   InstARM32Dmb(const InstARM32Dmb &) = delete;
1666   InstARM32Dmb &operator=(const InstARM32Dmb &) = delete;
1667 
1668 public:
create(Cfg * Func)1669   static InstARM32Dmb *create(Cfg *Func) {
1670     return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func);
1671   }
1672   void emit(const Cfg *Func) const override;
1673   void emitIAS(const Cfg *Func) const override;
1674   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1675   static bool classof(const Inst *Instr) { return isClassof(Instr, Dmb); }
1676 
1677 private:
1678   explicit InstARM32Dmb(Cfg *Func);
1679 };
1680 
1681 class InstARM32Nop final : public InstARM32Pred {
1682   InstARM32Nop() = delete;
1683   InstARM32Nop(const InstARM32Nop &) = delete;
1684   InstARM32Nop &operator=(const InstARM32Nop &) = delete;
1685 
1686 public:
create(Cfg * Func)1687   static InstARM32Nop *create(Cfg *Func) {
1688     return new (Func->allocate<InstARM32Nop>()) InstARM32Nop(Func);
1689   }
1690   void emit(const Cfg *Func) const override;
1691   void emitIAS(const Cfg *Func) const override;
1692   void dump(const Cfg *Func) const override;
classof(const Inst * Instr)1693   static bool classof(const Inst *Instr) { return isClassof(Instr, Nop); }
1694 
1695 private:
1696   explicit InstARM32Nop(Cfg *Func);
1697 };
1698 
1699 // Declare partial template specializations of emit() methods that already have
1700 // default implementations. Without this, there is the possibility of ODR
1701 // violations and link errors.
1702 
1703 template <> void InstARM32Ldr::emit(const Cfg *Func) const;
1704 template <> void InstARM32Movw::emit(const Cfg *Func) const;
1705 template <> void InstARM32Movt::emit(const Cfg *Func) const;
1706 template <> void InstARM32Vldr1d::emit(const Cfg *Func) const;
1707 template <> void InstARM32Vldr1q::emit(const Cfg *Func) const;
1708 
1709 } // end of namespace ARM32
1710 } // end of namespace Ice
1711 
1712 #endif // SUBZERO_SRC_ICEINSTARM32_H
1713