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