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 12namespace v8 { 13namespace 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. 83class Register; 84class VRegister; 85 86enum RegisterCode { 87#define REGISTER_CODE(R) kRegCode_##R, 88 GENERAL_REGISTERS(REGISTER_CODE) 89#undef REGISTER_CODE 90 kRegAfterLast 91}; 92 93class CPURegister : public RegisterBase<CPURegister, kRegAfterLast> { 94 public: 95 enum RegisterType : int8_t { kRegister, kVRegister, kNoRegister }; 96 97 static constexpr CPURegister no_reg() { 98 return CPURegister{kCode_no_reg, 0, kNoRegister}; 99 } 100 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 106 RegisterType type() const { return reg_type_; } 107 int SizeInBits() const { 108 DCHECK(is_valid()); 109 return reg_size_; 110 } 111 int SizeInBytes() const { 112 DCHECK(is_valid()); 113 DCHECK_EQ(SizeInBits() % 8, 0); 114 return reg_size_ / 8; 115 } 116 bool Is8Bits() const { 117 DCHECK(is_valid()); 118 return reg_size_ == 8; 119 } 120 bool Is16Bits() const { 121 DCHECK(is_valid()); 122 return reg_size_ == 16; 123 } 124 bool Is32Bits() const { 125 DCHECK(is_valid()); 126 return reg_size_ == 32; 127 } 128 bool Is64Bits() const { 129 DCHECK(is_valid()); 130 return reg_size_ == 64; 131 } 132 bool Is128Bits() const { 133 DCHECK(is_valid()); 134 return reg_size_ == 128; 135 } 136 bool IsNone() const { return reg_type_ == kNoRegister; } 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 152 bool IsRegister() const { return reg_type_ == kRegister; } 153 bool IsVRegister() const { return reg_type_ == kVRegister; } 154 155 bool IsFPRegister() const { return IsS() || IsD(); } 156 157 bool IsW() const { return IsRegister() && Is32Bits(); } 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. 166 bool IsV() const { return IsVRegister(); } 167 bool IsB() const { return IsV() && Is8Bits(); } 168 bool IsH() const { return IsV() && Is16Bits(); } 169 bool IsS() const { return IsV() && Is32Bits(); } 170 bool IsD() const { return IsV() && Is64Bits(); } 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 198 constexpr CPURegister(int code, int size, RegisterType type) 199 : RegisterBase(code), reg_size_(size), reg_type_(type) {} 200 201 static constexpr bool IsValidRegister(int code, int size) { 202 return (size == kWRegSizeInBits || size == kXRegSizeInBits) && 203 (code < kNumberOfRegisters || code == kSPRegInternalCode); 204 } 205 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 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 218 static constexpr bool IsNone(int code, int size, RegisterType type) { 219 return type == kNoRegister && code == 0 && size == 0; 220 } 221}; 222 223ASSERT_TRIVIALLY_COPYABLE(CPURegister); 224static_assert(sizeof(CPURegister) <= sizeof(int), 225 "CPURegister can efficiently be passed by value"); 226 227class Register : public CPURegister { 228 public: 229 static constexpr Register no_reg() { return Register(CPURegister::no_reg()); } 230 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 238 static constexpr Register from_code(int code) { 239 // Always return an X register. 240 return Register::Create(code, kXRegSizeInBits); 241 } 242 243 static const char* GetSpecialRegisterName(int code) { 244 return (code == kSPRegInternalCode) ? "sp" : "UNKNOWN"; 245 } 246 247 private: 248 constexpr explicit Register(const CPURegister& r) : CPURegister(r) {} 249}; 250 251ASSERT_TRIVIALLY_COPYABLE(Register); 252static_assert(sizeof(Register) <= sizeof(int), 253 "Register can efficiently be passed by value"); 254 255// Stack frame alignment and padding. 256constexpr 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 263constexpr AliasingKind kFPAliasing = AliasingKind::kOverlap; 264constexpr bool kSimdMaskRegisters = false; 265 266enum 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. 274enum 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 296VectorFormat VectorFormatHalfWidth(VectorFormat vform); 297VectorFormat VectorFormatDoubleWidth(VectorFormat vform); 298VectorFormat VectorFormatDoubleLanes(VectorFormat vform); 299VectorFormat VectorFormatHalfLanes(VectorFormat vform); 300VectorFormat ScalarFormatFromLaneSize(int lanesize); 301VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform); 302VectorFormat VectorFormatFillQ(int laneSize); 303VectorFormat VectorFormatFillQ(VectorFormat vform); 304VectorFormat ScalarFormatFromFormat(VectorFormat vform); 305V8_EXPORT_PRIVATE unsigned RegisterSizeInBitsFromFormat(VectorFormat vform); 306unsigned RegisterSizeInBytesFromFormat(VectorFormat vform); 307int LaneSizeInBytesFromFormat(VectorFormat vform); 308unsigned LaneSizeInBitsFromFormat(VectorFormat vform); 309int LaneSizeInBytesLog2FromFormat(VectorFormat vform); 310V8_EXPORT_PRIVATE int LaneCountFromFormat(VectorFormat vform); 311int MaxLaneCountFromFormat(VectorFormat vform); 312V8_EXPORT_PRIVATE bool IsVectorFormat(VectorFormat vform); 313int64_t MaxIntFromFormat(VectorFormat vform); 314int64_t MinIntFromFormat(VectorFormat vform); 315uint64_t MaxUintFromFormat(VectorFormat vform); 316 317class VRegister : public CPURegister { 318 public: 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 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 342 VRegister V8B() const { 343 return VRegister::Create(code(), kDRegSizeInBits, 8); 344 } 345 VRegister V16B() const { 346 return VRegister::Create(code(), kQRegSizeInBits, 16); 347 } 348 VRegister V4H() const { 349 return VRegister::Create(code(), kDRegSizeInBits, 4); 350 } 351 VRegister V8H() const { 352 return VRegister::Create(code(), kQRegSizeInBits, 8); 353 } 354 VRegister V2S() const { 355 return VRegister::Create(code(), kDRegSizeInBits, 2); 356 } 357 VRegister V4S() const { 358 return VRegister::Create(code(), kQRegSizeInBits, 4); 359 } 360 VRegister V2D() const { 361 return VRegister::Create(code(), kQRegSizeInBits, 2); 362 } 363 VRegister V1D() const { 364 return VRegister::Create(code(), kDRegSizeInBits, 1); 365 } 366 367 VRegister Format(VectorFormat f) const { 368 return VRegister::Create(code(), f); 369 } 370 371 bool Is8B() const { return (Is64Bits() && (lane_count_ == 8)); } 372 bool Is16B() const { return (Is128Bits() && (lane_count_ == 16)); } 373 bool Is4H() const { return (Is64Bits() && (lane_count_ == 4)); } 374 bool Is8H() const { return (Is128Bits() && (lane_count_ == 8)); } 375 bool Is2S() const { return (Is64Bits() && (lane_count_ == 2)); } 376 bool Is4S() const { return (Is128Bits() && (lane_count_ == 4)); } 377 bool Is1D() const { return (Is64Bits() && (lane_count_ == 1)); } 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. 383 bool Is1B() const { 384 DCHECK(!(Is8Bits() && IsVector())); 385 return Is8Bits(); 386 } 387 bool Is1H() const { 388 DCHECK(!(Is16Bits() && IsVector())); 389 return Is16Bits(); 390 } 391 bool Is1S() const { 392 DCHECK(!(Is32Bits() && IsVector())); 393 return Is32Bits(); 394 } 395 396 bool IsLaneSizeB() const { return LaneSizeInBits() == kBRegSizeInBits; } 397 bool IsLaneSizeH() const { return LaneSizeInBits() == kHRegSizeInBits; } 398 bool IsLaneSizeS() const { return LaneSizeInBits() == kSRegSizeInBits; } 399 bool IsLaneSizeD() const { return LaneSizeInBits() == kDRegSizeInBits; } 400 401 bool IsScalar() const { return lane_count_ == 1; } 402 bool IsVector() const { return lane_count_ > 1; } 403 404 bool IsSameFormat(const VRegister& other) const { 405 return (reg_size_ == other.reg_size_) && (lane_count_ == other.lane_count_); 406 } 407 408 int LaneCount() const { return lane_count_; } 409 410 unsigned LaneSizeInBytes() const { return SizeInBytes() / lane_count_; } 411 412 unsigned LaneSizeInBits() const { return LaneSizeInBytes() * 8; } 413 414 static constexpr int kMaxNumRegisters = kNumberOfVRegisters; 415 STATIC_ASSERT(kMaxNumRegisters == kDoubleAfterLast); 416 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 425 constexpr explicit VRegister(const CPURegister& r, int lane_count) 426 : CPURegister(r), lane_count_(lane_count) {} 427 428 static constexpr bool IsValidLaneCount(int lane_count) { 429 return base::bits::IsPowerOfTwo(lane_count) && lane_count <= 16; 430 } 431}; 432 433ASSERT_TRIVIALLY_COPYABLE(VRegister); 434static_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. 440constexpr Register NoReg = Register::no_reg(); 441constexpr VRegister NoVReg = VRegister::no_reg(); 442constexpr CPURegister NoCPUReg = CPURegister::no_reg(); 443constexpr Register no_reg = NoReg; 444constexpr 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); 454GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS) 455#undef DEFINE_REGISTERS 456 457DEFINE_REGISTER(Register, wsp, kSPRegInternalCode, kWRegSizeInBits); 458DEFINE_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); 467GENERAL_REGISTER_CODE_LIST(DEFINE_VREGISTERS) 468#undef DEFINE_VREGISTERS 469 470#undef DEFINE_REGISTER 471 472// Registers aliases. 473ALIAS_REGISTER(VRegister, v8_, v8); // Avoid conflicts with namespace v8. 474ALIAS_REGISTER(Register, ip0, x16); 475ALIAS_REGISTER(Register, ip1, x17); 476ALIAS_REGISTER(Register, wip0, w16); 477ALIAS_REGISTER(Register, wip1, w17); 478// Root register. 479ALIAS_REGISTER(Register, kRootRegister, x26); 480ALIAS_REGISTER(Register, rr, x26); 481// Pointer cage base register. 482#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE 483ALIAS_REGISTER(Register, kPtrComprCageBaseRegister, x28); 484#else 485ALIAS_REGISTER(Register, kPtrComprCageBaseRegister, kRootRegister); 486#endif 487// Context pointer register. 488ALIAS_REGISTER(Register, cp, x27); 489ALIAS_REGISTER(Register, fp, x29); 490ALIAS_REGISTER(Register, lr, x30); 491ALIAS_REGISTER(Register, xzr, x31); 492ALIAS_REGISTER(Register, wzr, w31); 493 494// Register used for padding stack slots. 495ALIAS_REGISTER(Register, padreg, x31); 496 497// Keeps the 0 double value. 498ALIAS_REGISTER(VRegister, fp_zero, d15); 499// MacroAssembler fixed V Registers. 500// d29 is not part of ALLOCATABLE_DOUBLE_REGISTERS, so use 27 and 28. 501ALIAS_REGISTER(VRegister, fp_fixed1, d27); 502ALIAS_REGISTER(VRegister, fp_fixed2, d28); 503 504// MacroAssembler scratch V registers. 505ALIAS_REGISTER(VRegister, fp_scratch, d30); 506ALIAS_REGISTER(VRegister, fp_scratch1, d30); 507ALIAS_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. 513V8_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). 523V8_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). 532bool 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). 540V8_EXPORT_PRIVATE bool AreConsecutive(const VRegister& reg1, 541 const VRegister& reg2, 542 const VRegister& reg3 = NoVReg, 543 const VRegister& reg4 = NoVReg); 544 545using FloatRegister = VRegister; 546using DoubleRegister = VRegister; 547using Simd128Register = VRegister; 548 549// Define a {RegisterName} method for {Register} and {VRegister}. 550DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS) 551DEFINE_REGISTER_NAMES(VRegister, VECTOR_REGISTERS) 552 553// Give alias names to registers for calling conventions. 554constexpr Register kReturnRegister0 = x0; 555constexpr Register kReturnRegister1 = x1; 556constexpr Register kReturnRegister2 = x2; 557constexpr Register kJSFunctionRegister = x1; 558constexpr Register kContextRegister = cp; 559constexpr Register kAllocateSizeRegister = x1; 560 561constexpr Register kInterpreterAccumulatorRegister = x0; 562constexpr Register kInterpreterBytecodeOffsetRegister = x19; 563constexpr Register kInterpreterBytecodeArrayRegister = x20; 564constexpr Register kInterpreterDispatchTableRegister = x21; 565 566constexpr Register kJavaScriptCallArgCountRegister = x0; 567constexpr Register kJavaScriptCallCodeStartRegister = x2; 568constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister; 569constexpr Register kJavaScriptCallNewTargetRegister = x3; 570constexpr Register kJavaScriptCallExtraArg1Register = x2; 571 572constexpr Register kOffHeapTrampolineRegister = ip0; 573constexpr Register kRuntimeCallFunctionRegister = x1; 574constexpr Register kRuntimeCallArgCountRegister = x0; 575constexpr Register kRuntimeCallArgvRegister = x11; 576constexpr Register kWasmInstanceRegister = x7; 577constexpr Register kWasmCompileLazyFuncIndexRegister = x8; 578 579constexpr DoubleRegister kFPReturnRegister0 = d0; 580 581} // namespace internal 582} // namespace v8 583 584#endif // V8_CODEGEN_ARM64_REGISTER_ARM64_H_ 585