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