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 "base/macros.h"
24 #include "utils/managed_register.h"
25
26 namespace art HIDDEN {
27 namespace arm64 {
28
29 const int kNumberOfXRegIds = kNumberOfXRegisters;
30 const int kNumberOfWRegIds = kNumberOfWRegisters;
31 const int kNumberOfDRegIds = kNumberOfDRegisters;
32 const int kNumberOfSRegIds = kNumberOfSRegisters;
33
34 const 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
58 class Arm64ManagedRegister : public ManagedRegister {
59 public:
AsXRegister()60 constexpr XRegister AsXRegister() const {
61 CHECK(IsXRegister());
62 return static_cast<XRegister>(id_);
63 }
64
AsWRegister()65 constexpr WRegister AsWRegister() const {
66 CHECK(IsWRegister());
67 return static_cast<WRegister>(id_ - kNumberOfXRegIds);
68 }
69
AsDRegister()70 constexpr DRegister AsDRegister() const {
71 CHECK(IsDRegister());
72 return static_cast<DRegister>(id_ - kNumberOfXRegIds - kNumberOfWRegIds);
73 }
74
AsSRegister()75 constexpr SRegister AsSRegister() const {
76 CHECK(IsSRegister());
77 return static_cast<SRegister>(id_ - kNumberOfXRegIds - kNumberOfWRegIds -
78 kNumberOfDRegIds);
79 }
80
AsOverlappingWRegister()81 constexpr WRegister AsOverlappingWRegister() const {
82 CHECK(IsValidManagedRegister());
83 if (IsZeroRegister()) return WZR;
84 return static_cast<WRegister>(AsXRegister());
85 }
86
AsOverlappingXRegister()87 constexpr XRegister AsOverlappingXRegister() const {
88 CHECK(IsValidManagedRegister());
89 return static_cast<XRegister>(AsWRegister());
90 }
91
AsOverlappingSRegister()92 constexpr SRegister AsOverlappingSRegister() const {
93 CHECK(IsValidManagedRegister());
94 return static_cast<SRegister>(AsDRegister());
95 }
96
AsOverlappingDRegister()97 constexpr DRegister AsOverlappingDRegister() const {
98 CHECK(IsValidManagedRegister());
99 return static_cast<DRegister>(AsSRegister());
100 }
101
IsXRegister()102 constexpr bool IsXRegister() const {
103 CHECK(IsValidManagedRegister());
104 return (0 <= id_) && (id_ < kNumberOfXRegIds);
105 }
106
IsWRegister()107 constexpr bool IsWRegister() const {
108 CHECK(IsValidManagedRegister());
109 const int test = id_ - kNumberOfXRegIds;
110 return (0 <= test) && (test < kNumberOfWRegIds);
111 }
112
IsDRegister()113 constexpr bool IsDRegister() const {
114 CHECK(IsValidManagedRegister());
115 const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds);
116 return (0 <= test) && (test < kNumberOfDRegIds);
117 }
118
IsSRegister()119 constexpr bool IsSRegister() const {
120 CHECK(IsValidManagedRegister());
121 const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds + kNumberOfDRegIds);
122 return (0 <= test) && (test < kNumberOfSRegIds);
123 }
124
IsGPRegister()125 constexpr bool IsGPRegister() const {
126 return IsXRegister() || IsWRegister();
127 }
128
IsFPRegister()129 constexpr bool IsFPRegister() const {
130 return IsDRegister() || IsSRegister();
131 }
132
IsSameType(Arm64ManagedRegister test)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
FromXRegister(XRegister r)149 static constexpr Arm64ManagedRegister FromXRegister(XRegister r) {
150 CHECK_NE(r, kNoRegister);
151 return FromRegId(r);
152 }
153
FromWRegister(WRegister r)154 static constexpr Arm64ManagedRegister FromWRegister(WRegister r) {
155 CHECK_NE(r, kNoWRegister);
156 return FromRegId(r + kNumberOfXRegIds);
157 }
158
FromDRegister(DRegister r)159 static constexpr Arm64ManagedRegister FromDRegister(DRegister r) {
160 CHECK_NE(r, kNoDRegister);
161 return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds));
162 }
163
FromSRegister(SRegister r)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.
FromWRegisterX(WRegister 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.
FromSRegisterD(SRegister r)177 static constexpr Arm64ManagedRegister FromSRegisterD(SRegister r) {
178 CHECK_NE(r, kNoSRegister);
179 return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds));
180 }
181
182 private:
IsValidManagedRegister()183 constexpr bool IsValidManagedRegister() const {
184 return (0 <= id_) && (id_ < kNumberOfRegIds);
185 }
186
IsStackPointer()187 constexpr bool IsStackPointer() const {
188 return IsXRegister() && (id_ == SP);
189 }
190
IsZeroRegister()191 constexpr bool IsZeroRegister() const {
192 return IsXRegister() && (id_ == XZR);
193 }
194
RegId()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
Arm64ManagedRegister(int reg_id)206 explicit constexpr Arm64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
207
FromRegId(int reg_id)208 static constexpr Arm64ManagedRegister FromRegId(int reg_id) {
209 Arm64ManagedRegister reg(reg_id);
210 CHECK(reg.IsValidManagedRegister());
211 return reg;
212 }
213 };
214
215 std::ostream& operator<<(std::ostream& os, const Arm64ManagedRegister& reg);
216
217 } // namespace arm64
218
AsArm64()219 constexpr 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