diff options
Diffstat (limited to 'deps/v8/src/arm64/register-arm64.h')
-rw-r--r-- | deps/v8/src/arm64/register-arm64.h | 750 |
1 files changed, 0 insertions, 750 deletions
diff --git a/deps/v8/src/arm64/register-arm64.h b/deps/v8/src/arm64/register-arm64.h deleted file mode 100644 index f5a79d46f1..0000000000 --- a/deps/v8/src/arm64/register-arm64.h +++ /dev/null @@ -1,750 +0,0 @@ -// Copyright 2018 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef V8_ARM64_REGISTER_ARM64_H_ -#define V8_ARM64_REGISTER_ARM64_H_ - -#include "src/arm64/utils-arm64.h" -#include "src/globals.h" -#include "src/register.h" -#include "src/reglist.h" - -namespace v8 { -namespace internal { - -// ----------------------------------------------------------------------------- -// Registers. -// clang-format off -#define GENERAL_REGISTER_CODE_LIST(R) \ - R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ - R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ - R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ - R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) - -#define GENERAL_REGISTERS(R) \ - R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \ - R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \ - R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \ - R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31) - -// x18 is the platform register and is reserved for the use of platform ABIs. -// It is known to be reserved by the OS at least on Windows and iOS. -#define ALLOCATABLE_GENERAL_REGISTERS(R) \ - R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \ - R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \ - R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x25) \ - R(x27) R(x28) - -#define FLOAT_REGISTERS(V) \ - V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) \ - V(s8) V(s9) V(s10) V(s11) V(s12) V(s13) V(s14) V(s15) \ - V(s16) V(s17) V(s18) V(s19) V(s20) V(s21) V(s22) V(s23) \ - V(s24) V(s25) V(s26) V(s27) V(s28) V(s29) V(s30) V(s31) - -#define DOUBLE_REGISTERS(R) \ - R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \ - R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \ - R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \ - R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31) - -#define SIMD128_REGISTERS(V) \ - V(q0) V(q1) V(q2) V(q3) V(q4) V(q5) V(q6) V(q7) \ - V(q8) V(q9) V(q10) V(q11) V(q12) V(q13) V(q14) V(q15) \ - V(q16) V(q17) V(q18) V(q19) V(q20) V(q21) V(q22) V(q23) \ - V(q24) V(q25) V(q26) V(q27) V(q28) V(q29) V(q30) V(q31) - -#define VECTOR_REGISTERS(V) \ - V(v0) V(v1) V(v2) V(v3) V(v4) V(v5) V(v6) V(v7) \ - V(v8) V(v9) V(v10) V(v11) V(v12) V(v13) V(v14) V(v15) \ - V(v16) V(v17) V(v18) V(v19) V(v20) V(v21) V(v22) V(v23) \ - V(v24) V(v25) V(v26) V(v27) V(v28) V(v29) V(v30) V(v31) - -// Register d29 could be allocated, but we keep an even length list here, in -// order to make stack alignment easier for save and restore. -#define ALLOCATABLE_DOUBLE_REGISTERS(R) \ - R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \ - R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \ - R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) R(d24) \ - R(d25) R(d26) R(d27) R(d28) -// clang-format on - -constexpr int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte; - -const int kNumRegs = kNumberOfRegisters; -// Registers x0-x17 are caller-saved. -const int kNumJSCallerSaved = 18; -const RegList kJSCallerSaved = 0x3ffff; - -// Number of registers for which space is reserved in safepoints. Must be a -// multiple of eight. -// TODO(all): Refine this number. -const int kNumSafepointRegisters = 32; - -// Define the list of registers actually saved at safepoints. -// Note that the number of saved registers may be smaller than the reserved -// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters. -#define kSafepointSavedRegisters CPURegList::GetSafepointSavedRegisters().list() -#define kNumSafepointSavedRegisters \ - CPURegList::GetSafepointSavedRegisters().Count() - -// Some CPURegister methods can return Register and VRegister types, so we -// need to declare them in advance. -class Register; -class VRegister; - -enum RegisterCode { -#define REGISTER_CODE(R) kRegCode_##R, - GENERAL_REGISTERS(REGISTER_CODE) -#undef REGISTER_CODE - kRegAfterLast -}; - -class CPURegister : public RegisterBase<CPURegister, kRegAfterLast> { - public: - enum RegisterType { kRegister, kVRegister, kNoRegister }; - - static constexpr CPURegister no_reg() { - return CPURegister{0, 0, kNoRegister}; - } - - template <int code, int size, RegisterType type> - static constexpr CPURegister Create() { - static_assert(IsValid(code, size, type), "Cannot create invalid registers"); - return CPURegister{code, size, type}; - } - - static CPURegister Create(int code, int size, RegisterType type) { - DCHECK(IsValid(code, size, type)); - return CPURegister{code, size, type}; - } - - RegisterType type() const { return reg_type_; } - int SizeInBits() const { - DCHECK(IsValid()); - return reg_size_; - } - int SizeInBytes() const { - DCHECK(IsValid()); - DCHECK_EQ(SizeInBits() % 8, 0); - return reg_size_ / 8; - } - bool Is8Bits() const { - DCHECK(IsValid()); - return reg_size_ == 8; - } - bool Is16Bits() const { - DCHECK(IsValid()); - return reg_size_ == 16; - } - bool Is32Bits() const { - DCHECK(IsValid()); - return reg_size_ == 32; - } - bool Is64Bits() const { - DCHECK(IsValid()); - return reg_size_ == 64; - } - bool Is128Bits() const { - DCHECK(IsValid()); - return reg_size_ == 128; - } - bool IsValid() const { return reg_type_ != kNoRegister; } - bool IsNone() const { return reg_type_ == kNoRegister; } - bool Is(const CPURegister& other) const { - return Aliases(other) && (reg_size_ == other.reg_size_); - } - bool Aliases(const CPURegister& other) const { - return (reg_code_ == other.reg_code_) && (reg_type_ == other.reg_type_); - } - - bool IsZero() const; - bool IsSP() const; - - bool IsRegister() const { return reg_type_ == kRegister; } - bool IsVRegister() const { return reg_type_ == kVRegister; } - - bool IsFPRegister() const { return IsS() || IsD(); } - - bool IsW() const { return IsRegister() && Is32Bits(); } - bool IsX() const { return IsRegister() && Is64Bits(); } - - // These assertions ensure that the size and type of the register are as - // described. They do not consider the number of lanes that make up a vector. - // So, for example, Is8B() implies IsD(), and Is1D() implies IsD, but IsD() - // does not imply Is1D() or Is8B(). - // Check the number of lanes, ie. the format of the vector, using methods such - // as Is8B(), Is1D(), etc. in the VRegister class. - bool IsV() const { return IsVRegister(); } - bool IsB() const { return IsV() && Is8Bits(); } - bool IsH() const { return IsV() && Is16Bits(); } - bool IsS() const { return IsV() && Is32Bits(); } - bool IsD() const { return IsV() && Is64Bits(); } - bool IsQ() const { return IsV() && Is128Bits(); } - - Register Reg() const; - VRegister VReg() const; - - Register X() const; - Register W() const; - VRegister V() const; - VRegister B() const; - VRegister H() const; - VRegister D() const; - VRegister S() const; - VRegister Q() const; - - bool IsSameSizeAndType(const CPURegister& other) const; - - bool is(const CPURegister& other) const { return Is(other); } - bool is_valid() const { return IsValid(); } - - protected: - int reg_size_; - RegisterType reg_type_; - -#if defined(V8_OS_WIN) && !defined(__clang__) - // MSVC has problem to parse template base class as friend class. - friend RegisterBase; -#else - friend class RegisterBase; -#endif - - constexpr CPURegister(int code, int size, RegisterType type) - : RegisterBase(code), reg_size_(size), reg_type_(type) {} - - static constexpr bool IsValidRegister(int code, int size) { - return (size == kWRegSizeInBits || size == kXRegSizeInBits) && - (code < kNumberOfRegisters || code == kSPRegInternalCode); - } - - static constexpr bool IsValidVRegister(int code, int size) { - return (size == kBRegSizeInBits || size == kHRegSizeInBits || - size == kSRegSizeInBits || size == kDRegSizeInBits || - size == kQRegSizeInBits) && - code < kNumberOfVRegisters; - } - - static constexpr bool IsValid(int code, int size, RegisterType type) { - return (type == kRegister && IsValidRegister(code, size)) || - (type == kVRegister && IsValidVRegister(code, size)); - } - - static constexpr bool IsNone(int code, int size, RegisterType type) { - return type == kNoRegister && code == 0 && size == 0; - } -}; - -ASSERT_TRIVIALLY_COPYABLE(CPURegister); - -class Register : public CPURegister { - public: - static constexpr Register no_reg() { return Register(CPURegister::no_reg()); } - - template <int code, int size> - static constexpr Register Create() { - return Register(CPURegister::Create<code, size, CPURegister::kRegister>()); - } - - static Register Create(int code, int size) { - return Register(CPURegister::Create(code, size, CPURegister::kRegister)); - } - - static Register XRegFromCode(unsigned code); - static Register WRegFromCode(unsigned code); - - static Register from_code(int code) { - // Always return an X register. - return Register::Create(code, kXRegSizeInBits); - } - - template <int code> - static Register from_code() { - // Always return an X register. - return Register::Create<code, kXRegSizeInBits>(); - } - - static const char* GetSpecialRegisterName(int code) { - return (code == kSPRegInternalCode) ? "sp" : "UNKNOWN"; - } - - private: - constexpr explicit Register(const CPURegister& r) : CPURegister(r) {} -}; - -ASSERT_TRIVIALLY_COPYABLE(Register); - -constexpr bool kPadArguments = true; -constexpr bool kSimpleFPAliasing = true; -constexpr bool kSimdMaskRegisters = false; - -enum DoubleRegisterCode { -#define REGISTER_CODE(R) kDoubleCode_##R, - DOUBLE_REGISTERS(REGISTER_CODE) -#undef REGISTER_CODE - kDoubleAfterLast -}; - -// Functions for handling NEON vector format information. -enum VectorFormat { - kFormatUndefined = 0xffffffff, - kFormat8B = NEON_8B, - kFormat16B = NEON_16B, - kFormat4H = NEON_4H, - kFormat8H = NEON_8H, - kFormat2S = NEON_2S, - kFormat4S = NEON_4S, - kFormat1D = NEON_1D, - kFormat2D = NEON_2D, - - // Scalar formats. We add the scalar bit to distinguish between scalar and - // vector enumerations; the bit is always set in the encoding of scalar ops - // and always clear for vector ops. Although kFormatD and kFormat1D appear - // to be the same, their meaning is subtly different. The first is a scalar - // operation, the second a vector operation that only affects one lane. - kFormatB = NEON_B | NEONScalar, - kFormatH = NEON_H | NEONScalar, - kFormatS = NEON_S | NEONScalar, - kFormatD = NEON_D | NEONScalar -}; - -VectorFormat VectorFormatHalfWidth(VectorFormat vform); -VectorFormat VectorFormatDoubleWidth(VectorFormat vform); -VectorFormat VectorFormatDoubleLanes(VectorFormat vform); -VectorFormat VectorFormatHalfLanes(VectorFormat vform); -VectorFormat ScalarFormatFromLaneSize(int lanesize); -VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform); -VectorFormat VectorFormatFillQ(VectorFormat vform); -VectorFormat ScalarFormatFromFormat(VectorFormat vform); -V8_EXPORT_PRIVATE unsigned RegisterSizeInBitsFromFormat(VectorFormat vform); -unsigned RegisterSizeInBytesFromFormat(VectorFormat vform); -int LaneSizeInBytesFromFormat(VectorFormat vform); -unsigned LaneSizeInBitsFromFormat(VectorFormat vform); -int LaneSizeInBytesLog2FromFormat(VectorFormat vform); -V8_EXPORT_PRIVATE int LaneCountFromFormat(VectorFormat vform); -int MaxLaneCountFromFormat(VectorFormat vform); -V8_EXPORT_PRIVATE bool IsVectorFormat(VectorFormat vform); -int64_t MaxIntFromFormat(VectorFormat vform); -int64_t MinIntFromFormat(VectorFormat vform); -uint64_t MaxUintFromFormat(VectorFormat vform); - -class VRegister : public CPURegister { - public: - static constexpr VRegister no_reg() { - return VRegister(CPURegister::no_reg(), 0); - } - - template <int code, int size, int lane_count = 1> - static constexpr VRegister Create() { - static_assert(IsValidLaneCount(lane_count), "Invalid lane count"); - return VRegister(CPURegister::Create<code, size, kVRegister>(), lane_count); - } - - static VRegister Create(int code, int size, int lane_count = 1) { - DCHECK(IsValidLaneCount(lane_count)); - return VRegister(CPURegister::Create(code, size, CPURegister::kVRegister), - lane_count); - } - - static VRegister Create(int reg_code, VectorFormat format) { - int reg_size = RegisterSizeInBitsFromFormat(format); - int reg_count = IsVectorFormat(format) ? LaneCountFromFormat(format) : 1; - return VRegister::Create(reg_code, reg_size, reg_count); - } - - static VRegister BRegFromCode(unsigned code); - static VRegister HRegFromCode(unsigned code); - static VRegister SRegFromCode(unsigned code); - static VRegister DRegFromCode(unsigned code); - static VRegister QRegFromCode(unsigned code); - static VRegister VRegFromCode(unsigned code); - - VRegister V8B() const { - return VRegister::Create(code(), kDRegSizeInBits, 8); - } - VRegister V16B() const { - return VRegister::Create(code(), kQRegSizeInBits, 16); - } - VRegister V4H() const { - return VRegister::Create(code(), kDRegSizeInBits, 4); - } - VRegister V8H() const { - return VRegister::Create(code(), kQRegSizeInBits, 8); - } - VRegister V2S() const { - return VRegister::Create(code(), kDRegSizeInBits, 2); - } - VRegister V4S() const { - return VRegister::Create(code(), kQRegSizeInBits, 4); - } - VRegister V2D() const { - return VRegister::Create(code(), kQRegSizeInBits, 2); - } - VRegister V1D() const { - return VRegister::Create(code(), kDRegSizeInBits, 1); - } - - bool Is8B() const { return (Is64Bits() && (lane_count_ == 8)); } - bool Is16B() const { return (Is128Bits() && (lane_count_ == 16)); } - bool Is4H() const { return (Is64Bits() && (lane_count_ == 4)); } - bool Is8H() const { return (Is128Bits() && (lane_count_ == 8)); } - bool Is2S() const { return (Is64Bits() && (lane_count_ == 2)); } - bool Is4S() const { return (Is128Bits() && (lane_count_ == 4)); } - bool Is1D() const { return (Is64Bits() && (lane_count_ == 1)); } - bool Is2D() const { return (Is128Bits() && (lane_count_ == 2)); } - - // For consistency, we assert the number of lanes of these scalar registers, - // even though there are no vectors of equivalent total size with which they - // could alias. - bool Is1B() const { - DCHECK(!(Is8Bits() && IsVector())); - return Is8Bits(); - } - bool Is1H() const { - DCHECK(!(Is16Bits() && IsVector())); - return Is16Bits(); - } - bool Is1S() const { - DCHECK(!(Is32Bits() && IsVector())); - return Is32Bits(); - } - - bool IsLaneSizeB() const { return LaneSizeInBits() == kBRegSizeInBits; } - bool IsLaneSizeH() const { return LaneSizeInBits() == kHRegSizeInBits; } - bool IsLaneSizeS() const { return LaneSizeInBits() == kSRegSizeInBits; } - bool IsLaneSizeD() const { return LaneSizeInBits() == kDRegSizeInBits; } - - bool IsScalar() const { return lane_count_ == 1; } - bool IsVector() const { return lane_count_ > 1; } - - bool IsSameFormat(const VRegister& other) const { - return (reg_size_ == other.reg_size_) && (lane_count_ == other.lane_count_); - } - - int LaneCount() const { return lane_count_; } - - unsigned LaneSizeInBytes() const { return SizeInBytes() / lane_count_; } - - unsigned LaneSizeInBits() const { return LaneSizeInBytes() * 8; } - - static constexpr int kMaxNumRegisters = kNumberOfVRegisters; - STATIC_ASSERT(kMaxNumRegisters == kDoubleAfterLast); - - static VRegister from_code(int code) { - // Always return a D register. - return VRegister::Create(code, kDRegSizeInBits); - } - - private: - int lane_count_; - - constexpr explicit VRegister(const CPURegister& r, int lane_count) - : CPURegister(r), lane_count_(lane_count) {} - - static constexpr bool IsValidLaneCount(int lane_count) { - return base::bits::IsPowerOfTwo(lane_count) && lane_count <= 16; - } -}; - -ASSERT_TRIVIALLY_COPYABLE(VRegister); - -// No*Reg is used to indicate an unused argument, or an error case. Note that -// these all compare equal (using the Is() method). The Register and VRegister -// variants are provided for convenience. -constexpr Register NoReg = Register::no_reg(); -constexpr VRegister NoVReg = VRegister::no_reg(); -constexpr CPURegister NoCPUReg = CPURegister::no_reg(); -constexpr Register no_reg = NoReg; -constexpr VRegister no_dreg = NoVReg; - -#define DEFINE_REGISTER(register_class, name, ...) \ - constexpr register_class name = register_class::Create<__VA_ARGS__>() -#define ALIAS_REGISTER(register_class, alias, name) \ - constexpr register_class alias = name - -#define DEFINE_REGISTERS(N) \ - DEFINE_REGISTER(Register, w##N, N, kWRegSizeInBits); \ - DEFINE_REGISTER(Register, x##N, N, kXRegSizeInBits); -GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS) -#undef DEFINE_REGISTERS - -DEFINE_REGISTER(Register, wsp, kSPRegInternalCode, kWRegSizeInBits); -DEFINE_REGISTER(Register, sp, kSPRegInternalCode, kXRegSizeInBits); - -#define DEFINE_VREGISTERS(N) \ - DEFINE_REGISTER(VRegister, b##N, N, kBRegSizeInBits); \ - DEFINE_REGISTER(VRegister, h##N, N, kHRegSizeInBits); \ - DEFINE_REGISTER(VRegister, s##N, N, kSRegSizeInBits); \ - DEFINE_REGISTER(VRegister, d##N, N, kDRegSizeInBits); \ - DEFINE_REGISTER(VRegister, q##N, N, kQRegSizeInBits); \ - DEFINE_REGISTER(VRegister, v##N, N, kQRegSizeInBits); -GENERAL_REGISTER_CODE_LIST(DEFINE_VREGISTERS) -#undef DEFINE_VREGISTERS - -#undef DEFINE_REGISTER - -// Registers aliases. -ALIAS_REGISTER(VRegister, v8_, v8); // Avoid conflicts with namespace v8. -ALIAS_REGISTER(Register, ip0, x16); -ALIAS_REGISTER(Register, ip1, x17); -ALIAS_REGISTER(Register, wip0, w16); -ALIAS_REGISTER(Register, wip1, w17); -// Root register. -ALIAS_REGISTER(Register, kRootRegister, x26); -ALIAS_REGISTER(Register, rr, x26); -// Context pointer register. -ALIAS_REGISTER(Register, cp, x27); -ALIAS_REGISTER(Register, fp, x29); -ALIAS_REGISTER(Register, lr, x30); -ALIAS_REGISTER(Register, xzr, x31); -ALIAS_REGISTER(Register, wzr, w31); - -// Register used for padding stack slots. -ALIAS_REGISTER(Register, padreg, x31); - -// Keeps the 0 double value. -ALIAS_REGISTER(VRegister, fp_zero, d15); -// MacroAssembler fixed V Registers. -ALIAS_REGISTER(VRegister, fp_fixed1, d28); -ALIAS_REGISTER(VRegister, fp_fixed2, d29); - -// MacroAssembler scratch V registers. -ALIAS_REGISTER(VRegister, fp_scratch, d30); -ALIAS_REGISTER(VRegister, fp_scratch1, d30); -ALIAS_REGISTER(VRegister, fp_scratch2, d31); - -#undef ALIAS_REGISTER - -// AreAliased returns true if any of the named registers overlap. Arguments set -// to NoReg are ignored. The system stack pointer may be specified. -bool AreAliased(const CPURegister& reg1, const CPURegister& reg2, - const CPURegister& reg3 = NoReg, - const CPURegister& reg4 = NoReg, - const CPURegister& reg5 = NoReg, - const CPURegister& reg6 = NoReg, - const CPURegister& reg7 = NoReg, - const CPURegister& reg8 = NoReg); - -// AreSameSizeAndType returns true if all of the specified registers have the -// same size, and are of the same type. The system stack pointer may be -// specified. Arguments set to NoReg are ignored, as are any subsequent -// arguments. At least one argument (reg1) must be valid (not NoCPUReg). -V8_EXPORT_PRIVATE bool AreSameSizeAndType( - const CPURegister& reg1, const CPURegister& reg2 = NoCPUReg, - const CPURegister& reg3 = NoCPUReg, const CPURegister& reg4 = NoCPUReg, - const CPURegister& reg5 = NoCPUReg, const CPURegister& reg6 = NoCPUReg, - const CPURegister& reg7 = NoCPUReg, const CPURegister& reg8 = NoCPUReg); - -// AreSameFormat returns true if all of the specified VRegisters have the same -// vector format. Arguments set to NoVReg are ignored, as are any subsequent -// arguments. At least one argument (reg1) must be valid (not NoVReg). -bool AreSameFormat(const VRegister& reg1, const VRegister& reg2, - const VRegister& reg3 = NoVReg, - const VRegister& reg4 = NoVReg); - -// AreConsecutive returns true if all of the specified VRegisters are -// consecutive in the register file. Arguments may be set to NoVReg, and if so, -// subsequent arguments must also be NoVReg. At least one argument (reg1) must -// be valid (not NoVReg). -V8_EXPORT_PRIVATE bool AreConsecutive(const VRegister& reg1, - const VRegister& reg2, - const VRegister& reg3 = NoVReg, - const VRegister& reg4 = NoVReg); - -typedef VRegister FloatRegister; -typedef VRegister DoubleRegister; -typedef VRegister Simd128Register; - -// ----------------------------------------------------------------------------- -// Lists of registers. -class V8_EXPORT_PRIVATE CPURegList { - public: - CPURegList() = default; - - template <typename... CPURegisters> - explicit CPURegList(CPURegister reg0, CPURegisters... regs) - : list_(CPURegister::ListOf(reg0, regs...)), - size_(reg0.SizeInBits()), - type_(reg0.type()) { - DCHECK(AreSameSizeAndType(reg0, regs...)); - DCHECK(IsValid()); - } - - CPURegList(CPURegister::RegisterType type, int size, RegList list) - : list_(list), size_(size), type_(type) { - DCHECK(IsValid()); - } - - CPURegList(CPURegister::RegisterType type, int size, int first_reg, - int last_reg) - : size_(size), type_(type) { - DCHECK( - ((type == CPURegister::kRegister) && (last_reg < kNumberOfRegisters)) || - ((type == CPURegister::kVRegister) && - (last_reg < kNumberOfVRegisters))); - DCHECK(last_reg >= first_reg); - list_ = (1ULL << (last_reg + 1)) - 1; - list_ &= ~((1ULL << first_reg) - 1); - DCHECK(IsValid()); - } - - CPURegister::RegisterType type() const { - DCHECK(IsValid()); - return type_; - } - - RegList list() const { - DCHECK(IsValid()); - return list_; - } - - inline void set_list(RegList new_list) { - DCHECK(IsValid()); - list_ = new_list; - } - - // Combine another CPURegList into this one. Registers that already exist in - // this list are left unchanged. The type and size of the registers in the - // 'other' list must match those in this list. - void Combine(const CPURegList& other); - - // Remove every register in the other CPURegList from this one. Registers that - // do not exist in this list are ignored. The type of the registers in the - // 'other' list must match those in this list. - void Remove(const CPURegList& other); - - // Variants of Combine and Remove which take CPURegisters. - void Combine(const CPURegister& other); - void Remove(const CPURegister& other1, const CPURegister& other2 = NoCPUReg, - const CPURegister& other3 = NoCPUReg, - const CPURegister& other4 = NoCPUReg); - - // Variants of Combine and Remove which take a single register by its code; - // the type and size of the register is inferred from this list. - void Combine(int code); - void Remove(int code); - - // Remove all callee-saved registers from the list. This can be useful when - // preparing registers for an AAPCS64 function call, for example. - void RemoveCalleeSaved(); - - CPURegister PopLowestIndex(); - CPURegister PopHighestIndex(); - - // AAPCS64 callee-saved registers. - static CPURegList GetCalleeSaved(int size = kXRegSizeInBits); - static CPURegList GetCalleeSavedV(int size = kDRegSizeInBits); - - // AAPCS64 caller-saved registers. Note that this includes lr. - // TODO(all): Determine how we handle d8-d15 being callee-saved, but the top - // 64-bits being caller-saved. - static CPURegList GetCallerSaved(int size = kXRegSizeInBits); - static CPURegList GetCallerSavedV(int size = kDRegSizeInBits); - - // Registers saved as safepoints. - static CPURegList GetSafepointSavedRegisters(); - - bool IsEmpty() const { - DCHECK(IsValid()); - return list_ == 0; - } - - bool IncludesAliasOf(const CPURegister& other1, - const CPURegister& other2 = NoCPUReg, - const CPURegister& other3 = NoCPUReg, - const CPURegister& other4 = NoCPUReg) const { - DCHECK(IsValid()); - RegList list = 0; - if (!other1.IsNone() && (other1.type() == type_)) list |= other1.bit(); - if (!other2.IsNone() && (other2.type() == type_)) list |= other2.bit(); - if (!other3.IsNone() && (other3.type() == type_)) list |= other3.bit(); - if (!other4.IsNone() && (other4.type() == type_)) list |= other4.bit(); - return (list_ & list) != 0; - } - - int Count() const { - DCHECK(IsValid()); - return CountSetBits(list_, kRegListSizeInBits); - } - - int RegisterSizeInBits() const { - DCHECK(IsValid()); - return size_; - } - - int RegisterSizeInBytes() const { - int size_in_bits = RegisterSizeInBits(); - DCHECK_EQ(size_in_bits % kBitsPerByte, 0); - return size_in_bits / kBitsPerByte; - } - - int TotalSizeInBytes() const { - DCHECK(IsValid()); - return RegisterSizeInBytes() * Count(); - } - - private: - RegList list_; - int size_; - CPURegister::RegisterType type_; - - bool IsValid() const { - constexpr RegList kValidRegisters{0x8000000ffffffff}; - constexpr RegList kValidVRegisters{0x0000000ffffffff}; - switch (type_) { - case CPURegister::kRegister: - return (list_ & kValidRegisters) == list_; - case CPURegister::kVRegister: - return (list_ & kValidVRegisters) == list_; - case CPURegister::kNoRegister: - return list_ == 0; - default: - UNREACHABLE(); - } - } -}; - -// AAPCS64 callee-saved registers. -#define kCalleeSaved CPURegList::GetCalleeSaved() -#define kCalleeSavedV CPURegList::GetCalleeSavedV() - -// AAPCS64 caller-saved registers. Note that this includes lr. -#define kCallerSaved CPURegList::GetCallerSaved() -#define kCallerSavedV CPURegList::GetCallerSavedV() - -// Define a {RegisterName} method for {Register} and {VRegister}. -DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS) -DEFINE_REGISTER_NAMES(VRegister, VECTOR_REGISTERS) - -// Give alias names to registers for calling conventions. -constexpr Register kReturnRegister0 = x0; -constexpr Register kReturnRegister1 = x1; -constexpr Register kReturnRegister2 = x2; -constexpr Register kJSFunctionRegister = x1; -constexpr Register kContextRegister = cp; -constexpr Register kAllocateSizeRegister = x1; - -constexpr Register kSpeculationPoisonRegister = x23; - -constexpr Register kInterpreterAccumulatorRegister = x0; -constexpr Register kInterpreterBytecodeOffsetRegister = x19; -constexpr Register kInterpreterBytecodeArrayRegister = x20; -constexpr Register kInterpreterDispatchTableRegister = x21; - -constexpr Register kJavaScriptCallArgCountRegister = x0; -constexpr Register kJavaScriptCallCodeStartRegister = x2; -constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister; -constexpr Register kJavaScriptCallNewTargetRegister = x3; -constexpr Register kJavaScriptCallExtraArg1Register = x2; - -constexpr Register kOffHeapTrampolineRegister = ip0; -constexpr Register kRuntimeCallFunctionRegister = x1; -constexpr Register kRuntimeCallArgCountRegister = x0; -constexpr Register kRuntimeCallArgvRegister = x11; -constexpr Register kWasmInstanceRegister = x7; -constexpr Register kWasmCompileLazyFuncIndexRegister = x8; - -} // namespace internal -} // namespace v8 - -#endif // V8_ARM64_REGISTER_ARM64_H_ |