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_S390_REGISTER_S390_H_
6 #define V8_CODEGEN_S390_REGISTER_S390_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(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
16 V(r8) V(r9) V(r10) V(fp) V(ip) V(r13) V(r14) V(sp)
17
18 #define ALLOCATABLE_GENERAL_REGISTERS(V) \
19 V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
20 V(r8) V(r9) V(r13)
21
22 #define DOUBLE_REGISTERS(V) \
23 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
24 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15)
25
26 #define FLOAT_REGISTERS DOUBLE_REGISTERS
27 #define SIMD128_REGISTERS DOUBLE_REGISTERS
28
29 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
30 V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
31 V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) V(d0)
32
33 #define C_REGISTERS(V) \
34 V(cr0) V(cr1) V(cr2) V(cr3) V(cr4) V(cr5) V(cr6) V(cr7) \
35 V(cr8) V(cr9) V(cr10) V(cr11) V(cr12) V(cr15)
36 // clang-format on
37
38 // The following constants describe the stack frame linkage area as
39 // defined by the ABI.
40
41 #if V8_TARGET_ARCH_S390X
42 // [0] Back Chain
43 // [1] Reserved for compiler use
44 // [2] GPR 2
45 // [3] GPR 3
46 // ...
47 // [15] GPR 15
48 // [16] FPR 0
49 // [17] FPR 2
50 // [18] FPR 4
51 // [19] FPR 6
52 const int kNumRequiredStackFrameSlots = 20;
53 const int kStackFrameRASlot = 14;
54 const int kStackFrameSPSlot = 15;
55 const int kStackFrameExtraParamSlot = 20;
56 #else
57 // [0] Back Chain
58 // [1] Reserved for compiler use
59 // [2] GPR 2
60 // [3] GPR 3
61 // ...
62 // [15] GPR 15
63 // [16..17] FPR 0
64 // [18..19] FPR 2
65 // [20..21] FPR 4
66 // [22..23] FPR 6
67 const int kNumRequiredStackFrameSlots = 24;
68 const int kStackFrameRASlot = 14;
69 const int kStackFrameSPSlot = 15;
70 const int kStackFrameExtraParamSlot = 24;
71 #endif
72
73 // zLinux ABI requires caller frames to include sufficient space for
74 // callee preserved register save area.
75 #if V8_TARGET_ARCH_S390X
76 const int kCalleeRegisterSaveAreaSize = 160;
77 #elif V8_TARGET_ARCH_S390
78 const int kCalleeRegisterSaveAreaSize = 96;
79 #else
80 const int kCalleeRegisterSaveAreaSize = 0;
81 #endif
82
83 enum RegisterCode {
84 #define REGISTER_CODE(R) kRegCode_##R,
85 GENERAL_REGISTERS(REGISTER_CODE)
86 #undef REGISTER_CODE
87 kRegAfterLast
88 };
89
90 class Register : public RegisterBase<Register, kRegAfterLast> {
91 public:
92 #if V8_TARGET_LITTLE_ENDIAN
93 static constexpr int kMantissaOffset = 0;
94 static constexpr int kExponentOffset = 4;
95 #else
96 static constexpr int kMantissaOffset = 4;
97 static constexpr int kExponentOffset = 0;
98 #endif
99
100 private:
101 friend class RegisterBase;
Register(int code)102 explicit constexpr Register(int code) : RegisterBase(code) {}
103 };
104
105 ASSERT_TRIVIALLY_COPYABLE(Register);
106 static_assert(sizeof(Register) <= sizeof(int),
107 "Register can efficiently be passed by value");
108
109 #define DEFINE_REGISTER(R) \
110 constexpr Register R = Register::from_code(kRegCode_##R);
111 GENERAL_REGISTERS(DEFINE_REGISTER)
112 #undef DEFINE_REGISTER
113 constexpr Register no_reg = Register::no_reg();
114
115 // Register aliases
116 constexpr Register kRootRegister = r10; // Roots array pointer.
117 constexpr Register cp = r13; // JavaScript context pointer.
118
119 // Returns the number of padding slots needed for stack pointer alignment.
ArgumentPaddingSlots(int argument_count)120 constexpr int ArgumentPaddingSlots(int argument_count) {
121 // No argument padding required.
122 return 0;
123 }
124
125 constexpr AliasingKind kFPAliasing = AliasingKind::kOverlap;
126 constexpr bool kSimdMaskRegisters = false;
127
128 enum DoubleRegisterCode {
129 #define REGISTER_CODE(R) kDoubleCode_##R,
130 DOUBLE_REGISTERS(REGISTER_CODE)
131 #undef REGISTER_CODE
132 kDoubleAfterLast
133 };
134
135 // Double word VFP register.
136 class DoubleRegister : public RegisterBase<DoubleRegister, kDoubleAfterLast> {
137 public:
138 // A few double registers are reserved: one as a scratch register and one to
139 // hold 0.0, that does not fit in the immediate field of vmov instructions.
140 // d14: 0.0
141 // d15: scratch register.
142 static constexpr int kSizeInBytes = 8;
143
144 // This function differs from kNumRegisters by returning the number of double
145 // registers supported by the current CPU, while kNumRegisters always returns
146 // 32.
147 inline static int SupportedRegisterCount();
148
149 private:
150 friend class RegisterBase;
151
DoubleRegister(int code)152 explicit constexpr DoubleRegister(int code) : RegisterBase(code) {}
153 };
154
155 ASSERT_TRIVIALLY_COPYABLE(DoubleRegister);
156 static_assert(sizeof(DoubleRegister) <= sizeof(int),
157 "DoubleRegister can efficiently be passed by value");
158
159 using FloatRegister = DoubleRegister;
160
161 // TODO(john.yan) Define SIMD registers.
162 using Simd128Register = DoubleRegister;
163
164 #define DEFINE_REGISTER(R) \
165 constexpr DoubleRegister R = DoubleRegister::from_code(kDoubleCode_##R);
166 DOUBLE_REGISTERS(DEFINE_REGISTER)
167 #undef DEFINE_REGISTER
168 constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
169
170 constexpr DoubleRegister kDoubleRegZero = d14;
171 constexpr DoubleRegister kScratchDoubleReg = d13;
172
173 Register ToRegister(int num);
174
175 enum CRegisterCode {
176 #define REGISTER_CODE(R) kCCode_##R,
177 C_REGISTERS(REGISTER_CODE)
178 #undef REGISTER_CODE
179 kCAfterLast
180 };
181
182 // Coprocessor register
183 class CRegister : public RegisterBase<CRegister, kCAfterLast> {
184 friend class RegisterBase;
CRegister(int code)185 explicit constexpr CRegister(int code) : RegisterBase(code) {}
186 };
187
188 constexpr CRegister no_creg = CRegister::no_reg();
189 #define DECLARE_C_REGISTER(R) \
190 constexpr CRegister R = CRegister::from_code(kCCode_##R);
191 C_REGISTERS(DECLARE_C_REGISTER)
192 #undef DECLARE_C_REGISTER
193
194 // Define {RegisterName} methods for the register types.
195 DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
196 DEFINE_REGISTER_NAMES(DoubleRegister, DOUBLE_REGISTERS)
197
198 // Give alias names to registers for calling conventions.
199 constexpr Register kReturnRegister0 = r2;
200 constexpr Register kReturnRegister1 = r3;
201 constexpr Register kReturnRegister2 = r4;
202 constexpr Register kJSFunctionRegister = r3;
203 constexpr Register kContextRegister = r13;
204 constexpr Register kAllocateSizeRegister = r3;
205 constexpr Register kInterpreterAccumulatorRegister = r2;
206 constexpr Register kInterpreterBytecodeOffsetRegister = r6;
207 constexpr Register kInterpreterBytecodeArrayRegister = r7;
208 constexpr Register kInterpreterDispatchTableRegister = r8;
209
210 constexpr Register kJavaScriptCallArgCountRegister = r2;
211 constexpr Register kJavaScriptCallCodeStartRegister = r4;
212 constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
213 constexpr Register kJavaScriptCallNewTargetRegister = r5;
214 constexpr Register kJavaScriptCallExtraArg1Register = r4;
215
216 constexpr Register kOffHeapTrampolineRegister = ip;
217 constexpr Register kRuntimeCallFunctionRegister = r3;
218 constexpr Register kRuntimeCallArgCountRegister = r2;
219 constexpr Register kRuntimeCallArgvRegister = r4;
220 constexpr Register kWasmInstanceRegister = r6;
221 constexpr Register kWasmCompileLazyFuncIndexRegister = r7;
222
223 constexpr DoubleRegister kFPReturnRegister0 = d0;
224
225 } // namespace internal
226 } // namespace v8
227
228 #endif // V8_CODEGEN_S390_REGISTER_S390_H_
229