v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
reglist-arm64.h
Go to the documentation of this file.
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
11#include "src/common/globals.h"
12
13namespace v8 {
14namespace internal {
15
16using RegList = RegListBase<Register>;
17using DoubleRegList = RegListBase<DoubleRegister>;
20
21constexpr int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
22
23// -----------------------------------------------------------------------------
24// Lists of registers.
26 public:
27 template <typename... CPURegisters>
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
37 CPURegList(int size, RegList list)
38 : list_(list.bits()), size_(size), type_(CPURegister::kRegister) {
39 DCHECK(is_valid());
40 }
41
42 CPURegList(int size, DoubleRegList list)
43 : list_(list.bits()), size_(size), type_(CPURegister::kVRegister) {
44 DCHECK(is_valid());
45 }
46
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
61
62 uint64_t bits() const { return list_; }
63
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
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
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
128 int Count() const { return CountSetBits(list_, kRegListSizeInBits); }
129
130 int RegisterSizeInBits() const { return size_; }
131
133 int size_in_bits = RegisterSizeInBits();
134 DCHECK_EQ(size_in_bits % kBitsPerByte, 0);
135 return size_in_bits / kBitsPerByte;
136 }
137
138 int TotalSizeInBytes() const { return RegisterSizeInBytes() * Count(); }
139
140 private:
141 uint64_t list_;
142 int size_;
144
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_
bool IncludesAliasOf(const CPURegister &other1, const CPURegister &other2=NoCPUReg, const CPURegister &other3=NoCPUReg, const CPURegister &other4=NoCPUReg) const
static CPURegList GetCallerSavedV(int size=kDRegSizeInBits)
static CPURegList GetCallerSaved(int size=kXRegSizeInBits)
static CPURegList GetCalleeSavedV(int size=kDRegSizeInBits)
CPURegList(CPURegister::RegisterType type, int size, int first_reg, int last_reg)
CPURegister PopHighestIndex()
CPURegister::RegisterType type() const
CPURegList(int size, DoubleRegList list)
CPURegister::RegisterType type_
void set_bits(uint64_t new_bits)
CPURegister PopLowestIndex()
uint64_t bits() const
CPURegList(int size, RegList list)
static CPURegList GetCalleeSaved(int size=kXRegSizeInBits)
CPURegList(CPURegister reg0, CPURegisters... regs)
RegisterType type() const
constexpr int8_t code() const
const int size_
Definition assembler.cc:132
const ObjectRef type_
std::vector< std::string > list_
RegListBase< DoubleRegister > DoubleRegList
Definition reglist-arm.h:15
V8_EXPORT_PRIVATE int CountSetBits(uint64_t value, int width)
constexpr int kBitsPerByte
Definition globals.h:682
RegListBase< Register > RegList
Definition reglist-arm.h:14
constexpr int kNumberOfRegisters
ContainedInLattice Combine(ContainedInLattice a, ContainedInLattice b)
constexpr int kNumberOfVRegisters
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)
constexpr int kRegListSizeInBits
#define UNREACHABLE()
Definition logging.h:67
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define ASSERT_TRIVIALLY_COPYABLE(T)
Definition macros.h:267
#define V8_EXPORT_PRIVATE
Definition macros.h:460