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