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