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_X64_REGISTER_X64_H_
6 #define V8_CODEGEN_X64_REGISTER_X64_H_
7
8 #include "src/codegen/register-base.h"
9
10 namespace v8 {
11 namespace internal {
12
13 #define GENERAL_REGISTERS(V) \
14 V(rax) \
15 V(rcx) \
16 V(rdx) \
17 V(rbx) \
18 V(rsp) \
19 V(rbp) \
20 V(rsi) \
21 V(rdi) \
22 V(r8) \
23 V(r9) \
24 V(r10) \
25 V(r11) \
26 V(r12) \
27 V(r13) \
28 V(r14) \
29 V(r15)
30
31 #define ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
32 V(rax) \
33 V(rbx) \
34 V(rdx) \
35 V(rcx) \
36 V(rsi) \
37 V(rdi) \
38 V(r8) \
39 V(r9) \
40 V(r11) \
41 V(r12) \
42 V(r15)
43
44 #ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
45 #define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V)
46 #else
47 #define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V) V(r14)
48 #endif
49
50 #define ALLOCATABLE_GENERAL_REGISTERS(V) \
51 ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
52 MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V)
53
54 enum RegisterCode {
55 #define REGISTER_CODE(R) kRegCode_##R,
56 GENERAL_REGISTERS(REGISTER_CODE)
57 #undef REGISTER_CODE
58 kRegAfterLast
59 };
60
61 class Register : public RegisterBase<Register, kRegAfterLast> {
62 public:
is_byte_register() const63 bool is_byte_register() const { return code() <= 3; }
64 // Return the high bit of the register code as a 0 or 1. Used often
65 // when constructing the REX prefix byte.
high_bit() const66 int high_bit() const { return code() >> 3; }
67 // Return the 3 low bits of the register code. Used when encoding registers
68 // in modR/M, SIB, and opcode bytes.
low_bits() const69 int low_bits() const { return code() & 0x7; }
70
71 private:
72 friend class RegisterBase<Register, kRegAfterLast>;
Register(int code)73 explicit constexpr Register(int code) : RegisterBase(code) {}
74 };
75
76 ASSERT_TRIVIALLY_COPYABLE(Register);
77 static_assert(sizeof(Register) <= sizeof(int),
78 "Register can efficiently be passed by value");
79
80 #define DECLARE_REGISTER(R) \
81 constexpr Register R = Register::from_code(kRegCode_##R);
82 GENERAL_REGISTERS(DECLARE_REGISTER)
83 #undef DECLARE_REGISTER
84 constexpr Register no_reg = Register::no_reg();
85
86 constexpr int kNumRegs = 16;
87
88 #ifdef V8_TARGET_OS_WIN
89 // Windows calling convention
90 constexpr Register arg_reg_1 = rcx;
91 constexpr Register arg_reg_2 = rdx;
92 constexpr Register arg_reg_3 = r8;
93 constexpr Register arg_reg_4 = r9;
94 #else
95 // AMD64 calling convention
96 constexpr Register arg_reg_1 = rdi;
97 constexpr Register arg_reg_2 = rsi;
98 constexpr Register arg_reg_3 = rdx;
99 constexpr Register arg_reg_4 = rcx;
100 #endif // V8_TARGET_OS_WIN
101
102 #define DOUBLE_REGISTERS(V) \
103 V(xmm0) \
104 V(xmm1) \
105 V(xmm2) \
106 V(xmm3) \
107 V(xmm4) \
108 V(xmm5) \
109 V(xmm6) \
110 V(xmm7) \
111 V(xmm8) \
112 V(xmm9) \
113 V(xmm10) \
114 V(xmm11) \
115 V(xmm12) \
116 V(xmm13) \
117 V(xmm14) \
118 V(xmm15)
119
120 #define FLOAT_REGISTERS DOUBLE_REGISTERS
121 #define SIMD128_REGISTERS DOUBLE_REGISTERS
122
123 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
124 V(xmm0) \
125 V(xmm1) \
126 V(xmm2) \
127 V(xmm3) \
128 V(xmm4) \
129 V(xmm5) \
130 V(xmm6) \
131 V(xmm7) \
132 V(xmm8) \
133 V(xmm9) \
134 V(xmm10) \
135 V(xmm11) \
136 V(xmm12) \
137 V(xmm13) \
138 V(xmm14)
139
140 #define YMM_REGISTERS(V) \
141 V(ymm0) \
142 V(ymm1) \
143 V(ymm2) \
144 V(ymm3) \
145 V(ymm4) \
146 V(ymm5) \
147 V(ymm6) \
148 V(ymm7) \
149 V(ymm8) \
150 V(ymm9) \
151 V(ymm10) \
152 V(ymm11) \
153 V(ymm12) \
154 V(ymm13) \
155 V(ymm14) \
156 V(ymm15)
157
158 // Returns the number of padding slots needed for stack pointer alignment.
ArgumentPaddingSlots(int argument_count)159 constexpr int ArgumentPaddingSlots(int argument_count) {
160 // No argument padding required.
161 return 0;
162 }
163
164 constexpr AliasingKind kFPAliasing = AliasingKind::kOverlap;
165 constexpr bool kSimdMaskRegisters = false;
166
167 enum DoubleRegisterCode {
168 #define REGISTER_CODE(R) kDoubleCode_##R,
169 DOUBLE_REGISTERS(REGISTER_CODE)
170 #undef REGISTER_CODE
171 kDoubleAfterLast
172 };
173
174 enum YMMRegisterCode {
175 #define REGISTER_CODE(R) kYMMCode_##R,
176 YMM_REGISTERS(REGISTER_CODE)
177 #undef REGISTER_CODE
178 kYMMAfterLast
179 };
180 static_assert(static_cast<int>(kDoubleAfterLast) ==
181 static_cast<int>(kYMMAfterLast),
182 "The number of XMM register codes must match the number of YMM "
183 "register codes");
184
185 class XMMRegister : public RegisterBase<XMMRegister, kDoubleAfterLast> {
186 public:
187 // Return the high bit of the register code as a 0 or 1. Used often
188 // when constructing the REX prefix byte.
high_bit() const189 int high_bit() const { return code() >> 3; }
190 // Return the 3 low bits of the register code. Used when encoding registers
191 // in modR/M, SIB, and opcode bytes.
low_bits() const192 int low_bits() const { return code() & 0x7; }
193
194 protected:
195 friend class RegisterBase<XMMRegister, kDoubleAfterLast>;
XMMRegister(int code)196 explicit constexpr XMMRegister(int code) : RegisterBase(code) {}
197 };
198
199 ASSERT_TRIVIALLY_COPYABLE(XMMRegister);
200 static_assert(sizeof(XMMRegister) <= sizeof(int),
201 "XMMRegister can efficiently be passed by value");
202
203 class YMMRegister : public XMMRegister {
204 public:
from_code(int code)205 static constexpr YMMRegister from_code(int code) {
206 DCHECK(base::IsInRange(code, 0, XMMRegister::kNumRegisters - 1));
207 return YMMRegister(code);
208 }
209
210 private:
211 friend class XMMRegister;
YMMRegister(int code)212 explicit constexpr YMMRegister(int code) : XMMRegister(code) {}
213 };
214
215 ASSERT_TRIVIALLY_COPYABLE(YMMRegister);
216 static_assert(sizeof(YMMRegister) <= sizeof(int),
217 "YMMRegister can efficiently be passed by value");
218
219 using FloatRegister = XMMRegister;
220
221 using DoubleRegister = XMMRegister;
222
223 using Simd128Register = XMMRegister;
224
225 #define DECLARE_REGISTER(R) \
226 constexpr DoubleRegister R = DoubleRegister::from_code(kDoubleCode_##R);
227 DOUBLE_REGISTERS(DECLARE_REGISTER)
228 #undef DECLARE_REGISTER
229 constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
230
231 #define DECLARE_REGISTER(R) \
232 constexpr YMMRegister R = YMMRegister::from_code(kYMMCode_##R);
233 YMM_REGISTERS(DECLARE_REGISTER)
234 #undef DECLARE_REGISTER
235
236 // Define {RegisterName} methods for the register types.
237 DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
238 DEFINE_REGISTER_NAMES(XMMRegister, DOUBLE_REGISTERS)
239 DEFINE_REGISTER_NAMES(YMMRegister, YMM_REGISTERS)
240
241 // Give alias names to registers for calling conventions.
242 constexpr Register kReturnRegister0 = rax;
243 constexpr Register kReturnRegister1 = rdx;
244 constexpr Register kReturnRegister2 = r8;
245 constexpr Register kJSFunctionRegister = rdi;
246 constexpr Register kContextRegister = rsi;
247 constexpr Register kAllocateSizeRegister = rdx;
248 constexpr Register kInterpreterAccumulatorRegister = rax;
249 constexpr Register kInterpreterBytecodeOffsetRegister = r9;
250 constexpr Register kInterpreterBytecodeArrayRegister = r12;
251 constexpr Register kInterpreterDispatchTableRegister = r15;
252
253 constexpr Register kJavaScriptCallArgCountRegister = rax;
254 constexpr Register kJavaScriptCallCodeStartRegister = rcx;
255 constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
256 constexpr Register kJavaScriptCallNewTargetRegister = rdx;
257 constexpr Register kJavaScriptCallExtraArg1Register = rbx;
258
259 constexpr Register kRuntimeCallFunctionRegister = rbx;
260 constexpr Register kRuntimeCallArgCountRegister = rax;
261 constexpr Register kRuntimeCallArgvRegister = r15;
262 constexpr Register kWasmInstanceRegister = rsi;
263
264 // Default scratch register used by MacroAssembler (and other code that needs
265 // a spare register). The register isn't callee save, and not used by the
266 // function calling convention.
267 constexpr Register kScratchRegister = r10;
268 constexpr XMMRegister kScratchDoubleReg = xmm15;
269 constexpr Register kRootRegister = r13; // callee save
270 #ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
271 constexpr Register kPtrComprCageBaseRegister = r14; // callee save
272 #else
273 constexpr Register kPtrComprCageBaseRegister = kRootRegister;
274 #endif
275
276 constexpr Register kOffHeapTrampolineRegister = kScratchRegister;
277
278 constexpr DoubleRegister kFPReturnRegister0 = xmm0;
279
280 } // namespace internal
281 } // namespace v8
282
283 #endif // V8_CODEGEN_X64_REGISTER_X64_H_
284