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