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