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_MIPS_MANAGED_REGISTER_MIPS_H_
18 #define ART_COMPILER_UTILS_MIPS_MANAGED_REGISTER_MIPS_H_
19 
20 #include "constants_mips.h"
21 #include "utils/managed_register.h"
22 
23 namespace art {
24 namespace mips {
25 
26 // Values for register pairs.
27 enum RegisterPair {
28   V0_V1 = 0,
29   A0_A1 = 1,
30   A2_A3 = 2,
31   T0_T1 = 3,
32   T2_T3 = 4,
33   T4_T5 = 5,
34   T6_T7 = 6,
35   S0_S1 = 7,
36   S2_S3 = 8,
37   S4_S5 = 9,
38   S6_S7 = 10,
39   A1_A2 = 11,  // Dalvik style passing
40   kNumberOfRegisterPairs = 12,
41   kNoRegisterPair = -1,
42 };
43 
44 std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
45 
46 const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
47 const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
48 
49 const int kNumberOfFRegIds = kNumberOfFRegisters;
50 const int kNumberOfFAllocIds = kNumberOfFRegisters;
51 
52 const int kNumberOfDRegIds = kNumberOfDRegisters;
53 const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
54 const int kNumberOfDAllocIds = kNumberOfDRegisters;
55 
56 const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
57 
58 const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfFRegIds +
59     kNumberOfDRegIds + kNumberOfPairRegIds;
60 const int kNumberOfAllocIds =
61     kNumberOfCoreAllocIds + kNumberOfFAllocIds + kNumberOfDAllocIds;
62 
63 // Register ids map:
64 //   [0..R[  core registers (enum Register)
65 //   [R..F[  single precision FP registers (enum FRegister)
66 //   [F..D[  double precision FP registers (enum DRegister)
67 //   [D..P[  core register pairs (enum RegisterPair)
68 // where
69 //   R = kNumberOfCoreRegIds
70 //   F = R + kNumberOfFRegIds
71 //   D = F + kNumberOfDRegIds
72 //   P = D + kNumberOfRegisterPairs
73 
74 // Allocation ids map:
75 //   [0..R[  core registers (enum Register)
76 //   [R..F[  single precision FP registers (enum FRegister)
77 // where
78 //   R = kNumberOfCoreRegIds
79 //   F = R + kNumberOfFRegIds
80 
81 
82 // An instance of class 'ManagedRegister' represents a single core register (enum
83 // Register), a single precision FP register (enum FRegister), a double precision
84 // FP register (enum DRegister), or a pair of core registers (enum RegisterPair).
85 // 'ManagedRegister::NoRegister()' provides an invalid register.
86 // There is a one-to-one mapping between ManagedRegister and register id.
87 class MipsManagedRegister : public ManagedRegister {
88  public:
AsCoreRegister()89   Register AsCoreRegister() const {
90     CHECK(IsCoreRegister());
91     return static_cast<Register>(id_);
92   }
93 
AsFRegister()94   FRegister AsFRegister() const {
95     CHECK(IsFRegister());
96     return static_cast<FRegister>(id_ - kNumberOfCoreRegIds);
97   }
98 
AsDRegister()99   DRegister AsDRegister() const {
100     CHECK(IsDRegister());
101     return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfFRegIds);
102   }
103 
AsOverlappingDRegisterLow()104   FRegister AsOverlappingDRegisterLow() const {
105     CHECK(IsOverlappingDRegister());
106     DRegister d_reg = AsDRegister();
107     return static_cast<FRegister>(d_reg * 2);
108   }
109 
AsOverlappingDRegisterHigh()110   FRegister AsOverlappingDRegisterHigh() const {
111     CHECK(IsOverlappingDRegister());
112     DRegister d_reg = AsDRegister();
113     return static_cast<FRegister>(d_reg * 2 + 1);
114   }
115 
AsRegisterPairLow()116   Register AsRegisterPairLow() const {
117     CHECK(IsRegisterPair());
118     // Appropriate mapping of register ids allows to use AllocIdLow().
119     return FromRegId(AllocIdLow()).AsCoreRegister();
120   }
121 
AsRegisterPairHigh()122   Register AsRegisterPairHigh() const {
123     CHECK(IsRegisterPair());
124     // Appropriate mapping of register ids allows to use AllocIdHigh().
125     return FromRegId(AllocIdHigh()).AsCoreRegister();
126   }
127 
IsCoreRegister()128   bool IsCoreRegister() const {
129     CHECK(IsValidManagedRegister());
130     return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
131   }
132 
IsFRegister()133   bool IsFRegister() const {
134     CHECK(IsValidManagedRegister());
135     const int test = id_ - kNumberOfCoreRegIds;
136     return (0 <= test) && (test < kNumberOfFRegIds);
137   }
138 
IsDRegister()139   bool IsDRegister() const {
140     CHECK(IsValidManagedRegister());
141     const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds);
142     return (0 <= test) && (test < kNumberOfDRegIds);
143   }
144 
145   // Returns true if this DRegister overlaps FRegisters.
IsOverlappingDRegister()146   bool IsOverlappingDRegister() const {
147     CHECK(IsValidManagedRegister());
148     const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds);
149     return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
150   }
151 
IsRegisterPair()152   bool IsRegisterPair() const {
153     CHECK(IsValidManagedRegister());
154     const int test =
155         id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds);
156     return (0 <= test) && (test < kNumberOfPairRegIds);
157   }
158 
159   void Print(std::ostream& os) const;
160 
161   // Returns true if the two managed-registers ('this' and 'other') overlap.
162   // Either managed-register may be the NoRegister. If both are the NoRegister
163   // then false is returned.
164   bool Overlaps(const MipsManagedRegister& other) const;
165 
FromCoreRegister(Register r)166   static MipsManagedRegister FromCoreRegister(Register r) {
167     CHECK_NE(r, kNoRegister);
168     return FromRegId(r);
169   }
170 
FromFRegister(FRegister r)171   static MipsManagedRegister FromFRegister(FRegister r) {
172     CHECK_NE(r, kNoFRegister);
173     return FromRegId(r + kNumberOfCoreRegIds);
174   }
175 
FromDRegister(DRegister r)176   static MipsManagedRegister FromDRegister(DRegister r) {
177     CHECK_NE(r, kNoDRegister);
178     return FromRegId(r + kNumberOfCoreRegIds + kNumberOfFRegIds);
179   }
180 
FromRegisterPair(RegisterPair r)181   static MipsManagedRegister FromRegisterPair(RegisterPair r) {
182     CHECK_NE(r, kNoRegisterPair);
183     return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds));
184   }
185 
186  private:
IsValidManagedRegister()187   bool IsValidManagedRegister() const {
188     return (0 <= id_) && (id_ < kNumberOfRegIds);
189   }
190 
RegId()191   int RegId() const {
192     CHECK(!IsNoRegister());
193     return id_;
194   }
195 
AllocId()196   int AllocId() const {
197     CHECK(IsValidManagedRegister() && !IsOverlappingDRegister() && !IsRegisterPair());
198     CHECK_LT(id_, kNumberOfAllocIds);
199     return id_;
200   }
201 
202   int AllocIdLow() const;
203   int AllocIdHigh() const;
204 
205   friend class ManagedRegister;
206 
MipsManagedRegister(int reg_id)207   explicit MipsManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
208 
FromRegId(int reg_id)209   static MipsManagedRegister FromRegId(int reg_id) {
210     MipsManagedRegister reg(reg_id);
211     CHECK(reg.IsValidManagedRegister());
212     return reg;
213   }
214 };
215 
216 std::ostream& operator<<(std::ostream& os, const MipsManagedRegister& reg);
217 
218 }  // namespace mips
219 
AsMips()220 inline mips::MipsManagedRegister ManagedRegister::AsMips() const {
221   mips::MipsManagedRegister reg(id_);
222   CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
223   return reg;
224 }
225 
226 }  // namespace art
227 
228 #endif  // ART_COMPILER_UTILS_MIPS_MANAGED_REGISTER_MIPS_H_
229