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