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