xref: /aosp_15_r20/art/compiler/utils/arm64/managed_register_arm64.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_UTILS_ARM64_MANAGED_REGISTER_ARM64_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_UTILS_ARM64_MANAGED_REGISTER_ARM64_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "arch/arm64/registers_arm64.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
24*795d594fSAndroid Build Coastguard Worker #include "utils/managed_register.h"
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
27*795d594fSAndroid Build Coastguard Worker namespace arm64 {
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker const int kNumberOfXRegIds = kNumberOfXRegisters;
30*795d594fSAndroid Build Coastguard Worker const int kNumberOfWRegIds = kNumberOfWRegisters;
31*795d594fSAndroid Build Coastguard Worker const int kNumberOfDRegIds = kNumberOfDRegisters;
32*795d594fSAndroid Build Coastguard Worker const int kNumberOfSRegIds = kNumberOfSRegisters;
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker const int kNumberOfRegIds = kNumberOfXRegIds + kNumberOfWRegIds +
35*795d594fSAndroid Build Coastguard Worker   kNumberOfDRegIds + kNumberOfSRegIds;
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker // Register ids map:
38*795d594fSAndroid Build Coastguard Worker //  [0..X[  core registers 64bit (enum XRegister)
39*795d594fSAndroid Build Coastguard Worker //  [X..W[  core registers 32bit (enum WRegister)
40*795d594fSAndroid Build Coastguard Worker //  [W..D[  double precision VFP registers (enum DRegister)
41*795d594fSAndroid Build Coastguard Worker //  [D..S[  single precision VFP registers (enum SRegister)
42*795d594fSAndroid Build Coastguard Worker //
43*795d594fSAndroid Build Coastguard Worker // where:
44*795d594fSAndroid Build Coastguard Worker //  X = kNumberOfXRegIds
45*795d594fSAndroid Build Coastguard Worker //  W = X + kNumberOfWRegIds
46*795d594fSAndroid Build Coastguard Worker //  D = W + kNumberOfDRegIds
47*795d594fSAndroid Build Coastguard Worker //  S = D + kNumberOfSRegIds
48*795d594fSAndroid Build Coastguard Worker //
49*795d594fSAndroid Build Coastguard Worker // An instance of class 'ManagedRegister' represents a single Arm64
50*795d594fSAndroid Build Coastguard Worker // register. A register can be one of the following:
51*795d594fSAndroid Build Coastguard Worker //  * core register 64bit context (enum XRegister)
52*795d594fSAndroid Build Coastguard Worker //  * core register 32bit context (enum WRegister)
53*795d594fSAndroid Build Coastguard Worker //  * VFP double precision register (enum DRegister)
54*795d594fSAndroid Build Coastguard Worker //  * VFP single precision register (enum SRegister)
55*795d594fSAndroid Build Coastguard Worker //
56*795d594fSAndroid Build Coastguard Worker // There is a one to one mapping between ManagedRegister and register id.
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker class Arm64ManagedRegister : public ManagedRegister {
59*795d594fSAndroid Build Coastguard Worker  public:
AsXRegister()60*795d594fSAndroid Build Coastguard Worker   constexpr XRegister AsXRegister() const {
61*795d594fSAndroid Build Coastguard Worker     CHECK(IsXRegister());
62*795d594fSAndroid Build Coastguard Worker     return static_cast<XRegister>(id_);
63*795d594fSAndroid Build Coastguard Worker   }
64*795d594fSAndroid Build Coastguard Worker 
AsWRegister()65*795d594fSAndroid Build Coastguard Worker   constexpr WRegister AsWRegister() const {
66*795d594fSAndroid Build Coastguard Worker     CHECK(IsWRegister());
67*795d594fSAndroid Build Coastguard Worker     return static_cast<WRegister>(id_ - kNumberOfXRegIds);
68*795d594fSAndroid Build Coastguard Worker   }
69*795d594fSAndroid Build Coastguard Worker 
AsDRegister()70*795d594fSAndroid Build Coastguard Worker   constexpr DRegister AsDRegister() const {
71*795d594fSAndroid Build Coastguard Worker     CHECK(IsDRegister());
72*795d594fSAndroid Build Coastguard Worker     return static_cast<DRegister>(id_ - kNumberOfXRegIds - kNumberOfWRegIds);
73*795d594fSAndroid Build Coastguard Worker   }
74*795d594fSAndroid Build Coastguard Worker 
AsSRegister()75*795d594fSAndroid Build Coastguard Worker   constexpr SRegister AsSRegister() const {
76*795d594fSAndroid Build Coastguard Worker     CHECK(IsSRegister());
77*795d594fSAndroid Build Coastguard Worker     return static_cast<SRegister>(id_ - kNumberOfXRegIds - kNumberOfWRegIds -
78*795d594fSAndroid Build Coastguard Worker                                   kNumberOfDRegIds);
79*795d594fSAndroid Build Coastguard Worker   }
80*795d594fSAndroid Build Coastguard Worker 
AsOverlappingWRegister()81*795d594fSAndroid Build Coastguard Worker   constexpr WRegister AsOverlappingWRegister() const {
82*795d594fSAndroid Build Coastguard Worker     CHECK(IsValidManagedRegister());
83*795d594fSAndroid Build Coastguard Worker     if (IsZeroRegister()) return WZR;
84*795d594fSAndroid Build Coastguard Worker     return static_cast<WRegister>(AsXRegister());
85*795d594fSAndroid Build Coastguard Worker   }
86*795d594fSAndroid Build Coastguard Worker 
AsOverlappingXRegister()87*795d594fSAndroid Build Coastguard Worker   constexpr XRegister AsOverlappingXRegister() const {
88*795d594fSAndroid Build Coastguard Worker     CHECK(IsValidManagedRegister());
89*795d594fSAndroid Build Coastguard Worker     return static_cast<XRegister>(AsWRegister());
90*795d594fSAndroid Build Coastguard Worker   }
91*795d594fSAndroid Build Coastguard Worker 
AsOverlappingSRegister()92*795d594fSAndroid Build Coastguard Worker   constexpr SRegister AsOverlappingSRegister() const {
93*795d594fSAndroid Build Coastguard Worker     CHECK(IsValidManagedRegister());
94*795d594fSAndroid Build Coastguard Worker     return static_cast<SRegister>(AsDRegister());
95*795d594fSAndroid Build Coastguard Worker   }
96*795d594fSAndroid Build Coastguard Worker 
AsOverlappingDRegister()97*795d594fSAndroid Build Coastguard Worker   constexpr DRegister AsOverlappingDRegister() const {
98*795d594fSAndroid Build Coastguard Worker     CHECK(IsValidManagedRegister());
99*795d594fSAndroid Build Coastguard Worker     return static_cast<DRegister>(AsSRegister());
100*795d594fSAndroid Build Coastguard Worker   }
101*795d594fSAndroid Build Coastguard Worker 
IsXRegister()102*795d594fSAndroid Build Coastguard Worker   constexpr bool IsXRegister() const {
103*795d594fSAndroid Build Coastguard Worker     CHECK(IsValidManagedRegister());
104*795d594fSAndroid Build Coastguard Worker     return (0 <= id_) && (id_ < kNumberOfXRegIds);
105*795d594fSAndroid Build Coastguard Worker   }
106*795d594fSAndroid Build Coastguard Worker 
IsWRegister()107*795d594fSAndroid Build Coastguard Worker   constexpr bool IsWRegister() const {
108*795d594fSAndroid Build Coastguard Worker     CHECK(IsValidManagedRegister());
109*795d594fSAndroid Build Coastguard Worker     const int test = id_ - kNumberOfXRegIds;
110*795d594fSAndroid Build Coastguard Worker     return (0 <= test) && (test < kNumberOfWRegIds);
111*795d594fSAndroid Build Coastguard Worker   }
112*795d594fSAndroid Build Coastguard Worker 
IsDRegister()113*795d594fSAndroid Build Coastguard Worker   constexpr bool IsDRegister() const {
114*795d594fSAndroid Build Coastguard Worker     CHECK(IsValidManagedRegister());
115*795d594fSAndroid Build Coastguard Worker     const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds);
116*795d594fSAndroid Build Coastguard Worker     return (0 <= test) && (test < kNumberOfDRegIds);
117*795d594fSAndroid Build Coastguard Worker   }
118*795d594fSAndroid Build Coastguard Worker 
IsSRegister()119*795d594fSAndroid Build Coastguard Worker   constexpr bool IsSRegister() const {
120*795d594fSAndroid Build Coastguard Worker     CHECK(IsValidManagedRegister());
121*795d594fSAndroid Build Coastguard Worker     const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds + kNumberOfDRegIds);
122*795d594fSAndroid Build Coastguard Worker     return (0 <= test) && (test < kNumberOfSRegIds);
123*795d594fSAndroid Build Coastguard Worker   }
124*795d594fSAndroid Build Coastguard Worker 
IsGPRegister()125*795d594fSAndroid Build Coastguard Worker   constexpr bool IsGPRegister() const {
126*795d594fSAndroid Build Coastguard Worker     return IsXRegister() || IsWRegister();
127*795d594fSAndroid Build Coastguard Worker   }
128*795d594fSAndroid Build Coastguard Worker 
IsFPRegister()129*795d594fSAndroid Build Coastguard Worker   constexpr bool IsFPRegister() const {
130*795d594fSAndroid Build Coastguard Worker     return IsDRegister() || IsSRegister();
131*795d594fSAndroid Build Coastguard Worker   }
132*795d594fSAndroid Build Coastguard Worker 
IsSameType(Arm64ManagedRegister test)133*795d594fSAndroid Build Coastguard Worker   constexpr bool IsSameType(Arm64ManagedRegister test) const {
134*795d594fSAndroid Build Coastguard Worker     CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
135*795d594fSAndroid Build Coastguard Worker     return
136*795d594fSAndroid Build Coastguard Worker       (IsXRegister() && test.IsXRegister()) ||
137*795d594fSAndroid Build Coastguard Worker       (IsWRegister() && test.IsWRegister()) ||
138*795d594fSAndroid Build Coastguard Worker       (IsDRegister() && test.IsDRegister()) ||
139*795d594fSAndroid Build Coastguard Worker       (IsSRegister() && test.IsSRegister());
140*795d594fSAndroid Build Coastguard Worker   }
141*795d594fSAndroid Build Coastguard Worker 
142*795d594fSAndroid Build Coastguard Worker   // Returns true if the two managed-registers ('this' and 'other') overlap.
143*795d594fSAndroid Build Coastguard Worker   // Either managed-register may be the NoRegister. If both are the NoRegister
144*795d594fSAndroid Build Coastguard Worker   // then false is returned.
145*795d594fSAndroid Build Coastguard Worker   bool Overlaps(const Arm64ManagedRegister& other) const;
146*795d594fSAndroid Build Coastguard Worker 
147*795d594fSAndroid Build Coastguard Worker   void Print(std::ostream& os) const;
148*795d594fSAndroid Build Coastguard Worker 
FromXRegister(XRegister r)149*795d594fSAndroid Build Coastguard Worker   static constexpr Arm64ManagedRegister FromXRegister(XRegister r) {
150*795d594fSAndroid Build Coastguard Worker     CHECK_NE(r, kNoRegister);
151*795d594fSAndroid Build Coastguard Worker     return FromRegId(r);
152*795d594fSAndroid Build Coastguard Worker   }
153*795d594fSAndroid Build Coastguard Worker 
FromWRegister(WRegister r)154*795d594fSAndroid Build Coastguard Worker   static constexpr Arm64ManagedRegister FromWRegister(WRegister r) {
155*795d594fSAndroid Build Coastguard Worker     CHECK_NE(r, kNoWRegister);
156*795d594fSAndroid Build Coastguard Worker     return FromRegId(r + kNumberOfXRegIds);
157*795d594fSAndroid Build Coastguard Worker   }
158*795d594fSAndroid Build Coastguard Worker 
FromDRegister(DRegister r)159*795d594fSAndroid Build Coastguard Worker   static constexpr Arm64ManagedRegister FromDRegister(DRegister r) {
160*795d594fSAndroid Build Coastguard Worker     CHECK_NE(r, kNoDRegister);
161*795d594fSAndroid Build Coastguard Worker     return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds));
162*795d594fSAndroid Build Coastguard Worker   }
163*795d594fSAndroid Build Coastguard Worker 
FromSRegister(SRegister r)164*795d594fSAndroid Build Coastguard Worker   static constexpr Arm64ManagedRegister FromSRegister(SRegister r) {
165*795d594fSAndroid Build Coastguard Worker     CHECK_NE(r, kNoSRegister);
166*795d594fSAndroid Build Coastguard Worker     return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds +
167*795d594fSAndroid Build Coastguard Worker                           kNumberOfDRegIds));
168*795d594fSAndroid Build Coastguard Worker   }
169*795d594fSAndroid Build Coastguard Worker 
170*795d594fSAndroid Build Coastguard Worker   // Returns the X register overlapping W register r.
FromWRegisterX(WRegister r)171*795d594fSAndroid Build Coastguard Worker   static constexpr Arm64ManagedRegister FromWRegisterX(WRegister r) {
172*795d594fSAndroid Build Coastguard Worker     CHECK_NE(r, kNoWRegister);
173*795d594fSAndroid Build Coastguard Worker     return FromRegId(r);
174*795d594fSAndroid Build Coastguard Worker   }
175*795d594fSAndroid Build Coastguard Worker 
176*795d594fSAndroid Build Coastguard Worker   // Return the D register overlapping S register r.
FromSRegisterD(SRegister r)177*795d594fSAndroid Build Coastguard Worker   static constexpr Arm64ManagedRegister FromSRegisterD(SRegister r) {
178*795d594fSAndroid Build Coastguard Worker     CHECK_NE(r, kNoSRegister);
179*795d594fSAndroid Build Coastguard Worker     return FromRegId(r + (kNumberOfXRegIds + kNumberOfWRegIds));
180*795d594fSAndroid Build Coastguard Worker   }
181*795d594fSAndroid Build Coastguard Worker 
182*795d594fSAndroid Build Coastguard Worker  private:
IsValidManagedRegister()183*795d594fSAndroid Build Coastguard Worker   constexpr bool IsValidManagedRegister() const {
184*795d594fSAndroid Build Coastguard Worker     return (0 <= id_) && (id_ < kNumberOfRegIds);
185*795d594fSAndroid Build Coastguard Worker   }
186*795d594fSAndroid Build Coastguard Worker 
IsStackPointer()187*795d594fSAndroid Build Coastguard Worker   constexpr bool IsStackPointer() const {
188*795d594fSAndroid Build Coastguard Worker     return IsXRegister() && (id_ == SP);
189*795d594fSAndroid Build Coastguard Worker   }
190*795d594fSAndroid Build Coastguard Worker 
IsZeroRegister()191*795d594fSAndroid Build Coastguard Worker   constexpr bool IsZeroRegister() const {
192*795d594fSAndroid Build Coastguard Worker     return IsXRegister() && (id_ == XZR);
193*795d594fSAndroid Build Coastguard Worker   }
194*795d594fSAndroid Build Coastguard Worker 
RegId()195*795d594fSAndroid Build Coastguard Worker   constexpr int RegId() const {
196*795d594fSAndroid Build Coastguard Worker     CHECK(!IsNoRegister());
197*795d594fSAndroid Build Coastguard Worker     return id_;
198*795d594fSAndroid Build Coastguard Worker   }
199*795d594fSAndroid Build Coastguard Worker 
200*795d594fSAndroid Build Coastguard Worker   int RegNo() const;
201*795d594fSAndroid Build Coastguard Worker   int RegIdLow() const;
202*795d594fSAndroid Build Coastguard Worker   int RegIdHigh() const;
203*795d594fSAndroid Build Coastguard Worker 
204*795d594fSAndroid Build Coastguard Worker   friend class ManagedRegister;
205*795d594fSAndroid Build Coastguard Worker 
Arm64ManagedRegister(int reg_id)206*795d594fSAndroid Build Coastguard Worker   explicit constexpr Arm64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
207*795d594fSAndroid Build Coastguard Worker 
FromRegId(int reg_id)208*795d594fSAndroid Build Coastguard Worker   static constexpr Arm64ManagedRegister FromRegId(int reg_id) {
209*795d594fSAndroid Build Coastguard Worker     Arm64ManagedRegister reg(reg_id);
210*795d594fSAndroid Build Coastguard Worker     CHECK(reg.IsValidManagedRegister());
211*795d594fSAndroid Build Coastguard Worker     return reg;
212*795d594fSAndroid Build Coastguard Worker   }
213*795d594fSAndroid Build Coastguard Worker };
214*795d594fSAndroid Build Coastguard Worker 
215*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const Arm64ManagedRegister& reg);
216*795d594fSAndroid Build Coastguard Worker 
217*795d594fSAndroid Build Coastguard Worker }  // namespace arm64
218*795d594fSAndroid Build Coastguard Worker 
AsArm64()219*795d594fSAndroid Build Coastguard Worker constexpr arm64::Arm64ManagedRegister ManagedRegister::AsArm64() const {
220*795d594fSAndroid Build Coastguard Worker   arm64::Arm64ManagedRegister reg(id_);
221*795d594fSAndroid Build Coastguard Worker   CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
222*795d594fSAndroid Build Coastguard Worker   return reg;
223*795d594fSAndroid Build Coastguard Worker }
224*795d594fSAndroid Build Coastguard Worker 
225*795d594fSAndroid Build Coastguard Worker }  // namespace art
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_UTILS_ARM64_MANAGED_REGISTER_ARM64_H_
228