1 // Copyright 2022 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_REGLIST_ARM64_H_ 6 #define V8_CODEGEN_ARM64_REGLIST_ARM64_H_ 7 8 #include "src/codegen/arm64/utils-arm64.h" 9 #include "src/codegen/register-arch.h" 10 #include "src/codegen/reglist-base.h" 11 #include "src/common/globals.h" 12 13 namespace v8 { 14 namespace internal { 15 16 using RegList = RegListBase<Register>; 17 using DoubleRegList = RegListBase<DoubleRegister>; 18 ASSERT_TRIVIALLY_COPYABLE(RegList); 19 ASSERT_TRIVIALLY_COPYABLE(DoubleRegList); 20 21 constexpr int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte; 22 23 // ----------------------------------------------------------------------------- 24 // Lists of registers. 25 class V8_EXPORT_PRIVATE CPURegList { 26 public: 27 template <typename... CPURegisters> CPURegList(CPURegister reg0,CPURegisters...regs)28 explicit CPURegList(CPURegister reg0, CPURegisters... regs) 29 : list_(((uint64_t{1} << reg0.code()) | ... | 30 (regs.is_valid() ? uint64_t{1} << regs.code() : 0))), 31 size_(reg0.SizeInBits()), 32 type_(reg0.type()) { 33 DCHECK(AreSameSizeAndType(reg0, regs...)); 34 DCHECK(is_valid()); 35 } 36 CPURegList(int size,RegList list)37 CPURegList(int size, RegList list) 38 : list_(list.bits()), size_(size), type_(CPURegister::kRegister) { 39 DCHECK(is_valid()); 40 } 41 CPURegList(int size,DoubleRegList list)42 CPURegList(int size, DoubleRegList list) 43 : list_(list.bits()), size_(size), type_(CPURegister::kVRegister) { 44 DCHECK(is_valid()); 45 } 46 CPURegList(CPURegister::RegisterType type,int size,int first_reg,int last_reg)47 CPURegList(CPURegister::RegisterType type, int size, int first_reg, 48 int last_reg) 49 : size_(size), type_(type) { 50 DCHECK( 51 ((type == CPURegister::kRegister) && (last_reg < kNumberOfRegisters)) || 52 ((type == CPURegister::kVRegister) && 53 (last_reg < kNumberOfVRegisters))); 54 DCHECK(last_reg >= first_reg); 55 list_ = (1ULL << (last_reg + 1)) - 1; 56 list_ &= ~((1ULL << first_reg) - 1); 57 DCHECK(is_valid()); 58 } 59 type()60 CPURegister::RegisterType type() const { return type_; } 61 bits()62 uint64_t bits() const { return list_; } 63 set_bits(uint64_t new_bits)64 inline void set_bits(uint64_t new_bits) { 65 list_ = new_bits; 66 DCHECK(is_valid()); 67 } 68 69 // Combine another CPURegList into this one. Registers that already exist in 70 // this list are left unchanged. The type and size of the registers in the 71 // 'other' list must match those in this list. 72 void Combine(const CPURegList& other); 73 74 // Remove every register in the other CPURegList from this one. Registers that 75 // do not exist in this list are ignored. The type of the registers in the 76 // 'other' list must match those in this list. 77 void Remove(const CPURegList& other); 78 79 // Variants of Combine and Remove which take CPURegisters. 80 void Combine(const CPURegister& other); 81 void Remove(const CPURegister& other1, const CPURegister& other2 = NoCPUReg, 82 const CPURegister& other3 = NoCPUReg, 83 const CPURegister& other4 = NoCPUReg); 84 85 // Variants of Combine and Remove which take a single register by its code; 86 // the type and size of the register is inferred from this list. 87 void Combine(int code); 88 void Remove(int code); 89 90 // Align the list to 16 bytes. 91 void Align(); 92 93 CPURegister PopLowestIndex(); 94 CPURegister PopHighestIndex(); 95 96 // AAPCS64 callee-saved registers. 97 static CPURegList GetCalleeSaved(int size = kXRegSizeInBits); 98 static CPURegList GetCalleeSavedV(int size = kDRegSizeInBits); 99 100 // AAPCS64 caller-saved registers. Note that this includes lr. 101 // TODO(all): Determine how we handle d8-d15 being callee-saved, but the top 102 // 64-bits being caller-saved. 103 static CPURegList GetCallerSaved(int size = kXRegSizeInBits); 104 static CPURegList GetCallerSavedV(int size = kDRegSizeInBits); 105 IsEmpty()106 bool IsEmpty() const { return list_ == 0; } 107 108 bool IncludesAliasOf(const CPURegister& other1, 109 const CPURegister& other2 = NoCPUReg, 110 const CPURegister& other3 = NoCPUReg, 111 const CPURegister& other4 = NoCPUReg) const { 112 uint64_t list = 0; 113 if (!other1.IsNone() && (other1.type() == type_)) { 114 list |= (uint64_t{1} << other1.code()); 115 } 116 if (!other2.IsNone() && (other2.type() == type_)) { 117 list |= (uint64_t{1} << other2.code()); 118 } 119 if (!other3.IsNone() && (other3.type() == type_)) { 120 list |= (uint64_t{1} << other3.code()); 121 } 122 if (!other4.IsNone() && (other4.type() == type_)) { 123 list |= (uint64_t{1} << other4.code()); 124 } 125 return (list_ & list) != 0; 126 } 127 Count()128 int Count() const { return CountSetBits(list_, kRegListSizeInBits); } 129 RegisterSizeInBits()130 int RegisterSizeInBits() const { return size_; } 131 RegisterSizeInBytes()132 int RegisterSizeInBytes() const { 133 int size_in_bits = RegisterSizeInBits(); 134 DCHECK_EQ(size_in_bits % kBitsPerByte, 0); 135 return size_in_bits / kBitsPerByte; 136 } 137 TotalSizeInBytes()138 int TotalSizeInBytes() const { return RegisterSizeInBytes() * Count(); } 139 140 private: 141 uint64_t list_; 142 int size_; 143 CPURegister::RegisterType type_; 144 is_valid()145 bool is_valid() const { 146 constexpr uint64_t kValidRegisters{0x8000000ffffffff}; 147 constexpr uint64_t kValidVRegisters{0x0000000ffffffff}; 148 switch (type_) { 149 case CPURegister::kRegister: 150 return (list_ & kValidRegisters) == list_; 151 case CPURegister::kVRegister: 152 return (list_ & kValidVRegisters) == list_; 153 case CPURegister::kNoRegister: 154 return list_ == 0; 155 default: 156 UNREACHABLE(); 157 } 158 } 159 }; 160 161 // AAPCS64 callee-saved registers. 162 #define kCalleeSaved CPURegList::GetCalleeSaved() 163 #define kCalleeSavedV CPURegList::GetCalleeSavedV() 164 165 // AAPCS64 caller-saved registers. Note that this includes lr. 166 #define kCallerSaved CPURegList::GetCallerSaved() 167 #define kCallerSavedV CPURegList::GetCallerSavedV() 168 169 } // namespace internal 170 } // namespace v8 171 172 #endif // V8_CODEGEN_ARM64_REGLIST_ARM64_H_ 173