xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceRegistersX8664.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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