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_ARM_REGISTER_ARM_H_
6 #define V8_CODEGEN_ARM_REGISTER_ARM_H_
7
8 #include "src/codegen/register-base.h"
9
10 namespace v8 {
11 namespace internal {
12
13 // clang-format off
14 #define GENERAL_REGISTERS(V) \
15 V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
16 V(r8) V(r9) V(r10) V(fp) V(ip) V(sp) V(lr) V(pc)
17
18 #define ALLOCATABLE_GENERAL_REGISTERS(V) \
19 V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
20 V(r8) V(r9)
21
22 #define FLOAT_REGISTERS(V) \
23 V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) \
24 V(s8) V(s9) V(s10) V(s11) V(s12) V(s13) V(s14) V(s15) \
25 V(s16) V(s17) V(s18) V(s19) V(s20) V(s21) V(s22) V(s23) \
26 V(s24) V(s25) V(s26) V(s27) V(s28) V(s29) V(s30) V(s31)
27
28 #define LOW_DOUBLE_REGISTERS(V) \
29 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
30 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15)
31
32 #define NON_LOW_DOUBLE_REGISTERS(V) \
33 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
34 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
35
36 #define DOUBLE_REGISTERS(V) \
37 LOW_DOUBLE_REGISTERS(V) NON_LOW_DOUBLE_REGISTERS(V)
38
39 #define SIMD128_REGISTERS(V) \
40 V(q0) V(q1) V(q2) V(q3) V(q4) V(q5) V(q6) V(q7) \
41 V(q8) V(q9) V(q10) V(q11) V(q12) V(q13) V(q14) V(q15)
42
43 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
44 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
45 V(d8) V(d9) V(d10) V(d11) V(d12) \
46 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
47 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
48
49 #define ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(V) \
50 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
51 V(d8) V(d9) V(d10) V(d11) V(d12) V(d15)
52
53 #define C_REGISTERS(V) \
54 V(cr0) V(cr1) V(cr2) V(cr3) V(cr4) V(cr5) V(cr6) V(cr7) \
55 V(cr8) V(cr9) V(cr10) V(cr11) V(cr12) V(cr15)
56 // clang-format on
57
58 // The ARM ABI does not specify the usage of register r9, which may be reserved
59 // as the static base or thread register on some platforms, in which case we
60 // leave it alone. Adjust the value of kR9Available accordingly:
61 const int kR9Available = 1; // 1 if available to us, 0 if reserved
62
63 enum RegisterCode {
64 #define REGISTER_CODE(R) kRegCode_##R,
65 GENERAL_REGISTERS(REGISTER_CODE)
66 #undef REGISTER_CODE
67 kRegAfterLast
68 };
69
70 class Register : public RegisterBase<Register, kRegAfterLast> {
71 friend class RegisterBase;
72
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 // r7: context register
81 #define DECLARE_REGISTER(R) \
82 constexpr Register R = Register::from_code(kRegCode_##R);
83 GENERAL_REGISTERS(DECLARE_REGISTER)
84 #undef DECLARE_REGISTER
85 constexpr Register no_reg = Register::no_reg();
86
87 // Returns the number of padding slots needed for stack pointer alignment.
ArgumentPaddingSlots(int argument_count)88 constexpr int ArgumentPaddingSlots(int argument_count) {
89 // No argument padding required.
90 return 0;
91 }
92
93 constexpr AliasingKind kFPAliasing = AliasingKind::kCombine;
94 constexpr bool kSimdMaskRegisters = false;
95
96 enum SwVfpRegisterCode {
97 #define REGISTER_CODE(R) kSwVfpCode_##R,
98 FLOAT_REGISTERS(REGISTER_CODE)
99 #undef REGISTER_CODE
100 kSwVfpAfterLast
101 };
102
103 // Representation of a list of non-overlapping VFP registers. This list
104 // represents the data layout of VFP registers as a bitfield:
105 // S registers cover 1 bit
106 // D registers cover 2 bits
107 // Q registers cover 4 bits
108 //
109 // This way, we make sure no registers in the list ever overlap. However, a list
110 // may represent multiple different sets of registers,
111 // e.g. [d0 s2 s3] <=> [s0 s1 d1].
112 using VfpRegList = uint64_t;
113
114 // Single word VFP register.
115 class SwVfpRegister : public RegisterBase<SwVfpRegister, kSwVfpAfterLast> {
116 public:
117 static constexpr int kSizeInBytes = 4;
118
split_code(int reg_code,int * vm,int * m)119 static void split_code(int reg_code, int* vm, int* m) {
120 DCHECK(from_code(reg_code).is_valid());
121 *m = reg_code & 0x1;
122 *vm = reg_code >> 1;
123 }
split_code(int * vm,int * m)124 void split_code(int* vm, int* m) const { split_code(code(), vm, m); }
ToVfpRegList()125 VfpRegList ToVfpRegList() const {
126 DCHECK(is_valid());
127 // Each bit in the list corresponds to a S register.
128 return uint64_t{0x1} << code();
129 }
130
131 private:
132 friend class RegisterBase;
SwVfpRegister(int code)133 explicit constexpr SwVfpRegister(int code) : RegisterBase(code) {}
134 };
135
136 ASSERT_TRIVIALLY_COPYABLE(SwVfpRegister);
137 static_assert(sizeof(SwVfpRegister) <= sizeof(int),
138 "SwVfpRegister can efficiently be passed by value");
139
140 using FloatRegister = SwVfpRegister;
141
142 enum DoubleRegisterCode {
143 #define REGISTER_CODE(R) kDoubleCode_##R,
144 DOUBLE_REGISTERS(REGISTER_CODE)
145 #undef REGISTER_CODE
146 kDoubleAfterLast
147 };
148
149 // Double word VFP register.
150 class DwVfpRegister : public RegisterBase<DwVfpRegister, kDoubleAfterLast> {
151 public:
152 static constexpr int kSizeInBytes = 8;
153
154 // This function differs from kNumRegisters by returning the number of double
155 // registers supported by the current CPU, while kNumRegisters always returns
156 // 32.
157 inline static int SupportedRegisterCount();
158
split_code(int reg_code,int * vm,int * m)159 static void split_code(int reg_code, int* vm, int* m) {
160 DCHECK(from_code(reg_code).is_valid());
161 *m = (reg_code & 0x10) >> 4;
162 *vm = reg_code & 0x0F;
163 }
split_code(int * vm,int * m)164 void split_code(int* vm, int* m) const { split_code(code(), vm, m); }
ToVfpRegList()165 VfpRegList ToVfpRegList() const {
166 DCHECK(is_valid());
167 // A D register overlaps two S registers.
168 return uint64_t{0x3} << (code() * 2);
169 }
170
171 private:
172 friend class RegisterBase;
173 friend class LowDwVfpRegister;
DwVfpRegister(int code)174 explicit constexpr DwVfpRegister(int code) : RegisterBase(code) {}
175 };
176
177 ASSERT_TRIVIALLY_COPYABLE(DwVfpRegister);
178 static_assert(sizeof(DwVfpRegister) <= sizeof(int),
179 "DwVfpRegister can efficiently be passed by value");
180
181 using DoubleRegister = DwVfpRegister;
182
183 // Double word VFP register d0-15.
184 class LowDwVfpRegister
185 : public RegisterBase<LowDwVfpRegister, kDoubleCode_d16> {
186 public:
DwVfpRegister()187 constexpr operator DwVfpRegister() const { return DwVfpRegister(code()); }
188
low()189 SwVfpRegister low() const { return SwVfpRegister::from_code(code() * 2); }
high()190 SwVfpRegister high() const {
191 return SwVfpRegister::from_code(code() * 2 + 1);
192 }
ToVfpRegList()193 VfpRegList ToVfpRegList() const {
194 DCHECK(is_valid());
195 // A D register overlaps two S registers.
196 return uint64_t{0x3} << (code() * 2);
197 }
198
199 private:
200 friend class RegisterBase;
LowDwVfpRegister(int code)201 explicit constexpr LowDwVfpRegister(int code) : RegisterBase(code) {}
202 };
203
204 enum Simd128RegisterCode {
205 #define REGISTER_CODE(R) kSimd128Code_##R,
206 SIMD128_REGISTERS(REGISTER_CODE)
207 #undef REGISTER_CODE
208 kSimd128AfterLast
209 };
210
211 // Quad word NEON register.
212 class QwNeonRegister : public RegisterBase<QwNeonRegister, kSimd128AfterLast> {
213 public:
split_code(int reg_code,int * vm,int * m)214 static void split_code(int reg_code, int* vm, int* m) {
215 DCHECK(from_code(reg_code).is_valid());
216 int encoded_code = reg_code << 1;
217 *m = (encoded_code & 0x10) >> 4;
218 *vm = encoded_code & 0x0F;
219 }
split_code(int * vm,int * m)220 void split_code(int* vm, int* m) const { split_code(code(), vm, m); }
low()221 DwVfpRegister low() const { return DwVfpRegister::from_code(code() * 2); }
high()222 DwVfpRegister high() const {
223 return DwVfpRegister::from_code(code() * 2 + 1);
224 }
ToVfpRegList()225 VfpRegList ToVfpRegList() const {
226 DCHECK(is_valid());
227 // A Q register overlaps four S registers.
228 return uint64_t{0xf} << (code() * 4);
229 }
230
231 private:
232 friend class RegisterBase;
QwNeonRegister(int code)233 explicit constexpr QwNeonRegister(int code) : RegisterBase(code) {}
234 };
235
236 using QuadRegister = QwNeonRegister;
237
238 using Simd128Register = QwNeonRegister;
239
240 enum CRegisterCode {
241 #define REGISTER_CODE(R) kCCode_##R,
242 C_REGISTERS(REGISTER_CODE)
243 #undef REGISTER_CODE
244 kCAfterLast
245 };
246
247 // Coprocessor register
248 class CRegister : public RegisterBase<CRegister, kCAfterLast> {
249 friend class RegisterBase;
CRegister(int code)250 explicit constexpr CRegister(int code) : RegisterBase(code) {}
251 };
252
253 // Support for the VFP registers s0 to s31 (d0 to d15).
254 // Note that "s(N):s(N+1)" is the same as "d(N/2)".
255 #define DECLARE_FLOAT_REGISTER(R) \
256 constexpr SwVfpRegister R = SwVfpRegister::from_code(kSwVfpCode_##R);
257 FLOAT_REGISTERS(DECLARE_FLOAT_REGISTER)
258 #undef DECLARE_FLOAT_REGISTER
259
260 #define DECLARE_LOW_DOUBLE_REGISTER(R) \
261 constexpr LowDwVfpRegister R = LowDwVfpRegister::from_code(kDoubleCode_##R);
262 LOW_DOUBLE_REGISTERS(DECLARE_LOW_DOUBLE_REGISTER)
263 #undef DECLARE_LOW_DOUBLE_REGISTER
264
265 #define DECLARE_DOUBLE_REGISTER(R) \
266 constexpr DwVfpRegister R = DwVfpRegister::from_code(kDoubleCode_##R);
267 NON_LOW_DOUBLE_REGISTERS(DECLARE_DOUBLE_REGISTER)
268 #undef DECLARE_DOUBLE_REGISTER
269
270 constexpr DwVfpRegister no_dreg = DwVfpRegister::no_reg();
271
272 #define DECLARE_SIMD128_REGISTER(R) \
273 constexpr Simd128Register R = Simd128Register::from_code(kSimd128Code_##R);
274 SIMD128_REGISTERS(DECLARE_SIMD128_REGISTER)
275 #undef DECLARE_SIMD128_REGISTER
276
277 // Aliases for double registers.
278 constexpr LowDwVfpRegister kFirstCalleeSavedDoubleReg = d8;
279 constexpr LowDwVfpRegister kLastCalleeSavedDoubleReg = d15;
280 constexpr LowDwVfpRegister kDoubleRegZero = d13;
281
282 constexpr CRegister no_creg = CRegister::no_reg();
283
284 #define DECLARE_C_REGISTER(R) \
285 constexpr CRegister R = CRegister::from_code(kCCode_##R);
286 C_REGISTERS(DECLARE_C_REGISTER)
287 #undef DECLARE_C_REGISTER
288
289 // Define {RegisterName} methods for the register types.
290 DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
291 DEFINE_REGISTER_NAMES(SwVfpRegister, FLOAT_REGISTERS)
292 DEFINE_REGISTER_NAMES(DwVfpRegister, DOUBLE_REGISTERS)
293 DEFINE_REGISTER_NAMES(LowDwVfpRegister, LOW_DOUBLE_REGISTERS)
294 DEFINE_REGISTER_NAMES(QwNeonRegister, SIMD128_REGISTERS)
295 DEFINE_REGISTER_NAMES(CRegister, C_REGISTERS)
296
297 // Give alias names to registers for calling conventions.
298 constexpr Register kReturnRegister0 = r0;
299 constexpr Register kReturnRegister1 = r1;
300 constexpr Register kReturnRegister2 = r2;
301 constexpr Register kJSFunctionRegister = r1;
302 constexpr Register kContextRegister = r7;
303 constexpr Register kAllocateSizeRegister = r1;
304 constexpr Register kInterpreterAccumulatorRegister = r0;
305 constexpr Register kInterpreterBytecodeOffsetRegister = r5;
306 constexpr Register kInterpreterBytecodeArrayRegister = r6;
307 constexpr Register kInterpreterDispatchTableRegister = r8;
308
309 constexpr Register kJavaScriptCallArgCountRegister = r0;
310 constexpr Register kJavaScriptCallCodeStartRegister = r2;
311 constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
312 constexpr Register kJavaScriptCallNewTargetRegister = r3;
313 constexpr Register kJavaScriptCallExtraArg1Register = r2;
314
315 constexpr Register kOffHeapTrampolineRegister = ip;
316 constexpr Register kRuntimeCallFunctionRegister = r1;
317 constexpr Register kRuntimeCallArgCountRegister = r0;
318 constexpr Register kRuntimeCallArgvRegister = r2;
319 constexpr Register kWasmInstanceRegister = r3;
320 constexpr Register kWasmCompileLazyFuncIndexRegister = r4;
321
322 // Give alias names to registers
323 constexpr Register cp = r7; // JavaScript context pointer.
324 constexpr Register r11 = fp;
325 constexpr Register kRootRegister = r10; // Roots array pointer.
326
327 constexpr DoubleRegister kFPReturnRegister0 = d0;
328
329 } // namespace internal
330 } // namespace v8
331
332 #endif // V8_CODEGEN_ARM_REGISTER_ARM_H_
333