1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2011 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_ARM_MANAGED_REGISTER_ARM_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_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 "base/macros.h"
23*795d594fSAndroid Build Coastguard Worker #include "constants_arm.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 arm {
28*795d594fSAndroid Build Coastguard Worker
29*795d594fSAndroid Build Coastguard Worker // Values for register pairs.
30*795d594fSAndroid Build Coastguard Worker enum RegisterPair {
31*795d594fSAndroid Build Coastguard Worker R0_R1 = 0,
32*795d594fSAndroid Build Coastguard Worker R2_R3 = 1,
33*795d594fSAndroid Build Coastguard Worker R4_R5 = 2,
34*795d594fSAndroid Build Coastguard Worker R6_R7 = 3,
35*795d594fSAndroid Build Coastguard Worker R1_R2 = 4, // Dalvik style passing
36*795d594fSAndroid Build Coastguard Worker kNumberOfRegisterPairs = 5,
37*795d594fSAndroid Build Coastguard Worker kNoRegisterPair = -1,
38*795d594fSAndroid Build Coastguard Worker };
39*795d594fSAndroid Build Coastguard Worker
40*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
41*795d594fSAndroid Build Coastguard Worker
42*795d594fSAndroid Build Coastguard Worker const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
43*795d594fSAndroid Build Coastguard Worker const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
44*795d594fSAndroid Build Coastguard Worker
45*795d594fSAndroid Build Coastguard Worker const int kNumberOfSRegIds = kNumberOfSRegisters;
46*795d594fSAndroid Build Coastguard Worker const int kNumberOfSAllocIds = kNumberOfSRegisters;
47*795d594fSAndroid Build Coastguard Worker
48*795d594fSAndroid Build Coastguard Worker const int kNumberOfDRegIds = kNumberOfDRegisters;
49*795d594fSAndroid Build Coastguard Worker const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
50*795d594fSAndroid Build Coastguard Worker const int kNumberOfDAllocIds = kNumberOfDRegIds - kNumberOfOverlappingDRegIds;
51*795d594fSAndroid Build Coastguard Worker
52*795d594fSAndroid Build Coastguard Worker const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
53*795d594fSAndroid Build Coastguard Worker
54*795d594fSAndroid Build Coastguard Worker const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfSRegIds +
55*795d594fSAndroid Build Coastguard Worker kNumberOfDRegIds + kNumberOfPairRegIds;
56*795d594fSAndroid Build Coastguard Worker const int kNumberOfAllocIds =
57*795d594fSAndroid Build Coastguard Worker kNumberOfCoreAllocIds + kNumberOfSAllocIds + kNumberOfDAllocIds;
58*795d594fSAndroid Build Coastguard Worker
59*795d594fSAndroid Build Coastguard Worker // Register ids map:
60*795d594fSAndroid Build Coastguard Worker // [0..R[ core registers (enum Register)
61*795d594fSAndroid Build Coastguard Worker // [R..S[ single precision VFP registers (enum SRegister)
62*795d594fSAndroid Build Coastguard Worker // [S..D[ double precision VFP registers (enum DRegister)
63*795d594fSAndroid Build Coastguard Worker // [D..P[ core register pairs (enum RegisterPair)
64*795d594fSAndroid Build Coastguard Worker // where
65*795d594fSAndroid Build Coastguard Worker // R = kNumberOfCoreRegIds
66*795d594fSAndroid Build Coastguard Worker // S = R + kNumberOfSRegIds
67*795d594fSAndroid Build Coastguard Worker // D = S + kNumberOfDRegIds
68*795d594fSAndroid Build Coastguard Worker // P = D + kNumberOfRegisterPairs
69*795d594fSAndroid Build Coastguard Worker
70*795d594fSAndroid Build Coastguard Worker // Allocation ids map:
71*795d594fSAndroid Build Coastguard Worker // [0..R[ core registers (enum Register)
72*795d594fSAndroid Build Coastguard Worker // [R..S[ single precision VFP registers (enum SRegister)
73*795d594fSAndroid Build Coastguard Worker // [S..N[ non-overlapping double precision VFP registers (16-31 in enum
74*795d594fSAndroid Build Coastguard Worker // DRegister, VFPv3-D32 only)
75*795d594fSAndroid Build Coastguard Worker // where
76*795d594fSAndroid Build Coastguard Worker // R = kNumberOfCoreAllocIds
77*795d594fSAndroid Build Coastguard Worker // S = R + kNumberOfSAllocIds
78*795d594fSAndroid Build Coastguard Worker // N = S + kNumberOfDAllocIds
79*795d594fSAndroid Build Coastguard Worker
80*795d594fSAndroid Build Coastguard Worker
81*795d594fSAndroid Build Coastguard Worker // An instance of class 'ManagedRegister' represents a single ARM register or a
82*795d594fSAndroid Build Coastguard Worker // pair of core ARM registers (enum RegisterPair). A single register is either a
83*795d594fSAndroid Build Coastguard Worker // core register (enum Register), a VFP single precision register
84*795d594fSAndroid Build Coastguard Worker // (enum SRegister), or a VFP double precision register (enum DRegister).
85*795d594fSAndroid Build Coastguard Worker // 'ManagedRegister::NoRegister()' returns an invalid ManagedRegister.
86*795d594fSAndroid Build Coastguard Worker // There is a one-to-one mapping between ManagedRegister and register id.
87*795d594fSAndroid Build Coastguard Worker class ArmManagedRegister : public ManagedRegister {
88*795d594fSAndroid Build Coastguard Worker public:
AsCoreRegister()89*795d594fSAndroid Build Coastguard Worker constexpr Register AsCoreRegister() const {
90*795d594fSAndroid Build Coastguard Worker CHECK(IsCoreRegister());
91*795d594fSAndroid Build Coastguard Worker return static_cast<Register>(id_);
92*795d594fSAndroid Build Coastguard Worker }
93*795d594fSAndroid Build Coastguard Worker
AsSRegister()94*795d594fSAndroid Build Coastguard Worker constexpr SRegister AsSRegister() const {
95*795d594fSAndroid Build Coastguard Worker CHECK(IsSRegister());
96*795d594fSAndroid Build Coastguard Worker return static_cast<SRegister>(id_ - kNumberOfCoreRegIds);
97*795d594fSAndroid Build Coastguard Worker }
98*795d594fSAndroid Build Coastguard Worker
AsDRegister()99*795d594fSAndroid Build Coastguard Worker constexpr DRegister AsDRegister() const {
100*795d594fSAndroid Build Coastguard Worker CHECK(IsDRegister());
101*795d594fSAndroid Build Coastguard Worker return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
102*795d594fSAndroid Build Coastguard Worker }
103*795d594fSAndroid Build Coastguard Worker
AsOverlappingDRegisterLow()104*795d594fSAndroid Build Coastguard Worker constexpr SRegister AsOverlappingDRegisterLow() const {
105*795d594fSAndroid Build Coastguard Worker CHECK(IsOverlappingDRegister());
106*795d594fSAndroid Build Coastguard Worker DRegister d_reg = AsDRegister();
107*795d594fSAndroid Build Coastguard Worker return static_cast<SRegister>(d_reg * 2);
108*795d594fSAndroid Build Coastguard Worker }
109*795d594fSAndroid Build Coastguard Worker
AsOverlappingDRegisterHigh()110*795d594fSAndroid Build Coastguard Worker constexpr SRegister AsOverlappingDRegisterHigh() const {
111*795d594fSAndroid Build Coastguard Worker CHECK(IsOverlappingDRegister());
112*795d594fSAndroid Build Coastguard Worker DRegister d_reg = AsDRegister();
113*795d594fSAndroid Build Coastguard Worker return static_cast<SRegister>(d_reg * 2 + 1);
114*795d594fSAndroid Build Coastguard Worker }
115*795d594fSAndroid Build Coastguard Worker
AsRegisterPair()116*795d594fSAndroid Build Coastguard Worker constexpr RegisterPair AsRegisterPair() const {
117*795d594fSAndroid Build Coastguard Worker CHECK(IsRegisterPair());
118*795d594fSAndroid Build Coastguard Worker Register reg_low = AsRegisterPairLow();
119*795d594fSAndroid Build Coastguard Worker if (reg_low == R1) {
120*795d594fSAndroid Build Coastguard Worker return R1_R2;
121*795d594fSAndroid Build Coastguard Worker } else {
122*795d594fSAndroid Build Coastguard Worker return static_cast<RegisterPair>(reg_low / 2);
123*795d594fSAndroid Build Coastguard Worker }
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker
AsRegisterPairLow()126*795d594fSAndroid Build Coastguard Worker constexpr Register AsRegisterPairLow() const {
127*795d594fSAndroid Build Coastguard Worker CHECK(IsRegisterPair());
128*795d594fSAndroid Build Coastguard Worker // Appropriate mapping of register ids allows to use AllocIdLow().
129*795d594fSAndroid Build Coastguard Worker return FromRegId(AllocIdLow()).AsCoreRegister();
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker
AsRegisterPairHigh()132*795d594fSAndroid Build Coastguard Worker constexpr Register AsRegisterPairHigh() const {
133*795d594fSAndroid Build Coastguard Worker CHECK(IsRegisterPair());
134*795d594fSAndroid Build Coastguard Worker // Appropriate mapping of register ids allows to use AllocIdHigh().
135*795d594fSAndroid Build Coastguard Worker return FromRegId(AllocIdHigh()).AsCoreRegister();
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker
IsCoreRegister()138*795d594fSAndroid Build Coastguard Worker constexpr bool IsCoreRegister() const {
139*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister());
140*795d594fSAndroid Build Coastguard Worker return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
141*795d594fSAndroid Build Coastguard Worker }
142*795d594fSAndroid Build Coastguard Worker
IsSRegister()143*795d594fSAndroid Build Coastguard Worker constexpr bool IsSRegister() const {
144*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister());
145*795d594fSAndroid Build Coastguard Worker const int test = id_ - kNumberOfCoreRegIds;
146*795d594fSAndroid Build Coastguard Worker return (0 <= test) && (test < kNumberOfSRegIds);
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker
IsDRegister()149*795d594fSAndroid Build Coastguard Worker constexpr bool IsDRegister() const {
150*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister());
151*795d594fSAndroid Build Coastguard Worker const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
152*795d594fSAndroid Build Coastguard Worker return (0 <= test) && (test < kNumberOfDRegIds);
153*795d594fSAndroid Build Coastguard Worker }
154*795d594fSAndroid Build Coastguard Worker
155*795d594fSAndroid Build Coastguard Worker // Returns true if this DRegister overlaps SRegisters.
IsOverlappingDRegister()156*795d594fSAndroid Build Coastguard Worker constexpr bool IsOverlappingDRegister() const {
157*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister());
158*795d594fSAndroid Build Coastguard Worker const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
159*795d594fSAndroid Build Coastguard Worker return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
160*795d594fSAndroid Build Coastguard Worker }
161*795d594fSAndroid Build Coastguard Worker
IsRegisterPair()162*795d594fSAndroid Build Coastguard Worker constexpr bool IsRegisterPair() const {
163*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister());
164*795d594fSAndroid Build Coastguard Worker const int test =
165*795d594fSAndroid Build Coastguard Worker id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds);
166*795d594fSAndroid Build Coastguard Worker return (0 <= test) && (test < kNumberOfPairRegIds);
167*795d594fSAndroid Build Coastguard Worker }
168*795d594fSAndroid Build Coastguard Worker
IsSameType(ArmManagedRegister test)169*795d594fSAndroid Build Coastguard Worker constexpr bool IsSameType(ArmManagedRegister test) const {
170*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
171*795d594fSAndroid Build Coastguard Worker return
172*795d594fSAndroid Build Coastguard Worker (IsCoreRegister() && test.IsCoreRegister()) ||
173*795d594fSAndroid Build Coastguard Worker (IsSRegister() && test.IsSRegister()) ||
174*795d594fSAndroid Build Coastguard Worker (IsDRegister() && test.IsDRegister()) ||
175*795d594fSAndroid Build Coastguard Worker (IsRegisterPair() && test.IsRegisterPair());
176*795d594fSAndroid Build Coastguard Worker }
177*795d594fSAndroid Build Coastguard Worker
178*795d594fSAndroid Build Coastguard Worker
179*795d594fSAndroid Build Coastguard Worker // Returns true if the two managed-registers ('this' and 'other') overlap.
180*795d594fSAndroid Build Coastguard Worker // Either managed-register may be the NoRegister. If both are the NoRegister
181*795d594fSAndroid Build Coastguard Worker // then false is returned.
182*795d594fSAndroid Build Coastguard Worker bool Overlaps(const ArmManagedRegister& other) const;
183*795d594fSAndroid Build Coastguard Worker
184*795d594fSAndroid Build Coastguard Worker void Print(std::ostream& os) const;
185*795d594fSAndroid Build Coastguard Worker
FromCoreRegister(Register r)186*795d594fSAndroid Build Coastguard Worker static constexpr ArmManagedRegister FromCoreRegister(Register r) {
187*795d594fSAndroid Build Coastguard Worker CHECK_NE(r, kNoRegister);
188*795d594fSAndroid Build Coastguard Worker return FromRegId(r);
189*795d594fSAndroid Build Coastguard Worker }
190*795d594fSAndroid Build Coastguard Worker
FromSRegister(SRegister r)191*795d594fSAndroid Build Coastguard Worker static constexpr ArmManagedRegister FromSRegister(SRegister r) {
192*795d594fSAndroid Build Coastguard Worker CHECK_NE(r, kNoSRegister);
193*795d594fSAndroid Build Coastguard Worker return FromRegId(r + kNumberOfCoreRegIds);
194*795d594fSAndroid Build Coastguard Worker }
195*795d594fSAndroid Build Coastguard Worker
FromDRegister(DRegister r)196*795d594fSAndroid Build Coastguard Worker static constexpr ArmManagedRegister FromDRegister(DRegister r) {
197*795d594fSAndroid Build Coastguard Worker CHECK_NE(r, kNoDRegister);
198*795d594fSAndroid Build Coastguard Worker return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds));
199*795d594fSAndroid Build Coastguard Worker }
200*795d594fSAndroid Build Coastguard Worker
FromRegisterPair(RegisterPair r)201*795d594fSAndroid Build Coastguard Worker static constexpr ArmManagedRegister FromRegisterPair(RegisterPair r) {
202*795d594fSAndroid Build Coastguard Worker CHECK_NE(r, kNoRegisterPair);
203*795d594fSAndroid Build Coastguard Worker return FromRegId(r + (kNumberOfCoreRegIds +
204*795d594fSAndroid Build Coastguard Worker kNumberOfSRegIds + kNumberOfDRegIds));
205*795d594fSAndroid Build Coastguard Worker }
206*795d594fSAndroid Build Coastguard Worker
207*795d594fSAndroid Build Coastguard Worker // Return a RegisterPair consisting of Register r_low and r_low + 1.
FromCoreRegisterPair(Register r_low)208*795d594fSAndroid Build Coastguard Worker static constexpr ArmManagedRegister FromCoreRegisterPair(Register r_low) {
209*795d594fSAndroid Build Coastguard Worker if (r_low != R1) { // not the dalvik special case
210*795d594fSAndroid Build Coastguard Worker CHECK_NE(r_low, kNoRegister);
211*795d594fSAndroid Build Coastguard Worker CHECK_EQ(0, (r_low % 2));
212*795d594fSAndroid Build Coastguard Worker const int r = r_low / 2;
213*795d594fSAndroid Build Coastguard Worker CHECK_LT(r, kNumberOfPairRegIds);
214*795d594fSAndroid Build Coastguard Worker return FromRegisterPair(static_cast<RegisterPair>(r));
215*795d594fSAndroid Build Coastguard Worker } else {
216*795d594fSAndroid Build Coastguard Worker return FromRegisterPair(R1_R2);
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker }
219*795d594fSAndroid Build Coastguard Worker
220*795d594fSAndroid Build Coastguard Worker // Return a DRegister overlapping SRegister r_low and r_low + 1.
FromSRegisterPair(SRegister r_low)221*795d594fSAndroid Build Coastguard Worker static constexpr ArmManagedRegister FromSRegisterPair(SRegister r_low) {
222*795d594fSAndroid Build Coastguard Worker CHECK_NE(r_low, kNoSRegister);
223*795d594fSAndroid Build Coastguard Worker CHECK_EQ(0, (r_low % 2));
224*795d594fSAndroid Build Coastguard Worker const int r = r_low / 2;
225*795d594fSAndroid Build Coastguard Worker CHECK_LT(r, kNumberOfOverlappingDRegIds);
226*795d594fSAndroid Build Coastguard Worker return FromDRegister(static_cast<DRegister>(r));
227*795d594fSAndroid Build Coastguard Worker }
228*795d594fSAndroid Build Coastguard Worker
RegId()229*795d594fSAndroid Build Coastguard Worker int RegId() const {
230*795d594fSAndroid Build Coastguard Worker CHECK(!IsNoRegister());
231*795d594fSAndroid Build Coastguard Worker return id_;
232*795d594fSAndroid Build Coastguard Worker }
233*795d594fSAndroid Build Coastguard Worker
234*795d594fSAndroid Build Coastguard Worker private:
IsValidManagedRegister()235*795d594fSAndroid Build Coastguard Worker constexpr bool IsValidManagedRegister() const {
236*795d594fSAndroid Build Coastguard Worker return (0 <= id_) && (id_ < kNumberOfRegIds);
237*795d594fSAndroid Build Coastguard Worker }
238*795d594fSAndroid Build Coastguard Worker
AllocId()239*795d594fSAndroid Build Coastguard Worker int AllocId() const {
240*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister() &&
241*795d594fSAndroid Build Coastguard Worker !IsOverlappingDRegister() && !IsRegisterPair());
242*795d594fSAndroid Build Coastguard Worker int r = id_;
243*795d594fSAndroid Build Coastguard Worker if ((kNumberOfDAllocIds > 0) && IsDRegister()) { // VFPv3-D32 only.
244*795d594fSAndroid Build Coastguard Worker r -= kNumberOfOverlappingDRegIds;
245*795d594fSAndroid Build Coastguard Worker }
246*795d594fSAndroid Build Coastguard Worker CHECK_LT(r, kNumberOfAllocIds);
247*795d594fSAndroid Build Coastguard Worker return r;
248*795d594fSAndroid Build Coastguard Worker }
249*795d594fSAndroid Build Coastguard Worker
250*795d594fSAndroid Build Coastguard Worker int AllocIdLow() const;
251*795d594fSAndroid Build Coastguard Worker int AllocIdHigh() const;
252*795d594fSAndroid Build Coastguard Worker
253*795d594fSAndroid Build Coastguard Worker friend class ManagedRegister;
254*795d594fSAndroid Build Coastguard Worker
ArmManagedRegister(int reg_id)255*795d594fSAndroid Build Coastguard Worker explicit constexpr ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
256*795d594fSAndroid Build Coastguard Worker
FromRegId(int reg_id)257*795d594fSAndroid Build Coastguard Worker static constexpr ArmManagedRegister FromRegId(int reg_id) {
258*795d594fSAndroid Build Coastguard Worker ArmManagedRegister reg(reg_id);
259*795d594fSAndroid Build Coastguard Worker CHECK(reg.IsValidManagedRegister());
260*795d594fSAndroid Build Coastguard Worker return reg;
261*795d594fSAndroid Build Coastguard Worker }
262*795d594fSAndroid Build Coastguard Worker };
263*795d594fSAndroid Build Coastguard Worker
264*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const ArmManagedRegister& reg);
265*795d594fSAndroid Build Coastguard Worker
266*795d594fSAndroid Build Coastguard Worker } // namespace arm
267*795d594fSAndroid Build Coastguard Worker
AsArm()268*795d594fSAndroid Build Coastguard Worker constexpr arm::ArmManagedRegister ManagedRegister::AsArm() const {
269*795d594fSAndroid Build Coastguard Worker arm::ArmManagedRegister reg(id_);
270*795d594fSAndroid Build Coastguard Worker CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
271*795d594fSAndroid Build Coastguard Worker return reg;
272*795d594fSAndroid Build Coastguard Worker }
273*795d594fSAndroid Build Coastguard Worker
274*795d594fSAndroid Build Coastguard Worker } // namespace art
275*795d594fSAndroid Build Coastguard Worker
276*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_
277