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