v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
register-arm.h
Go to the documentation of this file.
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
9
10namespace v8 {
11namespace 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
59#define REGISTER_CODE(R) kRegCode_##R,
61#undef REGISTER_CODE
63};
64
65class Register : public RegisterBase<Register, kRegAfterLast> {
66 friend class RegisterBase;
67
68 explicit constexpr Register(int code) : RegisterBase(code) {}
69};
70
72static_assert(sizeof(Register) <= sizeof(int),
73 "Register can efficiently be passed by value");
74
75// Assign |source| value to |no_reg| and return the |source|'s previous value.
78 source = Register::no_reg();
79 return result;
80}
81
82// r7: context register
83#define DECLARE_REGISTER(R) \
84 constexpr Register R = Register::from_code(kRegCode_##R);
86#undef DECLARE_REGISTER
88
89// ARM calling convention
90constexpr Register kCArgRegs[] = {r0, r1, r2, r3};
92// The hardfloat calling convention passes double arguments in registers d0-d7.
93static const int kDoubleRegisterPassedArguments = 8;
94
95// Returns the number of padding slots needed for stack pointer alignment.
96constexpr int ArgumentPaddingSlots(int argument_count) {
97 // No argument padding required.
98 return 0;
99}
100
102constexpr bool kSimdMaskRegisters = false;
103
105#define REGISTER_CODE(R) kSwVfpCode_##R,
107#undef REGISTER_CODE
110
111// Representation of a list of non-overlapping VFP registers. This list
112// represents the data layout of VFP registers as a bitfield:
113// S registers cover 1 bit
114// D registers cover 2 bits
115// Q registers cover 4 bits
116//
117// This way, we make sure no registers in the list ever overlap. However, a list
118// may represent multiple different sets of registers,
119// e.g. [d0 s2 s3] <=> [s0 s1 d1].
120using VfpRegList = uint64_t;
121
122// Single word VFP register.
123class SwVfpRegister : public RegisterBase<SwVfpRegister, kSwVfpAfterLast> {
124 public:
125 static constexpr int kSizeInBytes = 4;
126
127 static void split_code(int reg_code, int* vm, int* m) {
128 DCHECK(from_code(reg_code).is_valid());
129 *m = reg_code & 0x1;
130 *vm = reg_code >> 1;
131 }
132 void split_code(int* vm, int* m) const { split_code(code(), vm, m); }
134 // Each bit in the list corresponds to a S register.
135 return uint64_t{0x1} << code();
136 }
137
138 private:
139 friend class RegisterBase;
140 explicit constexpr SwVfpRegister(int code) : RegisterBase(code) {}
141};
142
144static_assert(sizeof(SwVfpRegister) <= sizeof(int),
145 "SwVfpRegister can efficiently be passed by value");
146
148
150#define REGISTER_CODE(R) kDoubleCode_##R,
152#undef REGISTER_CODE
155
156// Double word VFP register.
157class DwVfpRegister : public RegisterBase<DwVfpRegister, kDoubleAfterLast> {
158 public:
159 static constexpr int kSizeInBytes = 8;
160
161 // This function differs from kNumRegisters by returning the number of double
162 // registers supported by the current CPU, while kNumRegisters always returns
163 // 32.
164 inline static int SupportedRegisterCount();
165
166 static void split_code(int reg_code, int* vm, int* m) {
167 DCHECK(from_code(reg_code).is_valid());
168 *m = (reg_code & 0x10) >> 4;
169 *vm = reg_code & 0x0F;
170 }
171 void split_code(int* vm, int* m) const { split_code(code(), vm, m); }
173 // A D register overlaps two S registers.
174 return uint64_t{0x3} << (code() * 2);
175 }
176
177 private:
178 friend class RegisterBase;
179 friend class LowDwVfpRegister;
180 explicit constexpr DwVfpRegister(int code) : RegisterBase(code) {}
181};
182
184static_assert(sizeof(DwVfpRegister) <= sizeof(int),
185 "DwVfpRegister can efficiently be passed by value");
186
188
189// Double word VFP register d0-15.
191 : public RegisterBase<LowDwVfpRegister, kDoubleCode_d16> {
192 public:
193 constexpr operator DwVfpRegister() const { return DwVfpRegister(code()); }
194
197 return SwVfpRegister::from_code(code() * 2 + 1);
198 }
200 // A D register overlaps two S registers.
201 return uint64_t{0x3} << (code() * 2);
202 }
203
204 private:
205 friend class RegisterBase;
206 explicit constexpr LowDwVfpRegister(int code) : RegisterBase(code) {}
207};
208
210#define REGISTER_CODE(R) kSimd128Code_##R,
212#undef REGISTER_CODE
215
216// Quad word NEON register.
217class QwNeonRegister : public RegisterBase<QwNeonRegister, kSimd128AfterLast> {
218 public:
219 static void split_code(int reg_code, int* vm, int* m) {
220 V8_ASSUME(reg_code >= 0 && reg_code < kNumRegisters);
221 int encoded_code = reg_code << 1;
222 *m = (encoded_code & 0x10) >> 4;
223 *vm = encoded_code & 0x0F;
224 }
225 void split_code(int* vm, int* m) const { split_code(code(), vm, m); }
228 return DwVfpRegister::from_code(code() * 2 + 1);
229 }
231 // A Q register overlaps four S registers.
232 return uint64_t{0xf} << (code() * 4);
233 }
234
235 private:
236 friend class RegisterBase;
237 explicit constexpr QwNeonRegister(int code) : RegisterBase(code) {}
238};
239
241
243
245#define REGISTER_CODE(R) kCCode_##R,
247#undef REGISTER_CODE
250
251// Coprocessor register
252class CRegister : public RegisterBase<CRegister, kCAfterLast> {
253 friend class RegisterBase;
254 explicit constexpr CRegister(int code) : RegisterBase(code) {}
255};
256
257// Support for the VFP registers s0 to s31 (d0 to d15).
258// Note that "s(N):s(N+1)" is the same as "d(N/2)".
259#define DECLARE_FLOAT_REGISTER(R) \
260 constexpr SwVfpRegister R = SwVfpRegister::from_code(kSwVfpCode_##R);
262#undef DECLARE_FLOAT_REGISTER
263
264#define DECLARE_LOW_DOUBLE_REGISTER(R) \
265 constexpr LowDwVfpRegister R = LowDwVfpRegister::from_code(kDoubleCode_##R);
267#undef DECLARE_LOW_DOUBLE_REGISTER
268
269#define DECLARE_DOUBLE_REGISTER(R) \
270 constexpr DwVfpRegister R = DwVfpRegister::from_code(kDoubleCode_##R);
272#undef DECLARE_DOUBLE_REGISTER
273
275
276#define DECLARE_SIMD128_REGISTER(R) \
277 constexpr Simd128Register R = Simd128Register::from_code(kSimd128Code_##R);
279#undef DECLARE_SIMD128_REGISTER
280
281// Aliases for double registers.
285
287
288#define DECLARE_C_REGISTER(R) \
289 constexpr CRegister R = CRegister::from_code(kCCode_##R);
291#undef DECLARE_C_REGISTER
292
293// Define {RegisterName} methods for the register types.
300
301// Give alias names to registers for calling conventions.
313
319// DispatchHandle is only needed for the sandbox which is not available on
320// Arm32.
322
328
329// Give alias names to registers
330constexpr Register cp = r7; // JavaScript context pointer.
331constexpr Register r11 = fp;
332constexpr Register kRootRegister = r10; // Roots array pointer.
333
335
337
338} // namespace internal
339} // namespace v8
340
341#endif // V8_CODEGEN_ARM_REGISTER_ARM_H_
constexpr CRegister(int code)
static constexpr int kSizeInBytes
static void split_code(int reg_code, int *vm, int *m)
static int SupportedRegisterCount()
constexpr DwVfpRegister(int code)
void split_code(int *vm, int *m) const
VfpRegList ToVfpRegList() const
constexpr LowDwVfpRegister(int code)
SwVfpRegister high() const
SwVfpRegister low() const
VfpRegList ToVfpRegList() const
constexpr QwNeonRegister(int code)
void split_code(int *vm, int *m) const
static void split_code(int reg_code, int *vm, int *m)
DwVfpRegister low() const
VfpRegList ToVfpRegList() const
DwVfpRegister high() const
static constexpr SwVfpRegister from_code(int8_t code)
constexpr Register(int code)
static constexpr Register no_reg()
static void split_code(int reg_code, int *vm, int *m)
constexpr SwVfpRegister(int code)
void split_code(int *vm, int *m) const
VfpRegList ToVfpRegList() const
static constexpr int kSizeInBytes
ZoneVector< RpoNumber > & result
InstructionOperand source
int m
Definition mul-fft.cc:294
constexpr Register no_reg
constexpr Register kRootRegister
constexpr AliasingKind kFPAliasing
constexpr Register kRuntimeCallFunctionRegister
constexpr Register kRuntimeCallArgvRegister
constexpr Register kJavaScriptCallTargetRegister
uint64_t VfpRegList
constexpr DwVfpRegister no_dreg
constexpr LowDwVfpRegister kLastCalleeSavedDoubleReg
constexpr Register kJavaScriptCallArgCountRegister
constexpr Register kInterpreterAccumulatorRegister
static const int kRegisterPassedArguments
static const int kDoubleRegisterPassedArguments
constexpr DoubleRegister kFPReturnRegister0
constexpr Register kReturnRegister1
constexpr Register kMaglevExtraScratchRegister
constexpr Register kReturnRegister0
constexpr Register kWasmImplicitArgRegister
constexpr Register kContextRegister
constexpr Register kRuntimeCallArgCountRegister
constexpr Register kInterpreterDispatchTableRegister
constexpr Register kAllocateSizeRegister
constexpr LowDwVfpRegister kDoubleRegZero
constexpr Register kJavaScriptCallExtraArg1Register
constexpr Register kJavaScriptCallCodeStartRegister
constexpr Register r11
constexpr Register kReturnRegister2
Register ReassignRegister(Register &source)
constexpr CRegister no_creg
constexpr Register kWasmCompileLazyFuncIndexRegister
constexpr LowDwVfpRegister kFirstCalleeSavedDoubleReg
constexpr Register kStackPointerRegister
constexpr int ArgumentPaddingSlots(int argument_count)
constexpr Register cp
constexpr Register kCArgRegs[]
constexpr bool kSimdMaskRegisters
constexpr Register kJavaScriptCallDispatchHandleRegister
constexpr Register kInterpreterBytecodeOffsetRegister
constexpr Register kJavaScriptCallNewTargetRegister
constexpr Register kJSFunctionRegister
constexpr Register kInterpreterBytecodeArrayRegister
#define DECLARE_FLOAT_REGISTER(R)
#define GENERAL_REGISTERS(V)
#define SIMD128_REGISTERS(V)
#define FLOAT_REGISTERS(V)
#define C_REGISTERS(V)
#define DECLARE_DOUBLE_REGISTER(R)
#define LOW_DOUBLE_REGISTERS(V)
#define NON_LOW_DOUBLE_REGISTERS(V)
#define REGISTER_CODE(R)
#define DECLARE_C_REGISTER(R)
#define DECLARE_LOW_DOUBLE_REGISTER(R)
#define DECLARE_REGISTER(R)
#define DOUBLE_REGISTERS(V)
#define DECLARE_SIMD128_REGISTER(R)
#define DEFINE_REGISTER_NAMES(RegType, LIST)
#define DCHECK(condition)
Definition logging.h:482
#define ASSERT_TRIVIALLY_COPYABLE(T)
Definition macros.h:267
#define arraysize(array)
Definition macros.h:67
#define V8_ASSUME
Definition v8config.h:533