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_X64_REGISTER_X64_H_ |
6 | #define V8_X64_REGISTER_X64_H_ |
7 | |
8 | #include "src/register.h" |
9 | #include "src/reglist.h" |
10 | |
11 | namespace v8 { |
12 | namespace internal { |
13 | |
14 | #define GENERAL_REGISTERS(V) \ |
15 | V(rax) \ |
16 | V(rcx) \ |
17 | V(rdx) \ |
18 | V(rbx) \ |
19 | V(rsp) \ |
20 | V(rbp) \ |
21 | V(rsi) \ |
22 | V(rdi) \ |
23 | V(r8) \ |
24 | V(r9) \ |
25 | V(r10) \ |
26 | V(r11) \ |
27 | V(r12) \ |
28 | V(r13) \ |
29 | V(r14) \ |
30 | V(r15) |
31 | |
32 | #define ALLOCATABLE_GENERAL_REGISTERS(V) \ |
33 | V(rax) \ |
34 | V(rbx) \ |
35 | V(rdx) \ |
36 | V(rcx) \ |
37 | V(rsi) \ |
38 | V(rdi) \ |
39 | V(r8) \ |
40 | V(r9) \ |
41 | V(r11) \ |
42 | V(r12) \ |
43 | V(r14) \ |
44 | V(r15) |
45 | |
46 | enum RegisterCode { |
47 | #define REGISTER_CODE(R) kRegCode_##R, |
48 | GENERAL_REGISTERS(REGISTER_CODE) |
49 | #undef REGISTER_CODE |
50 | kRegAfterLast |
51 | }; |
52 | |
53 | class Register : public RegisterBase<Register, kRegAfterLast> { |
54 | public: |
55 | bool is_byte_register() const { return reg_code_ <= 3; } |
56 | // Return the high bit of the register code as a 0 or 1. Used often |
57 | // when constructing the REX prefix byte. |
58 | int high_bit() const { return reg_code_ >> 3; } |
59 | // Return the 3 low bits of the register code. Used when encoding registers |
60 | // in modR/M, SIB, and opcode bytes. |
61 | int low_bits() const { return reg_code_ & 0x7; } |
62 | |
63 | private: |
64 | friend class RegisterBase<Register, kRegAfterLast>; |
65 | explicit constexpr Register(int code) : RegisterBase(code) {} |
66 | }; |
67 | |
68 | ASSERT_TRIVIALLY_COPYABLE(Register); |
69 | static_assert(sizeof(Register) == sizeof(int), |
70 | "Register can efficiently be passed by value" ); |
71 | |
72 | #define DECLARE_REGISTER(R) \ |
73 | constexpr Register R = Register::from_code<kRegCode_##R>(); |
74 | GENERAL_REGISTERS(DECLARE_REGISTER) |
75 | #undef DECLARE_REGISTER |
76 | constexpr Register no_reg = Register::no_reg(); |
77 | |
78 | constexpr int kNumRegs = 16; |
79 | |
80 | constexpr RegList kJSCallerSaved = |
81 | Register::ListOf<rax, rcx, rdx, |
82 | rbx, // used as a caller-saved register in JavaScript code |
83 | rdi // callee function |
84 | >(); |
85 | |
86 | constexpr int kNumJSCallerSaved = 5; |
87 | |
88 | // Number of registers for which space is reserved in safepoints. |
89 | constexpr int kNumSafepointRegisters = 16; |
90 | |
91 | #ifdef _WIN64 |
92 | // Windows calling convention |
93 | constexpr Register arg_reg_1 = rcx; |
94 | constexpr Register arg_reg_2 = rdx; |
95 | constexpr Register arg_reg_3 = r8; |
96 | constexpr Register arg_reg_4 = r9; |
97 | #else |
98 | // AMD64 calling convention |
99 | constexpr Register arg_reg_1 = rdi; |
100 | constexpr Register arg_reg_2 = rsi; |
101 | constexpr Register arg_reg_3 = rdx; |
102 | constexpr Register arg_reg_4 = rcx; |
103 | #endif // _WIN64 |
104 | |
105 | #define DOUBLE_REGISTERS(V) \ |
106 | V(xmm0) \ |
107 | V(xmm1) \ |
108 | V(xmm2) \ |
109 | V(xmm3) \ |
110 | V(xmm4) \ |
111 | V(xmm5) \ |
112 | V(xmm6) \ |
113 | V(xmm7) \ |
114 | V(xmm8) \ |
115 | V(xmm9) \ |
116 | V(xmm10) \ |
117 | V(xmm11) \ |
118 | V(xmm12) \ |
119 | V(xmm13) \ |
120 | V(xmm14) \ |
121 | V(xmm15) |
122 | |
123 | #define FLOAT_REGISTERS DOUBLE_REGISTERS |
124 | #define SIMD128_REGISTERS DOUBLE_REGISTERS |
125 | |
126 | #define ALLOCATABLE_DOUBLE_REGISTERS(V) \ |
127 | V(xmm0) \ |
128 | V(xmm1) \ |
129 | V(xmm2) \ |
130 | V(xmm3) \ |
131 | V(xmm4) \ |
132 | V(xmm5) \ |
133 | V(xmm6) \ |
134 | V(xmm7) \ |
135 | V(xmm8) \ |
136 | V(xmm9) \ |
137 | V(xmm10) \ |
138 | V(xmm11) \ |
139 | V(xmm12) \ |
140 | V(xmm13) \ |
141 | V(xmm14) |
142 | |
143 | constexpr bool kPadArguments = false; |
144 | constexpr bool kSimpleFPAliasing = true; |
145 | constexpr bool kSimdMaskRegisters = false; |
146 | |
147 | enum DoubleRegisterCode { |
148 | #define REGISTER_CODE(R) kDoubleCode_##R, |
149 | DOUBLE_REGISTERS(REGISTER_CODE) |
150 | #undef REGISTER_CODE |
151 | kDoubleAfterLast |
152 | }; |
153 | |
154 | class XMMRegister : public RegisterBase<XMMRegister, kDoubleAfterLast> { |
155 | public: |
156 | // Return the high bit of the register code as a 0 or 1. Used often |
157 | // when constructing the REX prefix byte. |
158 | int high_bit() const { return reg_code_ >> 3; } |
159 | // Return the 3 low bits of the register code. Used when encoding registers |
160 | // in modR/M, SIB, and opcode bytes. |
161 | int low_bits() const { return reg_code_ & 0x7; } |
162 | |
163 | private: |
164 | friend class RegisterBase<XMMRegister, kDoubleAfterLast>; |
165 | explicit constexpr XMMRegister(int code) : RegisterBase(code) {} |
166 | }; |
167 | |
168 | ASSERT_TRIVIALLY_COPYABLE(XMMRegister); |
169 | static_assert(sizeof(XMMRegister) == sizeof(int), |
170 | "XMMRegister can efficiently be passed by value" ); |
171 | |
172 | typedef XMMRegister FloatRegister; |
173 | |
174 | typedef XMMRegister DoubleRegister; |
175 | |
176 | typedef XMMRegister Simd128Register; |
177 | |
178 | #define DECLARE_REGISTER(R) \ |
179 | constexpr DoubleRegister R = DoubleRegister::from_code<kDoubleCode_##R>(); |
180 | DOUBLE_REGISTERS(DECLARE_REGISTER) |
181 | #undef DECLARE_REGISTER |
182 | constexpr DoubleRegister no_dreg = DoubleRegister::no_reg(); |
183 | |
184 | // Define {RegisterName} methods for the register types. |
185 | DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS) |
186 | DEFINE_REGISTER_NAMES(XMMRegister, DOUBLE_REGISTERS) |
187 | |
188 | // Give alias names to registers for calling conventions. |
189 | constexpr Register kReturnRegister0 = rax; |
190 | constexpr Register kReturnRegister1 = rdx; |
191 | constexpr Register kReturnRegister2 = r8; |
192 | constexpr Register kJSFunctionRegister = rdi; |
193 | constexpr Register kContextRegister = rsi; |
194 | constexpr Register kAllocateSizeRegister = rdx; |
195 | constexpr Register kSpeculationPoisonRegister = r12; |
196 | constexpr Register kInterpreterAccumulatorRegister = rax; |
197 | constexpr Register kInterpreterBytecodeOffsetRegister = r9; |
198 | constexpr Register kInterpreterBytecodeArrayRegister = r14; |
199 | constexpr Register kInterpreterDispatchTableRegister = r15; |
200 | |
201 | constexpr Register kJavaScriptCallArgCountRegister = rax; |
202 | constexpr Register kJavaScriptCallCodeStartRegister = rcx; |
203 | constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister; |
204 | constexpr Register kJavaScriptCallNewTargetRegister = rdx; |
205 | constexpr Register = rbx; |
206 | |
207 | constexpr Register kRuntimeCallFunctionRegister = rbx; |
208 | constexpr Register kRuntimeCallArgCountRegister = rax; |
209 | constexpr Register kRuntimeCallArgvRegister = r15; |
210 | constexpr Register kWasmInstanceRegister = rsi; |
211 | |
212 | // Default scratch register used by MacroAssembler (and other code that needs |
213 | // a spare register). The register isn't callee save, and not used by the |
214 | // function calling convention. |
215 | constexpr Register kScratchRegister = r10; |
216 | constexpr XMMRegister kScratchDoubleReg = xmm15; |
217 | constexpr Register kRootRegister = r13; // callee save |
218 | |
219 | constexpr Register kOffHeapTrampolineRegister = kScratchRegister; |
220 | |
221 | } // namespace internal |
222 | } // namespace v8 |
223 | |
224 | #endif // V8_X64_REGISTER_X64_H_ |
225 | |