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