OSDN Git Service

Subzero: Cleanup Inst==>Instr.
[android-x86/external-swiftshader.git] / src / IceInstARM32.h
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
27 namespace Ice {
28 namespace ARM32 {
29
30 /// Encoding of an ARM 32-bit instruction.
31 using IValueT = uint32_t;
32
33 /// An Offset value (+/-) used in an ARM 32-bit instruction.
34 using IOffsetT = int32_t;
35
36 class TargetARM32;
37
38 /// OperandARM32 extends the Operand hierarchy. Its subclasses are
39 /// OperandARM32Mem and OperandARM32Flex.
40 class OperandARM32 : public Operand {
41   OperandARM32() = delete;
42   OperandARM32(const OperandARM32 &) = delete;
43   OperandARM32 &operator=(const OperandARM32 &) = delete;
44
45 public:
46   enum OperandKindARM32 {
47     k__Start = Operand::kTarget,
48     kMem,
49     kShAmtImm,
50     kFlexStart,
51     kFlexImm = kFlexStart,
52     kFlexFpImm,
53     kFlexFpZero,
54     kFlexReg,
55     kFlexEnd = kFlexReg
56   };
57
58   enum ShiftKind {
59     kNoShift = -1,
60 #define X(enum, emit) enum,
61     ICEINSTARM32SHIFT_TABLE
62 #undef X
63   };
64
65   using Operand::dump;
66   void dump(const Cfg *, Ostream &Str) const override {
67     if (BuildDefs::dump())
68       Str << "<OperandARM32>";
69   }
70
71 protected:
72   OperandARM32(OperandKindARM32 Kind, Type Ty)
73       : Operand(static_cast<OperandKind>(Kind), Ty) {}
74 };
75
76 /// OperandARM32Mem represents a memory operand in any of the various ARM32
77 /// addressing modes.
78 class OperandARM32Mem : public OperandARM32 {
79   OperandARM32Mem() = delete;
80   OperandARM32Mem(const OperandARM32Mem &) = delete;
81   OperandARM32Mem &operator=(const OperandARM32Mem &) = delete;
82
83 public:
84   /// Memory operand addressing mode.
85   /// The enum value also carries the encoding.
86   // TODO(jvoung): unify with the assembler.
87   enum AddrMode {
88     // bit encoding P U 0 W
89     Offset = (8 | 4 | 0) << 21,      // offset (w/o writeback to base)
90     PreIndex = (8 | 4 | 1) << 21,    // pre-indexed addressing with writeback
91     PostIndex = (0 | 4 | 0) << 21,   // post-indexed addressing with writeback
92     NegOffset = (8 | 0 | 0) << 21,   // negative offset (w/o writeback to base)
93     NegPreIndex = (8 | 0 | 1) << 21, // negative pre-indexed with writeback
94     NegPostIndex = (0 | 0 | 0) << 21 // negative post-indexed with writeback
95   };
96
97   /// Provide two constructors.
98   /// NOTE: The Variable-typed operands have to be registers.
99   ///
100   /// (1) Reg + Imm. The Immediate actually has a limited number of bits
101   /// for encoding, so check canHoldOffset first. It cannot handle general
102   /// Constant operands like ConstantRelocatable, since a relocatable can
103   /// potentially take up too many bits.
104   static OperandARM32Mem *create(Cfg *Func, Type Ty, Variable *Base,
105                                  ConstantInteger32 *ImmOffset,
106                                  AddrMode Mode = Offset) {
107     return new (Func->allocate<OperandARM32Mem>())
108         OperandARM32Mem(Func, Ty, Base, ImmOffset, Mode);
109   }
110   /// (2) Reg +/- Reg with an optional shift of some kind and amount. Note that
111   /// this mode is disallowed in the NaCl sandbox.
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   }
119   Variable *getBase() const { return Base; }
120   ConstantInteger32 *getOffset() const { return ImmOffset; }
121   Variable *getIndex() const { return Index; }
122   ShiftKind getShiftOp() const { return ShiftOp; }
123   uint16_t getShiftAmt() const { return ShiftAmt; }
124   AddrMode getAddrMode() const { return Mode; }
125
126   bool isRegReg() const { return Index != nullptr; }
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
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:
173   static OperandARM32ShAmtImm *create(Cfg *Func, ConstantInteger32 *ShAmt) {
174     return new (Func->allocate<OperandARM32ShAmtImm>())
175         OperandARM32ShAmtImm(ShAmt);
176   }
177
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
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:
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:
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
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
236   uint32_t getImm() const { return Imm; }
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:
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
263   static bool classof(const Operand *Operand) {
264     return Operand->getKind() == static_cast<OperandKind>(kFlexFpImm);
265   }
266
267   static bool canHoldImm(Operand *C, uint32_t *ModifiedImm);
268
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:
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
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.
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
319   static bool classof(const Operand *Operand) {
320     return Operand->getKind() == static_cast<OperandKind>(kFlexReg);
321   }
322
323   Variable *getReg() const { return Reg; }
324   ShiftKind getShiftOp() const { return ShiftOp; }
325   /// ShiftAmt can represent an immediate or a register.
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:
348   static StackVariable *create(Cfg *Func, Type Ty, SizeT Index) {
349     return new (Func->allocate<StackVariable>()) StackVariable(Ty, Index);
350   }
351   const static OperandKind StackVariableKind =
352       static_cast<OperandKind>(kVariable_Target);
353   static bool classof(const Operand *Operand) {
354     return Operand->getKind() == StackVariableKind;
355   }
356   void setBaseRegNum(int32_t RegNum) { BaseRegNum = RegNum; }
357   int32_t getBaseRegNum() const override { return BaseRegNum; }
358   // Inherit dump() and emit() from Variable.
359
360 private:
361   StackVariable(Type Ty, SizeT Index)
362       : Variable(StackVariableKind, Ty, Index) {}
363   int32_t BaseRegNum = Variable::NoRegister;
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     Label,
393     Ldr,
394     Ldrex,
395     Lsl,
396     Lsr,
397     Mla,
398     Mls,
399     Mov,
400     Movt,
401     Movw,
402     Mul,
403     Mvn,
404     Orr,
405     Pop,
406     Push,
407     Rbit,
408     Ret,
409     Rev,
410     Rsb,
411     Rsc,
412     Sbc,
413     Sdiv,
414     Str,
415     Strex,
416     Sub,
417     Sxt,
418     Trap,
419     Tst,
420     Udiv,
421     Umull,
422     Uxt,
423     Vabs,
424     Vadd,
425     Vand,
426     Vcmp,
427     Vcvt,
428     Vdiv,
429     Veor,
430     Vmla,
431     Vmls,
432     Vmrs,
433     Vmul,
434     Vorr,
435     Vsqrt,
436     Vsub
437   };
438
439   static constexpr size_t InstSize = sizeof(uint32_t);
440
441   static const char *getWidthString(Type Ty);
442   static const char *getVecWidthString(Type Ty);
443   static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond);
444
445   /// Called inside derived methods emit() to communicate that multiple
446   /// instructions are being generated. Used by emitIAS() methods to
447   /// generate textual fixups for instructions that are not yet
448   /// implemented.
449   void startNextInst(const Cfg *Func) const;
450
451   /// Shared emit routines for common forms of instructions.
452   static void emitThreeAddrFP(const char *Opcode, const InstARM32 *Instr,
453                               const Cfg *Func);
454   static void emitFourAddrFP(const char *Opcode, const InstARM32 *Instr,
455                              const Cfg *Func);
456
457   void dump(const Cfg *Func) const override;
458
459   void emitIAS(const Cfg *Func) const override;
460
461 protected:
462   InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest)
463       : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
464
465   static bool isClassof(const Inst *Instr, InstKindARM32 MyKind) {
466     return Instr->getKind() == static_cast<InstKind>(MyKind);
467   }
468
469   // Generates text of assembly instruction using method emit(), and then adds
470   // to the assembly buffer as a Fixup.
471   void emitUsingTextFixup(const Cfg *Func) const;
472 };
473
474 /// A predicable ARM instruction.
475 class InstARM32Pred : public InstARM32 {
476   InstARM32Pred() = delete;
477   InstARM32Pred(const InstARM32Pred &) = delete;
478   InstARM32Pred &operator=(const InstARM32Pred &) = delete;
479
480 public:
481   InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest,
482                 CondARM32::Cond Predicate)
483       : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {}
484
485   CondARM32::Cond getPredicate() const { return Predicate; }
486   void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; }
487
488   static const char *predString(CondARM32::Cond Predicate);
489   void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const;
490
491   /// Shared emit routines for common forms of instructions.
492   static void emitUnaryopGPR(const char *Opcode, const InstARM32Pred *Instr,
493                              const Cfg *Func, bool NeedsWidthSuffix);
494   static void emitUnaryopFP(const char *Opcode, const InstARM32Pred *Instr,
495                             const Cfg *Func);
496   static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Instr,
497                           const Cfg *Func);
498   static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Instr,
499                             const Cfg *Func, bool SetFlags);
500   static void emitFourAddr(const char *Opcode, const InstARM32Pred *Instr,
501                            const Cfg *Func);
502   static void emitCmpLike(const char *Opcode, const InstARM32Pred *Instr,
503                           const Cfg *Func);
504
505 protected:
506   CondARM32::Cond Predicate;
507 };
508
509 template <typename StreamType>
510 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) {
511   Stream << InstARM32Pred::predString(Predicate);
512   return Stream;
513 }
514
515 /// Instructions of the form x := op(y).
516 template <InstARM32::InstKindARM32 K, bool NeedsWidthSuffix>
517 class InstARM32UnaryopGPR : public InstARM32Pred {
518   InstARM32UnaryopGPR() = delete;
519   InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete;
520   InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete;
521
522 public:
523   static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
524                                      CondARM32::Cond Predicate) {
525     return new (Func->allocate<InstARM32UnaryopGPR>())
526         InstARM32UnaryopGPR(Func, Dest, Src, Predicate);
527   }
528   void emit(const Cfg *Func) const override {
529     if (!BuildDefs::dump())
530       return;
531     emitUnaryopGPR(Opcode, this, Func, NeedsWidthSuffix);
532   }
533   void emitIAS(const Cfg *Func) const override;
534   void dump(const Cfg *Func) const override {
535     if (!BuildDefs::dump())
536       return;
537     Ostream &Str = Func->getContext()->getStrDump();
538     dumpDest(Func);
539     Str << " = ";
540     dumpOpcodePred(Str, Opcode, getDest()->getType());
541     Str << " ";
542     dumpSources(Func);
543   }
544   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
545
546 private:
547   InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src,
548                       CondARM32::Cond Predicate)
549       : InstARM32Pred(Func, K, 1, Dest, Predicate) {
550     addSource(Src);
551   }
552
553   static const char *Opcode;
554 };
555
556 /// Instructions of the form x := op(y), for vector/FP.
557 template <InstARM32::InstKindARM32 K>
558 class InstARM32UnaryopFP : public InstARM32Pred {
559   InstARM32UnaryopFP() = delete;
560   InstARM32UnaryopFP(const InstARM32UnaryopFP &) = delete;
561   InstARM32UnaryopFP &operator=(const InstARM32UnaryopFP &) = delete;
562
563 public:
564   static InstARM32UnaryopFP *create(Cfg *Func, Variable *Dest, Variable *Src,
565                                     CondARM32::Cond Predicate) {
566     return new (Func->allocate<InstARM32UnaryopFP>())
567         InstARM32UnaryopFP(Func, Dest, Src, Predicate);
568   }
569   void emit(const Cfg *Func) const override {
570     if (!BuildDefs::dump())
571       return;
572     emitUnaryopFP(Opcode, this, Func);
573   }
574   void emitIAS(const Cfg *Func) const override;
575   void dump(const Cfg *Func) const override {
576     if (!BuildDefs::dump())
577       return;
578     Ostream &Str = Func->getContext()->getStrDump();
579     dumpDest(Func);
580     Str << " = ";
581     dumpOpcodePred(Str, Opcode, getDest()->getType());
582     Str << " ";
583     dumpSources(Func);
584   }
585   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
586
587 private:
588   InstARM32UnaryopFP(Cfg *Func, Variable *Dest, Operand *Src,
589                      CondARM32::Cond Predicate)
590       : InstARM32Pred(Func, K, 1, Dest, Predicate) {
591     addSource(Src);
592   }
593
594   static const char *Opcode;
595 };
596
597 /// Instructions of the form x := x op y.
598 template <InstARM32::InstKindARM32 K>
599 class InstARM32TwoAddrGPR : public InstARM32Pred {
600   InstARM32TwoAddrGPR() = delete;
601   InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete;
602   InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete;
603
604 public:
605   /// Dest must be a register.
606   static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src,
607                                      CondARM32::Cond Predicate) {
608     return new (Func->allocate<InstARM32TwoAddrGPR>())
609         InstARM32TwoAddrGPR(Func, Dest, Src, Predicate);
610   }
611   void emit(const Cfg *Func) const override {
612     if (!BuildDefs::dump())
613       return;
614     emitTwoAddr(Opcode, this, Func);
615   }
616   void emitIAS(const Cfg *Func) const override;
617   void dump(const Cfg *Func) const override {
618     if (!BuildDefs::dump())
619       return;
620     Ostream &Str = Func->getContext()->getStrDump();
621     dumpDest(Func);
622     Str << " = ";
623     dumpOpcodePred(Str, Opcode, getDest()->getType());
624     Str << " ";
625     dumpSources(Func);
626   }
627   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
628
629 private:
630   InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src,
631                       CondARM32::Cond Predicate)
632       : InstARM32Pred(Func, K, 2, Dest, Predicate) {
633     addSource(Dest);
634     addSource(Src);
635   }
636
637   static const char *Opcode;
638 };
639
640 /// Base class for load instructions.
641 template <InstARM32::InstKindARM32 K>
642 class InstARM32LoadBase : public InstARM32Pred {
643   InstARM32LoadBase() = delete;
644   InstARM32LoadBase(const InstARM32LoadBase &) = delete;
645   InstARM32LoadBase &operator=(const InstARM32LoadBase &) = delete;
646
647 public:
648   static InstARM32LoadBase *create(Cfg *Func, Variable *Dest, Operand *Source,
649                                    CondARM32::Cond Predicate) {
650     return new (Func->allocate<InstARM32LoadBase>())
651         InstARM32LoadBase(Func, Dest, Source, Predicate);
652   }
653   void emit(const Cfg *Func) const override;
654   void emitIAS(const Cfg *Func) const override;
655   void dump(const Cfg *Func) const override {
656     if (!BuildDefs::dump())
657       return;
658     Ostream &Str = Func->getContext()->getStrDump();
659     dumpOpcodePred(Str, Opcode, getDest()->getType());
660     Str << " ";
661     dumpDest(Func);
662     Str << ", ";
663     dumpSources(Func);
664   }
665   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
666
667 private:
668   InstARM32LoadBase(Cfg *Func, Variable *Dest, Operand *Source,
669                     CondARM32::Cond Predicate)
670       : InstARM32Pred(Func, K, 1, Dest, Predicate) {
671     addSource(Source);
672   }
673
674   static const char *Opcode;
675 };
676
677 /// Instructions of the form x := y op z. May have the side-effect of setting
678 /// status flags.
679 template <InstARM32::InstKindARM32 K>
680 class InstARM32ThreeAddrGPR : public InstARM32Pred {
681   InstARM32ThreeAddrGPR() = delete;
682   InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete;
683   InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete;
684
685 public:
686   /// Create an ordinary binary-op instruction like add, and sub. Dest and Src1
687   /// must be registers.
688   static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest,
689                                        Variable *Src0, Operand *Src1,
690                                        CondARM32::Cond Predicate,
691                                        bool SetFlags = false) {
692     return new (Func->allocate<InstARM32ThreeAddrGPR>())
693         InstARM32ThreeAddrGPR(Func, Dest, Src0, Src1, Predicate, SetFlags);
694   }
695   void emit(const Cfg *Func) const override {
696     if (!BuildDefs::dump())
697       return;
698     emitThreeAddr(Opcode, this, Func, SetFlags);
699   }
700   void emitIAS(const Cfg *Func) const override;
701   void dump(const Cfg *Func) const override {
702     if (!BuildDefs::dump())
703       return;
704     Ostream &Str = Func->getContext()->getStrDump();
705     dumpDest(Func);
706     Str << " = ";
707     dumpOpcodePred(Str, Opcode, getDest()->getType());
708     Str << (SetFlags ? ".s " : " ");
709     dumpSources(Func);
710   }
711   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
712
713 private:
714   InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
715                         Operand *Src1, CondARM32::Cond Predicate, bool SetFlags)
716       : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) {
717     HasSideEffects = SetFlags;
718     addSource(Src0);
719     addSource(Src1);
720   }
721
722   static const char *Opcode;
723   bool SetFlags;
724 };
725
726 /// Instructions of the form x := y op z, for vector/FP. We leave these as
727 /// unconditional: "ARM deprecates the conditional execution of any instruction
728 /// encoding provided by the Advanced SIMD Extension that is not also provided
729 /// by the floating-point (VFP) extension". They do not set flags.
730 template <InstARM32::InstKindARM32 K>
731 class InstARM32ThreeAddrFP : public InstARM32 {
732   InstARM32ThreeAddrFP() = delete;
733   InstARM32ThreeAddrFP(const InstARM32ThreeAddrFP &) = delete;
734   InstARM32ThreeAddrFP &operator=(const InstARM32ThreeAddrFP &) = delete;
735
736 public:
737   /// Create a vector/FP binary-op instruction like vadd, and vsub. Everything
738   /// must be a register.
739   static InstARM32ThreeAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
740                                       Variable *Src1) {
741     return new (Func->allocate<InstARM32ThreeAddrFP>())
742         InstARM32ThreeAddrFP(Func, Dest, Src0, Src1);
743   }
744   void emit(const Cfg *Func) const override {
745     if (!BuildDefs::dump())
746       return;
747     emitThreeAddrFP(Opcode, this, Func);
748   }
749   void emitIAS(const Cfg *Func) const override;
750   void dump(const Cfg *Func) const override {
751     if (!BuildDefs::dump())
752       return;
753     Ostream &Str = Func->getContext()->getStrDump();
754     dumpDest(Func);
755     Str << " = ";
756     Str << Opcode << "." << getDest()->getType() << " ";
757     dumpSources(Func);
758   }
759   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
760
761 private:
762   InstARM32ThreeAddrFP(Cfg *Func, Variable *Dest, Variable *Src0,
763                        Variable *Src1)
764       : InstARM32(Func, K, 2, Dest) {
765     addSource(Src0);
766     addSource(Src1);
767   }
768
769   static const char *Opcode;
770 };
771
772 /// Instructions of the form x := a op1 (y op2 z). E.g., multiply accumulate.
773 template <InstARM32::InstKindARM32 K>
774 class InstARM32FourAddrGPR : public InstARM32Pred {
775   InstARM32FourAddrGPR() = delete;
776   InstARM32FourAddrGPR(const InstARM32FourAddrGPR &) = delete;
777   InstARM32FourAddrGPR &operator=(const InstARM32FourAddrGPR &) = delete;
778
779 public:
780   // Every operand must be a register.
781   static InstARM32FourAddrGPR *create(Cfg *Func, Variable *Dest, Variable *Src0,
782                                       Variable *Src1, Variable *Src2,
783                                       CondARM32::Cond Predicate) {
784     return new (Func->allocate<InstARM32FourAddrGPR>())
785         InstARM32FourAddrGPR(Func, Dest, Src0, Src1, Src2, Predicate);
786   }
787   void emit(const Cfg *Func) const override {
788     if (!BuildDefs::dump())
789       return;
790     emitFourAddr(Opcode, this, Func);
791   }
792   void emitIAS(const Cfg *Func) const override;
793   void dump(const Cfg *Func) const override {
794     if (!BuildDefs::dump())
795       return;
796     Ostream &Str = Func->getContext()->getStrDump();
797     dumpDest(Func);
798     Str << " = ";
799     dumpOpcodePred(Str, Opcode, getDest()->getType());
800     Str << " ";
801     dumpSources(Func);
802   }
803   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
804
805 private:
806   InstARM32FourAddrGPR(Cfg *Func, Variable *Dest, Variable *Src0,
807                        Variable *Src1, Variable *Src2,
808                        CondARM32::Cond Predicate)
809       : InstARM32Pred(Func, K, 3, Dest, Predicate) {
810     addSource(Src0);
811     addSource(Src1);
812     addSource(Src2);
813   }
814
815   static const char *Opcode;
816 };
817
818 /// Instructions of the form x := x op1 (y op2 z). E.g., multiply accumulate.
819 /// We leave these as unconditional: "ARM deprecates the conditional execution
820 /// of any instruction encoding provided by the Advanced SIMD Extension that is
821 /// not also provided by the floating-point (VFP) extension". They do not set
822 /// flags.
823 template <InstARM32::InstKindARM32 K>
824 class InstARM32FourAddrFP : public InstARM32 {
825   InstARM32FourAddrFP() = delete;
826   InstARM32FourAddrFP(const InstARM32FourAddrFP &) = delete;
827   InstARM32FourAddrFP &operator=(const InstARM32FourAddrFP &) = delete;
828
829 public:
830   // Every operand must be a register.
831   static InstARM32FourAddrFP *create(Cfg *Func, Variable *Dest, Variable *Src0,
832                                      Variable *Src1) {
833     return new (Func->allocate<InstARM32FourAddrFP>())
834         InstARM32FourAddrFP(Func, Dest, Src0, Src1);
835   }
836   void emit(const Cfg *Func) const override {
837     if (!BuildDefs::dump())
838       return;
839     emitFourAddrFP(Opcode, this, Func);
840   }
841   void emitIAS(const Cfg *Func) const override;
842   void dump(const Cfg *Func) const override {
843     if (!BuildDefs::dump())
844       return;
845     Ostream &Str = Func->getContext()->getStrDump();
846     dumpDest(Func);
847     Str << " = ";
848     Str << Opcode << "." << getDest()->getType() << " ";
849     dumpDest(Func);
850     Str << ", ";
851     dumpSources(Func);
852   }
853   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
854
855 private:
856   InstARM32FourAddrFP(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1)
857       : InstARM32(Func, K, 3, Dest) {
858     addSource(Dest);
859     addSource(Src0);
860     addSource(Src1);
861   }
862
863   static const char *Opcode;
864 };
865
866 /// Instructions of the form x cmpop y (setting flags).
867 template <InstARM32::InstKindARM32 K>
868 class InstARM32CmpLike : public InstARM32Pred {
869   InstARM32CmpLike() = delete;
870   InstARM32CmpLike(const InstARM32CmpLike &) = delete;
871   InstARM32CmpLike &operator=(const InstARM32CmpLike &) = delete;
872
873 public:
874   static InstARM32CmpLike *create(Cfg *Func, Variable *Src0, Operand *Src1,
875                                   CondARM32::Cond Predicate) {
876     return new (Func->allocate<InstARM32CmpLike>())
877         InstARM32CmpLike(Func, Src0, Src1, Predicate);
878   }
879   void emit(const Cfg *Func) const override {
880     if (!BuildDefs::dump())
881       return;
882     emitCmpLike(Opcode, this, Func);
883   }
884   void emitIAS(const Cfg *Func) const override;
885   void dump(const Cfg *Func) const override {
886     if (!BuildDefs::dump())
887       return;
888     Ostream &Str = Func->getContext()->getStrDump();
889     dumpOpcodePred(Str, Opcode, getSrc(0)->getType());
890     Str << " ";
891     dumpSources(Func);
892   }
893   static bool classof(const Inst *Instr) { return isClassof(Instr, K); }
894
895 private:
896   InstARM32CmpLike(Cfg *Func, Variable *Src0, Operand *Src1,
897                    CondARM32::Cond Predicate)
898       : InstARM32Pred(Func, K, 2, nullptr, Predicate) {
899     HasSideEffects = true;
900     addSource(Src0);
901     addSource(Src1);
902   }
903
904   static const char *Opcode;
905 };
906
907 using InstARM32Adc = InstARM32ThreeAddrGPR<InstARM32::Adc>;
908 using InstARM32Add = InstARM32ThreeAddrGPR<InstARM32::Add>;
909 using InstARM32And = InstARM32ThreeAddrGPR<InstARM32::And>;
910 using InstARM32Asr = InstARM32ThreeAddrGPR<InstARM32::Asr>;
911 using InstARM32Bic = InstARM32ThreeAddrGPR<InstARM32::Bic>;
912 using InstARM32Eor = InstARM32ThreeAddrGPR<InstARM32::Eor>;
913 using InstARM32Lsl = InstARM32ThreeAddrGPR<InstARM32::Lsl>;
914 using InstARM32Lsr = InstARM32ThreeAddrGPR<InstARM32::Lsr>;
915 using InstARM32Mul = InstARM32ThreeAddrGPR<InstARM32::Mul>;
916 using InstARM32Orr = InstARM32ThreeAddrGPR<InstARM32::Orr>;
917 using InstARM32Rsb = InstARM32ThreeAddrGPR<InstARM32::Rsb>;
918 using InstARM32Rsc = InstARM32ThreeAddrGPR<InstARM32::Rsc>;
919 using InstARM32Sbc = InstARM32ThreeAddrGPR<InstARM32::Sbc>;
920 using InstARM32Sdiv = InstARM32ThreeAddrGPR<InstARM32::Sdiv>;
921 using InstARM32Sub = InstARM32ThreeAddrGPR<InstARM32::Sub>;
922 using InstARM32Udiv = InstARM32ThreeAddrGPR<InstARM32::Udiv>;
923 using InstARM32Vadd = InstARM32ThreeAddrFP<InstARM32::Vadd>;
924 using InstARM32Vand = InstARM32ThreeAddrFP<InstARM32::Vand>;
925 using InstARM32Vdiv = InstARM32ThreeAddrFP<InstARM32::Vdiv>;
926 using InstARM32Veor = InstARM32ThreeAddrFP<InstARM32::Veor>;
927 using InstARM32Vmla = InstARM32FourAddrFP<InstARM32::Vmla>;
928 using InstARM32Vmls = InstARM32FourAddrFP<InstARM32::Vmls>;
929 using InstARM32Vmul = InstARM32ThreeAddrFP<InstARM32::Vmul>;
930 using InstARM32Vorr = InstARM32ThreeAddrFP<InstARM32::Vorr>;
931 using InstARM32Vsub = InstARM32ThreeAddrFP<InstARM32::Vsub>;
932 using InstARM32Ldr = InstARM32LoadBase<InstARM32::Ldr>;
933 using InstARM32Ldrex = InstARM32LoadBase<InstARM32::Ldrex>;
934 /// MovT leaves the bottom bits alone so dest is also a source. This helps
935 /// indicate that a previous MovW setting dest is not dead code.
936 using InstARM32Movt = InstARM32TwoAddrGPR<InstARM32::Movt>;
937 using InstARM32Movw = InstARM32UnaryopGPR<InstARM32::Movw, false>;
938 using InstARM32Clz = InstARM32UnaryopGPR<InstARM32::Clz, false>;
939 using InstARM32Mvn = InstARM32UnaryopGPR<InstARM32::Mvn, false>;
940 using InstARM32Rbit = InstARM32UnaryopGPR<InstARM32::Rbit, false>;
941 using InstARM32Rev = InstARM32UnaryopGPR<InstARM32::Rev, false>;
942 // Technically, the uxt{b,h} and sxt{b,h} instructions have a rotation operand
943 // as well (rotate source by 8, 16, 24 bits prior to extending), but we aren't
944 // using that for now, so just model as a Unaryop.
945 using InstARM32Sxt = InstARM32UnaryopGPR<InstARM32::Sxt, true>;
946 using InstARM32Uxt = InstARM32UnaryopGPR<InstARM32::Uxt, true>;
947 using InstARM32Vsqrt = InstARM32UnaryopFP<InstARM32::Vsqrt>;
948 using InstARM32Mla = InstARM32FourAddrGPR<InstARM32::Mla>;
949 using InstARM32Mls = InstARM32FourAddrGPR<InstARM32::Mls>;
950 using InstARM32Cmn = InstARM32CmpLike<InstARM32::Cmn>;
951 using InstARM32Cmp = InstARM32CmpLike<InstARM32::Cmp>;
952 using InstARM32Tst = InstARM32CmpLike<InstARM32::Tst>;
953
954 // InstARM32Label represents an intra-block label that is the target of an
955 // intra-block branch. The offset between the label and the branch must be fit
956 // in the instruction immediate (considered "near").
957 class InstARM32Label : public InstARM32 {
958   InstARM32Label() = delete;
959   InstARM32Label(const InstARM32Label &) = delete;
960   InstARM32Label &operator=(const InstARM32Label &) = delete;
961
962 public:
963   static InstARM32Label *create(Cfg *Func, TargetARM32 *Target) {
964     return new (Func->allocate<InstARM32Label>()) InstARM32Label(Func, Target);
965   }
966   uint32_t getEmitInstCount() const override { return 0; }
967   IceString getName(const Cfg *Func) const;
968   SizeT getNumber() const { return Number; }
969   void emit(const Cfg *Func) const override;
970   void emitIAS(const Cfg *Func) const override;
971   void dump(const Cfg *Func) const override;
972
973 private:
974   InstARM32Label(Cfg *Func, TargetARM32 *Target);
975
976   SizeT Number; // used for unique label generation.
977 };
978
979 /// Direct branch instruction.
980 class InstARM32Br : public InstARM32Pred {
981   InstARM32Br() = delete;
982   InstARM32Br(const InstARM32Br &) = delete;
983   InstARM32Br &operator=(const InstARM32Br &) = delete;
984
985 public:
986   /// Create a conditional branch to one of two nodes.
987   static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue,
988                              CfgNode *TargetFalse, CondARM32::Cond Predicate) {
989     assert(Predicate != CondARM32::AL);
990     constexpr InstARM32Label *NoLabel = nullptr;
991     return new (Func->allocate<InstARM32Br>())
992         InstARM32Br(Func, TargetTrue, TargetFalse, NoLabel, Predicate);
993   }
994   /// Create an unconditional branch to a node.
995   static InstARM32Br *create(Cfg *Func, CfgNode *Target) {
996     constexpr CfgNode *NoCondTarget = nullptr;
997     constexpr InstARM32Label *NoLabel = nullptr;
998     return new (Func->allocate<InstARM32Br>())
999         InstARM32Br(Func, NoCondTarget, Target, NoLabel, CondARM32::AL);
1000   }
1001   /// Create a non-terminator conditional branch to a node, with a fallthrough
1002   /// to the next instruction in the current node. This is used for switch
1003   /// lowering.
1004   static InstARM32Br *create(Cfg *Func, CfgNode *Target,
1005                              CondARM32::Cond Predicate) {
1006     assert(Predicate != CondARM32::AL);
1007     constexpr CfgNode *NoUncondTarget = nullptr;
1008     constexpr InstARM32Label *NoLabel = nullptr;
1009     return new (Func->allocate<InstARM32Br>())
1010         InstARM32Br(Func, Target, NoUncondTarget, NoLabel, Predicate);
1011   }
1012   // Create a conditional intra-block branch (or unconditional, if
1013   // Condition==AL) to a label in the current block.
1014   static InstARM32Br *create(Cfg *Func, InstARM32Label *Label,
1015                              CondARM32::Cond Predicate) {
1016     constexpr CfgNode *NoCondTarget = nullptr;
1017     constexpr CfgNode *NoUncondTarget = nullptr;
1018     return new (Func->allocate<InstARM32Br>())
1019         InstARM32Br(Func, NoCondTarget, NoUncondTarget, Label, Predicate);
1020   }
1021   const CfgNode *getTargetTrue() const { return TargetTrue; }
1022   const CfgNode *getTargetFalse() const { return TargetFalse; }
1023   bool optimizeBranch(const CfgNode *NextNode);
1024   uint32_t getEmitInstCount() const override {
1025     uint32_t Sum = 0;
1026     if (Label)
1027       ++Sum;
1028     if (getTargetTrue())
1029       ++Sum;
1030     if (getTargetFalse())
1031       ++Sum;
1032     return Sum;
1033   }
1034   bool isUnconditionalBranch() const override {
1035     return getPredicate() == CondARM32::AL;
1036   }
1037   bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
1038   void emit(const Cfg *Func) const override;
1039   void emitIAS(const Cfg *Func) const override;
1040   void dump(const Cfg *Func) const override;
1041   static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
1042
1043 private:
1044   InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
1045               const InstARM32Label *Label, CondARM32::Cond Predicate);
1046
1047   const CfgNode *TargetTrue;
1048   const CfgNode *TargetFalse;
1049   const InstARM32Label *Label; // Intra-block branch target
1050 };
1051
1052 /// Call instruction (bl/blx). Arguments should have already been pushed.
1053 /// Technically bl and the register form of blx can be predicated, but we'll
1054 /// leave that out until needed.
1055 class InstARM32Call : public InstARM32 {
1056   InstARM32Call() = delete;
1057   InstARM32Call(const InstARM32Call &) = delete;
1058   InstARM32Call &operator=(const InstARM32Call &) = delete;
1059
1060 public:
1061   static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) {
1062     return new (Func->allocate<InstARM32Call>())
1063         InstARM32Call(Func, Dest, CallTarget);
1064   }
1065   Operand *getCallTarget() const { return getSrc(0); }
1066   void emit(const Cfg *Func) const override;
1067   void emitIAS(const Cfg *Func) const override;
1068   void dump(const Cfg *Func) const override;
1069   static bool classof(const Inst *Instr) { return isClassof(Instr, Call); }
1070
1071 private:
1072   InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget);
1073 };
1074
1075 class InstARM32RegisterStackOp : public InstARM32 {
1076   InstARM32RegisterStackOp() = delete;
1077   InstARM32RegisterStackOp(const InstARM32RegisterStackOp &) = delete;
1078   InstARM32RegisterStackOp &
1079   operator=(const InstARM32RegisterStackOp &) = delete;
1080
1081 public:
1082   void emit(const Cfg *Func) const override;
1083   void emitIAS(const Cfg *Func) const override;
1084   void dump(const Cfg *Func) const override;
1085
1086 protected:
1087   InstARM32RegisterStackOp(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs,
1088                            Variable *Dest)
1089       : InstARM32(Func, Kind, Maxsrcs, Dest) {}
1090   void emitUsingForm(const Cfg *Func, const EmitForm Form) const;
1091   void emitGPRsAsText(const Cfg *Func) const;
1092   void emitSRegsAsText(const Cfg *Func, const Variable *BaseReg,
1093                        SizeT Regcount) const;
1094   virtual const char *getDumpOpcode() const { return getGPROpcode(); }
1095   virtual const char *getGPROpcode() const = 0;
1096   virtual const char *getSRegOpcode() const = 0;
1097   virtual Variable *getStackReg(SizeT Index) const = 0;
1098   virtual SizeT getNumStackRegs() const = 0;
1099   virtual void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1100                              const Variable *Reg) const = 0;
1101   virtual void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1102                                 IValueT Registers) const = 0;
1103   virtual void emitSRegs(const Cfg *Func, const EmitForm Form,
1104                          const Variable *BaseReg, SizeT RegCount) const = 0;
1105 };
1106
1107 /// Pops a list of registers. It may be a list of GPRs, or a list of VFP "s"
1108 /// regs, but not both. In any case, the list must be sorted.
1109 class InstARM32Pop : public InstARM32RegisterStackOp {
1110   InstARM32Pop() = delete;
1111   InstARM32Pop(const InstARM32Pop &) = delete;
1112   InstARM32Pop &operator=(const InstARM32Pop &) = delete;
1113
1114 public:
1115   static InstARM32Pop *create(Cfg *Func, const VarList &Dests) {
1116     return new (Func->allocate<InstARM32Pop>()) InstARM32Pop(Func, Dests);
1117   }
1118   static bool classof(const Inst *Instr) { return isClassof(Instr, Pop); }
1119
1120 private:
1121   InstARM32Pop(Cfg *Func, const VarList &Dests);
1122   virtual const char *getGPROpcode() const final;
1123   virtual const char *getSRegOpcode() const final;
1124   Variable *getStackReg(SizeT Index) const final;
1125   SizeT getNumStackRegs() const final;
1126   void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1127                      const Variable *Reg) const final;
1128   void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1129                         IValueT Registers) const final;
1130   void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1131                  SizeT RegCount) const final;
1132
1133   VarList Dests;
1134 };
1135
1136 /// Pushes a list of registers. Just like Pop (see above), the list may be of
1137 /// GPRs, or VFP "s" registers, but not both.
1138 class InstARM32Push : public InstARM32RegisterStackOp {
1139   InstARM32Push() = delete;
1140   InstARM32Push(const InstARM32Push &) = delete;
1141   InstARM32Push &operator=(const InstARM32Push &) = delete;
1142
1143 public:
1144   static InstARM32Push *create(Cfg *Func, const VarList &Srcs) {
1145     return new (Func->allocate<InstARM32Push>()) InstARM32Push(Func, Srcs);
1146   }
1147   static bool classof(const Inst *Instr) { return isClassof(Instr, Push); }
1148
1149 private:
1150   InstARM32Push(Cfg *Func, const VarList &Srcs);
1151   const char *getGPROpcode() const final;
1152   const char *getSRegOpcode() const final;
1153   Variable *getStackReg(SizeT Index) const final;
1154   SizeT getNumStackRegs() const final;
1155   void emitSingleGPR(const Cfg *Func, const EmitForm Form,
1156                      const Variable *Reg) const final;
1157   void emitMultipleGPRs(const Cfg *Func, const EmitForm Form,
1158                         IValueT Registers) const final;
1159   void emitSRegs(const Cfg *Func, const EmitForm Form, const Variable *BaseReg,
1160                  SizeT RegCount) const final;
1161 };
1162
1163 /// Ret pseudo-instruction. This is actually a "bx" instruction with an "lr"
1164 /// register operand, but epilogue lowering will search for a Ret instead of a
1165 /// generic "bx". This instruction also takes a Source operand (for non-void
1166 /// returning functions) for liveness analysis, though a FakeUse before the ret
1167 /// would do just as well.
1168 ///
1169 /// NOTE: Even though "bx" can be predicated, for now leave out the predication
1170 /// since it's not yet known to be useful for Ret. That may complicate finding
1171 /// the terminator instruction if it's not guaranteed to be executed.
1172 class InstARM32Ret : public InstARM32 {
1173   InstARM32Ret() = delete;
1174   InstARM32Ret(const InstARM32Ret &) = delete;
1175   InstARM32Ret &operator=(const InstARM32Ret &) = delete;
1176
1177 public:
1178   static InstARM32Ret *create(Cfg *Func, Variable *LR,
1179                               Variable *Source = nullptr) {
1180     return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source);
1181   }
1182   void emit(const Cfg *Func) const override;
1183   void emitIAS(const Cfg *Func) const override;
1184   void dump(const Cfg *Func) const override;
1185   static bool classof(const Inst *Instr) { return isClassof(Instr, Ret); }
1186
1187 private:
1188   InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source);
1189 };
1190
1191 /// Store instruction. It's important for liveness that there is no Dest operand
1192 /// (OperandARM32Mem instead of Dest Variable).
1193 class InstARM32Str final : public InstARM32Pred {
1194   InstARM32Str() = delete;
1195   InstARM32Str(const InstARM32Str &) = delete;
1196   InstARM32Str &operator=(const InstARM32Str &) = delete;
1197
1198 public:
1199   /// Value must be a register.
1200   static InstARM32Str *create(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1201                               CondARM32::Cond Predicate) {
1202     return new (Func->allocate<InstARM32Str>())
1203         InstARM32Str(Func, Value, Mem, Predicate);
1204   }
1205   void emit(const Cfg *Func) const override;
1206   void emitIAS(const Cfg *Func) const override;
1207   void dump(const Cfg *Func) const override;
1208   static bool classof(const Inst *Instr) { return isClassof(Instr, Str); }
1209
1210 private:
1211   InstARM32Str(Cfg *Func, Variable *Value, OperandARM32Mem *Mem,
1212                CondARM32::Cond Predicate);
1213 };
1214
1215 /// Exclusive Store instruction. Like its non-exclusive sibling, it's important
1216 /// for liveness that there is no Dest operand (OperandARM32Mem instead of Dest
1217 /// Variable).
1218 class InstARM32Strex final : public InstARM32Pred {
1219   InstARM32Strex() = delete;
1220   InstARM32Strex(const InstARM32Strex &) = delete;
1221   InstARM32Strex &operator=(const InstARM32Strex &) = delete;
1222
1223 public:
1224   /// Value must be a register.
1225   static InstARM32Strex *create(Cfg *Func, Variable *Dest, Variable *Value,
1226                                 OperandARM32Mem *Mem,
1227                                 CondARM32::Cond Predicate) {
1228     return new (Func->allocate<InstARM32Strex>())
1229         InstARM32Strex(Func, Dest, Value, Mem, Predicate);
1230   }
1231   void emit(const Cfg *Func) const override;
1232   void emitIAS(const Cfg *Func) const override;
1233   void dump(const Cfg *Func) const override;
1234   static bool classof(const Inst *Instr) { return isClassof(Instr, Strex); }
1235
1236 private:
1237   InstARM32Strex(Cfg *Func, Variable *Dest, Variable *Value,
1238                  OperandARM32Mem *Mem, CondARM32::Cond Predicate);
1239 };
1240
1241 class InstARM32Trap : public InstARM32 {
1242   InstARM32Trap() = delete;
1243   InstARM32Trap(const InstARM32Trap &) = delete;
1244   InstARM32Trap &operator=(const InstARM32Trap &) = delete;
1245
1246 public:
1247   static InstARM32Trap *create(Cfg *Func) {
1248     return new (Func->allocate<InstARM32Trap>()) InstARM32Trap(Func);
1249   }
1250   void emit(const Cfg *Func) const override;
1251   void emitIAS(const Cfg *Func) const override;
1252   void dump(const Cfg *Func) const override;
1253   static bool classof(const Inst *Instr) { return isClassof(Instr, Trap); }
1254
1255 private:
1256   explicit InstARM32Trap(Cfg *Func);
1257 };
1258
1259 /// Unsigned Multiply Long: d.lo, d.hi := x * y
1260 class InstARM32Umull : public InstARM32Pred {
1261   InstARM32Umull() = delete;
1262   InstARM32Umull(const InstARM32Umull &) = delete;
1263   InstARM32Umull &operator=(const InstARM32Umull &) = delete;
1264
1265 public:
1266   /// Everything must be a register.
1267   static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi,
1268                                 Variable *Src0, Variable *Src1,
1269                                 CondARM32::Cond Predicate) {
1270     return new (Func->allocate<InstARM32Umull>())
1271         InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
1272   }
1273   void emit(const Cfg *Func) const override;
1274   void emitIAS(const Cfg *Func) const override;
1275   void dump(const Cfg *Func) const override;
1276   static bool classof(const Inst *Instr) { return isClassof(Instr, Umull); }
1277
1278 private:
1279   InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0,
1280                  Variable *Src1, CondARM32::Cond Predicate);
1281
1282   Variable *DestHi;
1283 };
1284
1285 /// Handles fp2int, int2fp, and fp2fp conversions.
1286 class InstARM32Vcvt final : public InstARM32Pred {
1287   InstARM32Vcvt() = delete;
1288   InstARM32Vcvt(const InstARM32Vcvt &) = delete;
1289   InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete;
1290
1291 public:
1292   enum VcvtVariant { S2si, S2ui, Si2s, Ui2s, D2si, D2ui, Si2d, Ui2d, S2d, D2s };
1293   static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src,
1294                                VcvtVariant Variant, CondARM32::Cond Predicate) {
1295     return new (Func->allocate<InstARM32Vcvt>())
1296         InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
1297   }
1298   void emit(const Cfg *Func) const override;
1299   void emitIAS(const Cfg *Func) const override;
1300   void dump(const Cfg *Func) const override;
1301   static bool classof(const Inst *Instr) { return isClassof(Instr, Vcvt); }
1302
1303 private:
1304   InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
1305                 CondARM32::Cond Predicate);
1306
1307   const VcvtVariant Variant;
1308 };
1309
1310 /// Handles (some of) vmov's various formats.
1311 class InstARM32Mov final : public InstARM32Pred {
1312   InstARM32Mov() = delete;
1313   InstARM32Mov(const InstARM32Mov &) = delete;
1314   InstARM32Mov &operator=(const InstARM32Mov &) = delete;
1315
1316 public:
1317   static InstARM32Mov *create(Cfg *Func, Variable *Dest, Operand *Src,
1318                               CondARM32::Cond Predicate) {
1319     return new (Func->allocate<InstARM32Mov>())
1320         InstARM32Mov(Func, Dest, Src, Predicate);
1321   }
1322   bool isRedundantAssign() const override {
1323     return !isMultiDest() && !isMultiSource() &&
1324            getPredicate() == CondARM32::AL &&
1325            checkForRedundantAssign(getDest(), getSrc(0));
1326   }
1327   bool isVarAssign() const override { return llvm::isa<Variable>(getSrc(0)); }
1328   void emit(const Cfg *Func) const override;
1329   void emitIAS(const Cfg *Func) const override;
1330   void dump(const Cfg *Func) const override;
1331   static bool classof(const Inst *Instr) { return isClassof(Instr, Mov); }
1332
1333   bool isMultiDest() const { return DestHi != nullptr; }
1334
1335   bool isMultiSource() const {
1336     assert(getSrcSize() == 1 || getSrcSize() == 2);
1337     return getSrcSize() == 2;
1338   }
1339
1340   Variable *getDestHi() const { return DestHi; }
1341
1342 private:
1343   InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
1344                CondARM32::Cond Predicate);
1345   void emitMultiDestSingleSource(const Cfg *Func) const;
1346   void emitSingleDestMultiSource(const Cfg *Func) const;
1347   void emitSingleDestSingleSource(const Cfg *Func) const;
1348
1349   Variable *DestHi = nullptr;
1350 };
1351
1352 class InstARM32Vcmp final : public InstARM32Pred {
1353   InstARM32Vcmp() = delete;
1354   InstARM32Vcmp(const InstARM32Vcmp &) = delete;
1355   InstARM32Vcmp &operator=(const InstARM32Vcmp &) = delete;
1356
1357 public:
1358   static InstARM32Vcmp *create(Cfg *Func, Variable *Src0, Variable *Src1,
1359                                CondARM32::Cond Predicate) {
1360     return new (Func->allocate<InstARM32Vcmp>())
1361         InstARM32Vcmp(Func, Src0, Src1, Predicate);
1362   }
1363   static InstARM32Vcmp *create(Cfg *Func, Variable *Src0,
1364                                OperandARM32FlexFpZero *Src1,
1365                                CondARM32::Cond Predicate) {
1366     return new (Func->allocate<InstARM32Vcmp>())
1367         InstARM32Vcmp(Func, Src0, Src1, Predicate);
1368   }
1369   void emit(const Cfg *Func) const override;
1370   void emitIAS(const Cfg *Func) const override;
1371   void dump(const Cfg *Func) const override;
1372   static bool classof(const Inst *Instr) { return isClassof(Instr, Vcmp); }
1373
1374 private:
1375   InstARM32Vcmp(Cfg *Func, Variable *Src0, Operand *Src1,
1376                 CondARM32::Cond Predicate);
1377 };
1378
1379 /// Copies the FP Status and Control Register the core flags.
1380 class InstARM32Vmrs final : public InstARM32Pred {
1381   InstARM32Vmrs() = delete;
1382   InstARM32Vmrs(const InstARM32Vmrs &) = delete;
1383   InstARM32Vmrs &operator=(const InstARM32Vmrs &) = delete;
1384
1385 public:
1386   static InstARM32Vmrs *create(Cfg *Func, CondARM32::Cond Predicate) {
1387     return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, Predicate);
1388   }
1389   void emit(const Cfg *Func) const override;
1390   void emitIAS(const Cfg *Func) const override;
1391   void dump(const Cfg *Func) const override;
1392   static bool classof(const Inst *Instr) { return isClassof(Instr, Vmrs); }
1393
1394 private:
1395   InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate);
1396 };
1397
1398 class InstARM32Vabs final : public InstARM32Pred {
1399   InstARM32Vabs() = delete;
1400   InstARM32Vabs(const InstARM32Vabs &) = delete;
1401   InstARM32Vabs &operator=(const InstARM32Vabs &) = delete;
1402
1403 public:
1404   static InstARM32Vabs *create(Cfg *Func, Variable *Dest, Variable *Src,
1405                                CondARM32::Cond Predicate) {
1406     return new (Func->allocate<InstARM32Vabs>())
1407         InstARM32Vabs(Func, Dest, Src, Predicate);
1408   }
1409   void emit(const Cfg *Func) const override;
1410   void emitIAS(const Cfg *Func) const override;
1411   void dump(const Cfg *Func) const override;
1412   static bool classof(const Inst *Instr) { return isClassof(Instr, Vabs); }
1413
1414 private:
1415   InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
1416                 CondARM32::Cond Predicate);
1417 };
1418
1419 class InstARM32Dmb final : public InstARM32Pred {
1420   InstARM32Dmb() = delete;
1421   InstARM32Dmb(const InstARM32Dmb &) = delete;
1422   InstARM32Dmb &operator=(const InstARM32Dmb &) = delete;
1423
1424 public:
1425   static InstARM32Dmb *create(Cfg *Func) {
1426     return new (Func->allocate<InstARM32Dmb>()) InstARM32Dmb(Func);
1427   }
1428   void emit(const Cfg *Func) const override;
1429   void emitIAS(const Cfg *Func) const override;
1430   void dump(const Cfg *Func) const override;
1431   static bool classof(const Inst *Instr) { return isClassof(Instr, Dmb); }
1432
1433 private:
1434   explicit InstARM32Dmb(Cfg *Func);
1435 };
1436
1437 // Declare partial template specializations of emit() methods that already have
1438 // default implementations. Without this, there is the possibility of ODR
1439 // violations and link errors.
1440
1441 template <> void InstARM32Ldr::emit(const Cfg *Func) const;
1442 template <> void InstARM32Movw::emit(const Cfg *Func) const;
1443 template <> void InstARM32Movt::emit(const Cfg *Func) const;
1444
1445 } // end of namespace ARM32
1446 } // end of namespace Ice
1447
1448 #endif // SUBZERO_SRC_ICEINSTARM32_H