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