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_X64_REGISTER_X64_H_
6#define V8_CODEGEN_X64_REGISTER_X64_H_
7
8#include "src/codegen/register-base.h"
9
10namespace v8 {
11namespace internal {
12
13#define GENERAL_REGISTERS(V) \
14  V(rax)                     \
15  V(rcx)                     \
16  V(rdx)                     \
17  V(rbx)                     \
18  V(rsp)                     \
19  V(rbp)                     \
20  V(rsi)                     \
21  V(rdi)                     \
22  V(r8)                      \
23  V(r9)                      \
24  V(r10)                     \
25  V(r11)                     \
26  V(r12)                     \
27  V(r13)                     \
28  V(r14)                     \
29  V(r15)
30
31#define ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
32  V(rax)                                        \
33  V(rbx)                                        \
34  V(rdx)                                        \
35  V(rcx)                                        \
36  V(rsi)                                        \
37  V(rdi)                                        \
38  V(r8)                                         \
39  V(r9)                                         \
40  V(r11)                                        \
41  V(r12)                                        \
42  V(r15)
43
44#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
45#define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V)
46#else
47#define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V) V(r14)
48#endif
49
50#define ALLOCATABLE_GENERAL_REGISTERS(V)  \
51  ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
52  MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V)
53
54enum RegisterCode {
55#define REGISTER_CODE(R) kRegCode_##R,
56  GENERAL_REGISTERS(REGISTER_CODE)
57#undef REGISTER_CODE
58      kRegAfterLast
59};
60
61class Register : public RegisterBase<Register, kRegAfterLast> {
62 public:
63  bool is_byte_register() const { return code() <= 3; }
64  // Return the high bit of the register code as a 0 or 1.  Used often
65  // when constructing the REX prefix byte.
66  int high_bit() const { return code() >> 3; }
67  // Return the 3 low bits of the register code.  Used when encoding registers
68  // in modR/M, SIB, and opcode bytes.
69  int low_bits() const { return code() & 0x7; }
70
71 private:
72  friend class RegisterBase<Register, kRegAfterLast>;
73  explicit constexpr Register(int code) : RegisterBase(code) {}
74};
75
76ASSERT_TRIVIALLY_COPYABLE(Register);
77static_assert(sizeof(Register) <= sizeof(int),
78              "Register can efficiently be passed by value");
79
80#define DECLARE_REGISTER(R) \
81  constexpr Register R = Register::from_code(kRegCode_##R);
82GENERAL_REGISTERS(DECLARE_REGISTER)
83#undef DECLARE_REGISTER
84constexpr Register no_reg = Register::no_reg();
85
86constexpr int kNumRegs = 16;
87
88#ifdef V8_TARGET_OS_WIN
89// Windows calling convention
90constexpr Register arg_reg_1 = rcx;
91constexpr Register arg_reg_2 = rdx;
92constexpr Register arg_reg_3 = r8;
93constexpr Register arg_reg_4 = r9;
94#else
95// AMD64 calling convention
96constexpr Register arg_reg_1 = rdi;
97constexpr Register arg_reg_2 = rsi;
98constexpr Register arg_reg_3 = rdx;
99constexpr Register arg_reg_4 = rcx;
100#endif  // V8_TARGET_OS_WIN
101
102#define DOUBLE_REGISTERS(V) \
103  V(xmm0)                   \
104  V(xmm1)                   \
105  V(xmm2)                   \
106  V(xmm3)                   \
107  V(xmm4)                   \
108  V(xmm5)                   \
109  V(xmm6)                   \
110  V(xmm7)                   \
111  V(xmm8)                   \
112  V(xmm9)                   \
113  V(xmm10)                  \
114  V(xmm11)                  \
115  V(xmm12)                  \
116  V(xmm13)                  \
117  V(xmm14)                  \
118  V(xmm15)
119
120#define FLOAT_REGISTERS DOUBLE_REGISTERS
121#define SIMD128_REGISTERS DOUBLE_REGISTERS
122
123#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
124  V(xmm0)                               \
125  V(xmm1)                               \
126  V(xmm2)                               \
127  V(xmm3)                               \
128  V(xmm4)                               \
129  V(xmm5)                               \
130  V(xmm6)                               \
131  V(xmm7)                               \
132  V(xmm8)                               \
133  V(xmm9)                               \
134  V(xmm10)                              \
135  V(xmm11)                              \
136  V(xmm12)                              \
137  V(xmm13)                              \
138  V(xmm14)
139
140#define YMM_REGISTERS(V) \
141  V(ymm0)                \
142  V(ymm1)                \
143  V(ymm2)                \
144  V(ymm3)                \
145  V(ymm4)                \
146  V(ymm5)                \
147  V(ymm6)                \
148  V(ymm7)                \
149  V(ymm8)                \
150  V(ymm9)                \
151  V(ymm10)               \
152  V(ymm11)               \
153  V(ymm12)               \
154  V(ymm13)               \
155  V(ymm14)               \
156  V(ymm15)
157
158// Returns the number of padding slots needed for stack pointer alignment.
159constexpr int ArgumentPaddingSlots(int argument_count) {
160  // No argument padding required.
161  return 0;
162}
163
164constexpr AliasingKind kFPAliasing = AliasingKind::kOverlap;
165constexpr bool kSimdMaskRegisters = false;
166
167enum DoubleRegisterCode {
168#define REGISTER_CODE(R) kDoubleCode_##R,
169  DOUBLE_REGISTERS(REGISTER_CODE)
170#undef REGISTER_CODE
171      kDoubleAfterLast
172};
173
174enum YMMRegisterCode {
175#define REGISTER_CODE(R) kYMMCode_##R,
176  YMM_REGISTERS(REGISTER_CODE)
177#undef REGISTER_CODE
178      kYMMAfterLast
179};
180static_assert(static_cast<int>(kDoubleAfterLast) ==
181                  static_cast<int>(kYMMAfterLast),
182              "The number of XMM register codes must match the number of YMM "
183              "register codes");
184
185class XMMRegister : public RegisterBase<XMMRegister, kDoubleAfterLast> {
186 public:
187  // Return the high bit of the register code as a 0 or 1.  Used often
188  // when constructing the REX prefix byte.
189  int high_bit() const { return code() >> 3; }
190  // Return the 3 low bits of the register code.  Used when encoding registers
191  // in modR/M, SIB, and opcode bytes.
192  int low_bits() const { return code() & 0x7; }
193
194 protected:
195  friend class RegisterBase<XMMRegister, kDoubleAfterLast>;
196  explicit constexpr XMMRegister(int code) : RegisterBase(code) {}
197};
198
199ASSERT_TRIVIALLY_COPYABLE(XMMRegister);
200static_assert(sizeof(XMMRegister) <= sizeof(int),
201              "XMMRegister can efficiently be passed by value");
202
203class YMMRegister : public XMMRegister {
204 public:
205  static constexpr YMMRegister from_code(int code) {
206    DCHECK(base::IsInRange(code, 0, XMMRegister::kNumRegisters - 1));
207    return YMMRegister(code);
208  }
209
210 private:
211  friend class XMMRegister;
212  explicit constexpr YMMRegister(int code) : XMMRegister(code) {}
213};
214
215ASSERT_TRIVIALLY_COPYABLE(YMMRegister);
216static_assert(sizeof(YMMRegister) <= sizeof(int),
217              "YMMRegister can efficiently be passed by value");
218
219using FloatRegister = XMMRegister;
220
221using DoubleRegister = XMMRegister;
222
223using Simd128Register = XMMRegister;
224
225#define DECLARE_REGISTER(R) \
226  constexpr DoubleRegister R = DoubleRegister::from_code(kDoubleCode_##R);
227DOUBLE_REGISTERS(DECLARE_REGISTER)
228#undef DECLARE_REGISTER
229constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
230
231#define DECLARE_REGISTER(R) \
232  constexpr YMMRegister R = YMMRegister::from_code(kYMMCode_##R);
233YMM_REGISTERS(DECLARE_REGISTER)
234#undef DECLARE_REGISTER
235
236// Define {RegisterName} methods for the register types.
237DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
238DEFINE_REGISTER_NAMES(XMMRegister, DOUBLE_REGISTERS)
239DEFINE_REGISTER_NAMES(YMMRegister, YMM_REGISTERS)
240
241// Give alias names to registers for calling conventions.
242constexpr Register kReturnRegister0 = rax;
243constexpr Register kReturnRegister1 = rdx;
244constexpr Register kReturnRegister2 = r8;
245constexpr Register kJSFunctionRegister = rdi;
246constexpr Register kContextRegister = rsi;
247constexpr Register kAllocateSizeRegister = rdx;
248constexpr Register kInterpreterAccumulatorRegister = rax;
249constexpr Register kInterpreterBytecodeOffsetRegister = r9;
250constexpr Register kInterpreterBytecodeArrayRegister = r12;
251constexpr Register kInterpreterDispatchTableRegister = r15;
252
253constexpr Register kJavaScriptCallArgCountRegister = rax;
254constexpr Register kJavaScriptCallCodeStartRegister = rcx;
255constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
256constexpr Register kJavaScriptCallNewTargetRegister = rdx;
257constexpr Register kJavaScriptCallExtraArg1Register = rbx;
258
259constexpr Register kRuntimeCallFunctionRegister = rbx;
260constexpr Register kRuntimeCallArgCountRegister = rax;
261constexpr Register kRuntimeCallArgvRegister = r15;
262constexpr Register kWasmInstanceRegister = rsi;
263
264// Default scratch register used by MacroAssembler (and other code that needs
265// a spare register). The register isn't callee save, and not used by the
266// function calling convention.
267constexpr Register kScratchRegister = r10;
268constexpr XMMRegister kScratchDoubleReg = xmm15;
269constexpr Register kRootRegister = r13;  // callee save
270#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
271constexpr Register kPtrComprCageBaseRegister = r14;  // callee save
272#else
273constexpr Register kPtrComprCageBaseRegister = kRootRegister;
274#endif
275
276constexpr Register kOffHeapTrampolineRegister = kScratchRegister;
277
278constexpr DoubleRegister kFPReturnRegister0 = xmm0;
279
280}  // namespace internal
281}  // namespace v8
282
283#endif  // V8_CODEGEN_X64_REGISTER_X64_H_
284