blob: 3576b5a7b645651104f7b8142aa476e92aa15495 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Ian Rogersb033c752011-07-20 12:22:35 -070016
17#ifndef ART_SRC_MANAGED_REGISTER_ARM_H_
18#define ART_SRC_MANAGED_REGISTER_ARM_H_
19
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070020#include "constants.h"
21#include "logging.h"
Ian Rogers2c8f6532011-09-02 17:16:34 -070022#include "managed_register.h"
Ian Rogersb033c752011-07-20 12:22:35 -070023
24namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070025namespace arm {
Ian Rogersb033c752011-07-20 12:22:35 -070026
27// Values for register pairs.
28enum RegisterPair {
29 R0_R1 = 0,
30 R2_R3 = 1,
31 R4_R5 = 2,
32 R6_R7 = 3,
Ian Rogers7a99c112011-09-07 12:48:27 -070033 R1_R2 = 4, // Dalvik style passing
34 kNumberOfRegisterPairs = 5,
Ian Rogersb033c752011-07-20 12:22:35 -070035 kNoRegisterPair = -1,
36};
37
38std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
39
40const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
41const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
42
43const int kNumberOfSRegIds = kNumberOfSRegisters;
44const int kNumberOfSAllocIds = kNumberOfSRegisters;
45
46const int kNumberOfDRegIds = kNumberOfDRegisters;
47const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
48const int kNumberOfDAllocIds = kNumberOfDRegIds - kNumberOfOverlappingDRegIds;
49
50const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
51
52const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfSRegIds +
53 kNumberOfDRegIds + kNumberOfPairRegIds;
54const int kNumberOfAllocIds =
55 kNumberOfCoreAllocIds + kNumberOfSAllocIds + kNumberOfDAllocIds;
56
57// Register ids map:
58// [0..R[ core registers (enum Register)
59// [R..S[ single precision VFP registers (enum SRegister)
60// [S..D[ double precision VFP registers (enum DRegister)
61// [D..P[ core register pairs (enum RegisterPair)
62// where
63// R = kNumberOfCoreRegIds
64// S = R + kNumberOfSRegIds
65// D = S + kNumberOfDRegIds
66// P = D + kNumberOfRegisterPairs
67
68// Allocation ids map:
69// [0..R[ core registers (enum Register)
70// [R..S[ single precision VFP registers (enum SRegister)
71// [S..N[ non-overlapping double precision VFP registers (16-31 in enum
72// DRegister, VFPv3-D32 only)
73// where
74// R = kNumberOfCoreAllocIds
75// S = R + kNumberOfSAllocIds
76// N = S + kNumberOfDAllocIds
77
78
79// An instance of class 'ManagedRegister' represents a single ARM register or a
80// pair of core ARM registers (enum RegisterPair). A single register is either a
81// core register (enum Register), a VFP single precision register
82// (enum SRegister), or a VFP double precision register (enum DRegister).
83// 'ManagedRegister::NoRegister()' returns an invalid ManagedRegister.
84// There is a one-to-one mapping between ManagedRegister and register id.
Ian Rogers2c8f6532011-09-02 17:16:34 -070085class ArmManagedRegister : public ManagedRegister {
Ian Rogersb033c752011-07-20 12:22:35 -070086 public:
Ian Rogersb033c752011-07-20 12:22:35 -070087 Register AsCoreRegister() const {
88 CHECK(IsCoreRegister());
89 return static_cast<Register>(id_);
90 }
91
92 SRegister AsSRegister() const {
93 CHECK(IsSRegister());
94 return static_cast<SRegister>(id_ - kNumberOfCoreRegIds);
95 }
96
97 DRegister AsDRegister() const {
98 CHECK(IsDRegister());
99 return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
100 }
101
102 SRegister AsOverlappingDRegisterLow() const {
103 CHECK(IsOverlappingDRegister());
104 DRegister d_reg = AsDRegister();
105 return static_cast<SRegister>(d_reg * 2);
106 }
107
108 SRegister AsOverlappingDRegisterHigh() const {
109 CHECK(IsOverlappingDRegister());
110 DRegister d_reg = AsDRegister();
111 return static_cast<SRegister>(d_reg * 2 + 1);
112 }
113
114 RegisterPair AsRegisterPair() const {
115 CHECK(IsRegisterPair());
116 Register reg_low = AsRegisterPairLow();
Ian Rogers7a99c112011-09-07 12:48:27 -0700117 if (reg_low == R1) {
118 return R1_R2;
119 } else {
120 return static_cast<RegisterPair>(reg_low / 2);
121 }
Ian Rogersb033c752011-07-20 12:22:35 -0700122 }
123
124 Register AsRegisterPairLow() const {
125 CHECK(IsRegisterPair());
126 // Appropriate mapping of register ids allows to use AllocIdLow().
127 return FromRegId(AllocIdLow()).AsCoreRegister();
128 }
129
130 Register AsRegisterPairHigh() const {
131 CHECK(IsRegisterPair());
132 // Appropriate mapping of register ids allows to use AllocIdHigh().
133 return FromRegId(AllocIdHigh()).AsCoreRegister();
134 }
135
136 bool IsCoreRegister() const {
137 CHECK(IsValidManagedRegister());
138 return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
139 }
140
141 bool IsSRegister() const {
142 CHECK(IsValidManagedRegister());
143 const int test = id_ - kNumberOfCoreRegIds;
144 return (0 <= test) && (test < kNumberOfSRegIds);
145 }
146
147 bool IsDRegister() const {
148 CHECK(IsValidManagedRegister());
149 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
150 return (0 <= test) && (test < kNumberOfDRegIds);
151 }
152
153 // Returns true if this DRegister overlaps SRegisters.
154 bool IsOverlappingDRegister() const {
155 CHECK(IsValidManagedRegister());
156 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
157 return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
158 }
159
160 bool IsRegisterPair() const {
161 CHECK(IsValidManagedRegister());
162 const int test =
163 id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds);
164 return (0 <= test) && (test < kNumberOfPairRegIds);
165 }
166
Ian Rogers2c8f6532011-09-02 17:16:34 -0700167 bool IsSameType(ArmManagedRegister test) const {
Ian Rogersb033c752011-07-20 12:22:35 -0700168 CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
169 return
170 (IsCoreRegister() && test.IsCoreRegister()) ||
171 (IsSRegister() && test.IsSRegister()) ||
172 (IsDRegister() && test.IsDRegister()) ||
173 (IsRegisterPair() && test.IsRegisterPair());
174 }
175
Ian Rogersb033c752011-07-20 12:22:35 -0700176
177 // Returns true if the two managed-registers ('this' and 'other') overlap.
178 // Either managed-register may be the NoRegister. If both are the NoRegister
179 // then false is returned.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700180 bool Overlaps(const ArmManagedRegister& other) const;
Ian Rogersb033c752011-07-20 12:22:35 -0700181
182 void Print(std::ostream& os) const;
183
Ian Rogers2c8f6532011-09-02 17:16:34 -0700184 static ArmManagedRegister FromCoreRegister(Register r) {
Ian Rogersb033c752011-07-20 12:22:35 -0700185 CHECK_NE(r, kNoRegister);
186 return FromRegId(r);
187 }
188
Ian Rogers2c8f6532011-09-02 17:16:34 -0700189 static ArmManagedRegister FromSRegister(SRegister r) {
Ian Rogersb033c752011-07-20 12:22:35 -0700190 CHECK_NE(r, kNoSRegister);
191 return FromRegId(r + kNumberOfCoreRegIds);
192 }
193
Ian Rogers2c8f6532011-09-02 17:16:34 -0700194 static ArmManagedRegister FromDRegister(DRegister r) {
Ian Rogersb033c752011-07-20 12:22:35 -0700195 CHECK_NE(r, kNoDRegister);
196 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds));
197 }
198
Ian Rogers2c8f6532011-09-02 17:16:34 -0700199 static ArmManagedRegister FromRegisterPair(RegisterPair r) {
Ian Rogersb033c752011-07-20 12:22:35 -0700200 CHECK_NE(r, kNoRegisterPair);
201 return FromRegId(r + (kNumberOfCoreRegIds +
202 kNumberOfSRegIds + kNumberOfDRegIds));
203 }
204
205 // Return a RegisterPair consisting of Register r_low and r_low + 1.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700206 static ArmManagedRegister FromCoreRegisterPair(Register r_low) {
Ian Rogers7a99c112011-09-07 12:48:27 -0700207 if (r_low != R1) { // not the dalvik special case
208 CHECK_NE(r_low, kNoRegister);
209 CHECK_EQ(0, (r_low % 2));
210 const int r = r_low / 2;
211 CHECK_LT(r, kNumberOfPairRegIds);
212 return FromRegisterPair(static_cast<RegisterPair>(r));
213 } else {
214 return FromRegisterPair(R1_R2);
215 }
Ian Rogersb033c752011-07-20 12:22:35 -0700216 }
217
218 // Return a DRegister overlapping SRegister r_low and r_low + 1.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700219 static ArmManagedRegister FromSRegisterPair(SRegister r_low) {
Ian Rogersb033c752011-07-20 12:22:35 -0700220 CHECK_NE(r_low, kNoSRegister);
221 CHECK_EQ(0, (r_low % 2));
222 const int r = r_low / 2;
223 CHECK_LT(r, kNumberOfOverlappingDRegIds);
224 return FromDRegister(static_cast<DRegister>(r));
225 }
226
227 private:
Ian Rogersb033c752011-07-20 12:22:35 -0700228 bool IsValidManagedRegister() const {
229 return (0 <= id_) && (id_ < kNumberOfRegIds);
230 }
231
232 int RegId() const {
233 CHECK(!IsNoRegister());
234 return id_;
235 }
236
237 int AllocId() const {
238 CHECK(IsValidManagedRegister() &&
239 !IsOverlappingDRegister() && !IsRegisterPair());
240 int r = id_;
241 if ((kNumberOfDAllocIds > 0) && IsDRegister()) { // VFPv3-D32 only.
242 r -= kNumberOfOverlappingDRegIds;
243 }
244 CHECK_LT(r, kNumberOfAllocIds);
245 return r;
246 }
247
248 int AllocIdLow() const;
249 int AllocIdHigh() const;
250
Ian Rogers2c8f6532011-09-02 17:16:34 -0700251 friend class ManagedRegister;
252
Elliott Hughesa51a3dd2011-10-17 15:19:26 -0700253 explicit ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
Ian Rogers2c8f6532011-09-02 17:16:34 -0700254
255 static ArmManagedRegister FromRegId(int reg_id) {
256 ArmManagedRegister reg(reg_id);
Ian Rogersb033c752011-07-20 12:22:35 -0700257 CHECK(reg.IsValidManagedRegister());
258 return reg;
259 }
Ian Rogersb033c752011-07-20 12:22:35 -0700260};
261
Ian Rogers2c8f6532011-09-02 17:16:34 -0700262std::ostream& operator<<(std::ostream& os, const ArmManagedRegister& reg);
263
264} // namespace arm
265
266inline arm::ArmManagedRegister ManagedRegister::AsArm() const {
267 arm::ArmManagedRegister reg(id_);
268 CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
269 return reg;
270}
Ian Rogersb033c752011-07-20 12:22:35 -0700271
272} // namespace art
273
274#endif // ART_SRC_MANAGED_REGISTER_ARM_H_