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