blob: f25b2f49a3a52eee80dd9b1d1fd436ae205e917f [file] [log] [blame]
Ian Rogersb033c752011-07-20 12:22:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#ifndef ART_SRC_MANAGED_REGISTER_ARM_H_
4#define ART_SRC_MANAGED_REGISTER_ARM_H_
5
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07006#include "constants.h"
7#include "logging.h"
Ian Rogers2c8f6532011-09-02 17:16:34 -07008#include "managed_register.h"
Ian Rogersb033c752011-07-20 12:22:35 -07009
10namespace art {
Ian Rogers2c8f6532011-09-02 17:16:34 -070011namespace arm {
Ian Rogersb033c752011-07-20 12:22:35 -070012
13// Values for register pairs.
14enum RegisterPair {
15 R0_R1 = 0,
16 R2_R3 = 1,
17 R4_R5 = 2,
18 R6_R7 = 3,
Ian Rogers7a99c112011-09-07 12:48:27 -070019 R1_R2 = 4, // Dalvik style passing
20 kNumberOfRegisterPairs = 5,
Ian Rogersb033c752011-07-20 12:22:35 -070021 kNoRegisterPair = -1,
22};
23
24std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
25
26const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
27const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
28
29const int kNumberOfSRegIds = kNumberOfSRegisters;
30const int kNumberOfSAllocIds = kNumberOfSRegisters;
31
32const int kNumberOfDRegIds = kNumberOfDRegisters;
33const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
34const int kNumberOfDAllocIds = kNumberOfDRegIds - kNumberOfOverlappingDRegIds;
35
36const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
37
38const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfSRegIds +
39 kNumberOfDRegIds + kNumberOfPairRegIds;
40const int kNumberOfAllocIds =
41 kNumberOfCoreAllocIds + kNumberOfSAllocIds + kNumberOfDAllocIds;
42
43// Register ids map:
44// [0..R[ core registers (enum Register)
45// [R..S[ single precision VFP registers (enum SRegister)
46// [S..D[ double precision VFP registers (enum DRegister)
47// [D..P[ core register pairs (enum RegisterPair)
48// where
49// R = kNumberOfCoreRegIds
50// S = R + kNumberOfSRegIds
51// D = S + kNumberOfDRegIds
52// P = D + kNumberOfRegisterPairs
53
54// Allocation ids map:
55// [0..R[ core registers (enum Register)
56// [R..S[ single precision VFP registers (enum SRegister)
57// [S..N[ non-overlapping double precision VFP registers (16-31 in enum
58// DRegister, VFPv3-D32 only)
59// where
60// R = kNumberOfCoreAllocIds
61// S = R + kNumberOfSAllocIds
62// N = S + kNumberOfDAllocIds
63
64
65// An instance of class 'ManagedRegister' represents a single ARM register or a
66// pair of core ARM registers (enum RegisterPair). A single register is either a
67// core register (enum Register), a VFP single precision register
68// (enum SRegister), or a VFP double precision register (enum DRegister).
69// 'ManagedRegister::NoRegister()' returns an invalid ManagedRegister.
70// There is a one-to-one mapping between ManagedRegister and register id.
Ian Rogers2c8f6532011-09-02 17:16:34 -070071class ArmManagedRegister : public ManagedRegister {
Ian Rogersb033c752011-07-20 12:22:35 -070072 public:
Ian Rogersb033c752011-07-20 12:22:35 -070073 Register AsCoreRegister() const {
74 CHECK(IsCoreRegister());
75 return static_cast<Register>(id_);
76 }
77
78 SRegister AsSRegister() const {
79 CHECK(IsSRegister());
80 return static_cast<SRegister>(id_ - kNumberOfCoreRegIds);
81 }
82
83 DRegister AsDRegister() const {
84 CHECK(IsDRegister());
85 return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
86 }
87
88 SRegister AsOverlappingDRegisterLow() const {
89 CHECK(IsOverlappingDRegister());
90 DRegister d_reg = AsDRegister();
91 return static_cast<SRegister>(d_reg * 2);
92 }
93
94 SRegister AsOverlappingDRegisterHigh() const {
95 CHECK(IsOverlappingDRegister());
96 DRegister d_reg = AsDRegister();
97 return static_cast<SRegister>(d_reg * 2 + 1);
98 }
99
100 RegisterPair AsRegisterPair() const {
101 CHECK(IsRegisterPair());
102 Register reg_low = AsRegisterPairLow();
Ian Rogers7a99c112011-09-07 12:48:27 -0700103 if (reg_low == R1) {
104 return R1_R2;
105 } else {
106 return static_cast<RegisterPair>(reg_low / 2);
107 }
Ian Rogersb033c752011-07-20 12:22:35 -0700108 }
109
110 Register AsRegisterPairLow() const {
111 CHECK(IsRegisterPair());
112 // Appropriate mapping of register ids allows to use AllocIdLow().
113 return FromRegId(AllocIdLow()).AsCoreRegister();
114 }
115
116 Register AsRegisterPairHigh() const {
117 CHECK(IsRegisterPair());
118 // Appropriate mapping of register ids allows to use AllocIdHigh().
119 return FromRegId(AllocIdHigh()).AsCoreRegister();
120 }
121
122 bool IsCoreRegister() const {
123 CHECK(IsValidManagedRegister());
124 return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
125 }
126
127 bool IsSRegister() const {
128 CHECK(IsValidManagedRegister());
129 const int test = id_ - kNumberOfCoreRegIds;
130 return (0 <= test) && (test < kNumberOfSRegIds);
131 }
132
133 bool IsDRegister() const {
134 CHECK(IsValidManagedRegister());
135 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
136 return (0 <= test) && (test < kNumberOfDRegIds);
137 }
138
139 // Returns true if this DRegister overlaps SRegisters.
140 bool IsOverlappingDRegister() const {
141 CHECK(IsValidManagedRegister());
142 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
143 return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
144 }
145
146 bool IsRegisterPair() const {
147 CHECK(IsValidManagedRegister());
148 const int test =
149 id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds);
150 return (0 <= test) && (test < kNumberOfPairRegIds);
151 }
152
Ian Rogers2c8f6532011-09-02 17:16:34 -0700153 bool IsSameType(ArmManagedRegister test) const {
Ian Rogersb033c752011-07-20 12:22:35 -0700154 CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
155 return
156 (IsCoreRegister() && test.IsCoreRegister()) ||
157 (IsSRegister() && test.IsSRegister()) ||
158 (IsDRegister() && test.IsDRegister()) ||
159 (IsRegisterPair() && test.IsRegisterPair());
160 }
161
Ian Rogersb033c752011-07-20 12:22:35 -0700162
163 // Returns true if the two managed-registers ('this' and 'other') overlap.
164 // Either managed-register may be the NoRegister. If both are the NoRegister
165 // then false is returned.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700166 bool Overlaps(const ArmManagedRegister& other) const;
Ian Rogersb033c752011-07-20 12:22:35 -0700167
168 void Print(std::ostream& os) const;
169
Ian Rogers2c8f6532011-09-02 17:16:34 -0700170 static ArmManagedRegister FromCoreRegister(Register r) {
Ian Rogersb033c752011-07-20 12:22:35 -0700171 CHECK_NE(r, kNoRegister);
172 return FromRegId(r);
173 }
174
Ian Rogers2c8f6532011-09-02 17:16:34 -0700175 static ArmManagedRegister FromSRegister(SRegister r) {
Ian Rogersb033c752011-07-20 12:22:35 -0700176 CHECK_NE(r, kNoSRegister);
177 return FromRegId(r + kNumberOfCoreRegIds);
178 }
179
Ian Rogers2c8f6532011-09-02 17:16:34 -0700180 static ArmManagedRegister FromDRegister(DRegister r) {
Ian Rogersb033c752011-07-20 12:22:35 -0700181 CHECK_NE(r, kNoDRegister);
182 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds));
183 }
184
Ian Rogers2c8f6532011-09-02 17:16:34 -0700185 static ArmManagedRegister FromRegisterPair(RegisterPair r) {
Ian Rogersb033c752011-07-20 12:22:35 -0700186 CHECK_NE(r, kNoRegisterPair);
187 return FromRegId(r + (kNumberOfCoreRegIds +
188 kNumberOfSRegIds + kNumberOfDRegIds));
189 }
190
191 // Return a RegisterPair consisting of Register r_low and r_low + 1.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700192 static ArmManagedRegister FromCoreRegisterPair(Register r_low) {
Ian Rogers7a99c112011-09-07 12:48:27 -0700193 if (r_low != R1) { // not the dalvik special case
194 CHECK_NE(r_low, kNoRegister);
195 CHECK_EQ(0, (r_low % 2));
196 const int r = r_low / 2;
197 CHECK_LT(r, kNumberOfPairRegIds);
198 return FromRegisterPair(static_cast<RegisterPair>(r));
199 } else {
200 return FromRegisterPair(R1_R2);
201 }
Ian Rogersb033c752011-07-20 12:22:35 -0700202 }
203
204 // Return a DRegister overlapping SRegister r_low and r_low + 1.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700205 static ArmManagedRegister FromSRegisterPair(SRegister r_low) {
Ian Rogersb033c752011-07-20 12:22:35 -0700206 CHECK_NE(r_low, kNoSRegister);
207 CHECK_EQ(0, (r_low % 2));
208 const int r = r_low / 2;
209 CHECK_LT(r, kNumberOfOverlappingDRegIds);
210 return FromDRegister(static_cast<DRegister>(r));
211 }
212
213 private:
Ian Rogersb033c752011-07-20 12:22:35 -0700214 bool IsValidManagedRegister() const {
215 return (0 <= id_) && (id_ < kNumberOfRegIds);
216 }
217
218 int RegId() const {
219 CHECK(!IsNoRegister());
220 return id_;
221 }
222
223 int AllocId() const {
224 CHECK(IsValidManagedRegister() &&
225 !IsOverlappingDRegister() && !IsRegisterPair());
226 int r = id_;
227 if ((kNumberOfDAllocIds > 0) && IsDRegister()) { // VFPv3-D32 only.
228 r -= kNumberOfOverlappingDRegIds;
229 }
230 CHECK_LT(r, kNumberOfAllocIds);
231 return r;
232 }
233
234 int AllocIdLow() const;
235 int AllocIdHigh() const;
236
Ian Rogers2c8f6532011-09-02 17:16:34 -0700237 friend class ManagedRegister;
238
239 ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
240
241 static ArmManagedRegister FromRegId(int reg_id) {
242 ArmManagedRegister reg(reg_id);
Ian Rogersb033c752011-07-20 12:22:35 -0700243 CHECK(reg.IsValidManagedRegister());
244 return reg;
245 }
Ian Rogersb033c752011-07-20 12:22:35 -0700246};
247
Ian Rogers2c8f6532011-09-02 17:16:34 -0700248std::ostream& operator<<(std::ostream& os, const ArmManagedRegister& reg);
249
250} // namespace arm
251
252inline arm::ArmManagedRegister ManagedRegister::AsArm() const {
253 arm::ArmManagedRegister reg(id_);
254 CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
255 return reg;
256}
Ian Rogersb033c752011-07-20 12:22:35 -0700257
258} // namespace art
259
260#endif // ART_SRC_MANAGED_REGISTER_ARM_H_