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 <android-base/logging.h>
21
22 #include "base/macros.h"
23 #include "constants_arm.h"
24 #include "utils/managed_register.h"
25
26 namespace art HIDDEN {
27 namespace arm {
28
29 // Values for register pairs.
30 enum RegisterPair {
31 R0_R1 = 0,
32 R2_R3 = 1,
33 R4_R5 = 2,
34 R6_R7 = 3,
35 R1_R2 = 4, // Dalvik style passing
36 kNumberOfRegisterPairs = 5,
37 kNoRegisterPair = -1,
38 };
39
40 std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
41
42 const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
43 const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
44
45 const int kNumberOfSRegIds = kNumberOfSRegisters;
46 const int kNumberOfSAllocIds = kNumberOfSRegisters;
47
48 const int kNumberOfDRegIds = kNumberOfDRegisters;
49 const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
50 const int kNumberOfDAllocIds = kNumberOfDRegIds - kNumberOfOverlappingDRegIds;
51
52 const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
53
54 const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfSRegIds +
55 kNumberOfDRegIds + kNumberOfPairRegIds;
56 const int kNumberOfAllocIds =
57 kNumberOfCoreAllocIds + kNumberOfSAllocIds + kNumberOfDAllocIds;
58
59 // Register ids map:
60 // [0..R[ core registers (enum Register)
61 // [R..S[ single precision VFP registers (enum SRegister)
62 // [S..D[ double precision VFP registers (enum DRegister)
63 // [D..P[ core register pairs (enum RegisterPair)
64 // where
65 // R = kNumberOfCoreRegIds
66 // S = R + kNumberOfSRegIds
67 // D = S + kNumberOfDRegIds
68 // P = D + kNumberOfRegisterPairs
69
70 // Allocation ids map:
71 // [0..R[ core registers (enum Register)
72 // [R..S[ single precision VFP registers (enum SRegister)
73 // [S..N[ non-overlapping double precision VFP registers (16-31 in enum
74 // DRegister, VFPv3-D32 only)
75 // where
76 // R = kNumberOfCoreAllocIds
77 // S = R + kNumberOfSAllocIds
78 // N = S + kNumberOfDAllocIds
79
80
81 // An instance of class 'ManagedRegister' represents a single ARM register or a
82 // pair of core ARM registers (enum RegisterPair). A single register is either a
83 // core register (enum Register), a VFP single precision register
84 // (enum SRegister), or a VFP double precision register (enum DRegister).
85 // 'ManagedRegister::NoRegister()' returns an invalid ManagedRegister.
86 // There is a one-to-one mapping between ManagedRegister and register id.
87 class ArmManagedRegister : public ManagedRegister {
88 public:
AsCoreRegister()89 constexpr Register AsCoreRegister() const {
90 CHECK(IsCoreRegister());
91 return static_cast<Register>(id_);
92 }
93
AsSRegister()94 constexpr SRegister AsSRegister() const {
95 CHECK(IsSRegister());
96 return static_cast<SRegister>(id_ - kNumberOfCoreRegIds);
97 }
98
AsDRegister()99 constexpr DRegister AsDRegister() const {
100 CHECK(IsDRegister());
101 return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
102 }
103
AsOverlappingDRegisterLow()104 constexpr SRegister AsOverlappingDRegisterLow() const {
105 CHECK(IsOverlappingDRegister());
106 DRegister d_reg = AsDRegister();
107 return static_cast<SRegister>(d_reg * 2);
108 }
109
AsOverlappingDRegisterHigh()110 constexpr SRegister AsOverlappingDRegisterHigh() const {
111 CHECK(IsOverlappingDRegister());
112 DRegister d_reg = AsDRegister();
113 return static_cast<SRegister>(d_reg * 2 + 1);
114 }
115
AsRegisterPair()116 constexpr RegisterPair AsRegisterPair() const {
117 CHECK(IsRegisterPair());
118 Register reg_low = AsRegisterPairLow();
119 if (reg_low == R1) {
120 return R1_R2;
121 } else {
122 return static_cast<RegisterPair>(reg_low / 2);
123 }
124 }
125
AsRegisterPairLow()126 constexpr Register AsRegisterPairLow() const {
127 CHECK(IsRegisterPair());
128 // Appropriate mapping of register ids allows to use AllocIdLow().
129 return FromRegId(AllocIdLow()).AsCoreRegister();
130 }
131
AsRegisterPairHigh()132 constexpr Register AsRegisterPairHigh() const {
133 CHECK(IsRegisterPair());
134 // Appropriate mapping of register ids allows to use AllocIdHigh().
135 return FromRegId(AllocIdHigh()).AsCoreRegister();
136 }
137
IsCoreRegister()138 constexpr bool IsCoreRegister() const {
139 CHECK(IsValidManagedRegister());
140 return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
141 }
142
IsSRegister()143 constexpr bool IsSRegister() const {
144 CHECK(IsValidManagedRegister());
145 const int test = id_ - kNumberOfCoreRegIds;
146 return (0 <= test) && (test < kNumberOfSRegIds);
147 }
148
IsDRegister()149 constexpr bool IsDRegister() const {
150 CHECK(IsValidManagedRegister());
151 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
152 return (0 <= test) && (test < kNumberOfDRegIds);
153 }
154
155 // Returns true if this DRegister overlaps SRegisters.
IsOverlappingDRegister()156 constexpr bool IsOverlappingDRegister() const {
157 CHECK(IsValidManagedRegister());
158 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
159 return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
160 }
161
IsRegisterPair()162 constexpr bool IsRegisterPair() const {
163 CHECK(IsValidManagedRegister());
164 const int test =
165 id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds);
166 return (0 <= test) && (test < kNumberOfPairRegIds);
167 }
168
IsSameType(ArmManagedRegister test)169 constexpr bool IsSameType(ArmManagedRegister test) const {
170 CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
171 return
172 (IsCoreRegister() && test.IsCoreRegister()) ||
173 (IsSRegister() && test.IsSRegister()) ||
174 (IsDRegister() && test.IsDRegister()) ||
175 (IsRegisterPair() && test.IsRegisterPair());
176 }
177
178
179 // Returns true if the two managed-registers ('this' and 'other') overlap.
180 // Either managed-register may be the NoRegister. If both are the NoRegister
181 // then false is returned.
182 bool Overlaps(const ArmManagedRegister& other) const;
183
184 void Print(std::ostream& os) const;
185
FromCoreRegister(Register r)186 static constexpr ArmManagedRegister FromCoreRegister(Register r) {
187 CHECK_NE(r, kNoRegister);
188 return FromRegId(r);
189 }
190
FromSRegister(SRegister r)191 static constexpr ArmManagedRegister FromSRegister(SRegister r) {
192 CHECK_NE(r, kNoSRegister);
193 return FromRegId(r + kNumberOfCoreRegIds);
194 }
195
FromDRegister(DRegister r)196 static constexpr ArmManagedRegister FromDRegister(DRegister r) {
197 CHECK_NE(r, kNoDRegister);
198 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds));
199 }
200
FromRegisterPair(RegisterPair r)201 static constexpr ArmManagedRegister FromRegisterPair(RegisterPair r) {
202 CHECK_NE(r, kNoRegisterPair);
203 return FromRegId(r + (kNumberOfCoreRegIds +
204 kNumberOfSRegIds + kNumberOfDRegIds));
205 }
206
207 // Return a RegisterPair consisting of Register r_low and r_low + 1.
FromCoreRegisterPair(Register r_low)208 static constexpr ArmManagedRegister FromCoreRegisterPair(Register r_low) {
209 if (r_low != R1) { // not the dalvik special case
210 CHECK_NE(r_low, kNoRegister);
211 CHECK_EQ(0, (r_low % 2));
212 const int r = r_low / 2;
213 CHECK_LT(r, kNumberOfPairRegIds);
214 return FromRegisterPair(static_cast<RegisterPair>(r));
215 } else {
216 return FromRegisterPair(R1_R2);
217 }
218 }
219
220 // Return a DRegister overlapping SRegister r_low and r_low + 1.
FromSRegisterPair(SRegister r_low)221 static constexpr ArmManagedRegister FromSRegisterPair(SRegister r_low) {
222 CHECK_NE(r_low, kNoSRegister);
223 CHECK_EQ(0, (r_low % 2));
224 const int r = r_low / 2;
225 CHECK_LT(r, kNumberOfOverlappingDRegIds);
226 return FromDRegister(static_cast<DRegister>(r));
227 }
228
RegId()229 int RegId() const {
230 CHECK(!IsNoRegister());
231 return id_;
232 }
233
234 private:
IsValidManagedRegister()235 constexpr bool IsValidManagedRegister() const {
236 return (0 <= id_) && (id_ < kNumberOfRegIds);
237 }
238
AllocId()239 int AllocId() const {
240 CHECK(IsValidManagedRegister() &&
241 !IsOverlappingDRegister() && !IsRegisterPair());
242 int r = id_;
243 if ((kNumberOfDAllocIds > 0) && IsDRegister()) { // VFPv3-D32 only.
244 r -= kNumberOfOverlappingDRegIds;
245 }
246 CHECK_LT(r, kNumberOfAllocIds);
247 return r;
248 }
249
250 int AllocIdLow() const;
251 int AllocIdHigh() const;
252
253 friend class ManagedRegister;
254
ArmManagedRegister(int reg_id)255 explicit constexpr ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
256
FromRegId(int reg_id)257 static constexpr ArmManagedRegister FromRegId(int reg_id) {
258 ArmManagedRegister reg(reg_id);
259 CHECK(reg.IsValidManagedRegister());
260 return reg;
261 }
262 };
263
264 std::ostream& operator<<(std::ostream& os, const ArmManagedRegister& reg);
265
266 } // namespace arm
267
AsArm()268 constexpr arm::ArmManagedRegister ManagedRegister::AsArm() const {
269 arm::ArmManagedRegister reg(id_);
270 CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
271 return reg;
272 }
273
274 } // namespace art
275
276 #endif // ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_
277