managed_register_arm.h revision 7a99c11d220ec68c208b507570e3a78c2c18a7a1
1// 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
6#include "constants.h"
7#include "logging.h"
8
9namespace art {
10
11// Values for register pairs.
12enum RegisterPair {
13  R0_R1 = 0,
14  R2_R3 = 1,
15  R4_R5 = 2,
16  R6_R7 = 3,
17  R1_R2 = 4,  // Dalvik style passing
18  kNumberOfRegisterPairs = 5,
19  kNoRegisterPair = -1,
20};
21
22std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
23
24const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
25const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
26
27const int kNumberOfSRegIds = kNumberOfSRegisters;
28const int kNumberOfSAllocIds = kNumberOfSRegisters;
29
30const int kNumberOfDRegIds = kNumberOfDRegisters;
31const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
32const int kNumberOfDAllocIds = kNumberOfDRegIds - kNumberOfOverlappingDRegIds;
33
34const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
35
36const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfSRegIds +
37    kNumberOfDRegIds + kNumberOfPairRegIds;
38const int kNumberOfAllocIds =
39    kNumberOfCoreAllocIds + kNumberOfSAllocIds + kNumberOfDAllocIds;
40
41// Register ids map:
42//   [0..R[  core registers (enum Register)
43//   [R..S[  single precision VFP registers (enum SRegister)
44//   [S..D[  double precision VFP registers (enum DRegister)
45//   [D..P[  core register pairs (enum RegisterPair)
46// where
47//   R = kNumberOfCoreRegIds
48//   S = R + kNumberOfSRegIds
49//   D = S + kNumberOfDRegIds
50//   P = D + kNumberOfRegisterPairs
51
52// Allocation ids map:
53//   [0..R[  core registers (enum Register)
54//   [R..S[  single precision VFP registers (enum SRegister)
55//   [S..N[  non-overlapping double precision VFP registers (16-31 in enum
56//           DRegister, VFPv3-D32 only)
57// where
58//   R = kNumberOfCoreAllocIds
59//   S = R + kNumberOfSAllocIds
60//   N = S + kNumberOfDAllocIds
61
62
63// An instance of class 'ManagedRegister' represents a single ARM register or a
64// pair of core ARM registers (enum RegisterPair). A single register is either a
65// core register (enum Register), a VFP single precision register
66// (enum SRegister), or a VFP double precision register (enum DRegister).
67// 'ManagedRegister::NoRegister()' returns an invalid ManagedRegister.
68// There is a one-to-one mapping between ManagedRegister and register id.
69class ManagedRegister {
70 public:
71  // ManagedRegister is a value class. There exists no method to change the
72  // internal state. We therefore allow a copy constructor and an
73  // assignment-operator.
74  ManagedRegister(const ManagedRegister& other) : id_(other.id_) { }
75
76  ManagedRegister& operator=(const ManagedRegister& other) {
77    id_ = other.id_;
78    return *this;
79  }
80
81  Register AsCoreRegister() const {
82    CHECK(IsCoreRegister());
83    return static_cast<Register>(id_);
84  }
85
86  SRegister AsSRegister() const {
87    CHECK(IsSRegister());
88    return static_cast<SRegister>(id_ - kNumberOfCoreRegIds);
89  }
90
91  DRegister AsDRegister() const {
92    CHECK(IsDRegister());
93    return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
94  }
95
96  SRegister AsOverlappingDRegisterLow() const {
97    CHECK(IsOverlappingDRegister());
98    DRegister d_reg = AsDRegister();
99    return static_cast<SRegister>(d_reg * 2);
100  }
101
102  SRegister AsOverlappingDRegisterHigh() const {
103    CHECK(IsOverlappingDRegister());
104    DRegister d_reg = AsDRegister();
105    return static_cast<SRegister>(d_reg * 2 + 1);
106  }
107
108  RegisterPair AsRegisterPair() const {
109    CHECK(IsRegisterPair());
110    Register reg_low = AsRegisterPairLow();
111    if (reg_low == R1) {
112      return R1_R2;
113    } else {
114      return static_cast<RegisterPair>(reg_low / 2);
115    }
116  }
117
118  Register AsRegisterPairLow() const {
119    CHECK(IsRegisterPair());
120    // Appropriate mapping of register ids allows to use AllocIdLow().
121    return FromRegId(AllocIdLow()).AsCoreRegister();
122  }
123
124  Register AsRegisterPairHigh() const {
125    CHECK(IsRegisterPair());
126    // Appropriate mapping of register ids allows to use AllocIdHigh().
127    return FromRegId(AllocIdHigh()).AsCoreRegister();
128  }
129
130  bool IsCoreRegister() const {
131    CHECK(IsValidManagedRegister());
132    return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
133  }
134
135  bool IsSRegister() const {
136    CHECK(IsValidManagedRegister());
137    const int test = id_ - kNumberOfCoreRegIds;
138    return (0 <= test) && (test < kNumberOfSRegIds);
139  }
140
141  bool IsDRegister() const {
142    CHECK(IsValidManagedRegister());
143    const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
144    return (0 <= test) && (test < kNumberOfDRegIds);
145  }
146
147  // Returns true if this DRegister overlaps SRegisters.
148  bool IsOverlappingDRegister() const {
149    CHECK(IsValidManagedRegister());
150    const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
151    return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
152  }
153
154  bool IsRegisterPair() const {
155    CHECK(IsValidManagedRegister());
156    const int test =
157        id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds);
158    return (0 <= test) && (test < kNumberOfPairRegIds);
159  }
160
161  bool IsSameType(ManagedRegister test) const {
162    CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
163    return
164      (IsCoreRegister() && test.IsCoreRegister()) ||
165      (IsSRegister() && test.IsSRegister()) ||
166      (IsDRegister() && test.IsDRegister()) ||
167      (IsRegisterPair() && test.IsRegisterPair());
168  }
169
170  bool IsNoRegister() const {
171    return id_ == kNoRegister;
172  }
173
174  // It is valid to invoke Equals on and with a NoRegister.
175  bool Equals(const ManagedRegister& other) const {
176    return id_ == other.id_;
177  }
178
179  // Returns true if the two managed-registers ('this' and 'other') overlap.
180  // Either managed-register may be the NoRegister. If both are the NoRegister
181  // then false is returned.
182  bool Overlaps(const ManagedRegister& other) const;
183
184  void Print(std::ostream& os) const;
185
186  static ManagedRegister NoRegister() {
187    return ManagedRegister();
188  }
189
190  static ManagedRegister FromCoreRegister(Register r) {
191    CHECK_NE(r, kNoRegister);
192    return FromRegId(r);
193  }
194
195  static ManagedRegister FromSRegister(SRegister r) {
196    CHECK_NE(r, kNoSRegister);
197    return FromRegId(r + kNumberOfCoreRegIds);
198  }
199
200  static ManagedRegister FromDRegister(DRegister r) {
201    CHECK_NE(r, kNoDRegister);
202    return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds));
203  }
204
205  static ManagedRegister FromRegisterPair(RegisterPair r) {
206    CHECK_NE(r, kNoRegisterPair);
207    return FromRegId(r + (kNumberOfCoreRegIds +
208                          kNumberOfSRegIds + kNumberOfDRegIds));
209  }
210
211  // Return a RegisterPair consisting of Register r_low and r_low + 1.
212  static ManagedRegister FromCoreRegisterPair(Register r_low) {
213    if (r_low != R1) {  // not the dalvik special case
214      CHECK_NE(r_low, kNoRegister);
215      CHECK_EQ(0, (r_low % 2));
216      const int r = r_low / 2;
217      CHECK_LT(r, kNumberOfPairRegIds);
218      return FromRegisterPair(static_cast<RegisterPair>(r));
219    } else {
220      return FromRegisterPair(R1_R2);
221    }
222  }
223
224  // Return a DRegister overlapping SRegister r_low and r_low + 1.
225  static ManagedRegister FromSRegisterPair(SRegister r_low) {
226    CHECK_NE(r_low, kNoSRegister);
227    CHECK_EQ(0, (r_low % 2));
228    const int r = r_low / 2;
229    CHECK_LT(r, kNumberOfOverlappingDRegIds);
230    return FromDRegister(static_cast<DRegister>(r));
231  }
232
233 private:
234  static const int kNoRegister = -1;
235
236  ManagedRegister() : id_(kNoRegister) { }
237
238  bool IsValidManagedRegister() const {
239    return (0 <= id_) && (id_ < kNumberOfRegIds);
240  }
241
242  int RegId() const {
243    CHECK(!IsNoRegister());
244    return id_;
245  }
246
247  int AllocId() const {
248    CHECK(IsValidManagedRegister() &&
249           !IsOverlappingDRegister() && !IsRegisterPair());
250    int r = id_;
251    if ((kNumberOfDAllocIds > 0) && IsDRegister()) {  // VFPv3-D32 only.
252      r -= kNumberOfOverlappingDRegIds;
253    }
254    CHECK_LT(r, kNumberOfAllocIds);
255    return r;
256  }
257
258  int AllocIdLow() const;
259  int AllocIdHigh() const;
260
261  static ManagedRegister FromRegId(int reg_id) {
262    ManagedRegister reg;
263    reg.id_ = reg_id;
264    CHECK(reg.IsValidManagedRegister());
265    return reg;
266  }
267
268  int id_;
269};
270
271std::ostream& operator<<(std::ostream& os, const ManagedRegister& reg);
272
273}  // namespace art
274
275#endif  // ART_SRC_MANAGED_REGISTER_ARM_H_
276