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