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