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