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