• 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_ARM64_REGISTER_ARM64_H_
6 #define V8_CODEGEN_ARM64_REGISTER_ARM64_H_
7 
8 #include "src/codegen/arm64/utils-arm64.h"
9 #include "src/codegen/register-base.h"
10 #include "src/common/globals.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 // -----------------------------------------------------------------------------
16 // Registers.
17 // clang-format off
18 #define GENERAL_REGISTER_CODE_LIST(R)                     \
19   R(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)          \
20   R(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)         \
21   R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)         \
22   R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
23 
24 #define GENERAL_REGISTERS(R)                              \
25   R(x0)  R(x1)  R(x2)  R(x3)  R(x4)  R(x5)  R(x6)  R(x7)  \
26   R(x8)  R(x9)  R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
27   R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \
28   R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31)
29 
30 // x18 is the platform register and is reserved for the use of platform ABIs.
31 // It is known to be reserved by the OS at least on Windows and iOS.
32 #define ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(R)                  \
33   R(x0)  R(x1)  R(x2)  R(x3)  R(x4)  R(x5)  R(x6)  R(x7)  \
34   R(x8)  R(x9)  R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
35          R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x25) \
36   R(x27)
37 
38 #ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
39 #define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(R)
40 #else
41 #define MAYBE_ALLOCATABLE_GENERAL_REGISTERS(R) R(x28)
42 #endif
43 
44 #define ALLOCATABLE_GENERAL_REGISTERS(V)  \
45   ALWAYS_ALLOCATABLE_GENERAL_REGISTERS(V) \
46   MAYBE_ALLOCATABLE_GENERAL_REGISTERS(V)
47 
48 #define FLOAT_REGISTERS(V)                                \
49   V(s0)  V(s1)  V(s2)  V(s3)  V(s4)  V(s5)  V(s6)  V(s7)  \
50   V(s8)  V(s9)  V(s10) V(s11) V(s12) V(s13) V(s14) V(s15) \
51   V(s16) V(s17) V(s18) V(s19) V(s20) V(s21) V(s22) V(s23) \
52   V(s24) V(s25) V(s26) V(s27) V(s28) V(s29) V(s30) V(s31)
53 
54 #define DOUBLE_REGISTERS(R)                               \
55   R(d0)  R(d1)  R(d2)  R(d3)  R(d4)  R(d5)  R(d6)  R(d7)  \
56   R(d8)  R(d9)  R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \
57   R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \
58   R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31)
59 
60 #define SIMD128_REGISTERS(V)                              \
61   V(q0)  V(q1)  V(q2)  V(q3)  V(q4)  V(q5)  V(q6)  V(q7)  \
62   V(q8)  V(q9)  V(q10) V(q11) V(q12) V(q13) V(q14) V(q15) \
63   V(q16) V(q17) V(q18) V(q19) V(q20) V(q21) V(q22) V(q23) \
64   V(q24) V(q25) V(q26) V(q27) V(q28) V(q29) V(q30) V(q31)
65 
66 #define VECTOR_REGISTERS(V)                               \
67   V(v0)  V(v1)  V(v2)  V(v3)  V(v4)  V(v5)  V(v6)  V(v7)  \
68   V(v8)  V(v9)  V(v10) V(v11) V(v12) V(v13) V(v14) V(v15) \
69   V(v16) V(v17) V(v18) V(v19) V(v20) V(v21) V(v22) V(v23) \
70   V(v24) V(v25) V(v26) V(v27) V(v28) V(v29) V(v30) V(v31)
71 
72 // Register d29 could be allocated, but we keep an even length list here, in
73 // order to make stack alignment easier for save and restore.
74 #define ALLOCATABLE_DOUBLE_REGISTERS(R)                   \
75   R(d0)  R(d1)  R(d2)  R(d3)  R(d4)  R(d5)  R(d6)  R(d7)  \
76   R(d8)  R(d9)  R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \
77   R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) R(d24) \
78   R(d25) R(d26) R(d27) R(d28)
79 // clang-format on
80 
81 // Some CPURegister methods can return Register and VRegister types, so we
82 // need to declare them in advance.
83 class Register;
84 class VRegister;
85 
86 enum RegisterCode {
87 #define REGISTER_CODE(R) kRegCode_##R,
88   GENERAL_REGISTERS(REGISTER_CODE)
89 #undef REGISTER_CODE
90       kRegAfterLast
91 };
92 
93 class CPURegister : public RegisterBase<CPURegister, kRegAfterLast> {
94  public:
95   enum RegisterType : int8_t { kRegister, kVRegister, kNoRegister };
96 
no_reg()97   static constexpr CPURegister no_reg() {
98     return CPURegister{kCode_no_reg, 0, kNoRegister};
99   }
100 
Create(int code,int size,RegisterType type)101   static constexpr CPURegister Create(int code, int size, RegisterType type) {
102     DCHECK(IsValid(code, size, type));
103     return CPURegister{code, size, type};
104   }
105 
type()106   RegisterType type() const { return reg_type_; }
SizeInBits()107   int SizeInBits() const {
108     DCHECK(is_valid());
109     return reg_size_;
110   }
SizeInBytes()111   int SizeInBytes() const {
112     DCHECK(is_valid());
113     DCHECK_EQ(SizeInBits() % 8, 0);
114     return reg_size_ / 8;
115   }
Is8Bits()116   bool Is8Bits() const {
117     DCHECK(is_valid());
118     return reg_size_ == 8;
119   }
Is16Bits()120   bool Is16Bits() const {
121     DCHECK(is_valid());
122     return reg_size_ == 16;
123   }
Is32Bits()124   bool Is32Bits() const {
125     DCHECK(is_valid());
126     return reg_size_ == 32;
127   }
Is64Bits()128   bool Is64Bits() const {
129     DCHECK(is_valid());
130     return reg_size_ == 64;
131   }
Is128Bits()132   bool Is128Bits() const {
133     DCHECK(is_valid());
134     return reg_size_ == 128;
135   }
IsNone()136   bool IsNone() const { return reg_type_ == kNoRegister; }
Aliases(const CPURegister & other)137   constexpr bool Aliases(const CPURegister& other) const {
138     return RegisterBase::operator==(other) && reg_type_ == other.reg_type_;
139   }
140 
141   constexpr bool operator==(const CPURegister& other) const {
142     return RegisterBase::operator==(other) && reg_size_ == other.reg_size_ &&
143            reg_type_ == other.reg_type_;
144   }
145   constexpr bool operator!=(const CPURegister& other) const {
146     return !operator==(other);
147   }
148 
149   bool IsZero() const;
150   bool IsSP() const;
151 
IsRegister()152   bool IsRegister() const { return reg_type_ == kRegister; }
IsVRegister()153   bool IsVRegister() const { return reg_type_ == kVRegister; }
154 
IsFPRegister()155   bool IsFPRegister() const { return IsS() || IsD(); }
156 
IsW()157   bool IsW() const { return IsRegister() && Is32Bits(); }
IsX()158   bool IsX() const { return IsRegister() && Is64Bits(); }
159 
160   // These assertions ensure that the size and type of the register are as
161   // described. They do not consider the number of lanes that make up a vector.
162   // So, for example, Is8B() implies IsD(), and Is1D() implies IsD, but IsD()
163   // does not imply Is1D() or Is8B().
164   // Check the number of lanes, ie. the format of the vector, using methods such
165   // as Is8B(), Is1D(), etc. in the VRegister class.
IsV()166   bool IsV() const { return IsVRegister(); }
IsB()167   bool IsB() const { return IsV() && Is8Bits(); }
IsH()168   bool IsH() const { return IsV() && Is16Bits(); }
IsS()169   bool IsS() const { return IsV() && Is32Bits(); }
IsD()170   bool IsD() const { return IsV() && Is64Bits(); }
IsQ()171   bool IsQ() const { return IsV() && Is128Bits(); }
172 
173   Register Reg() const;
174   VRegister VReg() const;
175 
176   Register X() const;
177   Register W() const;
178   VRegister V() const;
179   VRegister B() const;
180   VRegister H() const;
181   VRegister D() const;
182   VRegister S() const;
183   VRegister Q() const;
184 
185   bool IsSameSizeAndType(const CPURegister& other) const;
186 
187  protected:
188   uint8_t reg_size_;
189   RegisterType reg_type_;
190 
191 #if defined(V8_OS_WIN) && !defined(__clang__)
192   // MSVC has problem to parse template base class as friend class.
193   friend RegisterBase;
194 #else
195   friend class RegisterBase;
196 #endif
197 
CPURegister(int code,int size,RegisterType type)198   constexpr CPURegister(int code, int size, RegisterType type)
199       : RegisterBase(code), reg_size_(size), reg_type_(type) {}
200 
IsValidRegister(int code,int size)201   static constexpr bool IsValidRegister(int code, int size) {
202     return (size == kWRegSizeInBits || size == kXRegSizeInBits) &&
203            (code < kNumberOfRegisters || code == kSPRegInternalCode);
204   }
205 
IsValidVRegister(int code,int size)206   static constexpr bool IsValidVRegister(int code, int size) {
207     return (size == kBRegSizeInBits || size == kHRegSizeInBits ||
208             size == kSRegSizeInBits || size == kDRegSizeInBits ||
209             size == kQRegSizeInBits) &&
210            code < kNumberOfVRegisters;
211   }
212 
IsValid(int code,int size,RegisterType type)213   static constexpr bool IsValid(int code, int size, RegisterType type) {
214     return (type == kRegister && IsValidRegister(code, size)) ||
215            (type == kVRegister && IsValidVRegister(code, size));
216   }
217 
IsNone(int code,int size,RegisterType type)218   static constexpr bool IsNone(int code, int size, RegisterType type) {
219     return type == kNoRegister && code == 0 && size == 0;
220   }
221 };
222 
223 ASSERT_TRIVIALLY_COPYABLE(CPURegister);
224 static_assert(sizeof(CPURegister) <= sizeof(int),
225               "CPURegister can efficiently be passed by value");
226 
227 class Register : public CPURegister {
228  public:
no_reg()229   static constexpr Register no_reg() { return Register(CPURegister::no_reg()); }
230 
Create(int code,int size)231   static constexpr Register Create(int code, int size) {
232     return Register(CPURegister::Create(code, size, CPURegister::kRegister));
233   }
234 
235   static Register XRegFromCode(unsigned code);
236   static Register WRegFromCode(unsigned code);
237 
from_code(int code)238   static constexpr Register from_code(int code) {
239     // Always return an X register.
240     return Register::Create(code, kXRegSizeInBits);
241   }
242 
GetSpecialRegisterName(int code)243   static const char* GetSpecialRegisterName(int code) {
244     return (code == kSPRegInternalCode) ? "sp" : "UNKNOWN";
245   }
246 
247  private:
Register(const CPURegister & r)248   constexpr explicit Register(const CPURegister& r) : CPURegister(r) {}
249 };
250 
251 ASSERT_TRIVIALLY_COPYABLE(Register);
252 static_assert(sizeof(Register) <= sizeof(int),
253               "Register can efficiently be passed by value");
254 
255 // Stack frame alignment and padding.
ArgumentPaddingSlots(int argument_count)256 constexpr int ArgumentPaddingSlots(int argument_count) {
257   // Stack frames are aligned to 16 bytes.
258   constexpr int kStackFrameAlignment = 16;
259   constexpr int alignment_mask = kStackFrameAlignment / kSystemPointerSize - 1;
260   return argument_count & alignment_mask;
261 }
262 
263 constexpr AliasingKind kFPAliasing = AliasingKind::kOverlap;
264 constexpr bool kSimdMaskRegisters = false;
265 
266 enum DoubleRegisterCode {
267 #define REGISTER_CODE(R) kDoubleCode_##R,
268   DOUBLE_REGISTERS(REGISTER_CODE)
269 #undef REGISTER_CODE
270       kDoubleAfterLast
271 };
272 
273 // Functions for handling NEON vector format information.
274 enum VectorFormat {
275   kFormatUndefined = 0xffffffff,
276   kFormat8B = NEON_8B,
277   kFormat16B = NEON_16B,
278   kFormat4H = NEON_4H,
279   kFormat8H = NEON_8H,
280   kFormat2S = NEON_2S,
281   kFormat4S = NEON_4S,
282   kFormat1D = NEON_1D,
283   kFormat2D = NEON_2D,
284 
285   // Scalar formats. We add the scalar bit to distinguish between scalar and
286   // vector enumerations; the bit is always set in the encoding of scalar ops
287   // and always clear for vector ops. Although kFormatD and kFormat1D appear
288   // to be the same, their meaning is subtly different. The first is a scalar
289   // operation, the second a vector operation that only affects one lane.
290   kFormatB = NEON_B | NEONScalar,
291   kFormatH = NEON_H | NEONScalar,
292   kFormatS = NEON_S | NEONScalar,
293   kFormatD = NEON_D | NEONScalar
294 };
295 
296 VectorFormat VectorFormatHalfWidth(VectorFormat vform);
297 VectorFormat VectorFormatDoubleWidth(VectorFormat vform);
298 VectorFormat VectorFormatDoubleLanes(VectorFormat vform);
299 VectorFormat VectorFormatHalfLanes(VectorFormat vform);
300 VectorFormat ScalarFormatFromLaneSize(int lanesize);
301 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform);
302 VectorFormat VectorFormatFillQ(int laneSize);
303 VectorFormat VectorFormatFillQ(VectorFormat vform);
304 VectorFormat ScalarFormatFromFormat(VectorFormat vform);
305 V8_EXPORT_PRIVATE unsigned RegisterSizeInBitsFromFormat(VectorFormat vform);
306 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform);
307 int LaneSizeInBytesFromFormat(VectorFormat vform);
308 unsigned LaneSizeInBitsFromFormat(VectorFormat vform);
309 int LaneSizeInBytesLog2FromFormat(VectorFormat vform);
310 V8_EXPORT_PRIVATE int LaneCountFromFormat(VectorFormat vform);
311 int MaxLaneCountFromFormat(VectorFormat vform);
312 V8_EXPORT_PRIVATE bool IsVectorFormat(VectorFormat vform);
313 int64_t MaxIntFromFormat(VectorFormat vform);
314 int64_t MinIntFromFormat(VectorFormat vform);
315 uint64_t MaxUintFromFormat(VectorFormat vform);
316 
317 class VRegister : public CPURegister {
318  public:
no_reg()319   static constexpr VRegister no_reg() {
320     return VRegister(CPURegister::no_reg(), 0);
321   }
322 
323   static constexpr VRegister Create(int code, int size, int lane_count = 1) {
324     DCHECK(IsValidLaneCount(lane_count));
325     return VRegister(CPURegister::Create(code, size, CPURegister::kVRegister),
326                      lane_count);
327   }
328 
Create(int reg_code,VectorFormat format)329   static VRegister Create(int reg_code, VectorFormat format) {
330     int reg_size = RegisterSizeInBitsFromFormat(format);
331     int reg_count = IsVectorFormat(format) ? LaneCountFromFormat(format) : 1;
332     return VRegister::Create(reg_code, reg_size, reg_count);
333   }
334 
335   static VRegister BRegFromCode(unsigned code);
336   static VRegister HRegFromCode(unsigned code);
337   static VRegister SRegFromCode(unsigned code);
338   static VRegister DRegFromCode(unsigned code);
339   static VRegister QRegFromCode(unsigned code);
340   static VRegister VRegFromCode(unsigned code);
341 
V8B()342   VRegister V8B() const {
343     return VRegister::Create(code(), kDRegSizeInBits, 8);
344   }
V16B()345   VRegister V16B() const {
346     return VRegister::Create(code(), kQRegSizeInBits, 16);
347   }
V4H()348   VRegister V4H() const {
349     return VRegister::Create(code(), kDRegSizeInBits, 4);
350   }
V8H()351   VRegister V8H() const {
352     return VRegister::Create(code(), kQRegSizeInBits, 8);
353   }
V2S()354   VRegister V2S() const {
355     return VRegister::Create(code(), kDRegSizeInBits, 2);
356   }
V4S()357   VRegister V4S() const {
358     return VRegister::Create(code(), kQRegSizeInBits, 4);
359   }
V2D()360   VRegister V2D() const {
361     return VRegister::Create(code(), kQRegSizeInBits, 2);
362   }
V1D()363   VRegister V1D() const {
364     return VRegister::Create(code(), kDRegSizeInBits, 1);
365   }
366 
Format(VectorFormat f)367   VRegister Format(VectorFormat f) const {
368     return VRegister::Create(code(), f);
369   }
370 
Is8B()371   bool Is8B() const { return (Is64Bits() && (lane_count_ == 8)); }
Is16B()372   bool Is16B() const { return (Is128Bits() && (lane_count_ == 16)); }
Is4H()373   bool Is4H() const { return (Is64Bits() && (lane_count_ == 4)); }
Is8H()374   bool Is8H() const { return (Is128Bits() && (lane_count_ == 8)); }
Is2S()375   bool Is2S() const { return (Is64Bits() && (lane_count_ == 2)); }
Is4S()376   bool Is4S() const { return (Is128Bits() && (lane_count_ == 4)); }
Is1D()377   bool Is1D() const { return (Is64Bits() && (lane_count_ == 1)); }
Is2D()378   bool Is2D() const { return (Is128Bits() && (lane_count_ == 2)); }
379 
380   // For consistency, we assert the number of lanes of these scalar registers,
381   // even though there are no vectors of equivalent total size with which they
382   // could alias.
Is1B()383   bool Is1B() const {
384     DCHECK(!(Is8Bits() && IsVector()));
385     return Is8Bits();
386   }
Is1H()387   bool Is1H() const {
388     DCHECK(!(Is16Bits() && IsVector()));
389     return Is16Bits();
390   }
Is1S()391   bool Is1S() const {
392     DCHECK(!(Is32Bits() && IsVector()));
393     return Is32Bits();
394   }
395 
IsLaneSizeB()396   bool IsLaneSizeB() const { return LaneSizeInBits() == kBRegSizeInBits; }
IsLaneSizeH()397   bool IsLaneSizeH() const { return LaneSizeInBits() == kHRegSizeInBits; }
IsLaneSizeS()398   bool IsLaneSizeS() const { return LaneSizeInBits() == kSRegSizeInBits; }
IsLaneSizeD()399   bool IsLaneSizeD() const { return LaneSizeInBits() == kDRegSizeInBits; }
400 
IsScalar()401   bool IsScalar() const { return lane_count_ == 1; }
IsVector()402   bool IsVector() const { return lane_count_ > 1; }
403 
IsSameFormat(const VRegister & other)404   bool IsSameFormat(const VRegister& other) const {
405     return (reg_size_ == other.reg_size_) && (lane_count_ == other.lane_count_);
406   }
407 
LaneCount()408   int LaneCount() const { return lane_count_; }
409 
LaneSizeInBytes()410   unsigned LaneSizeInBytes() const { return SizeInBytes() / lane_count_; }
411 
LaneSizeInBits()412   unsigned LaneSizeInBits() const { return LaneSizeInBytes() * 8; }
413 
414   static constexpr int kMaxNumRegisters = kNumberOfVRegisters;
415   STATIC_ASSERT(kMaxNumRegisters == kDoubleAfterLast);
416 
from_code(int code)417   static constexpr VRegister from_code(int code) {
418     // Always return a D register.
419     return VRegister::Create(code, kDRegSizeInBits);
420   }
421 
422  private:
423   int8_t lane_count_;
424 
VRegister(const CPURegister & r,int lane_count)425   constexpr explicit VRegister(const CPURegister& r, int lane_count)
426       : CPURegister(r), lane_count_(lane_count) {}
427 
IsValidLaneCount(int lane_count)428   static constexpr bool IsValidLaneCount(int lane_count) {
429     return base::bits::IsPowerOfTwo(lane_count) && lane_count <= 16;
430   }
431 };
432 
433 ASSERT_TRIVIALLY_COPYABLE(VRegister);
434 static_assert(sizeof(VRegister) <= sizeof(int),
435               "VRegister can efficiently be passed by value");
436 
437 // No*Reg is used to indicate an unused argument, or an error case. Note that
438 // these all compare equal. The Register and VRegister variants are provided for
439 // convenience.
440 constexpr Register NoReg = Register::no_reg();
441 constexpr VRegister NoVReg = VRegister::no_reg();
442 constexpr CPURegister NoCPUReg = CPURegister::no_reg();
443 constexpr Register no_reg = NoReg;
444 constexpr VRegister no_dreg = NoVReg;
445 
446 #define DEFINE_REGISTER(register_class, name, ...) \
447   constexpr register_class name = register_class::Create(__VA_ARGS__)
448 #define ALIAS_REGISTER(register_class, alias, name) \
449   constexpr register_class alias = name
450 
451 #define DEFINE_REGISTERS(N)                            \
452   DEFINE_REGISTER(Register, w##N, N, kWRegSizeInBits); \
453   DEFINE_REGISTER(Register, x##N, N, kXRegSizeInBits);
454 GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS)
455 #undef DEFINE_REGISTERS
456 
457 DEFINE_REGISTER(Register, wsp, kSPRegInternalCode, kWRegSizeInBits);
458 DEFINE_REGISTER(Register, sp, kSPRegInternalCode, kXRegSizeInBits);
459 
460 #define DEFINE_VREGISTERS(N)                            \
461   DEFINE_REGISTER(VRegister, b##N, N, kBRegSizeInBits); \
462   DEFINE_REGISTER(VRegister, h##N, N, kHRegSizeInBits); \
463   DEFINE_REGISTER(VRegister, s##N, N, kSRegSizeInBits); \
464   DEFINE_REGISTER(VRegister, d##N, N, kDRegSizeInBits); \
465   DEFINE_REGISTER(VRegister, q##N, N, kQRegSizeInBits); \
466   DEFINE_REGISTER(VRegister, v##N, N, kQRegSizeInBits);
467 GENERAL_REGISTER_CODE_LIST(DEFINE_VREGISTERS)
468 #undef DEFINE_VREGISTERS
469 
470 #undef DEFINE_REGISTER
471 
472 // Registers aliases.
473 ALIAS_REGISTER(VRegister, v8_, v8);  // Avoid conflicts with namespace v8.
474 ALIAS_REGISTER(Register, ip0, x16);
475 ALIAS_REGISTER(Register, ip1, x17);
476 ALIAS_REGISTER(Register, wip0, w16);
477 ALIAS_REGISTER(Register, wip1, w17);
478 // Root register.
479 ALIAS_REGISTER(Register, kRootRegister, x26);
480 ALIAS_REGISTER(Register, rr, x26);
481 // Pointer cage base register.
482 #ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
483 ALIAS_REGISTER(Register, kPtrComprCageBaseRegister, x28);
484 #else
485 ALIAS_REGISTER(Register, kPtrComprCageBaseRegister, kRootRegister);
486 #endif
487 // Context pointer register.
488 ALIAS_REGISTER(Register, cp, x27);
489 ALIAS_REGISTER(Register, fp, x29);
490 ALIAS_REGISTER(Register, lr, x30);
491 ALIAS_REGISTER(Register, xzr, x31);
492 ALIAS_REGISTER(Register, wzr, w31);
493 
494 // Register used for padding stack slots.
495 ALIAS_REGISTER(Register, padreg, x31);
496 
497 // Keeps the 0 double value.
498 ALIAS_REGISTER(VRegister, fp_zero, d15);
499 // MacroAssembler fixed V Registers.
500 // d29 is not part of ALLOCATABLE_DOUBLE_REGISTERS, so use 27 and 28.
501 ALIAS_REGISTER(VRegister, fp_fixed1, d27);
502 ALIAS_REGISTER(VRegister, fp_fixed2, d28);
503 
504 // MacroAssembler scratch V registers.
505 ALIAS_REGISTER(VRegister, fp_scratch, d30);
506 ALIAS_REGISTER(VRegister, fp_scratch1, d30);
507 ALIAS_REGISTER(VRegister, fp_scratch2, d31);
508 
509 #undef ALIAS_REGISTER
510 
511 // AreAliased returns true if any of the named registers overlap. Arguments set
512 // to NoReg are ignored. The system stack pointer may be specified.
513 V8_EXPORT_PRIVATE bool AreAliased(
514     const CPURegister& reg1, const CPURegister& reg2,
515     const CPURegister& reg3 = NoReg, const CPURegister& reg4 = NoReg,
516     const CPURegister& reg5 = NoReg, const CPURegister& reg6 = NoReg,
517     const CPURegister& reg7 = NoReg, const CPURegister& reg8 = NoReg);
518 
519 // AreSameSizeAndType returns true if all of the specified registers have the
520 // same size, and are of the same type. The system stack pointer may be
521 // specified. Arguments set to NoReg are ignored, as are any subsequent
522 // arguments. At least one argument (reg1) must be valid (not NoCPUReg).
523 V8_EXPORT_PRIVATE bool AreSameSizeAndType(
524     const CPURegister& reg1, const CPURegister& reg2 = NoCPUReg,
525     const CPURegister& reg3 = NoCPUReg, const CPURegister& reg4 = NoCPUReg,
526     const CPURegister& reg5 = NoCPUReg, const CPURegister& reg6 = NoCPUReg,
527     const CPURegister& reg7 = NoCPUReg, const CPURegister& reg8 = NoCPUReg);
528 
529 // AreSameFormat returns true if all of the specified VRegisters have the same
530 // vector format. Arguments set to NoVReg are ignored, as are any subsequent
531 // arguments. At least one argument (reg1) must be valid (not NoVReg).
532 bool AreSameFormat(const VRegister& reg1, const VRegister& reg2,
533                    const VRegister& reg3 = NoVReg,
534                    const VRegister& reg4 = NoVReg);
535 
536 // AreConsecutive returns true if all of the specified VRegisters are
537 // consecutive in the register file. Arguments may be set to NoVReg, and if so,
538 // subsequent arguments must also be NoVReg. At least one argument (reg1) must
539 // be valid (not NoVReg).
540 V8_EXPORT_PRIVATE bool AreConsecutive(const VRegister& reg1,
541                                       const VRegister& reg2,
542                                       const VRegister& reg3 = NoVReg,
543                                       const VRegister& reg4 = NoVReg);
544 
545 using FloatRegister = VRegister;
546 using DoubleRegister = VRegister;
547 using Simd128Register = VRegister;
548 
549 // Define a {RegisterName} method for {Register} and {VRegister}.
550 DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
551 DEFINE_REGISTER_NAMES(VRegister, VECTOR_REGISTERS)
552 
553 // Give alias names to registers for calling conventions.
554 constexpr Register kReturnRegister0 = x0;
555 constexpr Register kReturnRegister1 = x1;
556 constexpr Register kReturnRegister2 = x2;
557 constexpr Register kJSFunctionRegister = x1;
558 constexpr Register kContextRegister = cp;
559 constexpr Register kAllocateSizeRegister = x1;
560 
561 constexpr Register kInterpreterAccumulatorRegister = x0;
562 constexpr Register kInterpreterBytecodeOffsetRegister = x19;
563 constexpr Register kInterpreterBytecodeArrayRegister = x20;
564 constexpr Register kInterpreterDispatchTableRegister = x21;
565 
566 constexpr Register kJavaScriptCallArgCountRegister = x0;
567 constexpr Register kJavaScriptCallCodeStartRegister = x2;
568 constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
569 constexpr Register kJavaScriptCallNewTargetRegister = x3;
570 constexpr Register kJavaScriptCallExtraArg1Register = x2;
571 
572 constexpr Register kOffHeapTrampolineRegister = ip0;
573 constexpr Register kRuntimeCallFunctionRegister = x1;
574 constexpr Register kRuntimeCallArgCountRegister = x0;
575 constexpr Register kRuntimeCallArgvRegister = x11;
576 constexpr Register kWasmInstanceRegister = x7;
577 constexpr Register kWasmCompileLazyFuncIndexRegister = x8;
578 
579 constexpr DoubleRegister kFPReturnRegister0 = d0;
580 
581 }  // namespace internal
582 }  // namespace v8
583 
584 #endif  // V8_CODEGEN_ARM64_REGISTER_ARM64_H_
585