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