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