• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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