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
23namespace art {
24namespace mips {
25
26// Values for register pairs.
27enum 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
44std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
45
46const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
47const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
48
49const int kNumberOfFRegIds = kNumberOfFRegisters;
50const int kNumberOfFAllocIds = kNumberOfFRegisters;
51
52const int kNumberOfDRegIds = kNumberOfDRegisters;
53const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
54const int kNumberOfDAllocIds = kNumberOfDRegisters;
55
56const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
57
58const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfFRegIds +
59    kNumberOfDRegIds + kNumberOfPairRegIds;
60const 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.
87class MipsManagedRegister : public ManagedRegister {
88 public:
89  Register AsCoreRegister() const {
90    CHECK(IsCoreRegister());
91    return static_cast<Register>(id_);
92  }
93
94  FRegister AsFRegister() const {
95    CHECK(IsFRegister());
96    return static_cast<FRegister>(id_ - kNumberOfCoreRegIds);
97  }
98
99  DRegister AsDRegister() const {
100    CHECK(IsDRegister());
101    return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfFRegIds);
102  }
103
104  FRegister AsOverlappingDRegisterLow() const {
105    CHECK(IsOverlappingDRegister());
106    DRegister d_reg = AsDRegister();
107    return static_cast<FRegister>(d_reg * 2);
108  }
109
110  FRegister AsOverlappingDRegisterHigh() const {
111    CHECK(IsOverlappingDRegister());
112    DRegister d_reg = AsDRegister();
113    return static_cast<FRegister>(d_reg * 2 + 1);
114  }
115
116  Register AsRegisterPairLow() const {
117    CHECK(IsRegisterPair());
118    // Appropriate mapping of register ids allows to use AllocIdLow().
119    return FromRegId(AllocIdLow()).AsCoreRegister();
120  }
121
122  Register AsRegisterPairHigh() const {
123    CHECK(IsRegisterPair());
124    // Appropriate mapping of register ids allows to use AllocIdHigh().
125    return FromRegId(AllocIdHigh()).AsCoreRegister();
126  }
127
128  bool IsCoreRegister() const {
129    CHECK(IsValidManagedRegister());
130    return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
131  }
132
133  bool IsFRegister() const {
134    CHECK(IsValidManagedRegister());
135    const int test = id_ - kNumberOfCoreRegIds;
136    return (0 <= test) && (test < kNumberOfFRegIds);
137  }
138
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.
146  bool IsOverlappingDRegister() const {
147    CHECK(IsValidManagedRegister());
148    const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds);
149    return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
150  }
151
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
166  static MipsManagedRegister FromCoreRegister(Register r) {
167    CHECK_NE(r, kNoRegister);
168    return FromRegId(r);
169  }
170
171  static MipsManagedRegister FromFRegister(FRegister r) {
172    CHECK_NE(r, kNoFRegister);
173    return FromRegId(r + kNumberOfCoreRegIds);
174  }
175
176  static MipsManagedRegister FromDRegister(DRegister r) {
177    CHECK_NE(r, kNoDRegister);
178    return FromRegId(r + kNumberOfCoreRegIds + kNumberOfFRegIds);
179  }
180
181  static MipsManagedRegister FromRegisterPair(RegisterPair r) {
182    CHECK_NE(r, kNoRegisterPair);
183    return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds));
184  }
185
186 private:
187  bool IsValidManagedRegister() const {
188    return (0 <= id_) && (id_ < kNumberOfRegIds);
189  }
190
191  int RegId() const {
192    CHECK(!IsNoRegister());
193    return id_;
194  }
195
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
207  explicit MipsManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
208
209  static MipsManagedRegister FromRegId(int reg_id) {
210    MipsManagedRegister reg(reg_id);
211    CHECK(reg.IsValidManagedRegister());
212    return reg;
213  }
214};
215
216std::ostream& operator<<(std::ostream& os, const MipsManagedRegister& reg);
217
218}  // namespace mips
219
220inline 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