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