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.h"
9 #include "src/codegen/reglist.h"
10 
11 namespace v8 {
12 namespace internal {
13 
14 // clang-format off
15 #define GENERAL_REGISTERS(V)                              \
16   V(r0)  V(sp)  V(r2)  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)  \
17   V(r8)  V(r9)  V(r10) V(r11) V(ip) V(r13) V(r14) V(r15)  \
18   V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
19   V(r24) V(r25) V(r26) V(r27) V(r28) V(r29) V(r30) V(fp)
20 
21 #if V8_EMBEDDED_CONSTANT_POOL
22 #define ALLOCATABLE_GENERAL_REGISTERS(V)                  \
23   V(r3)  V(r4)  V(r5)  V(r6)  V(r7)                       \
24   V(r8)  V(r9)  V(r10) V(r14) V(r15)                      \
25   V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
26   V(r24) V(r25) V(r26) V(r27) V(r30)
27 #else
28 #define ALLOCATABLE_GENERAL_REGISTERS(V)                  \
29   V(r3)  V(r4)  V(r5)  V(r6)  V(r7)                       \
30   V(r8)  V(r9)  V(r10) V(r14) V(r15)                      \
31   V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
32   V(r24) V(r25) V(r26) V(r27) V(r28) V(r30)
33 #endif
34 
35 #define LOW_DOUBLE_REGISTERS(V)                           \
36   V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
37   V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13) V(d14) V(d15)
38 
39 #define NON_LOW_DOUBLE_REGISTERS(V)                       \
40   V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
41   V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
42 
43 #define DOUBLE_REGISTERS(V) \
44   LOW_DOUBLE_REGISTERS(V) NON_LOW_DOUBLE_REGISTERS(V)
45 
46 #define FLOAT_REGISTERS DOUBLE_REGISTERS
47 #define SIMD128_REGISTERS DOUBLE_REGISTERS
48 
49 #define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
50   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   V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
53   V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
54 
55 #define C_REGISTERS(V)                                            \
56   V(cr0)  V(cr1)  V(cr2)  V(cr3)  V(cr4)  V(cr5)  V(cr6)  V(cr7)  \
57   V(cr8)  V(cr9)  V(cr10) V(cr11) V(cr12) V(cr15)
58 // clang-format on
59 
60 // Register list in load/store instructions
61 // Note that the bit values must match those used in actual instruction encoding
62 
63 // Caller-saved/arguments registers
64 const RegList kJSCallerSaved = 1 << 3 |   // r3  a1
65                                1 << 4 |   // r4  a2
66                                1 << 5 |   // r5  a3
67                                1 << 6 |   // r6  a4
68                                1 << 7 |   // r7  a5
69                                1 << 8 |   // r8  a6
70                                1 << 9 |   // r9  a7
71                                1 << 10 |  // r10 a8
72                                1 << 11;
73 
74 const int kNumJSCallerSaved = 9;
75 
76 // Return the code of the n-th caller-saved register available to JavaScript
77 // e.g. JSCallerSavedReg(0) returns r0.code() == 0
78 int JSCallerSavedCode(int n);
79 
80 // Callee-saved registers preserved when switching from C to JavaScript
81 const RegList kCalleeSaved = 1 << 14 |  // r14
82                              1 << 15 |  // r15
83                              1 << 16 |  // r16
84                              1 << 17 |  // r17
85                              1 << 18 |  // r18
86                              1 << 19 |  // r19
87                              1 << 20 |  // r20
88                              1 << 21 |  // r21
89                              1 << 22 |  // r22
90                              1 << 23 |  // r23
91                              1 << 24 |  // r24
92                              1 << 25 |  // r25
93                              1 << 26 |  // r26
94                              1 << 27 |  // r27
95                              1 << 28 |  // r28
96                              1 << 29 |  // r29
97                              1 << 30 |  // r20
98                              1 << 31;   // r31
99 
100 const int kNumCalleeSaved = 18;
101 
102 const RegList kCallerSavedDoubles = 1 << 0 |   // d0
103                                     1 << 1 |   // d1
104                                     1 << 2 |   // d2
105                                     1 << 3 |   // d3
106                                     1 << 4 |   // d4
107                                     1 << 5 |   // d5
108                                     1 << 6 |   // d6
109                                     1 << 7 |   // d7
110                                     1 << 8 |   // d8
111                                     1 << 9 |   // d9
112                                     1 << 10 |  // d10
113                                     1 << 11 |  // d11
114                                     1 << 12 |  // d12
115                                     1 << 13;   // d13
116 
117 const int kNumCallerSavedDoubles = 14;
118 
119 const RegList kCalleeSavedDoubles = 1 << 14 |  // d14
120                                     1 << 15 |  // d15
121                                     1 << 16 |  // d16
122                                     1 << 17 |  // d17
123                                     1 << 18 |  // d18
124                                     1 << 19 |  // d19
125                                     1 << 20 |  // d20
126                                     1 << 21 |  // d21
127                                     1 << 22 |  // d22
128                                     1 << 23 |  // d23
129                                     1 << 24 |  // d24
130                                     1 << 25 |  // d25
131                                     1 << 26 |  // d26
132                                     1 << 27 |  // d27
133                                     1 << 28 |  // d28
134                                     1 << 29 |  // d29
135                                     1 << 30 |  // d30
136                                     1 << 31;   // d31
137 
138 const int kNumCalleeSavedDoubles = 18;
139 
140 // The following constants describe the stack frame linkage area as
141 // defined by the ABI.  Note that kNumRequiredStackFrameSlots must
142 // satisfy alignment requirements (rounding up if required).
143 #if V8_TARGET_ARCH_PPC64 &&     \
144     (V8_TARGET_LITTLE_ENDIAN || \
145      (defined(_CALL_ELF) && _CALL_ELF == 2))  // ELFv2 ABI
146 // [0] back chain
147 // [1] condition register save area
148 // [2] link register save area
149 // [3] TOC save area
150 // [4] Parameter1 save area
151 // ...
152 // [11] Parameter8 save area
153 // [12] Parameter9 slot (if necessary)
154 // ...
155 const int kNumRequiredStackFrameSlots = 12;
156 const int kStackFrameLRSlot = 2;
157 const int kStackFrameExtraParamSlot = 12;
158 #else  // AIX
159 // [0] back chain
160 // [1] condition register save area
161 // [2] link register save area
162 // [3] reserved for compiler
163 // [4] reserved by binder
164 // [5] TOC save area
165 // [6] Parameter1 save area
166 // ...
167 // [13] Parameter8 save area
168 // [14] Parameter9 slot (if necessary)
169 // ...
170 const int kNumRequiredStackFrameSlots = 14;
171 const int kStackFrameLRSlot = 2;
172 const int kStackFrameExtraParamSlot = 14;
173 #endif
174 
175 enum RegisterCode {
176 #define REGISTER_CODE(R) kRegCode_##R,
177   GENERAL_REGISTERS(REGISTER_CODE)
178 #undef REGISTER_CODE
179       kRegAfterLast
180 };
181 
182 class Register : public RegisterBase<Register, kRegAfterLast> {
183  public:
184 #if V8_TARGET_LITTLE_ENDIAN
185   static constexpr int kMantissaOffset = 0;
186   static constexpr int kExponentOffset = 4;
187 #else
188   static constexpr int kMantissaOffset = 4;
189   static constexpr int kExponentOffset = 0;
190 #endif
191 
192  private:
193   friend class RegisterBase;
Register(int code)194   explicit constexpr Register(int code) : RegisterBase(code) {}
195 };
196 
197 ASSERT_TRIVIALLY_COPYABLE(Register);
198 static_assert(sizeof(Register) == sizeof(int),
199               "Register can efficiently be passed by value");
200 
201 #define DEFINE_REGISTER(R) \
202   constexpr Register R = Register::from_code(kRegCode_##R);
203 GENERAL_REGISTERS(DEFINE_REGISTER)
204 #undef DEFINE_REGISTER
205 constexpr Register no_reg = Register::no_reg();
206 
207 // Aliases
208 constexpr Register kConstantPoolRegister = r28;  // Constant pool.
209 constexpr Register kRootRegister = r29;          // Roots array pointer.
210 constexpr Register cp = r30;                     // JavaScript context pointer.
211 
212 constexpr bool kPadArguments = false;
213 constexpr bool kSimpleFPAliasing = true;
214 constexpr bool kSimdMaskRegisters = false;
215 
216 enum DoubleRegisterCode {
217 #define REGISTER_CODE(R) kDoubleCode_##R,
218   DOUBLE_REGISTERS(REGISTER_CODE)
219 #undef REGISTER_CODE
220       kDoubleAfterLast
221 };
222 
223 // Double word FP register.
224 class DoubleRegister : public RegisterBase<DoubleRegister, kDoubleAfterLast> {
225  public:
226   // A few double registers are reserved: one as a scratch register and one to
227   // hold 0.0, that does not fit in the immediate field of vmov instructions.
228   // d14: 0.0
229   // d15: scratch register.
230   static constexpr int kSizeInBytes = 8;
231   inline static int NumRegisters();
232 
233  private:
234   friend class RegisterBase;
DoubleRegister(int code)235   explicit constexpr DoubleRegister(int code) : RegisterBase(code) {}
236 };
237 
238 ASSERT_TRIVIALLY_COPYABLE(DoubleRegister);
239 static_assert(sizeof(DoubleRegister) == sizeof(int),
240               "DoubleRegister can efficiently be passed by value");
241 
242 using FloatRegister = DoubleRegister;
243 
244 // TODO(ppc) Define SIMD registers.
245 using Simd128Register = DoubleRegister;
246 
247 #define DEFINE_REGISTER(R) \
248   constexpr DoubleRegister R = DoubleRegister::from_code(kDoubleCode_##R);
249 DOUBLE_REGISTERS(DEFINE_REGISTER)
250 #undef DEFINE_REGISTER
251 constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
252 
253 constexpr DoubleRegister kFirstCalleeSavedDoubleReg = d14;
254 constexpr DoubleRegister kLastCalleeSavedDoubleReg = d31;
255 constexpr DoubleRegister kDoubleRegZero = d14;
256 constexpr DoubleRegister kScratchDoubleReg = d13;
257 
258 Register ToRegister(int num);
259 
260 enum CRegisterCode {
261 #define REGISTER_CODE(R) kCCode_##R,
262   C_REGISTERS(REGISTER_CODE)
263 #undef REGISTER_CODE
264       kCAfterLast
265 };
266 
267 // Coprocessor register
268 class CRegister : public RegisterBase<CRegister, kCAfterLast> {
269   friend class RegisterBase;
CRegister(int code)270   explicit constexpr CRegister(int code) : RegisterBase(code) {}
271 };
272 
273 constexpr CRegister no_creg = CRegister::no_reg();
274 #define DECLARE_C_REGISTER(R) \
275   constexpr CRegister R = CRegister::from_code(kCCode_##R);
276 C_REGISTERS(DECLARE_C_REGISTER)
277 #undef DECLARE_C_REGISTER
278 
279 // Define {RegisterName} methods for the register types.
280 DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
281 DEFINE_REGISTER_NAMES(DoubleRegister, DOUBLE_REGISTERS)
282 
283 // Give alias names to registers for calling conventions.
284 constexpr Register kReturnRegister0 = r3;
285 constexpr Register kReturnRegister1 = r4;
286 constexpr Register kReturnRegister2 = r5;
287 constexpr Register kJSFunctionRegister = r4;
288 constexpr Register kContextRegister = r30;
289 constexpr Register kAllocateSizeRegister = r4;
290 constexpr Register kSpeculationPoisonRegister = r14;
291 constexpr Register kInterpreterAccumulatorRegister = r3;
292 constexpr Register kInterpreterBytecodeOffsetRegister = r15;
293 constexpr Register kInterpreterBytecodeArrayRegister = r16;
294 constexpr Register kInterpreterDispatchTableRegister = r17;
295 
296 constexpr Register kJavaScriptCallArgCountRegister = r3;
297 constexpr Register kJavaScriptCallCodeStartRegister = r5;
298 constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
299 constexpr Register kJavaScriptCallNewTargetRegister = r6;
300 constexpr Register kJavaScriptCallExtraArg1Register = r5;
301 
302 constexpr Register kOffHeapTrampolineRegister = ip;
303 constexpr Register kRuntimeCallFunctionRegister = r4;
304 constexpr Register kRuntimeCallArgCountRegister = r3;
305 constexpr Register kRuntimeCallArgvRegister = r5;
306 constexpr Register kWasmInstanceRegister = r10;
307 constexpr Register kWasmCompileLazyFuncIndexRegister = r15;
308 
309 }  // namespace internal
310 }  // namespace v8
311 
312 #endif  // V8_CODEGEN_PPC_REGISTER_PPC_H_
313