v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
register-riscv.h
Go to the documentation of this file.
1// Copyright 2021 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_RISCV_REGISTER_RISCV_H_
6#define V8_CODEGEN_RISCV_REGISTER_RISCV_H_
7
10
11namespace v8 {
12namespace internal {
13
14// clang-format off
15
16#define GENERAL_REGISTERS(V) \
17 V(zero_reg) V(ra) V(sp) V(gp) V(tp) V(t0) V(t1) V(t2) \
18 V(fp) V(s1) V(a0) V(a1) V(a2) V(a3) V(a4) V(a5) \
19 V(a6) V(a7) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) V(s8) V(s9) \
20 V(s10) V(s11) V(t3) V(t4) V(t5) V(t6)
21
22// s3: scratch register s4: scratch register 2 used in code-generator-riscv64
23// s6: roots in Javascript code s7: context register
24// s11: PtrComprCageBaseRegister
25// t3 t5 : scratch register used in scratch_register_list
26// t6 : call reg.
27// t0 t1 t2 t4:caller saved scratch register can be used in macroassembler and
28// t2: kMaglevExtraScratchRegister
29// builtin-riscv64
30#define ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
31 V(a0) V(a1) V(a2) V(a3) \
32 V(a4) V(a5) V(a6) V(a7) V(t0) \
33 V(t1) V(t2) V(t4) V(s7) V(s8) V(s9) V(s10)
34
35#ifdef V8_COMPRESS_POINTERS
36#define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V)
37#else
38#define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V) V(s11)
39#endif
40
41#define ALLOCATABLE_GENERAL_REGISTERS(V) \
42 ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
43 MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V)
44
45#define DOUBLE_REGISTERS(V) \
46 V(ft0) V(ft1) V(ft2) V(ft3) V(ft4) V(ft5) V(ft6) V(ft7) \
47 V(fs0) V(fs1) V(fa0) V(fa1) V(fa2) V(fa3) V(fa4) V(fa5) \
48 V(fa6) V(fa7) V(fs2) V(fs3) V(fs4) V(fs5) V(fs6) V(fs7) \
49 V(fs8) V(fs9) V(fs10) V(fs11) V(ft8) V(ft9) V(ft10) V(ft11)
50
51#define FLOAT_REGISTERS DOUBLE_REGISTERS
52#define VECTOR_REGISTERS(V) \
53 V(v0) V(v1) V(v2) V(v3) V(v4) V(v5) V(v6) V(v7) \
54 V(v8) V(v9) V(v10) V(v11) V(v12) V(v13) V(v14) V(v15) \
55 V(v16) V(v17) V(v18) V(v19) V(v20) V(v21) V(v22) V(v23) \
56 V(v24) V(v25) V(v26) V(v27) V(v28) V(v29) V(v30) V(v31)
57
58#define ALLOCATABLE_SIMD128_REGISTERS(V) \
59 V(v1) V(v2) V(v3) V(v4) V(v5) V(v6) V(v7) \
60 V(v10) V(v11) V(v12) V(v13) V(v14) V(v15) V(v16) \
61 V(v17) V(v18) V(v19) V(v20) V(v21) V(v22) V(v26) \
62 V(v27) V(v28) V(v29) V(v30) V(v31)
63
64#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
65 V(ft1) V(ft2) V(ft3) V(ft4) V(ft5) V(ft6) V(ft7) V(ft8) \
66 V(ft9) V(ft10) V(ft11) V(fa0) V(fa1) V(fa2) V(fa3) V(fa4) V(fa5) \
67 V(fa6) V(fa7)
68
69// Returns the number of padding slots needed for stack pointer alignment.
70constexpr int ArgumentPaddingSlots(int argument_count) {
71 // No argument padding required.
72 return 0;
73}
74
75// clang-format on
76
77// Note that the bit values must match those used in actual instruction
78// encoding.
79const int kNumRegs = 32;
80const int kUndefIndex = -1;
81// Map with indexes on stack that corresponds to codes of saved registers.
83 kUndefIndex, // ra
84 kUndefIndex, // sp
85 kUndefIndex, // gp
86 kUndefIndex, // tp
87 0, // t0
88 1, // t1
89 2, // t2
90 3, // s0/fp
91 4, // s1
92 5, // a0
93 6, // a1
94 7, // a2
95 8, // a3
96 9, // a4
97 10, // a5
98 11, // a6
99 12, // a7
100 13, // s2
101 14, // s3
102 15, // s4
103 16, // s5
104 17, // s6
105 18, // s7
106 19, // s8
107 10, // s9
108 21, // s10
109 22, // s11
110 kUndefIndex, // t3
111 23, // t4
112 kUndefIndex, // t5
113 kUndefIndex}; // t6
114// CPU Registers.
115//
116// 1) We would prefer to use an enum, but enum values are assignment-
117// compatible with int, which has caused code-generation bugs.
118//
119// 2) We would prefer to use a class instead of a struct but we don't like
120// the register initialization to depend on the particular initialization
121// order (which appears to be different on OS X, Linux, and Windows for the
122// installed versions of C++ we tried). Using a struct permits C-style
123// "initialization". Also, the Register objects cannot be const as this
124// forces initialization stubs in MSVC, making us dependent on initialization
125// order.
126//
127// 3) By not using an enum, we are possibly preventing the compiler from
128// doing certain constant folds, which may significantly reduce the
129// code generated for some assembly instructions (because they boil down
130// to a few constants). If this is a problem, we could change the code
131// such that we use an enum in optimized mode, and the struct in debug
132// mode. This way we get the compile-time error checking in debug mode
133// and best performance in optimized code.
134
135// -----------------------------------------------------------------------------
136// Implementation of Register and FPURegister.
137
139#define REGISTER_CODE(R) kRegCode_##R,
141#undef REGISTER_CODE
143};
144
145class Register : public RegisterBase<Register, kRegAfterLast> {
146 public:
147#if defined(V8_TARGET_LITTLE_ENDIAN)
148 static constexpr int kMantissaOffset = 0;
149 static constexpr int kExponentOffset = 4;
150#elif defined(V8_TARGET_BIG_ENDIAN)
151 static constexpr int kMantissaOffset = 4;
152 static constexpr int kExponentOffset = 0;
153#else
154#error Unknown endianness
155#endif
156
157 private:
158 friend class RegisterBase;
159 explicit constexpr Register(int code) : RegisterBase(code) {}
160};
161
162// s7: context register
163// s3: scratch register
164// s4: scratch register 2
165#define DECLARE_REGISTER(R) \
166 constexpr Register R = Register::from_code(kRegCode_##R);
168#undef DECLARE_REGISTER
169
170constexpr Register no_reg = Register::no_reg();
171
172int ToNumber(Register reg);
173
174Register ToRegister(int num);
175
176constexpr bool kPadArguments = false;
178constexpr bool kSimdMaskRegisters = false;
179
181#define REGISTER_CODE(R) kDoubleCode_##R,
183#undef REGISTER_CODE
185};
186
188#define REGISTER_CODE(R) kVRCode_##R,
190#undef REGISTER_CODE
193class VRegister : public RegisterBase<VRegister, kVRAfterLast> {
194 friend class RegisterBase;
195
196 public:
197 explicit constexpr VRegister(int code) : RegisterBase(code) {}
198};
199
200// Coprocessor register.
201class FPURegister : public RegisterBase<FPURegister, kDoubleAfterLast> {
202 public:
203 // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
204 // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
205 // number of Double regs (64-bit regs, or FPU-reg-pairs).
206
207 FPURegister low() const {
208 // TODO(plind): Create DCHECK for FR=0 mode. This usage suspect for FR=1.
209 // Find low reg of a Double-reg pair, which is the reg itself.
211 }
213 // TODO(plind): Create DCHECK for FR=0 mode. This usage illegal in FR=1.
214 // Find high reg of a Doubel-reg pair, which is reg + 1.
215 return FPURegister::from_code(code() + 1);
216 }
217
218 // FIXME(riscv64): In Rvv, Vector regs is different from Float Regs. But in
219 // this cl, in order to facilitate modification, it is assumed that the vector
220 // register and floating point register are shared.
221 VRegister toV() const {
222 DCHECK(base::IsInRange(static_cast<int>(code()), 0, kVRAfterLast - 1));
223 return VRegister(code());
224 }
225
226 private:
227 friend class RegisterBase;
228 explicit constexpr FPURegister(int code) : RegisterBase(code) {}
229};
230
231// A few double registers are reserved: one as a scratch register and one to
232// hold 0.0.
233// fs9: 0.0
234// fs11: scratch register.
235
236// For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
237using FloatRegister = FPURegister;
238
239using DoubleRegister = FPURegister;
240
241using Simd128Register = VRegister;
242
243#define DECLARE_DOUBLE_REGISTER(R) \
244 constexpr DoubleRegister R = DoubleRegister::from_code(kDoubleCode_##R);
246#undef DECLARE_DOUBLE_REGISTER
247
249
250#define DECLARE_VECTOR_REGISTER(R) \
251 constexpr VRegister R = VRegister::from_code(kVRCode_##R);
253#undef DECLARE_VECTOR_REGISTER
254
255const VRegister no_msareg = VRegister::no_reg();
256
257// Assign |source| value to |no_reg| and return the |source|'s previous value.
258inline Register ReassignRegister(Register& source) {
259 Register result = source;
260 source = Register::no_reg();
261 return result;
262}
263
264// Register aliases.
265// cp is assumed to be a callee saved register.
266constexpr Register kRootRegister = s6;
267constexpr Register cp = s7;
268constexpr Register kScratchReg = s3;
269constexpr Register kScratchReg2 = s4;
271constexpr Register padreg = t6;
272
273constexpr DoubleRegister kScratchDoubleReg = ft0;
274
275constexpr DoubleRegister kDoubleRegZero = fs9;
277
278// Define {RegisterName} methods for the register types.
282
283// Give alias names to registers for calling conventions.
284constexpr Register kCArgRegs[] = {a0, a1, a2, a3, a4, a5, a6, a7};
286constexpr int kFPRegisterPassedArguments = 8;
287
288constexpr Register kReturnRegister0 = a0;
289constexpr Register kReturnRegister1 = a1;
290constexpr Register kReturnRegister2 = a2;
291constexpr Register kJSFunctionRegister = a1;
292constexpr Register kContextRegister = s7;
293constexpr Register kAllocateSizeRegister = a1;
294constexpr Register kInterpreterAccumulatorRegister = a0;
295constexpr Register kInterpreterBytecodeOffsetRegister = t0;
296constexpr Register kInterpreterBytecodeArrayRegister = t1;
297constexpr Register kInterpreterDispatchTableRegister = t2;
298
299constexpr Register kJavaScriptCallArgCountRegister = a0;
300constexpr Register kJavaScriptCallCodeStartRegister = a2;
302constexpr Register kJavaScriptCallNewTargetRegister = a3;
303constexpr Register kJavaScriptCallExtraArg1Register = a2;
304#ifdef V8_TARGET_ARCH_RISCV64
305constexpr Register kJavaScriptCallDispatchHandleRegister = a4;
306#else
308#endif
309
310constexpr Register kRuntimeCallFunctionRegister = a1;
311constexpr Register kRuntimeCallArgCountRegister = a0;
312constexpr Register kRuntimeCallArgvRegister = a2;
313constexpr Register kWasmImplicitArgRegister = a7;
314constexpr Register kWasmCompileLazyFuncIndexRegister = t0;
315constexpr Register kWasmTrapHandlerFaultAddressRegister = t6;
316
317constexpr DoubleRegister kFPReturnRegister0 = fa0;
318
320
323
324constexpr VRegister kSimd128ScratchReg = v24;
327constexpr VRegister kSimd128RegZero = v25;
328
329#ifdef V8_COMPRESS_POINTERS
330constexpr Register kPtrComprCageBaseRegister = s11; // callee save
331#else
333#endif
334
335} // namespace internal
336} // namespace v8
337
338#endif // V8_CODEGEN_RISCV_REGISTER_RISCV_H_
FPURegister low() const
FPURegister high() const
constexpr FPURegister(int code)
static constexpr FPURegister from_code(int8_t code)
static constexpr int kMantissaOffset
friend class RegisterBase
constexpr Register(int code)
static constexpr int kExponentOffset
static constexpr Register no_reg()
static constexpr VRegister no_reg()
constexpr VRegister(int code)
ZoneVector< RpoNumber > & result
LiftoffRegister reg
InstructionOperand source
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
Definition bounds.h:20
constexpr Register no_reg
constexpr Register kRootRegister
const Simd128Register no_msareg
constexpr AliasingKind kFPAliasing
constexpr Register kRuntimeCallFunctionRegister
constexpr int kFPRegisterPassedArguments
DwVfpRegister DoubleRegister
constexpr Simd128Register kSimd128RegZero
constexpr DoubleRegister kScratchDoubleReg
constexpr int kNumRegs
constexpr Register kRuntimeCallArgvRegister
constexpr Register kJavaScriptCallTargetRegister
constexpr DwVfpRegister no_dreg
constexpr Register kJavaScriptCallArgCountRegister
constexpr Register kInterpreterAccumulatorRegister
int ToNumber(Register reg)
constexpr Register kScratchReg2
constexpr VRegister kSimd128ScratchReg2
constexpr Register kScratchReg
static const int kRegisterPassedArguments
constexpr Register kSimulatorBreakArgument
QwNeonRegister Simd128Register
constexpr DoubleRegister kSingleRegZero
constexpr DoubleRegister kFPReturnRegister0
constexpr Register kReturnRegister1
constexpr Register kMaglevExtraScratchRegister
constexpr Simd128Register kSimd128ScratchReg
constexpr Register kReturnRegister0
constexpr bool kPadArguments
constexpr Register kWasmImplicitArgRegister
constexpr Register kContextRegister
constexpr VRegister kSimd128ScratchReg3
constexpr Register kRuntimeCallArgCountRegister
constexpr Register kInterpreterDispatchTableRegister
constexpr Register kAllocateSizeRegister
constexpr Register kWasmTrapHandlerFaultAddressRegister
constexpr LowDwVfpRegister kDoubleRegZero
constexpr Register kJavaScriptCallExtraArg1Register
Register ToRegister(int num)
constexpr Register kJavaScriptCallCodeStartRegister
constexpr Register kPtrComprCageBaseRegister
constexpr Register kReturnRegister2
Register ReassignRegister(Register &source)
constexpr Register kWasmCompileLazyFuncIndexRegister
const int kSafepointRegisterStackIndexMap[kNumRegs]
constexpr Register kStackPointerRegister
constexpr int ArgumentPaddingSlots(int argument_count)
constexpr Register cp
constexpr Register kCArgRegs[]
constexpr Register kMaglevFlagsRegister
constexpr bool kSimdMaskRegisters
constexpr Register kJavaScriptCallDispatchHandleRegister
const int kUndefIndex
constexpr Register kInterpreterBytecodeOffsetRegister
constexpr Register kJavaScriptCallNewTargetRegister
constexpr Register kJSFunctionRegister
SwVfpRegister FloatRegister
constexpr Register kInterpreterBytecodeArrayRegister
constexpr Register padreg
#define VECTOR_REGISTERS(V)
#define GENERAL_REGISTERS(V)
#define DECLARE_DOUBLE_REGISTER(R)
#define REGISTER_CODE(R)
#define DECLARE_REGISTER(R)
#define DOUBLE_REGISTERS(V)
#define DEFINE_REGISTER_NAMES(RegType, LIST)
#define DECLARE_VECTOR_REGISTER(R)
#define DCHECK(condition)
Definition logging.h:482
#define arraysize(array)
Definition macros.h:67