1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_
18 #define ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_
19
20 #include "base/logging.h"
21 #include "constants_arm.h"
22 #include "debug/dwarf/register.h"
23 #include "utils/managed_register.h"
24
25 // TODO(VIXL): Make VIXL compile with -Wshadow.
26 #pragma GCC diagnostic push
27 #pragma GCC diagnostic ignored "-Wshadow"
28 #include "aarch32/macro-assembler-aarch32.h"
29 #pragma GCC diagnostic pop
30
31 namespace art {
32 namespace arm {
33
34 // Values for register pairs.
35 enum RegisterPair {
36 R0_R1 = 0,
37 R2_R3 = 1,
38 R4_R5 = 2,
39 R6_R7 = 3,
40 R1_R2 = 4, // Dalvik style passing
41 kNumberOfRegisterPairs = 5,
42 kNoRegisterPair = -1,
43 };
44
45 std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
46
47 const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
48 const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
49
50 const int kNumberOfSRegIds = kNumberOfSRegisters;
51 const int kNumberOfSAllocIds = kNumberOfSRegisters;
52
53 const int kNumberOfDRegIds = kNumberOfDRegisters;
54 const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
55 const int kNumberOfDAllocIds = kNumberOfDRegIds - kNumberOfOverlappingDRegIds;
56
57 const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
58
59 const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfSRegIds +
60 kNumberOfDRegIds + kNumberOfPairRegIds;
61 const int kNumberOfAllocIds =
62 kNumberOfCoreAllocIds + kNumberOfSAllocIds + kNumberOfDAllocIds;
63
64 // Register ids map:
65 // [0..R[ core registers (enum Register)
66 // [R..S[ single precision VFP registers (enum SRegister)
67 // [S..D[ double precision VFP registers (enum DRegister)
68 // [D..P[ core register pairs (enum RegisterPair)
69 // where
70 // R = kNumberOfCoreRegIds
71 // S = R + kNumberOfSRegIds
72 // D = S + kNumberOfDRegIds
73 // P = D + kNumberOfRegisterPairs
74
75 // Allocation ids map:
76 // [0..R[ core registers (enum Register)
77 // [R..S[ single precision VFP registers (enum SRegister)
78 // [S..N[ non-overlapping double precision VFP registers (16-31 in enum
79 // DRegister, VFPv3-D32 only)
80 // where
81 // R = kNumberOfCoreAllocIds
82 // S = R + kNumberOfSAllocIds
83 // N = S + kNumberOfDAllocIds
84
85
86 // An instance of class 'ManagedRegister' represents a single ARM register or a
87 // pair of core ARM registers (enum RegisterPair). A single register is either a
88 // core register (enum Register), a VFP single precision register
89 // (enum SRegister), or a VFP double precision register (enum DRegister).
90 // 'ManagedRegister::NoRegister()' returns an invalid ManagedRegister.
91 // There is a one-to-one mapping between ManagedRegister and register id.
92 class ArmManagedRegister : public ManagedRegister {
93 public:
AsCoreRegister()94 constexpr Register AsCoreRegister() const {
95 CHECK(IsCoreRegister());
96 return static_cast<Register>(id_);
97 }
98
AsVIXLRegister()99 vixl::aarch32::Register AsVIXLRegister() const {
100 CHECK(IsCoreRegister());
101 return vixl::aarch32::Register(id_);
102 }
103
AsSRegister()104 constexpr SRegister AsSRegister() const {
105 CHECK(IsSRegister());
106 return static_cast<SRegister>(id_ - kNumberOfCoreRegIds);
107 }
108
AsVIXLSRegister()109 vixl::aarch32::SRegister AsVIXLSRegister() const {
110 CHECK(IsSRegister());
111 return vixl::aarch32::SRegister(id_ - kNumberOfCoreRegIds);
112 }
113
AsDRegister()114 constexpr DRegister AsDRegister() const {
115 CHECK(IsDRegister());
116 return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
117 }
118
AsVIXLDRegister()119 vixl::aarch32::DRegister AsVIXLDRegister() const {
120 CHECK(IsDRegister());
121 return vixl::aarch32::DRegister(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
122 }
123
AsOverlappingDRegisterLow()124 constexpr SRegister AsOverlappingDRegisterLow() const {
125 CHECK(IsOverlappingDRegister());
126 DRegister d_reg = AsDRegister();
127 return static_cast<SRegister>(d_reg * 2);
128 }
129
AsOverlappingDRegisterHigh()130 constexpr SRegister AsOverlappingDRegisterHigh() const {
131 CHECK(IsOverlappingDRegister());
132 DRegister d_reg = AsDRegister();
133 return static_cast<SRegister>(d_reg * 2 + 1);
134 }
135
AsRegisterPair()136 constexpr RegisterPair AsRegisterPair() const {
137 CHECK(IsRegisterPair());
138 Register reg_low = AsRegisterPairLow();
139 if (reg_low == R1) {
140 return R1_R2;
141 } else {
142 return static_cast<RegisterPair>(reg_low / 2);
143 }
144 }
145
AsRegisterPairLow()146 constexpr Register AsRegisterPairLow() const {
147 CHECK(IsRegisterPair());
148 // Appropriate mapping of register ids allows to use AllocIdLow().
149 return FromRegId(AllocIdLow()).AsCoreRegister();
150 }
151
AsVIXLRegisterPairLow()152 vixl::aarch32::Register AsVIXLRegisterPairLow() const {
153 return vixl::aarch32::Register(AsRegisterPairLow());
154 }
155
AsRegisterPairHigh()156 constexpr Register AsRegisterPairHigh() const {
157 CHECK(IsRegisterPair());
158 // Appropriate mapping of register ids allows to use AllocIdHigh().
159 return FromRegId(AllocIdHigh()).AsCoreRegister();
160 }
161
AsVIXLRegisterPairHigh()162 vixl::aarch32::Register AsVIXLRegisterPairHigh() const {
163 return vixl::aarch32::Register(AsRegisterPairHigh());
164 }
165
IsCoreRegister()166 constexpr bool IsCoreRegister() const {
167 CHECK(IsValidManagedRegister());
168 return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
169 }
170
IsSRegister()171 constexpr bool IsSRegister() const {
172 CHECK(IsValidManagedRegister());
173 const int test = id_ - kNumberOfCoreRegIds;
174 return (0 <= test) && (test < kNumberOfSRegIds);
175 }
176
IsDRegister()177 constexpr bool IsDRegister() const {
178 CHECK(IsValidManagedRegister());
179 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
180 return (0 <= test) && (test < kNumberOfDRegIds);
181 }
182
183 // Returns true if this DRegister overlaps SRegisters.
IsOverlappingDRegister()184 constexpr bool IsOverlappingDRegister() const {
185 CHECK(IsValidManagedRegister());
186 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
187 return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
188 }
189
IsRegisterPair()190 constexpr bool IsRegisterPair() const {
191 CHECK(IsValidManagedRegister());
192 const int test =
193 id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds);
194 return (0 <= test) && (test < kNumberOfPairRegIds);
195 }
196
IsSameType(ArmManagedRegister test)197 constexpr bool IsSameType(ArmManagedRegister test) const {
198 CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
199 return
200 (IsCoreRegister() && test.IsCoreRegister()) ||
201 (IsSRegister() && test.IsSRegister()) ||
202 (IsDRegister() && test.IsDRegister()) ||
203 (IsRegisterPair() && test.IsRegisterPair());
204 }
205
206
207 // Returns true if the two managed-registers ('this' and 'other') overlap.
208 // Either managed-register may be the NoRegister. If both are the NoRegister
209 // then false is returned.
210 bool Overlaps(const ArmManagedRegister& other) const;
211
212 void Print(std::ostream& os) const;
213
FromCoreRegister(Register r)214 static constexpr ArmManagedRegister FromCoreRegister(Register r) {
215 CHECK_NE(r, kNoRegister);
216 return FromRegId(r);
217 }
218
FromSRegister(SRegister r)219 static constexpr ArmManagedRegister FromSRegister(SRegister r) {
220 CHECK_NE(r, kNoSRegister);
221 return FromRegId(r + kNumberOfCoreRegIds);
222 }
223
FromDRegister(DRegister r)224 static constexpr ArmManagedRegister FromDRegister(DRegister r) {
225 CHECK_NE(r, kNoDRegister);
226 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds));
227 }
228
FromRegisterPair(RegisterPair r)229 static constexpr ArmManagedRegister FromRegisterPair(RegisterPair r) {
230 CHECK_NE(r, kNoRegisterPair);
231 return FromRegId(r + (kNumberOfCoreRegIds +
232 kNumberOfSRegIds + kNumberOfDRegIds));
233 }
234
235 // Return a RegisterPair consisting of Register r_low and r_low + 1.
FromCoreRegisterPair(Register r_low)236 static constexpr ArmManagedRegister FromCoreRegisterPair(Register r_low) {
237 if (r_low != R1) { // not the dalvik special case
238 CHECK_NE(r_low, kNoRegister);
239 CHECK_EQ(0, (r_low % 2));
240 const int r = r_low / 2;
241 CHECK_LT(r, kNumberOfPairRegIds);
242 return FromRegisterPair(static_cast<RegisterPair>(r));
243 } else {
244 return FromRegisterPair(R1_R2);
245 }
246 }
247
248 // Return a DRegister overlapping SRegister r_low and r_low + 1.
FromSRegisterPair(SRegister r_low)249 static constexpr ArmManagedRegister FromSRegisterPair(SRegister r_low) {
250 CHECK_NE(r_low, kNoSRegister);
251 CHECK_EQ(0, (r_low % 2));
252 const int r = r_low / 2;
253 CHECK_LT(r, kNumberOfOverlappingDRegIds);
254 return FromDRegister(static_cast<DRegister>(r));
255 }
256
257 private:
IsValidManagedRegister()258 constexpr bool IsValidManagedRegister() const {
259 return (0 <= id_) && (id_ < kNumberOfRegIds);
260 }
261
RegId()262 int RegId() const {
263 CHECK(!IsNoRegister());
264 return id_;
265 }
266
AllocId()267 int AllocId() const {
268 CHECK(IsValidManagedRegister() &&
269 !IsOverlappingDRegister() && !IsRegisterPair());
270 int r = id_;
271 if ((kNumberOfDAllocIds > 0) && IsDRegister()) { // VFPv3-D32 only.
272 r -= kNumberOfOverlappingDRegIds;
273 }
274 CHECK_LT(r, kNumberOfAllocIds);
275 return r;
276 }
277
278 int AllocIdLow() const;
279 int AllocIdHigh() const;
280
281 friend class ManagedRegister;
282
ArmManagedRegister(int reg_id)283 explicit constexpr ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
284
FromRegId(int reg_id)285 static constexpr ArmManagedRegister FromRegId(int reg_id) {
286 ArmManagedRegister reg(reg_id);
287 CHECK(reg.IsValidManagedRegister());
288 return reg;
289 }
290 };
291
292 std::ostream& operator<<(std::ostream& os, const ArmManagedRegister& reg);
293
294 } // namespace arm
295
AsArm()296 constexpr inline arm::ArmManagedRegister ManagedRegister::AsArm() const {
297 arm::ArmManagedRegister reg(id_);
298 CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
299 return reg;
300 }
301
302 } // namespace art
303
304 #endif // ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_
305