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
10namespace v8 {
11namespace 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// ...
78const int kNumRequiredStackFrameSlots = 12;
79const int kStackFrameLRSlot = 2;
80const 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// ...
93const int kNumRequiredStackFrameSlots = 14;
94const int kStackFrameLRSlot = 2;
95const int kStackFrameExtraParamSlot = 14;
96#endif
97
98enum RegisterCode {
99#define REGISTER_CODE(R) kRegCode_##R,
100  GENERAL_REGISTERS(REGISTER_CODE)
101#undef REGISTER_CODE
102      kRegAfterLast
103};
104
105class 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;
117  explicit constexpr Register(int code) : RegisterBase(code) {}
118};
119
120ASSERT_TRIVIALLY_COPYABLE(Register);
121static_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);
126GENERAL_REGISTERS(DEFINE_REGISTER)
127#undef DEFINE_REGISTER
128constexpr Register no_reg = Register::no_reg();
129
130// Aliases
131constexpr Register kConstantPoolRegister = r28;  // Constant pool.
132constexpr Register kRootRegister = r29;          // Roots array pointer.
133constexpr Register cp = r30;                     // JavaScript context pointer.
134
135// Returns the number of padding slots needed for stack pointer alignment.
136constexpr int ArgumentPaddingSlots(int argument_count) {
137  // No argument padding required.
138  return 0;
139}
140
141constexpr AliasingKind kFPAliasing = AliasingKind::kOverlap;
142constexpr bool kSimdMaskRegisters = false;
143
144enum 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.
152class 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;
167  explicit constexpr DoubleRegister(int code) : RegisterBase(code) {}
168};
169
170ASSERT_TRIVIALLY_COPYABLE(DoubleRegister);
171static_assert(sizeof(DoubleRegister) <= sizeof(int),
172              "DoubleRegister can efficiently be passed by value");
173
174using 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.
199enum Simd128RegisterCode {
200#define REGISTER_CODE(R) kSimd128Code_##R,
201  SIMD128_REGISTERS(REGISTER_CODE)
202#undef REGISTER_CODE
203      kSimd128AfterLast
204};
205
206// Simd128 register.
207class Simd128Register
208    : public RegisterBase<Simd128Register, kSimd128AfterLast> {
209 private:
210  friend class RegisterBase;
211  explicit constexpr Simd128Register(int code) : RegisterBase(code) {}
212};
213ASSERT_TRIVIALLY_COPYABLE(Simd128Register);
214static_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);
219SIMD128_REGISTERS(DECLARE_SIMD128_REGISTER)
220#undef DECLARE_SIMD128_REGISTER
221const Simd128Register no_simdreg = Simd128Register::no_reg();
222
223#define DEFINE_REGISTER(R) \
224  constexpr DoubleRegister R = DoubleRegister::from_code(kDoubleCode_##R);
225DOUBLE_REGISTERS(DEFINE_REGISTER)
226#undef DEFINE_REGISTER
227constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
228
229constexpr DoubleRegister kFirstCalleeSavedDoubleReg = d14;
230constexpr DoubleRegister kLastCalleeSavedDoubleReg = d31;
231constexpr DoubleRegister kDoubleRegZero = d14;
232constexpr DoubleRegister kScratchDoubleReg = d13;
233// Simd128 zero and scratch regs must have the same numbers as Double zero and
234// scratch
235constexpr Simd128Register kSimd128RegZero = v14;
236constexpr Simd128Register kScratchSimd128Reg = v13;
237
238Register ToRegister(int num);
239
240enum CRegisterCode {
241#define REGISTER_CODE(R) kCCode_##R,
242  C_REGISTERS(REGISTER_CODE)
243#undef REGISTER_CODE
244      kCAfterLast
245};
246
247// Coprocessor register
248class CRegister : public RegisterBase<CRegister, kCAfterLast> {
249  friend class RegisterBase;
250  explicit constexpr CRegister(int code) : RegisterBase(code) {}
251};
252
253constexpr CRegister no_creg = CRegister::no_reg();
254#define DECLARE_C_REGISTER(R) \
255  constexpr CRegister R = CRegister::from_code(kCCode_##R);
256C_REGISTERS(DECLARE_C_REGISTER)
257#undef DECLARE_C_REGISTER
258
259// Define {RegisterName} methods for the register types.
260DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
261DEFINE_REGISTER_NAMES(DoubleRegister, DOUBLE_REGISTERS)
262DEFINE_REGISTER_NAMES(Simd128Register, SIMD128_REGISTERS)
263
264// Give alias names to registers for calling conventions.
265constexpr Register kReturnRegister0 = r3;
266constexpr Register kReturnRegister1 = r4;
267constexpr Register kReturnRegister2 = r5;
268constexpr Register kJSFunctionRegister = r4;
269constexpr Register kContextRegister = r30;
270constexpr Register kAllocateSizeRegister = r4;
271constexpr Register kInterpreterAccumulatorRegister = r3;
272constexpr Register kInterpreterBytecodeOffsetRegister = r15;
273constexpr Register kInterpreterBytecodeArrayRegister = r16;
274constexpr Register kInterpreterDispatchTableRegister = r17;
275
276constexpr Register kJavaScriptCallArgCountRegister = r3;
277constexpr Register kJavaScriptCallCodeStartRegister = r5;
278constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
279constexpr Register kJavaScriptCallNewTargetRegister = r6;
280constexpr Register kJavaScriptCallExtraArg1Register = r5;
281
282constexpr Register kOffHeapTrampolineRegister = ip;
283constexpr Register kRuntimeCallFunctionRegister = r4;
284constexpr Register kRuntimeCallArgCountRegister = r3;
285constexpr Register kRuntimeCallArgvRegister = r5;
286constexpr Register kWasmInstanceRegister = r10;
287constexpr Register kWasmCompileLazyFuncIndexRegister = r15;
288
289constexpr DoubleRegister kFPReturnRegister0 = d1;
290
291}  // namespace internal
292}  // namespace v8
293
294#endif  // V8_CODEGEN_PPC_REGISTER_PPC_H_
295