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
24 namespace art {
25 namespace arm64 {
26
27 const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
28 const int kNumberOfWRegIds = kNumberOfWRegisters;
29 const int kNumberOfDRegIds = kNumberOfDRegisters;
30 const int kNumberOfSRegIds = kNumberOfSRegisters;
31
32 const 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
56 class Arm64ManagedRegister : public ManagedRegister {
57 public:
AsCoreRegister()58 Register AsCoreRegister() const {
59 CHECK(IsCoreRegister());
60 return static_cast<Register>(id_);
61 }
62
AsWRegister()63 WRegister AsWRegister() const {
64 CHECK(IsWRegister());
65 return static_cast<WRegister>(id_ - kNumberOfCoreRegIds);
66 }
67
AsDRegister()68 DRegister AsDRegister() const {
69 CHECK(IsDRegister());
70 return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfWRegIds);
71 }
72
AsSRegister()73 SRegister AsSRegister() const {
74 CHECK(IsSRegister());
75 return static_cast<SRegister>(id_ - kNumberOfCoreRegIds - kNumberOfWRegIds -
76 kNumberOfDRegIds);
77 }
78
AsOverlappingCoreRegisterLow()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.
AsOverlappingWRegisterCore()86 Register AsOverlappingWRegisterCore() const {
87 CHECK(IsValidManagedRegister());
88 return static_cast<Register>(AsWRegister());
89 }
90
AsOverlappingDRegisterLow()91 SRegister AsOverlappingDRegisterLow() const {
92 CHECK(IsValidManagedRegister());
93 return static_cast<SRegister>(AsDRegister());
94 }
95
96 // FIXME: Find better naming.
AsOverlappingSRegisterD()97 DRegister AsOverlappingSRegisterD() const {
98 CHECK(IsValidManagedRegister());
99 return static_cast<DRegister>(AsSRegister());
100 }
101
IsCoreRegister()102 bool IsCoreRegister() const {
103 CHECK(IsValidManagedRegister());
104 return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
105 }
106
IsWRegister()107 bool IsWRegister() const {
108 CHECK(IsValidManagedRegister());
109 const int test = id_ - kNumberOfCoreRegIds;
110 return (0 <= test) && (test < kNumberOfWRegIds);
111 }
112
IsDRegister()113 bool IsDRegister() const {
114 CHECK(IsValidManagedRegister());
115 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfWRegIds);
116 return (0 <= test) && (test < kNumberOfDRegIds);
117 }
118
IsSRegister()119 bool IsSRegister() const {
120 CHECK(IsValidManagedRegister());
121 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfWRegIds +
122 kNumberOfDRegIds);
123 return (0 <= test) && (test < kNumberOfSRegIds);
124 }
125
IsGPRegister()126 bool IsGPRegister() const {
127 return IsCoreRegister() || IsWRegister();
128 }
129
IsFPRegister()130 bool IsFPRegister() const {
131 return IsDRegister() || IsSRegister();
132 }
133
IsSameType(Arm64ManagedRegister test)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
FromCoreRegister(Register r)150 static Arm64ManagedRegister FromCoreRegister(Register r) {
151 CHECK_NE(r, kNoRegister);
152 return FromRegId(r);
153 }
154
FromWRegister(WRegister r)155 static Arm64ManagedRegister FromWRegister(WRegister r) {
156 CHECK_NE(r, kNoWRegister);
157 return FromRegId(r + kNumberOfCoreRegIds);
158 }
159
FromDRegister(DRegister r)160 static Arm64ManagedRegister FromDRegister(DRegister r) {
161 CHECK_NE(r, kNoDRegister);
162 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfWRegIds));
163 }
164
FromSRegister(SRegister r)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.
FromWRegisterCore(WRegister 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.
FromSRegisterD(SRegister r)178 static Arm64ManagedRegister FromSRegisterD(SRegister r) {
179 CHECK_NE(r, kNoSRegister);
180 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfWRegIds));
181 }
182
183 private:
IsValidManagedRegister()184 bool IsValidManagedRegister() const {
185 return (0 <= id_) && (id_ < kNumberOfRegIds);
186 }
187
IsStackPointer()188 bool IsStackPointer() const {
189 return IsCoreRegister() && (id_ == SP);
190 }
191
IsZeroRegister()192 bool IsZeroRegister() const {
193 return IsCoreRegister() && (id_ == XZR);
194 }
195
RegId()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
Arm64ManagedRegister(int reg_id)207 explicit Arm64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
208
FromRegId(int reg_id)209 static Arm64ManagedRegister FromRegId(int reg_id) {
210 Arm64ManagedRegister reg(reg_id);
211 CHECK(reg.IsValidManagedRegister());
212 return reg;
213 }
214 };
215
216 std::ostream& operator<<(std::ostream& os, const Arm64ManagedRegister& reg);
217
218 } // namespace arm64
219
AsArm64()220 inline 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