1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceRegistersX8664.h - Register information ---*- 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 registers and their encodings for x86-64. 12*03ce13f7SAndroid Build Coastguard Worker /// 13*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 14*03ce13f7SAndroid Build Coastguard Worker 15*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEREGISTERSX8664_H 16*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEREGISTERSX8664_H 17*03ce13f7SAndroid Build Coastguard Worker 18*03ce13f7SAndroid Build Coastguard Worker #include "IceBitVector.h" 19*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h" 20*03ce13f7SAndroid Build Coastguard Worker #include "IceInstX8664.def" 21*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLowering.h" 22*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLoweringX86RegClass.h" 23*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h" 24*03ce13f7SAndroid Build Coastguard Worker 25*03ce13f7SAndroid Build Coastguard Worker #include <initializer_list> 26*03ce13f7SAndroid Build Coastguard Worker 27*03ce13f7SAndroid Build Coastguard Worker namespace Ice { 28*03ce13f7SAndroid Build Coastguard Worker using namespace ::Ice::X86; 29*03ce13f7SAndroid Build Coastguard Worker 30*03ce13f7SAndroid Build Coastguard Worker class RegX8664 { 31*03ce13f7SAndroid Build Coastguard Worker public: 32*03ce13f7SAndroid Build Coastguard Worker /// An enum of every register. The enum value may not match the encoding used 33*03ce13f7SAndroid Build Coastguard Worker /// to binary encode register operands in instructions. 34*03ce13f7SAndroid Build Coastguard Worker enum AllRegisters { 35*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 36*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 37*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 38*03ce13f7SAndroid Build Coastguard Worker val, 39*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 40*03ce13f7SAndroid Build Coastguard Worker #undef X 41*03ce13f7SAndroid Build Coastguard Worker Reg_NUM 42*03ce13f7SAndroid Build Coastguard Worker }; 43*03ce13f7SAndroid Build Coastguard Worker 44*03ce13f7SAndroid Build Coastguard Worker /// An enum of GPR Registers. The enum value does match the encoding used to 45*03ce13f7SAndroid Build Coastguard Worker /// binary encode register operands in instructions. 46*03ce13f7SAndroid Build Coastguard Worker enum GPRRegister { 47*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 48*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 49*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 50*03ce13f7SAndroid Build Coastguard Worker Encoded_##val = encode, 51*03ce13f7SAndroid Build Coastguard Worker REGX8664_GPR_TABLE 52*03ce13f7SAndroid Build Coastguard Worker #undef X 53*03ce13f7SAndroid Build Coastguard Worker Encoded_Not_GPR = -1 54*03ce13f7SAndroid Build Coastguard Worker }; 55*03ce13f7SAndroid Build Coastguard Worker 56*03ce13f7SAndroid Build Coastguard Worker /// An enum of XMM Registers. The enum value does match the encoding used to 57*03ce13f7SAndroid Build Coastguard Worker /// binary encode register operands in instructions. 58*03ce13f7SAndroid Build Coastguard Worker enum XmmRegister { 59*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 60*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 61*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 62*03ce13f7SAndroid Build Coastguard Worker Encoded_##val = encode, 63*03ce13f7SAndroid Build Coastguard Worker REGX8664_XMM_TABLE 64*03ce13f7SAndroid Build Coastguard Worker #undef X 65*03ce13f7SAndroid Build Coastguard Worker Encoded_Not_Xmm = -1 66*03ce13f7SAndroid Build Coastguard Worker }; 67*03ce13f7SAndroid Build Coastguard Worker 68*03ce13f7SAndroid Build Coastguard Worker /// An enum of Byte Registers. The enum value does match the encoding used to 69*03ce13f7SAndroid Build Coastguard Worker /// binary encode register operands in instructions. 70*03ce13f7SAndroid Build Coastguard Worker enum ByteRegister { 71*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 72*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 73*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 74*03ce13f7SAndroid Build Coastguard Worker Encoded_8_##val = encode, 75*03ce13f7SAndroid Build Coastguard Worker REGX8664_BYTEREG_TABLE 76*03ce13f7SAndroid Build Coastguard Worker #undef X 77*03ce13f7SAndroid Build Coastguard Worker Encoded_Not_ByteReg = -1 78*03ce13f7SAndroid Build Coastguard Worker }; 79*03ce13f7SAndroid Build Coastguard Worker getRegName(RegNumT RegNum)80*03ce13f7SAndroid Build Coastguard Worker static inline const char *getRegName(RegNumT RegNum) { 81*03ce13f7SAndroid Build Coastguard Worker static const char *const RegNames[Reg_NUM] = { 82*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 83*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 84*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 85*03ce13f7SAndroid Build Coastguard Worker name, 86*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 87*03ce13f7SAndroid Build Coastguard Worker #undef X 88*03ce13f7SAndroid Build Coastguard Worker }; 89*03ce13f7SAndroid Build Coastguard Worker RegNum.assertIsValid(); 90*03ce13f7SAndroid Build Coastguard Worker return RegNames[RegNum]; 91*03ce13f7SAndroid Build Coastguard Worker } 92*03ce13f7SAndroid Build Coastguard Worker getEncodedGPR(RegNumT RegNum)93*03ce13f7SAndroid Build Coastguard Worker static inline GPRRegister getEncodedGPR(RegNumT RegNum) { 94*03ce13f7SAndroid Build Coastguard Worker static const GPRRegister GPRRegs[Reg_NUM] = { 95*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 96*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 97*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 98*03ce13f7SAndroid Build Coastguard Worker GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR), 99*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 100*03ce13f7SAndroid Build Coastguard Worker #undef X 101*03ce13f7SAndroid Build Coastguard Worker }; 102*03ce13f7SAndroid Build Coastguard Worker RegNum.assertIsValid(); 103*03ce13f7SAndroid Build Coastguard Worker assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR); 104*03ce13f7SAndroid Build Coastguard Worker return GPRRegs[RegNum]; 105*03ce13f7SAndroid Build Coastguard Worker } 106*03ce13f7SAndroid Build Coastguard Worker getEncodedByteReg(RegNumT RegNum)107*03ce13f7SAndroid Build Coastguard Worker static inline ByteRegister getEncodedByteReg(RegNumT RegNum) { 108*03ce13f7SAndroid Build Coastguard Worker static const ByteRegister ByteRegs[Reg_NUM] = { 109*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 110*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 111*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 112*03ce13f7SAndroid Build Coastguard Worker ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg), 113*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 114*03ce13f7SAndroid Build Coastguard Worker #undef X 115*03ce13f7SAndroid Build Coastguard Worker }; 116*03ce13f7SAndroid Build Coastguard Worker RegNum.assertIsValid(); 117*03ce13f7SAndroid Build Coastguard Worker assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg); 118*03ce13f7SAndroid Build Coastguard Worker return ByteRegs[RegNum]; 119*03ce13f7SAndroid Build Coastguard Worker } 120*03ce13f7SAndroid Build Coastguard Worker isXmm(RegNumT RegNum)121*03ce13f7SAndroid Build Coastguard Worker static inline bool isXmm(RegNumT RegNum) { 122*03ce13f7SAndroid Build Coastguard Worker static const bool IsXmm[Reg_NUM] = { 123*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 124*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 125*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 126*03ce13f7SAndroid Build Coastguard Worker isXmm, 127*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 128*03ce13f7SAndroid Build Coastguard Worker #undef X 129*03ce13f7SAndroid Build Coastguard Worker }; 130*03ce13f7SAndroid Build Coastguard Worker return IsXmm[RegNum]; 131*03ce13f7SAndroid Build Coastguard Worker } 132*03ce13f7SAndroid Build Coastguard Worker getEncodedXmm(RegNumT RegNum)133*03ce13f7SAndroid Build Coastguard Worker static inline XmmRegister getEncodedXmm(RegNumT RegNum) { 134*03ce13f7SAndroid Build Coastguard Worker static const XmmRegister XmmRegs[Reg_NUM] = { 135*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 136*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 137*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 138*03ce13f7SAndroid Build Coastguard Worker XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm), 139*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 140*03ce13f7SAndroid Build Coastguard Worker #undef X 141*03ce13f7SAndroid Build Coastguard Worker }; 142*03ce13f7SAndroid Build Coastguard Worker RegNum.assertIsValid(); 143*03ce13f7SAndroid Build Coastguard Worker assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm); 144*03ce13f7SAndroid Build Coastguard Worker return XmmRegs[RegNum]; 145*03ce13f7SAndroid Build Coastguard Worker } 146*03ce13f7SAndroid Build Coastguard Worker getEncoding(RegNumT RegNum)147*03ce13f7SAndroid Build Coastguard Worker static inline uint32_t getEncoding(RegNumT RegNum) { 148*03ce13f7SAndroid Build Coastguard Worker static const uint32_t Encoding[Reg_NUM] = { 149*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 150*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 151*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 152*03ce13f7SAndroid Build Coastguard Worker encode, 153*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 154*03ce13f7SAndroid Build Coastguard Worker #undef X 155*03ce13f7SAndroid Build Coastguard Worker }; 156*03ce13f7SAndroid Build Coastguard Worker RegNum.assertIsValid(); 157*03ce13f7SAndroid Build Coastguard Worker return Encoding[RegNum]; 158*03ce13f7SAndroid Build Coastguard Worker } 159*03ce13f7SAndroid Build Coastguard Worker getBaseReg(RegNumT RegNum)160*03ce13f7SAndroid Build Coastguard Worker static inline RegNumT getBaseReg(RegNumT RegNum) { 161*03ce13f7SAndroid Build Coastguard Worker static const RegNumT BaseRegs[Reg_NUM] = { 162*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 163*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 164*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 165*03ce13f7SAndroid Build Coastguard Worker base, 166*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 167*03ce13f7SAndroid Build Coastguard Worker #undef X 168*03ce13f7SAndroid Build Coastguard Worker }; 169*03ce13f7SAndroid Build Coastguard Worker RegNum.assertIsValid(); 170*03ce13f7SAndroid Build Coastguard Worker return BaseRegs[RegNum]; 171*03ce13f7SAndroid Build Coastguard Worker } 172*03ce13f7SAndroid Build Coastguard Worker 173*03ce13f7SAndroid Build Coastguard Worker private: getFirstGprForType(Type Ty)174*03ce13f7SAndroid Build Coastguard Worker static inline RegNumT getFirstGprForType(Type Ty) { 175*03ce13f7SAndroid Build Coastguard Worker switch (Ty) { 176*03ce13f7SAndroid Build Coastguard Worker default: 177*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable("Invalid type for GPR."); 178*03ce13f7SAndroid Build Coastguard Worker case IceType_i1: 179*03ce13f7SAndroid Build Coastguard Worker case IceType_i8: 180*03ce13f7SAndroid Build Coastguard Worker return Reg_al; 181*03ce13f7SAndroid Build Coastguard Worker case IceType_i16: 182*03ce13f7SAndroid Build Coastguard Worker return Reg_ax; 183*03ce13f7SAndroid Build Coastguard Worker case IceType_i32: 184*03ce13f7SAndroid Build Coastguard Worker return Reg_eax; 185*03ce13f7SAndroid Build Coastguard Worker case IceType_i64: 186*03ce13f7SAndroid Build Coastguard Worker return Reg_rax; 187*03ce13f7SAndroid Build Coastguard Worker } 188*03ce13f7SAndroid Build Coastguard Worker } 189*03ce13f7SAndroid Build Coastguard Worker 190*03ce13f7SAndroid Build Coastguard Worker public: getGprForType(Type Ty,RegNumT RegNum)191*03ce13f7SAndroid Build Coastguard Worker static inline RegNumT getGprForType(Type Ty, RegNumT RegNum) { 192*03ce13f7SAndroid Build Coastguard Worker assert(RegNum.hasValue()); 193*03ce13f7SAndroid Build Coastguard Worker 194*03ce13f7SAndroid Build Coastguard Worker if (!isScalarIntegerType(Ty)) { 195*03ce13f7SAndroid Build Coastguard Worker return RegNum; 196*03ce13f7SAndroid Build Coastguard Worker } 197*03ce13f7SAndroid Build Coastguard Worker 198*03ce13f7SAndroid Build Coastguard Worker assert(Ty == IceType_i1 || Ty == IceType_i8 || Ty == IceType_i16 || 199*03ce13f7SAndroid Build Coastguard Worker Ty == IceType_i32 || Ty == IceType_i64); 200*03ce13f7SAndroid Build Coastguard Worker 201*03ce13f7SAndroid Build Coastguard Worker if (RegNum == Reg_ah) { 202*03ce13f7SAndroid Build Coastguard Worker assert(Ty == IceType_i8); 203*03ce13f7SAndroid Build Coastguard Worker return RegNum; 204*03ce13f7SAndroid Build Coastguard Worker } 205*03ce13f7SAndroid Build Coastguard Worker 206*03ce13f7SAndroid Build Coastguard Worker assert(RegNum != Reg_bh); 207*03ce13f7SAndroid Build Coastguard Worker assert(RegNum != Reg_ch); 208*03ce13f7SAndroid Build Coastguard Worker assert(RegNum != Reg_dh); 209*03ce13f7SAndroid Build Coastguard Worker 210*03ce13f7SAndroid Build Coastguard Worker const RegNumT FirstGprForType = getFirstGprForType(Ty); 211*03ce13f7SAndroid Build Coastguard Worker 212*03ce13f7SAndroid Build Coastguard Worker switch (RegNum) { 213*03ce13f7SAndroid Build Coastguard Worker default: 214*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Unknown register."); 215*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 216*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 217*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 218*03ce13f7SAndroid Build Coastguard Worker case val: { \ 219*03ce13f7SAndroid Build Coastguard Worker if (!isGPR) \ 220*03ce13f7SAndroid Build Coastguard Worker return val; \ 221*03ce13f7SAndroid Build Coastguard Worker assert((is64) || (is32) || (is16) || (is8) || getBaseReg(val) == Reg_rsp); \ 222*03ce13f7SAndroid Build Coastguard Worker constexpr AllRegisters FirstGprWithRegNumSize = \ 223*03ce13f7SAndroid Build Coastguard Worker ((is64) || val == Reg_rsp) \ 224*03ce13f7SAndroid Build Coastguard Worker ? Reg_rax \ 225*03ce13f7SAndroid Build Coastguard Worker : (((is32) || val == Reg_esp) \ 226*03ce13f7SAndroid Build Coastguard Worker ? Reg_eax \ 227*03ce13f7SAndroid Build Coastguard Worker : (((is16) || val == Reg_sp) ? Reg_ax : Reg_al)); \ 228*03ce13f7SAndroid Build Coastguard Worker const auto NewRegNum = \ 229*03ce13f7SAndroid Build Coastguard Worker RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType); \ 230*03ce13f7SAndroid Build Coastguard Worker assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) && \ 231*03ce13f7SAndroid Build Coastguard Worker "Error involving " #val); \ 232*03ce13f7SAndroid Build Coastguard Worker return NewRegNum; \ 233*03ce13f7SAndroid Build Coastguard Worker } 234*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 235*03ce13f7SAndroid Build Coastguard Worker #undef X 236*03ce13f7SAndroid Build Coastguard Worker } 237*03ce13f7SAndroid Build Coastguard Worker } 238*03ce13f7SAndroid Build Coastguard Worker 239*03ce13f7SAndroid Build Coastguard Worker static inline void initRegisterSet(const::Ice::ClFlags & Flags,std::array<SmallBitVector,RCX86_NUM> * TypeToRegisterSet,std::array<SmallBitVector,Reg_NUM> * RegisterAliases)240*03ce13f7SAndroid Build Coastguard Worker initRegisterSet(const ::Ice::ClFlags &Flags, 241*03ce13f7SAndroid Build Coastguard Worker std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet, 242*03ce13f7SAndroid Build Coastguard Worker std::array<SmallBitVector, Reg_NUM> *RegisterAliases) { 243*03ce13f7SAndroid Build Coastguard Worker SmallBitVector IntegerRegistersI64(Reg_NUM); 244*03ce13f7SAndroid Build Coastguard Worker SmallBitVector IntegerRegistersI32(Reg_NUM); 245*03ce13f7SAndroid Build Coastguard Worker SmallBitVector IntegerRegistersI16(Reg_NUM); 246*03ce13f7SAndroid Build Coastguard Worker SmallBitVector IntegerRegistersI8(Reg_NUM); 247*03ce13f7SAndroid Build Coastguard Worker SmallBitVector FloatRegisters(Reg_NUM); 248*03ce13f7SAndroid Build Coastguard Worker SmallBitVector VectorRegisters(Reg_NUM); 249*03ce13f7SAndroid Build Coastguard Worker SmallBitVector Trunc64To8Registers(Reg_NUM); 250*03ce13f7SAndroid Build Coastguard Worker SmallBitVector Trunc32To8Registers(Reg_NUM); 251*03ce13f7SAndroid Build Coastguard Worker SmallBitVector Trunc16To8Registers(Reg_NUM); 252*03ce13f7SAndroid Build Coastguard Worker SmallBitVector Trunc8RcvrRegisters(Reg_NUM); 253*03ce13f7SAndroid Build Coastguard Worker SmallBitVector AhRcvrRegisters(Reg_NUM); 254*03ce13f7SAndroid Build Coastguard Worker SmallBitVector InvalidRegisters(Reg_NUM); 255*03ce13f7SAndroid Build Coastguard Worker 256*03ce13f7SAndroid Build Coastguard Worker static constexpr struct { 257*03ce13f7SAndroid Build Coastguard Worker uint16_t Val; 258*03ce13f7SAndroid Build Coastguard Worker unsigned IsReservedWhenSandboxing : 1; 259*03ce13f7SAndroid Build Coastguard Worker unsigned Is64 : 1; 260*03ce13f7SAndroid Build Coastguard Worker unsigned Is32 : 1; 261*03ce13f7SAndroid Build Coastguard Worker unsigned Is16 : 1; 262*03ce13f7SAndroid Build Coastguard Worker unsigned Is8 : 1; 263*03ce13f7SAndroid Build Coastguard Worker unsigned IsXmm : 1; 264*03ce13f7SAndroid Build Coastguard Worker unsigned Is64To8 : 1; 265*03ce13f7SAndroid Build Coastguard Worker unsigned Is32To8 : 1; 266*03ce13f7SAndroid Build Coastguard Worker unsigned Is16To8 : 1; 267*03ce13f7SAndroid Build Coastguard Worker unsigned IsTrunc8Rcvr : 1; 268*03ce13f7SAndroid Build Coastguard Worker unsigned IsAhRcvr : 1; 269*03ce13f7SAndroid Build Coastguard Worker #define NUM_ALIASES_BITS 2 270*03ce13f7SAndroid Build Coastguard Worker SizeT NumAliases : (NUM_ALIASES_BITS + 1); 271*03ce13f7SAndroid Build Coastguard Worker uint16_t Aliases[1 << NUM_ALIASES_BITS]; 272*03ce13f7SAndroid Build Coastguard Worker #undef NUM_ALIASES_BITS 273*03ce13f7SAndroid Build Coastguard Worker } X8664RegTable[Reg_NUM] = { 274*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 275*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 276*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 277*03ce13f7SAndroid Build Coastguard Worker { \ 278*03ce13f7SAndroid Build Coastguard Worker val, \ 279*03ce13f7SAndroid Build Coastguard Worker sboxres, \ 280*03ce13f7SAndroid Build Coastguard Worker is64, \ 281*03ce13f7SAndroid Build Coastguard Worker is32, \ 282*03ce13f7SAndroid Build Coastguard Worker is16, \ 283*03ce13f7SAndroid Build Coastguard Worker is8, \ 284*03ce13f7SAndroid Build Coastguard Worker isXmm, \ 285*03ce13f7SAndroid Build Coastguard Worker is64To8, \ 286*03ce13f7SAndroid Build Coastguard Worker is32To8, \ 287*03ce13f7SAndroid Build Coastguard Worker is16To8, \ 288*03ce13f7SAndroid Build Coastguard Worker isTrunc8Rcvr, \ 289*03ce13f7SAndroid Build Coastguard Worker isAhRcvr, \ 290*03ce13f7SAndroid Build Coastguard Worker (std::initializer_list<uint16_t> aliases).size(), \ 291*03ce13f7SAndroid Build Coastguard Worker aliases, \ 292*03ce13f7SAndroid Build Coastguard Worker }, 293*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 294*03ce13f7SAndroid Build Coastguard Worker #undef X 295*03ce13f7SAndroid Build Coastguard Worker }; 296*03ce13f7SAndroid Build Coastguard Worker 297*03ce13f7SAndroid Build Coastguard Worker for (SizeT ii = 0; ii < llvm::array_lengthof(X8664RegTable); ++ii) { 298*03ce13f7SAndroid Build Coastguard Worker const auto &Entry = X8664RegTable[ii]; 299*03ce13f7SAndroid Build Coastguard Worker // Even though the register is disabled for register allocation, it might 300*03ce13f7SAndroid Build Coastguard Worker // still be used by the Target Lowering (e.g., base pointer), so the 301*03ce13f7SAndroid Build Coastguard Worker // register alias table still needs to be defined. 302*03ce13f7SAndroid Build Coastguard Worker (*RegisterAliases)[Entry.Val].resize(Reg_NUM); 303*03ce13f7SAndroid Build Coastguard Worker for (Ice::SizeT J = 0; J < Entry.NumAliases; ++J) { 304*03ce13f7SAndroid Build Coastguard Worker SizeT Alias = Entry.Aliases[J]; 305*03ce13f7SAndroid Build Coastguard Worker assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias"); 306*03ce13f7SAndroid Build Coastguard Worker (*RegisterAliases)[Entry.Val].set(Alias); 307*03ce13f7SAndroid Build Coastguard Worker } 308*03ce13f7SAndroid Build Coastguard Worker 309*03ce13f7SAndroid Build Coastguard Worker (*RegisterAliases)[Entry.Val].set(Entry.Val); 310*03ce13f7SAndroid Build Coastguard Worker 311*03ce13f7SAndroid Build Coastguard Worker (IntegerRegistersI64)[Entry.Val] = Entry.Is64; 312*03ce13f7SAndroid Build Coastguard Worker (IntegerRegistersI32)[Entry.Val] = Entry.Is32; 313*03ce13f7SAndroid Build Coastguard Worker (IntegerRegistersI16)[Entry.Val] = Entry.Is16; 314*03ce13f7SAndroid Build Coastguard Worker (IntegerRegistersI8)[Entry.Val] = Entry.Is8; 315*03ce13f7SAndroid Build Coastguard Worker (FloatRegisters)[Entry.Val] = Entry.IsXmm; 316*03ce13f7SAndroid Build Coastguard Worker (VectorRegisters)[Entry.Val] = Entry.IsXmm; 317*03ce13f7SAndroid Build Coastguard Worker (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8; 318*03ce13f7SAndroid Build Coastguard Worker (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8; 319*03ce13f7SAndroid Build Coastguard Worker (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8; 320*03ce13f7SAndroid Build Coastguard Worker (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr; 321*03ce13f7SAndroid Build Coastguard Worker (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr; 322*03ce13f7SAndroid Build Coastguard Worker } 323*03ce13f7SAndroid Build Coastguard Worker 324*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_void] = InvalidRegisters; 325*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8; 326*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8; 327*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16; 328*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32; 329*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_i64] = IntegerRegistersI64; 330*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_f32] = FloatRegisters; 331*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_f64] = FloatRegisters; 332*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters; 333*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters; 334*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters; 335*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters; 336*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters; 337*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters; 338*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters; 339*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers; 340*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers; 341*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers; 342*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters; 343*03ce13f7SAndroid Build Coastguard Worker (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters; 344*03ce13f7SAndroid Build Coastguard Worker } 345*03ce13f7SAndroid Build Coastguard Worker 346*03ce13f7SAndroid Build Coastguard Worker static inline SmallBitVector getRegisterSet(const::Ice::ClFlags & Flags,TargetLowering::RegSetMask Include,TargetLowering::RegSetMask Exclude)347*03ce13f7SAndroid Build Coastguard Worker getRegisterSet(const ::Ice::ClFlags &Flags, 348*03ce13f7SAndroid Build Coastguard Worker TargetLowering::RegSetMask Include, 349*03ce13f7SAndroid Build Coastguard Worker TargetLowering::RegSetMask Exclude) { 350*03ce13f7SAndroid Build Coastguard Worker SmallBitVector Registers(Reg_NUM); 351*03ce13f7SAndroid Build Coastguard Worker 352*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 353*03ce13f7SAndroid Build Coastguard Worker sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ 354*03ce13f7SAndroid Build Coastguard Worker is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ 355*03ce13f7SAndroid Build Coastguard Worker if (scratch && (Include & TargetLowering::RegSet_CallerSave)) \ 356*03ce13f7SAndroid Build Coastguard Worker Registers[val] = true; \ 357*03ce13f7SAndroid Build Coastguard Worker if (preserved && (Include & TargetLowering::RegSet_CalleeSave)) \ 358*03ce13f7SAndroid Build Coastguard Worker Registers[val] = true; \ 359*03ce13f7SAndroid Build Coastguard Worker if (stackptr && (Include & TargetLowering::RegSet_StackPointer)) \ 360*03ce13f7SAndroid Build Coastguard Worker Registers[val] = true; \ 361*03ce13f7SAndroid Build Coastguard Worker if (frameptr && (Include & TargetLowering::RegSet_FramePointer)) \ 362*03ce13f7SAndroid Build Coastguard Worker Registers[val] = true; \ 363*03ce13f7SAndroid Build Coastguard Worker if (scratch && (Exclude & TargetLowering::RegSet_CallerSave)) \ 364*03ce13f7SAndroid Build Coastguard Worker Registers[val] = false; \ 365*03ce13f7SAndroid Build Coastguard Worker if (preserved && (Exclude & TargetLowering::RegSet_CalleeSave)) \ 366*03ce13f7SAndroid Build Coastguard Worker Registers[val] = false; \ 367*03ce13f7SAndroid Build Coastguard Worker if (stackptr && (Exclude & TargetLowering::RegSet_StackPointer)) \ 368*03ce13f7SAndroid Build Coastguard Worker Registers[val] = false; \ 369*03ce13f7SAndroid Build Coastguard Worker if (frameptr && (Exclude & TargetLowering::RegSet_FramePointer)) \ 370*03ce13f7SAndroid Build Coastguard Worker Registers[val] = false; 371*03ce13f7SAndroid Build Coastguard Worker 372*03ce13f7SAndroid Build Coastguard Worker REGX8664_TABLE 373*03ce13f7SAndroid Build Coastguard Worker 374*03ce13f7SAndroid Build Coastguard Worker #undef X 375*03ce13f7SAndroid Build Coastguard Worker 376*03ce13f7SAndroid Build Coastguard Worker return Registers; 377*03ce13f7SAndroid Build Coastguard Worker } 378*03ce13f7SAndroid Build Coastguard Worker 379*03ce13f7SAndroid Build Coastguard Worker #if defined(_WIN64) 380*03ce13f7SAndroid Build Coastguard Worker // Microsoft x86-64 calling convention: 381*03ce13f7SAndroid Build Coastguard Worker // 382*03ce13f7SAndroid Build Coastguard Worker // * The first four arguments of vector/fp type, regardless of their 383*03ce13f7SAndroid Build Coastguard Worker // position relative to the other arguments in the argument list, are placed 384*03ce13f7SAndroid Build Coastguard Worker // in registers %xmm0 - %xmm3. 385*03ce13f7SAndroid Build Coastguard Worker // 386*03ce13f7SAndroid Build Coastguard Worker // * The first four arguments of integer types, regardless of their position 387*03ce13f7SAndroid Build Coastguard Worker // relative to the other arguments in the argument list, are placed in 388*03ce13f7SAndroid Build Coastguard Worker // registers %rcx, %rdx, %r8, and %r9. 389*03ce13f7SAndroid Build Coastguard Worker 390*03ce13f7SAndroid Build Coastguard Worker /// The maximum number of arguments to pass in XMM registers 391*03ce13f7SAndroid Build Coastguard Worker static constexpr uint32_t X86_MAX_XMM_ARGS = 4; 392*03ce13f7SAndroid Build Coastguard Worker /// The maximum number of arguments to pass in GPR registers 393*03ce13f7SAndroid Build Coastguard Worker static constexpr uint32_t X86_MAX_GPR_ARGS = 4; getRegisterForGprArgNum(Type Ty,uint32_t ArgNum)394*03ce13f7SAndroid Build Coastguard Worker static inline RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) { 395*03ce13f7SAndroid Build Coastguard Worker if (ArgNum >= X86_MAX_GPR_ARGS) { 396*03ce13f7SAndroid Build Coastguard Worker return RegNumT(); 397*03ce13f7SAndroid Build Coastguard Worker } 398*03ce13f7SAndroid Build Coastguard Worker static const AllRegisters GprForArgNum[] = { 399*03ce13f7SAndroid Build Coastguard Worker Reg_rcx, 400*03ce13f7SAndroid Build Coastguard Worker Reg_rdx, 401*03ce13f7SAndroid Build Coastguard Worker Reg_r8, 402*03ce13f7SAndroid Build Coastguard Worker Reg_r9, 403*03ce13f7SAndroid Build Coastguard Worker }; 404*03ce13f7SAndroid Build Coastguard Worker static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS, 405*03ce13f7SAndroid Build Coastguard Worker "Mismatch between MAX_GPR_ARGS and GprForArgNum."); 406*03ce13f7SAndroid Build Coastguard Worker assert(Ty == IceType_i64 || Ty == IceType_i32); 407*03ce13f7SAndroid Build Coastguard Worker return RegX8664::getGprForType(Ty, GprForArgNum[ArgNum]); 408*03ce13f7SAndroid Build Coastguard Worker } 409*03ce13f7SAndroid Build Coastguard Worker // Given the absolute argument position and argument position by type, return 410*03ce13f7SAndroid Build Coastguard Worker // the register index to assign it to. getArgIndex(SizeT argPos,SizeT argPosByType)411*03ce13f7SAndroid Build Coastguard Worker static inline SizeT getArgIndex(SizeT argPos, SizeT argPosByType) { 412*03ce13f7SAndroid Build Coastguard Worker // Microsoft x64 ABI: register is selected by arg position (e.g. 1st int as 413*03ce13f7SAndroid Build Coastguard Worker // 2nd param goes into 2nd int reg) 414*03ce13f7SAndroid Build Coastguard Worker (void)argPosByType; 415*03ce13f7SAndroid Build Coastguard Worker return argPos; 416*03ce13f7SAndroid Build Coastguard Worker }; 417*03ce13f7SAndroid Build Coastguard Worker 418*03ce13f7SAndroid Build Coastguard Worker #else 419*03ce13f7SAndroid Build Coastguard Worker // System V x86-64 calling convention: 420*03ce13f7SAndroid Build Coastguard Worker // 421*03ce13f7SAndroid Build Coastguard Worker // * The first eight arguments of vector/fp type, regardless of their 422*03ce13f7SAndroid Build Coastguard Worker // position relative to the other arguments in the argument list, are placed 423*03ce13f7SAndroid Build Coastguard Worker // in registers %xmm0 - %xmm7. 424*03ce13f7SAndroid Build Coastguard Worker // 425*03ce13f7SAndroid Build Coastguard Worker // * The first six arguments of integer types, regardless of their position 426*03ce13f7SAndroid Build Coastguard Worker // relative to the other arguments in the argument list, are placed in 427*03ce13f7SAndroid Build Coastguard Worker // registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9. 428*03ce13f7SAndroid Build Coastguard Worker // 429*03ce13f7SAndroid Build Coastguard Worker // This intends to match the section "Function Calling Sequence" of the 430*03ce13f7SAndroid Build Coastguard Worker // document "System V Application Binary Interface." 431*03ce13f7SAndroid Build Coastguard Worker 432*03ce13f7SAndroid Build Coastguard Worker /// The maximum number of arguments to pass in XMM registers 433*03ce13f7SAndroid Build Coastguard Worker static constexpr uint32_t X86_MAX_XMM_ARGS = 8; 434*03ce13f7SAndroid Build Coastguard Worker /// The maximum number of arguments to pass in GPR registers 435*03ce13f7SAndroid Build Coastguard Worker static constexpr uint32_t X86_MAX_GPR_ARGS = 6; 436*03ce13f7SAndroid Build Coastguard Worker /// Get the register for a given argument slot in the GPRs. getRegisterForGprArgNum(Type Ty,uint32_t ArgNum)437*03ce13f7SAndroid Build Coastguard Worker static inline RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) { 438*03ce13f7SAndroid Build Coastguard Worker if (ArgNum >= X86_MAX_GPR_ARGS) { 439*03ce13f7SAndroid Build Coastguard Worker return RegNumT(); 440*03ce13f7SAndroid Build Coastguard Worker } 441*03ce13f7SAndroid Build Coastguard Worker static const AllRegisters GprForArgNum[] = { 442*03ce13f7SAndroid Build Coastguard Worker Reg_rdi, Reg_rsi, Reg_rdx, Reg_rcx, Reg_r8, Reg_r9, 443*03ce13f7SAndroid Build Coastguard Worker }; 444*03ce13f7SAndroid Build Coastguard Worker static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS, 445*03ce13f7SAndroid Build Coastguard Worker "Mismatch between MAX_GPR_ARGS and GprForArgNum."); 446*03ce13f7SAndroid Build Coastguard Worker assert(Ty == IceType_i64 || Ty == IceType_i32); 447*03ce13f7SAndroid Build Coastguard Worker return RegX8664::getGprForType(Ty, GprForArgNum[ArgNum]); 448*03ce13f7SAndroid Build Coastguard Worker } 449*03ce13f7SAndroid Build Coastguard Worker // Given the absolute argument position and argument position by type, return 450*03ce13f7SAndroid Build Coastguard Worker // the register index to assign it to. getArgIndex(SizeT argPos,SizeT argPosByType)451*03ce13f7SAndroid Build Coastguard Worker static inline SizeT getArgIndex(SizeT argPos, SizeT argPosByType) { 452*03ce13f7SAndroid Build Coastguard Worker (void)argPos; 453*03ce13f7SAndroid Build Coastguard Worker return argPosByType; 454*03ce13f7SAndroid Build Coastguard Worker } 455*03ce13f7SAndroid Build Coastguard Worker #endif 456*03ce13f7SAndroid Build Coastguard Worker 457*03ce13f7SAndroid Build Coastguard Worker /// Get the register for a given argument slot in the XMM registers. getRegisterForXmmArgNum(uint32_t ArgNum)458*03ce13f7SAndroid Build Coastguard Worker static inline RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) { 459*03ce13f7SAndroid Build Coastguard Worker // TODO(sehr): Change to use the CCArg technique used in ARM32. 460*03ce13f7SAndroid Build Coastguard Worker static_assert(Reg_xmm0 + 1 == Reg_xmm1, 461*03ce13f7SAndroid Build Coastguard Worker "Inconsistency between XMM register numbers and ordinals"); 462*03ce13f7SAndroid Build Coastguard Worker if (ArgNum >= X86_MAX_XMM_ARGS) { 463*03ce13f7SAndroid Build Coastguard Worker return RegNumT(); 464*03ce13f7SAndroid Build Coastguard Worker } 465*03ce13f7SAndroid Build Coastguard Worker return RegNumT::fixme(Reg_xmm0 + ArgNum); 466*03ce13f7SAndroid Build Coastguard Worker } 467*03ce13f7SAndroid Build Coastguard Worker }; 468*03ce13f7SAndroid Build Coastguard Worker 469*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice 470*03ce13f7SAndroid Build Coastguard Worker 471*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEREGISTERSX8664_H 472