v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
register-mips64.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_MIPS64_REGISTER_MIPS64_H_
6#define V8_CODEGEN_MIPS64_REGISTER_MIPS64_H_
7
10
11namespace v8 {
12namespace internal {
13
14// clang-format off
15#define GENERAL_REGISTERS(V) \
16 V(zero_reg) V(at) V(v0) V(v1) V(a0) V(a1) V(a2) V(a3) \
17 V(a4) V(a5) V(a6) V(a7) V(t0) V(t1) V(t2) V(t3) \
18 V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) V(t8) V(t9) \
19 V(k0) V(k1) V(gp) V(sp) V(fp) V(ra)
20
21#define ALLOCATABLE_GENERAL_REGISTERS(V) \
22 V(a0) V(a1) V(a2) V(a3) \
23 V(a4) V(a5) V(a6) V(a7) V(t0) V(t1) V(t2) V(t3) V(s7) \
24 V(v0) V(v1)
25
26#define DOUBLE_REGISTERS(V) \
27 V(f0) V(f1) V(f2) V(f3) V(f4) V(f5) V(f6) V(f7) \
28 V(f8) V(f9) V(f10) V(f11) V(f12) V(f13) V(f14) V(f15) \
29 V(f16) V(f17) V(f18) V(f19) V(f20) V(f21) V(f22) V(f23) \
30 V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
31
32// Currently, MIPS64 just use even float point register, except
33// for C function param registers.
34#define DOUBLE_USE_REGISTERS(V) \
35 V(f0) V(f2) V(f4) V(f6) V(f8) V(f10) V(f12) V(f13) \
36 V(f14) V(f15) V(f16) V(f17) V(f18) V(f19) V(f20) V(f22) \
37 V(f24) V(f26) V(f28) V(f30)
38
39#define FLOAT_REGISTERS DOUBLE_REGISTERS
40#define SIMD128_REGISTERS(V) \
41 V(w0) V(w1) V(w2) V(w3) V(w4) V(w5) V(w6) V(w7) \
42 V(w8) V(w9) V(w10) V(w11) V(w12) V(w13) V(w14) V(w15) \
43 V(w16) V(w17) V(w18) V(w19) V(w20) V(w21) V(w22) V(w23) \
44 V(w24) V(w25) V(w26) V(w27) V(w28) V(w29) V(w30) V(w31)
45
46#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
47 V(f0) V(f2) V(f4) V(f6) V(f8) V(f10) V(f12) V(f14) \
48 V(f16) V(f18) V(f20) V(f22) V(f24) V(f26)
49// clang-format on
50
51// Note that the bit values must match those used in actual instruction
52// encoding.
53const int kNumRegs = 32;
54
55// CPU Registers.
56//
57// 1) We would prefer to use an enum, but enum values are assignment-
58// compatible with int, which has caused code-generation bugs.
59//
60// 2) We would prefer to use a class instead of a struct but we don't like
61// the register initialization to depend on the particular initialization
62// order (which appears to be different on OS X, Linux, and Windows for the
63// installed versions of C++ we tried). Using a struct permits C-style
64// "initialization". Also, the Register objects cannot be const as this
65// forces initialization stubs in MSVC, making us dependent on initialization
66// order.
67//
68// 3) By not using an enum, we are possibly preventing the compiler from
69// doing certain constant folds, which may significantly reduce the
70// code generated for some assembly instructions (because they boil down
71// to a few constants). If this is a problem, we could change the code
72// such that we use an enum in optimized mode, and the struct in debug
73// mode. This way we get the compile-time error checking in debug mode
74// and best performance in optimized code.
75
76// -----------------------------------------------------------------------------
77// Implementation of Register and FPURegister.
78
80#define REGISTER_CODE(R) kRegCode_##R,
82#undef REGISTER_CODE
84};
85
86class Register : public RegisterBase<Register, kRegAfterLast> {
87 public:
88#if defined(V8_TARGET_LITTLE_ENDIAN)
89 static constexpr int kMantissaOffset = 0;
90 static constexpr int kExponentOffset = 4;
91#elif defined(V8_TARGET_BIG_ENDIAN)
92 static constexpr int kMantissaOffset = 4;
93 static constexpr int kExponentOffset = 0;
94#else
95#error Unknown endianness
96#endif
97
98 private:
99 friend class RegisterBase;
100 explicit constexpr Register(int code) : RegisterBase(code) {}
101};
102
103// s7: context register
104// s3: scratch register
105// s4: scratch register 2
106#define DECLARE_REGISTER(R) \
107 constexpr Register R = Register::from_code(kRegCode_##R);
109#undef DECLARE_REGISTER
110
111constexpr Register no_reg = Register::no_reg();
112
113int ToNumber(Register reg);
114
115Register ToRegister(int num);
116
117// Assign |source| value to |no_reg| and return the |source|'s previous value.
118inline Register ReassignRegister(Register& source) {
119 Register result = source;
120 source = Register::no_reg();
121 return result;
122}
123
124// Returns the number of padding slots needed for stack pointer alignment.
125constexpr int ArgumentPaddingSlots(int argument_count) {
126 // No argument padding required.
127 return 0;
128}
129
131constexpr bool kSimdMaskRegisters = false;
132
134#define REGISTER_CODE(R) kMsaCode_##R,
136#undef REGISTER_CODE
139
140// MIPS SIMD (MSA) register
141class MSARegister : public RegisterBase<MSARegister, kMsaAfterLast> {
142 friend class RegisterBase;
143 explicit constexpr MSARegister(int code) : RegisterBase(code) {}
144};
145
147#define REGISTER_CODE(R) kDoubleCode_##R,
149#undef REGISTER_CODE
151};
152
153// Coprocessor register.
154class FPURegister : public RegisterBase<FPURegister, kDoubleAfterLast> {
155 public:
156 // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
157 // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
158 // number of Double regs (64-bit regs, or FPU-reg-pairs).
159
160 FPURegister low() const {
161 // TODO(plind): Create DCHECK for FR=0 mode. This usage suspect for FR=1.
162 // Find low reg of a Double-reg pair, which is the reg itself.
163 DCHECK_EQ(code() % 2, 0); // Specified Double reg must be even.
165 }
167 // TODO(plind): Create DCHECK for FR=0 mode. This usage illegal in FR=1.
168 // Find high reg of a Doubel-reg pair, which is reg + 1.
169 DCHECK_EQ(code() % 2, 0); // Specified Double reg must be even.
170 return FPURegister::from_code(code() + 1);
171 }
172
174
175 private:
176 friend class RegisterBase;
177 explicit constexpr FPURegister(int code) : RegisterBase(code) {}
178};
179
180// A few double registers are reserved: one as a scratch register and one to
181// hold 0.0.
182// f28: 0.0
183// f30: scratch register.
184
185// V8 now supports the O32 ABI, and the FPU Registers are organized as 32
186// 32-bit registers, f0 through f31. When used as 'double' they are used
187// in pairs, starting with the even numbered register. So a double operation
188// on f0 really uses f0 and f1.
189// (Modern mips hardware also supports 32 64-bit registers, via setting
190// (privileged) Status Register FR bit to 1. This is used by the N32 ABI,
191// but it is not in common use. Someday we will want to support this in v8.)
192
193// For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
194using FloatRegister = FPURegister;
195
196using DoubleRegister = FPURegister;
197
198#define DECLARE_DOUBLE_REGISTER(R) \
199 constexpr DoubleRegister R = DoubleRegister::from_code(kDoubleCode_##R);
201#undef DECLARE_DOUBLE_REGISTER
202
204
205// SIMD registers.
206using Simd128Register = MSARegister;
207
208#define DECLARE_SIMD128_REGISTER(R) \
209 constexpr Simd128Register R = Simd128Register::from_code(kMsaCode_##R);
211#undef DECLARE_SIMD128_REGISTER
212
214
215// Register aliases.
216// cp is assumed to be a callee saved register.
217constexpr Register kRootRegister = s6;
218constexpr Register cp = s7;
219constexpr Register kScratchReg = s3;
220constexpr Register kScratchReg2 = s4;
221constexpr DoubleRegister kScratchDoubleReg = f30;
222constexpr DoubleRegister kScratchDoubleReg2 = f31;
223// FPU zero reg is often used to hold 0.0, but it's not hardwired to 0.0.
224constexpr DoubleRegister kDoubleRegZero = f28;
225// Used on mips64r6 for compare operations.
226// We use the last non-callee saved odd register for N64 ABI
228// MSA zero and scratch regs must have the same numbers as FPU zero and scratch
229// MSA zero reg is often used to hold 0, but it's not hardwired to 0.
232
233// FPU (coprocessor 1) control registers.
234// Currently only FCSR (#31) is implemented.
236 bool is_valid() const { return reg_code == kFCSRRegister; }
237 bool is(FPUControlRegister creg) const { return reg_code == creg.reg_code; }
238 int code() const {
239 DCHECK(is_valid());
240 return reg_code;
241 }
242 int bit() const {
243 DCHECK(is_valid());
244 return 1 << reg_code;
245 }
246 void setcode(int f) {
247 reg_code = f;
248 DCHECK(is_valid());
249 }
250 // Unfortunately we can't make this private in a struct.
251 int reg_code;
252};
253
254constexpr FPUControlRegister no_fpucreg = {kInvalidFPUControlRegister};
255constexpr FPUControlRegister FCSR = {kFCSRRegister};
256
257// MSA control registers
259 bool is_valid() const {
261 }
262 bool is(MSAControlRegister creg) const { return reg_code == creg.reg_code; }
263 int code() const {
264 DCHECK(is_valid());
265 return reg_code;
266 }
267 int bit() const {
268 DCHECK(is_valid());
269 return 1 << reg_code;
270 }
271 void setcode(int f) {
272 reg_code = f;
273 DCHECK(is_valid());
274 }
275 // Unfortunately we can't make this private in a struct.
277};
278
282
283// Define {RegisterName} methods for the register types.
287
288constexpr Register kCArgRegs[] = {a0, a1, a2, a3, a4, a5, a6, a7};
290constexpr int kFPRegisterPassedArguments = 8;
291
292constexpr Register kReturnRegister0 = v0;
293constexpr Register kReturnRegister1 = v1;
294constexpr Register kReturnRegister2 = a0;
295constexpr Register kJSFunctionRegister = a1;
296constexpr Register kContextRegister = s7;
297constexpr Register kAllocateSizeRegister = a0;
298constexpr Register kInterpreterAccumulatorRegister = v0;
299constexpr Register kInterpreterBytecodeOffsetRegister = t0;
300constexpr Register kInterpreterBytecodeArrayRegister = t1;
301constexpr Register kInterpreterDispatchTableRegister = t2;
302constexpr Register kJavaScriptCallArgCountRegister = a0;
303constexpr Register kJavaScriptCallCodeStartRegister = a2;
305constexpr Register kJavaScriptCallNewTargetRegister = a3;
306constexpr Register kJavaScriptCallExtraArg1Register = a2;
307constexpr Register kJavaScriptCallDispatchHandleRegister = a4;
308
309constexpr Register kRuntimeCallFunctionRegister = a1;
310constexpr Register kRuntimeCallArgCountRegister = a0;
311constexpr Register kRuntimeCallArgvRegister = a2;
312constexpr Register kWasmImplicitArgRegister = a0;
313constexpr Register kWasmCompileLazyFuncIndexRegister = t0;
314
316
317} // namespace internal
318} // namespace v8
319
320#endif // V8_CODEGEN_MIPS64_REGISTER_MIPS64_H_
FPURegister low() const
FPURegister high() const
constexpr FPURegister(int code)
MSARegister toW() const
constexpr MSARegister(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()
ZoneVector< RpoNumber > & result
LiftoffRegister reg
InstructionOperand source
constexpr Register no_reg
constexpr Register kRootRegister
constexpr FPUControlRegister no_fpucreg
const Simd128Register no_msareg
const int kInvalidMSAControlRegister
const int kInvalidFPUControlRegister
const int kFCSRRegister
constexpr AliasingKind kFPAliasing
constexpr Register kRuntimeCallFunctionRegister
constexpr int kFPRegisterPassedArguments
constexpr DoubleRegister kDoubleCompareReg
DwVfpRegister DoubleRegister
constexpr Simd128Register kSimd128RegZero
constexpr DoubleRegister kScratchDoubleReg
constexpr int kNumRegs
constexpr Register kRuntimeCallArgvRegister
constexpr Register kJavaScriptCallTargetRegister
constexpr DwVfpRegister no_dreg
constexpr FPUControlRegister FCSR
constexpr DoubleRegister kScratchDoubleReg2
constexpr Register kJavaScriptCallArgCountRegister
constexpr Register kInterpreterAccumulatorRegister
int ToNumber(Register reg)
constexpr Register kScratchReg2
constexpr Register kScratchReg
static const int kRegisterPassedArguments
constexpr MSAControlRegister MSAIR
QwNeonRegister Simd128Register
constexpr DoubleRegister kFPReturnRegister0
constexpr Register kReturnRegister1
constexpr Simd128Register kSimd128ScratchReg
constexpr MSAControlRegister MSACSR
constexpr Register kReturnRegister0
const int kMSAIRRegister
constexpr Register kWasmImplicitArgRegister
constexpr Register kContextRegister
constexpr Register kRuntimeCallArgCountRegister
constexpr Register kInterpreterDispatchTableRegister
constexpr Register kAllocateSizeRegister
constexpr MSAControlRegister no_msacreg
constexpr LowDwVfpRegister kDoubleRegZero
constexpr Register kJavaScriptCallExtraArg1Register
Register ToRegister(int num)
constexpr Register kJavaScriptCallCodeStartRegister
constexpr Register kReturnRegister2
Register ReassignRegister(Register &source)
constexpr Register kWasmCompileLazyFuncIndexRegister
constexpr int ArgumentPaddingSlots(int argument_count)
constexpr Register cp
constexpr Register kCArgRegs[]
constexpr bool kSimdMaskRegisters
const int kMSACSRRegister
constexpr Register kJavaScriptCallDispatchHandleRegister
constexpr Register kInterpreterBytecodeOffsetRegister
constexpr Register kJavaScriptCallNewTargetRegister
constexpr Register kJSFunctionRegister
SwVfpRegister FloatRegister
constexpr Register kInterpreterBytecodeArrayRegister
#define GENERAL_REGISTERS(V)
#define SIMD128_REGISTERS(V)
#define DECLARE_DOUBLE_REGISTER(R)
#define REGISTER_CODE(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 DCHECK_EQ(v1, v2)
Definition logging.h:485
#define arraysize(array)
Definition macros.h:67
bool is(FPUControlRegister creg) const
bool is(MSAControlRegister creg) const