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
10namespace v8 {
11namespace 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
52const int kNumRequiredStackFrameSlots = 20;
53const int kStackFrameRASlot = 14;
54const int kStackFrameSPSlot = 15;
55const 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
67const int kNumRequiredStackFrameSlots = 24;
68const int kStackFrameRASlot = 14;
69const int kStackFrameSPSlot = 15;
70const 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
76const int kCalleeRegisterSaveAreaSize = 160;
77#elif V8_TARGET_ARCH_S390
78const int kCalleeRegisterSaveAreaSize = 96;
79#else
80const int kCalleeRegisterSaveAreaSize = 0;
81#endif
82
83enum RegisterCode {
84#define REGISTER_CODE(R) kRegCode_##R,
85  GENERAL_REGISTERS(REGISTER_CODE)
86#undef REGISTER_CODE
87      kRegAfterLast
88};
89
90class 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;
102  explicit constexpr Register(int code) : RegisterBase(code) {}
103};
104
105ASSERT_TRIVIALLY_COPYABLE(Register);
106static_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);
111GENERAL_REGISTERS(DEFINE_REGISTER)
112#undef DEFINE_REGISTER
113constexpr Register no_reg = Register::no_reg();
114
115// Register aliases
116constexpr Register kRootRegister = r10;  // Roots array pointer.
117constexpr Register cp = r13;             // JavaScript context pointer.
118
119// Returns the number of padding slots needed for stack pointer alignment.
120constexpr int ArgumentPaddingSlots(int argument_count) {
121  // No argument padding required.
122  return 0;
123}
124
125constexpr AliasingKind kFPAliasing = AliasingKind::kOverlap;
126constexpr bool kSimdMaskRegisters = false;
127
128enum 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.
136class 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
152  explicit constexpr DoubleRegister(int code) : RegisterBase(code) {}
153};
154
155ASSERT_TRIVIALLY_COPYABLE(DoubleRegister);
156static_assert(sizeof(DoubleRegister) <= sizeof(int),
157              "DoubleRegister can efficiently be passed by value");
158
159using FloatRegister = DoubleRegister;
160
161// TODO(john.yan) Define SIMD registers.
162using Simd128Register = DoubleRegister;
163
164#define DEFINE_REGISTER(R) \
165  constexpr DoubleRegister R = DoubleRegister::from_code(kDoubleCode_##R);
166DOUBLE_REGISTERS(DEFINE_REGISTER)
167#undef DEFINE_REGISTER
168constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
169
170constexpr DoubleRegister kDoubleRegZero = d14;
171constexpr DoubleRegister kScratchDoubleReg = d13;
172
173Register ToRegister(int num);
174
175enum CRegisterCode {
176#define REGISTER_CODE(R) kCCode_##R,
177  C_REGISTERS(REGISTER_CODE)
178#undef REGISTER_CODE
179      kCAfterLast
180};
181
182// Coprocessor register
183class CRegister : public RegisterBase<CRegister, kCAfterLast> {
184  friend class RegisterBase;
185  explicit constexpr CRegister(int code) : RegisterBase(code) {}
186};
187
188constexpr CRegister no_creg = CRegister::no_reg();
189#define DECLARE_C_REGISTER(R) \
190  constexpr CRegister R = CRegister::from_code(kCCode_##R);
191C_REGISTERS(DECLARE_C_REGISTER)
192#undef DECLARE_C_REGISTER
193
194// Define {RegisterName} methods for the register types.
195DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
196DEFINE_REGISTER_NAMES(DoubleRegister, DOUBLE_REGISTERS)
197
198// Give alias names to registers for calling conventions.
199constexpr Register kReturnRegister0 = r2;
200constexpr Register kReturnRegister1 = r3;
201constexpr Register kReturnRegister2 = r4;
202constexpr Register kJSFunctionRegister = r3;
203constexpr Register kContextRegister = r13;
204constexpr Register kAllocateSizeRegister = r3;
205constexpr Register kInterpreterAccumulatorRegister = r2;
206constexpr Register kInterpreterBytecodeOffsetRegister = r6;
207constexpr Register kInterpreterBytecodeArrayRegister = r7;
208constexpr Register kInterpreterDispatchTableRegister = r8;
209
210constexpr Register kJavaScriptCallArgCountRegister = r2;
211constexpr Register kJavaScriptCallCodeStartRegister = r4;
212constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
213constexpr Register kJavaScriptCallNewTargetRegister = r5;
214constexpr Register kJavaScriptCallExtraArg1Register = r4;
215
216constexpr Register kOffHeapTrampolineRegister = ip;
217constexpr Register kRuntimeCallFunctionRegister = r3;
218constexpr Register kRuntimeCallArgCountRegister = r2;
219constexpr Register kRuntimeCallArgvRegister = r4;
220constexpr Register kWasmInstanceRegister = r6;
221constexpr Register kWasmCompileLazyFuncIndexRegister = r7;
222
223constexpr DoubleRegister kFPReturnRegister0 = d0;
224
225}  // namespace internal
226}  // namespace v8
227
228#endif  // V8_CODEGEN_S390_REGISTER_S390_H_
229