1/*
2 * Copyright (C) 2014 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_ARM64_MANAGED_REGISTER_ARM64_H_
18#define ART_COMPILER_UTILS_ARM64_MANAGED_REGISTER_ARM64_H_
19
20#include "base/logging.h"
21#include "constants_arm64.h"
22#include "utils/managed_register.h"
23
24namespace art {
25namespace arm64 {
26
27const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
28const int kNumberOfWRegIds = kNumberOfWRegisters;
29const int kNumberOfDRegIds = kNumberOfDRegisters;
30const int kNumberOfSRegIds = kNumberOfSRegisters;
31
32const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfWRegIds +
33  kNumberOfDRegIds + kNumberOfSRegIds;
34
35// Register ids map:
36//  [0..X[  core registers 64bit (enum Register)
37//  [X..W[  core registers 32bit (enum WRegister)
38//  [W..D[  double precision VFP registers (enum DRegister)
39//  [D..S[  single precision VFP registers (enum SRegister)
40//
41// where:
42//  X = kNumberOfCoreRegIds
43//  W = X + kNumberOfWRegIds
44//  D = W + kNumberOfDRegIds
45//  S = D + kNumberOfSRegIds
46//
47// An instance of class 'ManagedRegister' represents a single Arm64
48// register. A register can be one of the following:
49//  * core register 64bit context (enum Register)
50//  * core register 32bit context (enum WRegister)
51//  * VFP double precision register (enum DRegister)
52//  * VFP single precision register (enum SRegister)
53//
54// There is a one to one mapping between ManagedRegister and register id.
55
56class Arm64ManagedRegister : public ManagedRegister {
57 public:
58  Register AsCoreRegister() const {
59    CHECK(IsCoreRegister());
60    return static_cast<Register>(id_);
61  }
62
63  WRegister AsWRegister() const {
64    CHECK(IsWRegister());
65    return static_cast<WRegister>(id_ - kNumberOfCoreRegIds);
66  }
67
68  DRegister AsDRegister() const {
69    CHECK(IsDRegister());
70    return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfWRegIds);
71  }
72
73  SRegister AsSRegister() const {
74    CHECK(IsSRegister());
75    return static_cast<SRegister>(id_ - kNumberOfCoreRegIds - kNumberOfWRegIds -
76                                  kNumberOfDRegIds);
77  }
78
79  WRegister AsOverlappingCoreRegisterLow() const {
80    CHECK(IsValidManagedRegister());
81    if (IsZeroRegister()) return W31;
82    return static_cast<WRegister>(AsCoreRegister());
83  }
84
85  // FIXME: Find better naming.
86  Register AsOverlappingWRegisterCore() const {
87    CHECK(IsValidManagedRegister());
88    return static_cast<Register>(AsWRegister());
89  }
90
91  SRegister AsOverlappingDRegisterLow() const {
92    CHECK(IsValidManagedRegister());
93    return static_cast<SRegister>(AsDRegister());
94  }
95
96  // FIXME: Find better naming.
97  DRegister AsOverlappingSRegisterD() const {
98    CHECK(IsValidManagedRegister());
99    return static_cast<DRegister>(AsSRegister());
100  }
101
102  bool IsCoreRegister() const {
103    CHECK(IsValidManagedRegister());
104    return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
105  }
106
107  bool IsWRegister() const {
108    CHECK(IsValidManagedRegister());
109    const int test = id_ - kNumberOfCoreRegIds;
110    return (0 <= test) && (test < kNumberOfWRegIds);
111  }
112
113  bool IsDRegister() const {
114    CHECK(IsValidManagedRegister());
115    const int test = id_ - (kNumberOfCoreRegIds + kNumberOfWRegIds);
116    return (0 <= test) && (test < kNumberOfDRegIds);
117  }
118
119  bool IsSRegister() const {
120    CHECK(IsValidManagedRegister());
121    const int test = id_ - (kNumberOfCoreRegIds + kNumberOfWRegIds +
122                            kNumberOfDRegIds);
123    return (0 <= test) && (test < kNumberOfSRegIds);
124  }
125
126  bool IsGPRegister() const {
127    return IsCoreRegister() || IsWRegister();
128  }
129
130  bool IsFPRegister() const {
131    return IsDRegister() || IsSRegister();
132  }
133
134  bool IsSameType(Arm64ManagedRegister test) const {
135    CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
136    return
137      (IsCoreRegister() && test.IsCoreRegister()) ||
138      (IsWRegister() && test.IsWRegister()) ||
139      (IsDRegister() && test.IsDRegister()) ||
140      (IsSRegister() && test.IsSRegister());
141  }
142
143  // Returns true if the two managed-registers ('this' and 'other') overlap.
144  // Either managed-register may be the NoRegister. If both are the NoRegister
145  // then false is returned.
146  bool Overlaps(const Arm64ManagedRegister& other) const;
147
148  void Print(std::ostream& os) const;
149
150  static Arm64ManagedRegister FromCoreRegister(Register r) {
151    CHECK_NE(r, kNoRegister);
152    return FromRegId(r);
153  }
154
155  static Arm64ManagedRegister FromWRegister(WRegister r) {
156    CHECK_NE(r, kNoWRegister);
157    return FromRegId(r + kNumberOfCoreRegIds);
158  }
159
160  static Arm64ManagedRegister FromDRegister(DRegister r) {
161    CHECK_NE(r, kNoDRegister);
162    return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfWRegIds));
163  }
164
165  static Arm64ManagedRegister FromSRegister(SRegister r) {
166    CHECK_NE(r, kNoSRegister);
167    return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfWRegIds +
168                          kNumberOfDRegIds));
169  }
170
171  // Returns the X register overlapping W register r.
172  static Arm64ManagedRegister FromWRegisterCore(WRegister r) {
173    CHECK_NE(r, kNoWRegister);
174    return FromRegId(r);
175  }
176
177  // Return the D register overlapping S register r.
178  static Arm64ManagedRegister FromSRegisterD(SRegister r) {
179    CHECK_NE(r, kNoSRegister);
180    return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfWRegIds));
181  }
182
183 private:
184  bool IsValidManagedRegister() const {
185    return (0 <= id_) && (id_ < kNumberOfRegIds);
186  }
187
188  bool IsStackPointer() const {
189    return IsCoreRegister() && (id_ == SP);
190  }
191
192  bool IsZeroRegister() const {
193    return IsCoreRegister() && (id_ == XZR);
194  }
195
196  int RegId() const {
197    CHECK(!IsNoRegister());
198    return id_;
199  }
200
201  int RegNo() const;
202  int RegIdLow() const;
203  int RegIdHigh() const;
204
205  friend class ManagedRegister;
206
207  explicit Arm64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
208
209  static Arm64ManagedRegister FromRegId(int reg_id) {
210    Arm64ManagedRegister reg(reg_id);
211    CHECK(reg.IsValidManagedRegister());
212    return reg;
213  }
214};
215
216std::ostream& operator<<(std::ostream& os, const Arm64ManagedRegister& reg);
217
218}  // namespace arm64
219
220inline arm64::Arm64ManagedRegister ManagedRegister::AsArm64() const {
221  arm64::Arm64ManagedRegister reg(id_);
222  CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
223  return reg;
224}
225
226}  // namespace art
227
228#endif  // ART_COMPILER_UTILS_ARM64_MANAGED_REGISTER_ARM64_H_
229