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