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