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_PPC_REGISTER_PPC_H_
6 #define V8_CODEGEN_PPC_REGISTER_PPC_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(sp) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
16 V(r8) V(r9) V(r10) V(r11) V(ip) V(r13) V(r14) V(r15) \
17 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
18 V(r24) V(r25) V(r26) V(r27) V(r28) V(r29) V(r30) V(fp)
19
20 #if V8_EMBEDDED_CONSTANT_POOL
21 #define ALLOCATABLE_GENERAL_REGISTERS(V) \
22 V(r3) V(r4) V(r5) V(r6) V(r7) \
23 V(r8) V(r9) V(r10) V(r14) V(r15) \
24 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
25 V(r24) V(r25) V(r26) V(r27) V(r30)
26 #else
27 #define ALLOCATABLE_GENERAL_REGISTERS(V) \
28 V(r3) V(r4) V(r5) V(r6) V(r7) \
29 V(r8) V(r9) V(r10) V(r14) V(r15) \
30 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
31 V(r24) V(r25) V(r26) V(r27) V(r28) V(r30)
32 #endif
33
34 #define LOW_DOUBLE_REGISTERS(V) \
35 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
36 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15)
37
38 #define NON_LOW_DOUBLE_REGISTERS(V) \
39 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
40 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
41
42 #define DOUBLE_REGISTERS(V) \
43 LOW_DOUBLE_REGISTERS(V) NON_LOW_DOUBLE_REGISTERS(V)
44
45 #define FLOAT_REGISTERS DOUBLE_REGISTERS
46 #define SIMD128_REGISTERS(V) \
47 V(v0) V(v1) V(v2) V(v3) V(v4) V(v5) V(v6) V(v7) \
48 V(v8) V(v9) V(v10) V(v11) V(v12) V(v13) V(v14) V(v15) \
49 V(v16) V(v17) V(v18) V(v19) V(v20) V(v21) V(v22) V(v23) \
50 V(v24) V(v25) V(v26) V(v27) V(v28) V(v29) V(v30) V(v31)
51
52 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
53 V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
54 V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) \
55 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
56 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
57
58 #define C_REGISTERS(V) \
59 V(cr0) V(cr1) V(cr2) V(cr3) V(cr4) V(cr5) V(cr6) V(cr7) \
60 V(cr8) V(cr9) V(cr10) V(cr11) V(cr12) V(cr15)
61 // clang-format on
62
63 // The following constants describe the stack frame linkage area as
64 // defined by the ABI. Note that kNumRequiredStackFrameSlots must
65 // satisfy alignment requirements (rounding up if required).
66 #if V8_TARGET_ARCH_PPC64 && \
67 (V8_TARGET_LITTLE_ENDIAN || \
68 (defined(_CALL_ELF) && _CALL_ELF == 2)) // ELFv2 ABI
69 // [0] back chain
70 // [1] condition register save area
71 // [2] link register save area
72 // [3] TOC save area
73 // [4] Parameter1 save area
74 // ...
75 // [11] Parameter8 save area
76 // [12] Parameter9 slot (if necessary)
77 // ...
78 const int kNumRequiredStackFrameSlots = 12;
79 const int kStackFrameLRSlot = 2;
80 const int kStackFrameExtraParamSlot = 12;
81 #else // AIX
82 // [0] back chain
83 // [1] condition register save area
84 // [2] link register save area
85 // [3] reserved for compiler
86 // [4] reserved by binder
87 // [5] TOC save area
88 // [6] Parameter1 save area
89 // ...
90 // [13] Parameter8 save area
91 // [14] Parameter9 slot (if necessary)
92 // ...
93 const int kNumRequiredStackFrameSlots = 14;
94 const int kStackFrameLRSlot = 2;
95 const int kStackFrameExtraParamSlot = 14;
96 #endif
97
98 enum RegisterCode {
99 #define REGISTER_CODE(R) kRegCode_##R,
100 GENERAL_REGISTERS(REGISTER_CODE)
101 #undef REGISTER_CODE
102 kRegAfterLast
103 };
104
105 class Register : public RegisterBase<Register, kRegAfterLast> {
106 public:
107 #if V8_TARGET_LITTLE_ENDIAN
108 static constexpr int kMantissaOffset = 0;
109 static constexpr int kExponentOffset = 4;
110 #else
111 static constexpr int kMantissaOffset = 4;
112 static constexpr int kExponentOffset = 0;
113 #endif
114
115 private:
116 friend class RegisterBase;
Register(int code)117 explicit constexpr Register(int code) : RegisterBase(code) {}
118 };
119
120 ASSERT_TRIVIALLY_COPYABLE(Register);
121 static_assert(sizeof(Register) <= sizeof(int),
122 "Register can efficiently be passed by value");
123
124 #define DEFINE_REGISTER(R) \
125 constexpr Register R = Register::from_code(kRegCode_##R);
126 GENERAL_REGISTERS(DEFINE_REGISTER)
127 #undef DEFINE_REGISTER
128 constexpr Register no_reg = Register::no_reg();
129
130 // Aliases
131 constexpr Register kConstantPoolRegister = r28; // Constant pool.
132 constexpr Register kRootRegister = r29; // Roots array pointer.
133 constexpr Register cp = r30; // JavaScript context pointer.
134
135 // Returns the number of padding slots needed for stack pointer alignment.
ArgumentPaddingSlots(int argument_count)136 constexpr int ArgumentPaddingSlots(int argument_count) {
137 // No argument padding required.
138 return 0;
139 }
140
141 constexpr AliasingKind kFPAliasing = AliasingKind::kOverlap;
142 constexpr bool kSimdMaskRegisters = false;
143
144 enum DoubleRegisterCode {
145 #define REGISTER_CODE(R) kDoubleCode_##R,
146 DOUBLE_REGISTERS(REGISTER_CODE)
147 #undef REGISTER_CODE
148 kDoubleAfterLast
149 };
150
151 // Double word FP register.
152 class DoubleRegister : public RegisterBase<DoubleRegister, kDoubleAfterLast> {
153 public:
154 // A few double registers are reserved: one as a scratch register and one to
155 // hold 0.0, that does not fit in the immediate field of vmov instructions.
156 // d14: 0.0
157 // d15: scratch register.
158 static constexpr int kSizeInBytes = 8;
159
160 // This function differs from kNumRegisters by returning the number of double
161 // registers supported by the current CPU, while kNumRegisters always returns
162 // 32.
163 inline static int SupportedRegisterCount();
164
165 private:
166 friend class RegisterBase;
DoubleRegister(int code)167 explicit constexpr DoubleRegister(int code) : RegisterBase(code) {}
168 };
169
170 ASSERT_TRIVIALLY_COPYABLE(DoubleRegister);
171 static_assert(sizeof(DoubleRegister) <= sizeof(int),
172 "DoubleRegister can efficiently be passed by value");
173
174 using FloatRegister = DoubleRegister;
175
176 // | | 0
177 // | | 1
178 // | | 2
179 // | | ...
180 // | | 31
181 // VSX |
182 // | | 32
183 // | | 33
184 // | VMX | 34
185 // | | ...
186 // | | 63
187 //
188 // VSX registers (0 to 63) can be used by VSX vector instructions, which are
189 // mainly focused on Floating Point arithmetic. They do have few Integer
190 // Instructions such as logical operations, merge and select. The main Simd
191 // integer instructions such as add/sub/mul/ extract_lane/replace_lane,
192 // comparisons etc. are only available with VMX instructions and can only access
193 // the VMX set of vector registers (which is a subset of VSX registers). So to
194 // assure access to all Simd instructions in V8 and avoid moving data between
195 // registers, we are only using the upper 32 registers (VMX set) for Simd
196 // operations and only use the lower set for scalar (non simd) floating point
197 // operations which makes our Simd register set separate from Floating Point
198 // ones.
199 enum Simd128RegisterCode {
200 #define REGISTER_CODE(R) kSimd128Code_##R,
201 SIMD128_REGISTERS(REGISTER_CODE)
202 #undef REGISTER_CODE
203 kSimd128AfterLast
204 };
205
206 // Simd128 register.
207 class Simd128Register
208 : public RegisterBase<Simd128Register, kSimd128AfterLast> {
209 private:
210 friend class RegisterBase;
Simd128Register(int code)211 explicit constexpr Simd128Register(int code) : RegisterBase(code) {}
212 };
213 ASSERT_TRIVIALLY_COPYABLE(Simd128Register);
214 static_assert(sizeof(Simd128Register) <= sizeof(int),
215 "Simd128Register can efficiently be passed by value");
216
217 #define DECLARE_SIMD128_REGISTER(R) \
218 constexpr Simd128Register R = Simd128Register::from_code(kSimd128Code_##R);
219 SIMD128_REGISTERS(DECLARE_SIMD128_REGISTER)
220 #undef DECLARE_SIMD128_REGISTER
221 const Simd128Register no_simdreg = Simd128Register::no_reg();
222
223 #define DEFINE_REGISTER(R) \
224 constexpr DoubleRegister R = DoubleRegister::from_code(kDoubleCode_##R);
225 DOUBLE_REGISTERS(DEFINE_REGISTER)
226 #undef DEFINE_REGISTER
227 constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
228
229 constexpr DoubleRegister kFirstCalleeSavedDoubleReg = d14;
230 constexpr DoubleRegister kLastCalleeSavedDoubleReg = d31;
231 constexpr DoubleRegister kDoubleRegZero = d14;
232 constexpr DoubleRegister kScratchDoubleReg = d13;
233 // Simd128 zero and scratch regs must have the same numbers as Double zero and
234 // scratch
235 constexpr Simd128Register kSimd128RegZero = v14;
236 constexpr Simd128Register kScratchSimd128Reg = v13;
237
238 Register ToRegister(int num);
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 constexpr CRegister no_creg = CRegister::no_reg();
254 #define DECLARE_C_REGISTER(R) \
255 constexpr CRegister R = CRegister::from_code(kCCode_##R);
256 C_REGISTERS(DECLARE_C_REGISTER)
257 #undef DECLARE_C_REGISTER
258
259 // Define {RegisterName} methods for the register types.
260 DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
261 DEFINE_REGISTER_NAMES(DoubleRegister, DOUBLE_REGISTERS)
262 DEFINE_REGISTER_NAMES(Simd128Register, SIMD128_REGISTERS)
263
264 // Give alias names to registers for calling conventions.
265 constexpr Register kReturnRegister0 = r3;
266 constexpr Register kReturnRegister1 = r4;
267 constexpr Register kReturnRegister2 = r5;
268 constexpr Register kJSFunctionRegister = r4;
269 constexpr Register kContextRegister = r30;
270 constexpr Register kAllocateSizeRegister = r4;
271 constexpr Register kInterpreterAccumulatorRegister = r3;
272 constexpr Register kInterpreterBytecodeOffsetRegister = r15;
273 constexpr Register kInterpreterBytecodeArrayRegister = r16;
274 constexpr Register kInterpreterDispatchTableRegister = r17;
275
276 constexpr Register kJavaScriptCallArgCountRegister = r3;
277 constexpr Register kJavaScriptCallCodeStartRegister = r5;
278 constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
279 constexpr Register kJavaScriptCallNewTargetRegister = r6;
280 constexpr Register kJavaScriptCallExtraArg1Register = r5;
281
282 constexpr Register kOffHeapTrampolineRegister = ip;
283 constexpr Register kRuntimeCallFunctionRegister = r4;
284 constexpr Register kRuntimeCallArgCountRegister = r3;
285 constexpr Register kRuntimeCallArgvRegister = r5;
286 constexpr Register kWasmInstanceRegister = r10;
287 constexpr Register kWasmCompileLazyFuncIndexRegister = r15;
288
289 constexpr DoubleRegister kFPReturnRegister0 = d1;
290
291 } // namespace internal
292 } // namespace v8
293
294 #endif // V8_CODEGEN_PPC_REGISTER_PPC_H_
295