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