blob: 83773bbdc1036bda47d29fba8f6877bcb5d09f7f [file] [log] [blame]
Jan Voungbd385e42014-09-18 18:18:10 -07001//===- 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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the registers and their encodings for x86-32.
Andrew Scull9612d322015-07-06 14:53:25 -070012///
Jan Voungbd385e42014-09-18 18:18:10 -070013//===----------------------------------------------------------------------===//
14
15#ifndef SUBZERO_SRC_ICEREGISTERSX8632_H
16#define SUBZERO_SRC_ICEREGISTERSX8632_H
17
Nicolas Capens557d0152021-07-14 17:06:38 -040018#include "IceBitVector.h"
Jan Voungbd385e42014-09-18 18:18:10 -070019#include "IceDefs.h"
20#include "IceInstX8632.def"
Nicolas Capens557d0152021-07-14 17:06:38 -040021#include "IceTargetLowering.h"
22#include "IceTargetLoweringX86RegClass.h"
Jan Voung3b43b892014-09-24 13:32:39 -070023#include "IceTypes.h"
Jan Voungbd385e42014-09-18 18:18:10 -070024
Nicolas Capens557d0152021-07-14 17:06:38 -040025#include <initializer_list>
26
Jan Voungbd385e42014-09-18 18:18:10 -070027namespace Ice {
Nicolas Capens557d0152021-07-14 17:06:38 -040028using namespace ::Ice::X86;
Jan Voungbd385e42014-09-18 18:18:10 -070029
John Porto5d0acff2015-06-30 15:29:21 -070030class RegX8632 {
31public:
Andrew Scull57e12682015-09-16 11:30:19 -070032 /// An enum of every register. The enum value may not match the encoding used
33 /// to binary encode register operands in instructions.
John Porto5d0acff2015-06-30 15:29:21 -070034 enum AllRegisters {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -070035#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
36 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
37 isTrunc8Rcvr, isAhRcvr, aliases) \
Jan Voungbd385e42014-09-18 18:18:10 -070038 val,
John Porto5d0acff2015-06-30 15:29:21 -070039 REGX8632_TABLE
Jan Voungbd385e42014-09-18 18:18:10 -070040#undef X
Jim Stichnoth5bff61c2015-10-28 09:26:00 -070041 Reg_NUM
John Porto5d0acff2015-06-30 15:29:21 -070042 };
Jan Voungbd385e42014-09-18 18:18:10 -070043
Andrew Scull57e12682015-09-16 11:30:19 -070044 /// An enum of GPR Registers. The enum value does match the encoding used to
45 /// binary encode register operands in instructions.
John Porto5d0acff2015-06-30 15:29:21 -070046 enum GPRRegister {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -070047#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
48 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
49 isTrunc8Rcvr, isAhRcvr, aliases) \
Jim Stichnoth728c1d42015-07-15 09:00:07 -070050 Encoded_##val = encode,
John Porto5d0acff2015-06-30 15:29:21 -070051 REGX8632_GPR_TABLE
Jan Voung8acded02014-09-22 18:02:25 -070052#undef X
John Porto5d0acff2015-06-30 15:29:21 -070053 Encoded_Not_GPR = -1
54 };
Jan Voung8acded02014-09-22 18:02:25 -070055
Andrew Scull57e12682015-09-16 11:30:19 -070056 /// An enum of XMM Registers. The enum value does match the encoding used to
57 /// binary encode register operands in instructions.
John Porto5d0acff2015-06-30 15:29:21 -070058 enum XmmRegister {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -070059#define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
60 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \
61 isTrunc8Rcvr, isAhRcvr, aliases) \
Jim Stichnoth728c1d42015-07-15 09:00:07 -070062 Encoded_##val = encode,
John Porto5d0acff2015-06-30 15:29:21 -070063 REGX8632_XMM_TABLE
Jan Voung8acded02014-09-22 18:02:25 -070064#undef X
John Porto5d0acff2015-06-30 15:29:21 -070065 Encoded_Not_Xmm = -1
66 };
Jan Voung8acded02014-09-22 18:02:25 -070067
Andrew Scull57e12682015-09-16 11:30:19 -070068 /// An enum of Byte Registers. The enum value does match the encoding used to
69 /// binary encode register operands in instructions.
John Porto5d0acff2015-06-30 15:29:21 -070070 enum ByteRegister {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -070071#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,
John Porto5d0acff2015-06-30 15:29:21 -070075 REGX8632_BYTEREG_TABLE
Jan Voung8acded02014-09-22 18:02:25 -070076#undef X
John Porto5d0acff2015-06-30 15:29:21 -070077 Encoded_Not_ByteReg = -1
78 };
Jan Voung8acded02014-09-22 18:02:25 -070079
Andrew Scull87f80c12015-07-20 10:19:16 -070080 /// An enum of X87 Stack Registers. The enum value does match the encoding
81 /// used to binary encode register operands in instructions.
John Porto5d0acff2015-06-30 15:29:21 -070082 enum X87STRegister {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -070083#define X(val, encode, name) Encoded_##val = encode,
John Porto5d0acff2015-06-30 15:29:21 -070084 X87ST_REGX8632_TABLE
Jan Voung479e5632014-10-08 21:05:27 -070085#undef X
John Porto5d0acff2015-06-30 15:29:21 -070086 Encoded_Not_X87STReg = -1
87 };
88
Jim Stichnoth8aa39662016-02-10 11:20:30 -080089 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);
John Porto5d0acff2015-06-30 15:29:21 -070093 }
Nicolas Capens557d0152021-07-14 17:06:38 -040094
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
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
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
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
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
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
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
188private:
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
203public:
204 // Return a register in RegNum's alias set that is suitable for Ty.
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
251public:
252 static inline void
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
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.
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.
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.
407 static inline SizeT getArgIndex(SizeT argPos, SizeT argPosByType) {
408 (void)argPos;
409 return argPosByType;
410 };
Jan Voung479e5632014-10-08 21:05:27 -0700411};
412
Jan Voungbd385e42014-09-18 18:18:10 -0700413} // end of namespace Ice
414
415#endif // SUBZERO_SRC_ICEREGISTERSX8632_H