1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_CODEGEN_IA32_REGISTER_IA32_H_
6 #define V8_CODEGEN_IA32_REGISTER_IA32_H_
7
8 #include "src/codegen/register.h"
9 #include "src/codegen/reglist.h"
10
11 namespace v8 {
12 namespace internal {
13
14 #define GENERAL_REGISTERS(V) \
15 V(eax) \
16 V(ecx) \
17 V(edx) \
18 V(ebx) \
19 V(esp) \
20 V(ebp) \
21 V(esi) \
22 V(edi)
23
24 #define ALLOCATABLE_GENERAL_REGISTERS(V) \
25 V(eax) \
26 V(ecx) \
27 V(edx) \
28 V(esi) \
29 V(edi)
30
31 #define DOUBLE_REGISTERS(V) \
32 V(xmm0) \
33 V(xmm1) \
34 V(xmm2) \
35 V(xmm3) \
36 V(xmm4) \
37 V(xmm5) \
38 V(xmm6) \
39 V(xmm7)
40
41 #define FLOAT_REGISTERS DOUBLE_REGISTERS
42 #define SIMD128_REGISTERS DOUBLE_REGISTERS
43
44 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
45 V(xmm1) \
46 V(xmm2) \
47 V(xmm3) \
48 V(xmm4) \
49 V(xmm5) \
50 V(xmm6) \
51 V(xmm7)
52
53 enum RegisterCode {
54 #define REGISTER_CODE(R) kRegCode_##R,
55 GENERAL_REGISTERS(REGISTER_CODE)
56 #undef REGISTER_CODE
57 kRegAfterLast
58 };
59
60 class Register : public RegisterBase<Register, kRegAfterLast> {
61 public:
is_byte_register()62 bool is_byte_register() const { return code() <= 3; }
63
64 private:
65 friend class RegisterBase<Register, kRegAfterLast>;
Register(int code)66 explicit constexpr Register(int code) : RegisterBase(code) {}
67 };
68
69 ASSERT_TRIVIALLY_COPYABLE(Register);
70 static_assert(sizeof(Register) == sizeof(int),
71 "Register can efficiently be passed by value");
72
73 #define DEFINE_REGISTER(R) \
74 constexpr Register R = Register::from_code(kRegCode_##R);
75 GENERAL_REGISTERS(DEFINE_REGISTER)
76 #undef DEFINE_REGISTER
77 constexpr Register no_reg = Register::no_reg();
78
79 // Returns the number of padding slots needed for stack pointer alignment.
ArgumentPaddingSlots(int argument_count)80 constexpr int ArgumentPaddingSlots(int argument_count) {
81 // No argument padding required.
82 return 0;
83 }
84
85 constexpr bool kSimpleFPAliasing = true;
86 constexpr bool kSimdMaskRegisters = false;
87
88 enum DoubleCode {
89 #define REGISTER_CODE(R) kDoubleCode_##R,
90 DOUBLE_REGISTERS(REGISTER_CODE)
91 #undef REGISTER_CODE
92 kDoubleAfterLast
93 };
94
95 class XMMRegister : public RegisterBase<XMMRegister, kDoubleAfterLast> {
96 friend class RegisterBase<XMMRegister, kDoubleAfterLast>;
XMMRegister(int code)97 explicit constexpr XMMRegister(int code) : RegisterBase(code) {}
98 };
99
100 using FloatRegister = XMMRegister;
101
102 using DoubleRegister = XMMRegister;
103
104 using Simd128Register = XMMRegister;
105
106 #define DEFINE_REGISTER(R) \
107 constexpr DoubleRegister R = DoubleRegister::from_code(kDoubleCode_##R);
108 DOUBLE_REGISTERS(DEFINE_REGISTER)
109 #undef DEFINE_REGISTER
110 constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
111
112 // Note that the bit values must match those used in actual instruction encoding
113 constexpr int kNumRegs = 8;
114
115 // Caller-saved registers
116 constexpr RegList kJSCallerSaved =
117 Register::ListOf(eax, ecx, edx,
118 ebx, // used as caller-saved register in JavaScript code
119 edi); // callee function
120
121 constexpr int kNumJSCallerSaved = 5;
122
123 // Number of registers for which space is reserved in safepoints.
124 constexpr int kNumSafepointRegisters = 8;
125
126 // Define {RegisterName} methods for the register types.
127 DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
128 DEFINE_REGISTER_NAMES(XMMRegister, DOUBLE_REGISTERS)
129
130 // Give alias names to registers for calling conventions.
131 constexpr Register kReturnRegister0 = eax;
132 constexpr Register kReturnRegister1 = edx;
133 constexpr Register kReturnRegister2 = edi;
134 constexpr Register kJSFunctionRegister = edi;
135 constexpr Register kContextRegister = esi;
136 constexpr Register kAllocateSizeRegister = edx;
137 constexpr Register kInterpreterAccumulatorRegister = eax;
138 constexpr Register kInterpreterBytecodeOffsetRegister = edx;
139 constexpr Register kInterpreterBytecodeArrayRegister = edi;
140 constexpr Register kInterpreterDispatchTableRegister = esi;
141
142 constexpr Register kJavaScriptCallArgCountRegister = eax;
143 constexpr Register kJavaScriptCallCodeStartRegister = ecx;
144 constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
145 constexpr Register kJavaScriptCallNewTargetRegister = edx;
146
147 // The ExtraArg1Register not part of the real JS calling convention and is
148 // mostly there to simplify consistent interface descriptor definitions across
149 // platforms. Note that on ia32 it aliases kJavaScriptCallCodeStartRegister.
150 constexpr Register kJavaScriptCallExtraArg1Register = ecx;
151
152 // The off-heap trampoline does not need a register on ia32 (it uses a
153 // pc-relative call instead).
154 constexpr Register kOffHeapTrampolineRegister = no_reg;
155
156 constexpr Register kRuntimeCallFunctionRegister = edx;
157 constexpr Register kRuntimeCallArgCountRegister = eax;
158 constexpr Register kRuntimeCallArgvRegister = ecx;
159 constexpr Register kWasmInstanceRegister = esi;
160 constexpr Register kWasmCompileLazyFuncIndexRegister = edi;
161
162 constexpr Register kRootRegister = ebx;
163
164 constexpr DoubleRegister kFPReturnRegister0 = xmm1; // xmm0 isn't allocatable.
165
166 } // namespace internal
167 } // namespace v8
168
169 #endif // V8_CODEGEN_IA32_REGISTER_IA32_H_
170