xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceRegistersX8632.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 //===- subzero/src/IceRegistersX8632.h - Register information ---*- C++ -*-===//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Declares the registers and their encodings for x86-32.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef SUBZERO_SRC_ICEREGISTERSX8632_H
16 #define SUBZERO_SRC_ICEREGISTERSX8632_H
17 
18 #include "IceBitVector.h"
19 #include "IceDefs.h"
20 #include "IceInstX8632.def"
21 #include "IceTargetLowering.h"
22 #include "IceTargetLoweringX86RegClass.h"
23 #include "IceTypes.h"
24 
25 #include <initializer_list>
26 
27 namespace Ice {
28 using namespace ::Ice::X86;
29 
30 class RegX8632 {
31 public:
32   /// An enum of every register. The enum value may not match the encoding used
33   /// to binary encode register operands in instructions.
34   enum AllRegisters {
35 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
36           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
37           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
38   val,
39     REGX8632_TABLE
40 #undef X
41         Reg_NUM
42   };
43 
44   /// An enum of GPR Registers. The enum value does match the encoding used to
45   /// binary encode register operands in instructions.
46   enum GPRRegister {
47 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
48           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
49           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
50   Encoded_##val = encode,
51     REGX8632_GPR_TABLE
52 #undef X
53         Encoded_Not_GPR = -1
54   };
55 
56   /// An enum of XMM Registers. The enum value does match the encoding used to
57   /// binary encode register operands in instructions.
58   enum XmmRegister {
59 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
60           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
61           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
62   Encoded_##val = encode,
63     REGX8632_XMM_TABLE
64 #undef X
65         Encoded_Not_Xmm = -1
66   };
67 
68   /// An enum of Byte Registers. The enum value does match the encoding used to
69   /// binary encode register operands in instructions.
70   enum ByteRegister {
71 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
72           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
73           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
74   Encoded_8_##val = encode,
75     REGX8632_BYTEREG_TABLE
76 #undef X
77         Encoded_Not_ByteReg = -1
78   };
79 
80   /// An enum of X87 Stack Registers. The enum value does match the encoding
81   /// used to binary encode register operands in instructions.
82   enum X87STRegister {
83 #define X(val, encode, name) Encoded_##val = encode,
84     X87ST_REGX8632_TABLE
85 #undef X
86         Encoded_Not_X87STReg = -1
87   };
88 
getEncodedSTReg(uint32_t X87RegNum)89   static inline X87STRegister getEncodedSTReg(uint32_t X87RegNum) {
90     assert(int(Encoded_X87ST_First) <= int(X87RegNum));
91     assert(X87RegNum <= Encoded_X87ST_Last);
92     return X87STRegister(X87RegNum);
93   }
94 
getRegName(RegNumT RegNum)95   static inline const char *getRegName(RegNumT RegNum) {
96     static const char *const RegNames[Reg_NUM] = {
97 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
98           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
99           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
100   name,
101         REGX8632_TABLE
102 #undef X
103     };
104     RegNum.assertIsValid();
105     return RegNames[RegNum];
106   }
107 
getEncodedGPR(RegNumT RegNum)108   static inline GPRRegister getEncodedGPR(RegNumT RegNum) {
109     static const GPRRegister GPRRegs[Reg_NUM] = {
110 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
111           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
112           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
113   GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
114         REGX8632_TABLE
115 #undef X
116     };
117     RegNum.assertIsValid();
118     assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
119     return GPRRegs[RegNum];
120   }
121 
getEncodedByteReg(RegNumT RegNum)122   static inline ByteRegister getEncodedByteReg(RegNumT RegNum) {
123     static const ByteRegister ByteRegs[Reg_NUM] = {
124 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
125           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
126           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
127   ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
128         REGX8632_TABLE
129 #undef X
130     };
131     RegNum.assertIsValid();
132     assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
133     return ByteRegs[RegNum];
134   }
135 
isXmm(RegNumT RegNum)136   static inline bool isXmm(RegNumT RegNum) {
137     static const bool IsXmm[Reg_NUM] = {
138 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
139           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
140           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
141   isXmm,
142         REGX8632_TABLE
143 #undef X
144     };
145     return IsXmm[RegNum];
146   }
147 
getEncodedXmm(RegNumT RegNum)148   static inline XmmRegister getEncodedXmm(RegNumT RegNum) {
149     static const XmmRegister XmmRegs[Reg_NUM] = {
150 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
151           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
152           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
153   XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
154         REGX8632_TABLE
155 #undef X
156     };
157     RegNum.assertIsValid();
158     assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
159     return XmmRegs[RegNum];
160   }
161 
getEncoding(RegNumT RegNum)162   static inline uint32_t getEncoding(RegNumT RegNum) {
163     static const uint32_t Encoding[Reg_NUM] = {
164 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
165           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
166           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
167   encode,
168         REGX8632_TABLE
169 #undef X
170     };
171     RegNum.assertIsValid();
172     return Encoding[RegNum];
173   }
174 
getBaseReg(RegNumT RegNum)175   static inline RegNumT getBaseReg(RegNumT RegNum) {
176     static const RegNumT BaseRegs[Reg_NUM] = {
177 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
178           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
179           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
180   base,
181         REGX8632_TABLE
182 #undef X
183     };
184     RegNum.assertIsValid();
185     return BaseRegs[RegNum];
186   }
187 
188 private:
getFirstGprForType(Type Ty)189   static inline AllRegisters getFirstGprForType(Type Ty) {
190     switch (Ty) {
191     default:
192       llvm_unreachable("Invalid type for GPR.");
193     case IceType_i1:
194     case IceType_i8:
195       return Reg_al;
196     case IceType_i16:
197       return Reg_ax;
198     case IceType_i32:
199       return Reg_eax;
200     }
201   }
202 
203 public:
204   // Return a register in RegNum's alias set that is suitable for Ty.
getGprForType(Type Ty,RegNumT RegNum)205   static inline RegNumT getGprForType(Type Ty, RegNumT RegNum) {
206     assert(RegNum.hasValue());
207 
208     if (!isScalarIntegerType(Ty)) {
209       return RegNum;
210     }
211 
212     // [abcd]h registers are not convertible to their ?l, ?x, and e?x versions.
213     switch (RegNum) {
214     default:
215       break;
216     case Reg_ah:
217     case Reg_bh:
218     case Reg_ch:
219     case Reg_dh:
220       assert(isByteSizedType(Ty));
221       return RegNum;
222     }
223 
224     const AllRegisters FirstGprForType = getFirstGprForType(Ty);
225 
226     switch (RegNum) {
227     default:
228       llvm::report_fatal_error("Unknown register.");
229 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
230           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
231           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
232   case val: {                                                                  \
233     if (!isGPR)                                                                \
234       return val;                                                              \
235     assert((is32) || (is16) || (is8) || getBaseReg(val) == Reg_esp);           \
236     constexpr AllRegisters FirstGprWithRegNumSize =                            \
237         (((is32) || val == Reg_esp)                                            \
238              ? Reg_eax                                                         \
239              : (((is16) || val == Reg_sp) ? Reg_ax : Reg_al));                 \
240     const RegNumT NewRegNum =                                                  \
241         RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType);     \
242     assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) &&                      \
243            "Error involving " #val);                                           \
244     return NewRegNum;                                                          \
245   }
246       REGX8632_TABLE
247 #undef X
248     }
249   }
250 
251 public:
252   static inline void
initRegisterSet(const::Ice::ClFlags &,std::array<SmallBitVector,RCX86_NUM> * TypeToRegisterSet,std::array<SmallBitVector,Reg_NUM> * RegisterAliases)253   initRegisterSet(const ::Ice::ClFlags & /*Flags*/,
254                   std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
255                   std::array<SmallBitVector, Reg_NUM> *RegisterAliases) {
256     SmallBitVector IntegerRegistersI32(Reg_NUM);
257     SmallBitVector IntegerRegistersI16(Reg_NUM);
258     SmallBitVector IntegerRegistersI8(Reg_NUM);
259     SmallBitVector FloatRegisters(Reg_NUM);
260     SmallBitVector VectorRegisters(Reg_NUM);
261     SmallBitVector Trunc64To8Registers(Reg_NUM);
262     SmallBitVector Trunc32To8Registers(Reg_NUM);
263     SmallBitVector Trunc16To8Registers(Reg_NUM);
264     SmallBitVector Trunc8RcvrRegisters(Reg_NUM);
265     SmallBitVector AhRcvrRegisters(Reg_NUM);
266     SmallBitVector InvalidRegisters(Reg_NUM);
267 
268     static constexpr struct {
269       uint16_t Val;
270       unsigned Is64 : 1;
271       unsigned Is32 : 1;
272       unsigned Is16 : 1;
273       unsigned Is8 : 1;
274       unsigned IsXmm : 1;
275       unsigned Is64To8 : 1;
276       unsigned Is32To8 : 1;
277       unsigned Is16To8 : 1;
278       unsigned IsTrunc8Rcvr : 1;
279       unsigned IsAhRcvr : 1;
280 #define NUM_ALIASES_BITS 2
281       SizeT NumAliases : (NUM_ALIASES_BITS + 1);
282       uint16_t Aliases[1 << NUM_ALIASES_BITS];
283 #undef NUM_ALIASES_BITS
284     } X8632RegTable[Reg_NUM] = {
285 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,      \
286           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,       \
287           isTrunc8Rcvr, isAhRcvr, aliases)                                      \
288   {                                                                             \
289       val,          is64,     is32,                                             \
290       is16,         is8,      isXmm,                                            \
291       is64To8,      is32To8,  is16To8,                                          \
292       isTrunc8Rcvr, isAhRcvr, (std::initializer_list<uint16_t> aliases).size(), \
293       aliases,                                                                  \
294   },
295         REGX8632_TABLE
296 #undef X
297     };
298 
299     for (SizeT ii = 0; ii < llvm::array_lengthof(X8632RegTable); ++ii) {
300       const auto &Entry = X8632RegTable[ii];
301       (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
302       (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
303       (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
304       (FloatRegisters)[Entry.Val] = Entry.IsXmm;
305       (VectorRegisters)[Entry.Val] = Entry.IsXmm;
306       (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
307       (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
308       (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
309       (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
310       (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
311       (*RegisterAliases)[Entry.Val].resize(Reg_NUM);
312       for (SizeT J = 0; J < Entry.NumAliases; J++) {
313         SizeT Alias = Entry.Aliases[J];
314         assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
315         (*RegisterAliases)[Entry.Val].set(Alias);
316       }
317       (*RegisterAliases)[Entry.Val].set(Entry.Val);
318     }
319 
320     (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
321     (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
322     (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
323     (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
324     (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
325     (*TypeToRegisterSet)[RC_i64] = InvalidRegisters;
326     (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
327     (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
328     (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
329     (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
330     (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
331     (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
332     (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
333     (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
334     (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
335     (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
336     (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
337     (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
338     (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
339     (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
340   }
341 
342   static inline SmallBitVector
getRegisterSet(const::Ice::ClFlags &,TargetLowering::RegSetMask Include,TargetLowering::RegSetMask Exclude)343   getRegisterSet(const ::Ice::ClFlags & /*Flags*/,
344                  TargetLowering::RegSetMask Include,
345                  TargetLowering::RegSetMask Exclude) {
346     SmallBitVector Registers(Reg_NUM);
347 
348 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr,     \
349           isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8,      \
350           isTrunc8Rcvr, isAhRcvr, aliases)                                     \
351   if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave))         \
352     Registers[val] = true;                                                     \
353   if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave))       \
354     Registers[val] = true;                                                     \
355   if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer))      \
356     Registers[val] = true;                                                     \
357   if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer))      \
358     Registers[val] = true;                                                     \
359   if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave))         \
360     Registers[val] = false;                                                    \
361   if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave))       \
362     Registers[val] = false;                                                    \
363   if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer))      \
364     Registers[val] = false;                                                    \
365   if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer))      \
366     Registers[val] = false;
367 
368     REGX8632_TABLE
369 
370 #undef X
371 
372     return Registers;
373   }
374 
375   // x86-32 calling convention:
376   //
377   // * The first four arguments of vector type, regardless of their position
378   // relative to the other arguments in the argument list, are placed in
379   // registers xmm0 - xmm3.
380   //
381   // This intends to match the section "IA-32 Function Calling Convention" of
382   // the document "OS X ABI Function Call Guide" by Apple.
383 
384   /// The maximum number of arguments to pass in XMM registers
385   static constexpr uint32_t X86_MAX_XMM_ARGS = 4;
386   /// The maximum number of arguments to pass in GPR registers
387   static constexpr uint32_t X86_MAX_GPR_ARGS = 0;
388   /// Get the register for a given argument slot in the XMM registers.
getRegisterForXmmArgNum(uint32_t ArgNum)389   static inline RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
390     // TODO(sehr): Change to use the CCArg technique used in ARM32.
391     static_assert(Reg_xmm0 + 1 == Reg_xmm1,
392                   "Inconsistency between XMM register numbers and ordinals");
393     if (ArgNum >= X86_MAX_XMM_ARGS) {
394       return RegNumT();
395     }
396     return RegNumT::fixme(Reg_xmm0 + ArgNum);
397   }
398   /// Get the register for a given argument slot in the GPRs.
getRegisterForGprArgNum(Type Ty,uint32_t ArgNum)399   static inline RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
400     assert(Ty == IceType_i64 || Ty == IceType_i32);
401     (void)Ty;
402     (void)ArgNum;
403     return RegNumT();
404   }
405   // Given the absolute argument position and argument position by type, return
406   // the register index to assign it to.
getArgIndex(SizeT argPos,SizeT argPosByType)407   static inline SizeT getArgIndex(SizeT argPos, SizeT argPosByType) {
408     (void)argPos;
409     return argPosByType;
410   };
411 };
412 
413 } // end of namespace Ice
414 
415 #endif // SUBZERO_SRC_ICEREGISTERSX8632_H
416