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_X86_MANAGED_REGISTER_X86_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_UTILS_X86_MANAGED_REGISTER_X86_H_
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
21*795d594fSAndroid Build Coastguard Worker #include "constants_x86.h"
22*795d594fSAndroid Build Coastguard Worker #include "utils/managed_register.h"
23*795d594fSAndroid Build Coastguard Worker
24*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
25*795d594fSAndroid Build Coastguard Worker namespace x86 {
26*795d594fSAndroid Build Coastguard Worker
27*795d594fSAndroid Build Coastguard Worker // Values for register pairs.
28*795d594fSAndroid Build Coastguard Worker // The registers in kReservedCpuRegistersArray in x86.cc are not used in pairs.
29*795d594fSAndroid Build Coastguard Worker // The table kRegisterPairs in x86.cc must be kept in sync with this enum.
30*795d594fSAndroid Build Coastguard Worker enum RegisterPair {
31*795d594fSAndroid Build Coastguard Worker EAX_EDX = 0,
32*795d594fSAndroid Build Coastguard Worker EAX_ECX = 1,
33*795d594fSAndroid Build Coastguard Worker EAX_EBX = 2,
34*795d594fSAndroid Build Coastguard Worker EAX_EDI = 3,
35*795d594fSAndroid Build Coastguard Worker EDX_ECX = 4,
36*795d594fSAndroid Build Coastguard Worker EDX_EBX = 5,
37*795d594fSAndroid Build Coastguard Worker EDX_EDI = 6,
38*795d594fSAndroid Build Coastguard Worker ECX_EBX = 7,
39*795d594fSAndroid Build Coastguard Worker ECX_EDI = 8,
40*795d594fSAndroid Build Coastguard Worker EBX_EDI = 9,
41*795d594fSAndroid Build Coastguard Worker ECX_EDX = 10, // Dalvik style passing
42*795d594fSAndroid Build Coastguard Worker kNumberOfRegisterPairs = 11,
43*795d594fSAndroid Build Coastguard Worker kNoRegisterPair = -1,
44*795d594fSAndroid Build Coastguard Worker };
45*795d594fSAndroid Build Coastguard Worker
46*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
47*795d594fSAndroid Build Coastguard Worker
48*795d594fSAndroid Build Coastguard Worker const int kNumberOfCpuRegIds = kNumberOfCpuRegisters;
49*795d594fSAndroid Build Coastguard Worker const int kNumberOfCpuAllocIds = kNumberOfCpuRegisters;
50*795d594fSAndroid Build Coastguard Worker
51*795d594fSAndroid Build Coastguard Worker const int kNumberOfXmmRegIds = kNumberOfXmmRegisters;
52*795d594fSAndroid Build Coastguard Worker const int kNumberOfXmmAllocIds = kNumberOfXmmRegisters;
53*795d594fSAndroid Build Coastguard Worker
54*795d594fSAndroid Build Coastguard Worker const int kNumberOfX87RegIds = kNumberOfX87Registers;
55*795d594fSAndroid Build Coastguard Worker const int kNumberOfX87AllocIds = kNumberOfX87Registers;
56*795d594fSAndroid Build Coastguard Worker
57*795d594fSAndroid Build Coastguard Worker const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
58*795d594fSAndroid Build Coastguard Worker
59*795d594fSAndroid Build Coastguard Worker const int kNumberOfRegIds = kNumberOfCpuRegIds + kNumberOfXmmRegIds +
60*795d594fSAndroid Build Coastguard Worker kNumberOfX87RegIds + kNumberOfPairRegIds;
61*795d594fSAndroid Build Coastguard Worker const int kNumberOfAllocIds = kNumberOfCpuAllocIds + kNumberOfXmmAllocIds +
62*795d594fSAndroid Build Coastguard Worker kNumberOfX87RegIds;
63*795d594fSAndroid Build Coastguard Worker
64*795d594fSAndroid Build Coastguard Worker // Register ids map:
65*795d594fSAndroid Build Coastguard Worker // [0..R[ cpu registers (enum Register)
66*795d594fSAndroid Build Coastguard Worker // [R..X[ xmm registers (enum XmmRegister)
67*795d594fSAndroid Build Coastguard Worker // [X..S[ x87 registers (enum X87Register)
68*795d594fSAndroid Build Coastguard Worker // [S..P[ register pairs (enum RegisterPair)
69*795d594fSAndroid Build Coastguard Worker // where
70*795d594fSAndroid Build Coastguard Worker // R = kNumberOfCpuRegIds
71*795d594fSAndroid Build Coastguard Worker // X = R + kNumberOfXmmRegIds
72*795d594fSAndroid Build Coastguard Worker // S = X + kNumberOfX87RegIds
73*795d594fSAndroid Build Coastguard Worker // P = X + kNumberOfRegisterPairs
74*795d594fSAndroid Build Coastguard Worker
75*795d594fSAndroid Build Coastguard Worker // Allocation ids map:
76*795d594fSAndroid Build Coastguard Worker // [0..R[ cpu registers (enum Register)
77*795d594fSAndroid Build Coastguard Worker // [R..X[ xmm registers (enum XmmRegister)
78*795d594fSAndroid Build Coastguard Worker // [X..S[ x87 registers (enum X87Register)
79*795d594fSAndroid Build Coastguard Worker // where
80*795d594fSAndroid Build Coastguard Worker // R = kNumberOfCpuRegIds
81*795d594fSAndroid Build Coastguard Worker // X = R + kNumberOfXmmRegIds
82*795d594fSAndroid Build Coastguard Worker // S = X + kNumberOfX87RegIds
83*795d594fSAndroid Build Coastguard Worker
84*795d594fSAndroid Build Coastguard Worker
85*795d594fSAndroid Build Coastguard Worker // An instance of class 'ManagedRegister' represents a single cpu register (enum
86*795d594fSAndroid Build Coastguard Worker // Register), an xmm register (enum XmmRegister), or a pair of cpu registers
87*795d594fSAndroid Build Coastguard Worker // (enum RegisterPair).
88*795d594fSAndroid Build Coastguard Worker // 'ManagedRegister::NoRegister()' provides an invalid register.
89*795d594fSAndroid Build Coastguard Worker // There is a one-to-one mapping between ManagedRegister and register id.
90*795d594fSAndroid Build Coastguard Worker class X86ManagedRegister : public ManagedRegister {
91*795d594fSAndroid Build Coastguard Worker public:
AsByteRegister()92*795d594fSAndroid Build Coastguard Worker constexpr ByteRegister AsByteRegister() const {
93*795d594fSAndroid Build Coastguard Worker CHECK(IsCpuRegister());
94*795d594fSAndroid Build Coastguard Worker CHECK_LT(AsCpuRegister(), ESP); // ESP, EBP, ESI and EDI cannot be encoded as byte registers.
95*795d594fSAndroid Build Coastguard Worker return static_cast<ByteRegister>(id_);
96*795d594fSAndroid Build Coastguard Worker }
97*795d594fSAndroid Build Coastguard Worker
AsCpuRegister()98*795d594fSAndroid Build Coastguard Worker constexpr Register AsCpuRegister() const {
99*795d594fSAndroid Build Coastguard Worker CHECK(IsCpuRegister());
100*795d594fSAndroid Build Coastguard Worker return static_cast<Register>(id_);
101*795d594fSAndroid Build Coastguard Worker }
102*795d594fSAndroid Build Coastguard Worker
AsXmmRegister()103*795d594fSAndroid Build Coastguard Worker constexpr XmmRegister AsXmmRegister() const {
104*795d594fSAndroid Build Coastguard Worker CHECK(IsXmmRegister());
105*795d594fSAndroid Build Coastguard Worker return static_cast<XmmRegister>(id_ - kNumberOfCpuRegIds);
106*795d594fSAndroid Build Coastguard Worker }
107*795d594fSAndroid Build Coastguard Worker
AsX87Register()108*795d594fSAndroid Build Coastguard Worker constexpr X87Register AsX87Register() const {
109*795d594fSAndroid Build Coastguard Worker CHECK(IsX87Register());
110*795d594fSAndroid Build Coastguard Worker return static_cast<X87Register>(id_ -
111*795d594fSAndroid Build Coastguard Worker (kNumberOfCpuRegIds + kNumberOfXmmRegIds));
112*795d594fSAndroid Build Coastguard Worker }
113*795d594fSAndroid Build Coastguard Worker
AsRegisterPairLow()114*795d594fSAndroid Build Coastguard Worker constexpr Register AsRegisterPairLow() const {
115*795d594fSAndroid Build Coastguard Worker CHECK(IsRegisterPair());
116*795d594fSAndroid Build Coastguard Worker // Appropriate mapping of register ids allows to use AllocIdLow().
117*795d594fSAndroid Build Coastguard Worker return FromRegId(AllocIdLow()).AsCpuRegister();
118*795d594fSAndroid Build Coastguard Worker }
119*795d594fSAndroid Build Coastguard Worker
AsRegisterPairHigh()120*795d594fSAndroid Build Coastguard Worker constexpr Register AsRegisterPairHigh() const {
121*795d594fSAndroid Build Coastguard Worker CHECK(IsRegisterPair());
122*795d594fSAndroid Build Coastguard Worker // Appropriate mapping of register ids allows to use AllocIdHigh().
123*795d594fSAndroid Build Coastguard Worker return FromRegId(AllocIdHigh()).AsCpuRegister();
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker
AsRegisterPair()126*795d594fSAndroid Build Coastguard Worker constexpr RegisterPair AsRegisterPair() const {
127*795d594fSAndroid Build Coastguard Worker CHECK(IsRegisterPair());
128*795d594fSAndroid Build Coastguard Worker return static_cast<RegisterPair>(id_ -
129*795d594fSAndroid Build Coastguard Worker (kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds));
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker
IsCpuRegister()132*795d594fSAndroid Build Coastguard Worker constexpr bool IsCpuRegister() const {
133*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister());
134*795d594fSAndroid Build Coastguard Worker return (0 <= id_) && (id_ < kNumberOfCpuRegIds);
135*795d594fSAndroid Build Coastguard Worker }
136*795d594fSAndroid Build Coastguard Worker
IsXmmRegister()137*795d594fSAndroid Build Coastguard Worker constexpr bool IsXmmRegister() const {
138*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister());
139*795d594fSAndroid Build Coastguard Worker const int test = id_ - kNumberOfCpuRegIds;
140*795d594fSAndroid Build Coastguard Worker return (0 <= test) && (test < kNumberOfXmmRegIds);
141*795d594fSAndroid Build Coastguard Worker }
142*795d594fSAndroid Build Coastguard Worker
IsX87Register()143*795d594fSAndroid Build Coastguard Worker constexpr bool IsX87Register() const {
144*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister());
145*795d594fSAndroid Build Coastguard Worker const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds);
146*795d594fSAndroid Build Coastguard Worker return (0 <= test) && (test < kNumberOfX87RegIds);
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker
IsRegisterPair()149*795d594fSAndroid Build Coastguard Worker constexpr bool IsRegisterPair() const {
150*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister());
151*795d594fSAndroid Build Coastguard Worker const int test = id_ -
152*795d594fSAndroid Build Coastguard Worker (kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds);
153*795d594fSAndroid Build Coastguard Worker return (0 <= test) && (test < kNumberOfPairRegIds);
154*795d594fSAndroid Build Coastguard Worker }
155*795d594fSAndroid Build Coastguard Worker
156*795d594fSAndroid Build Coastguard Worker void Print(std::ostream& os) const;
157*795d594fSAndroid Build Coastguard Worker
158*795d594fSAndroid Build Coastguard Worker // Returns true if the two managed-registers ('this' and 'other') overlap.
159*795d594fSAndroid Build Coastguard Worker // Either managed-register may be the NoRegister. If both are the NoRegister
160*795d594fSAndroid Build Coastguard Worker // then false is returned.
161*795d594fSAndroid Build Coastguard Worker bool Overlaps(const X86ManagedRegister& other) const;
162*795d594fSAndroid Build Coastguard Worker
FromCpuRegister(Register r)163*795d594fSAndroid Build Coastguard Worker static constexpr X86ManagedRegister FromCpuRegister(Register r) {
164*795d594fSAndroid Build Coastguard Worker CHECK_NE(r, kNoRegister);
165*795d594fSAndroid Build Coastguard Worker return FromRegId(r);
166*795d594fSAndroid Build Coastguard Worker }
167*795d594fSAndroid Build Coastguard Worker
FromXmmRegister(XmmRegister r)168*795d594fSAndroid Build Coastguard Worker static constexpr X86ManagedRegister FromXmmRegister(XmmRegister r) {
169*795d594fSAndroid Build Coastguard Worker CHECK_NE(r, kNoXmmRegister);
170*795d594fSAndroid Build Coastguard Worker return FromRegId(r + kNumberOfCpuRegIds);
171*795d594fSAndroid Build Coastguard Worker }
172*795d594fSAndroid Build Coastguard Worker
FromX87Register(X87Register r)173*795d594fSAndroid Build Coastguard Worker static constexpr X86ManagedRegister FromX87Register(X87Register r) {
174*795d594fSAndroid Build Coastguard Worker CHECK_NE(r, kNoX87Register);
175*795d594fSAndroid Build Coastguard Worker return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds);
176*795d594fSAndroid Build Coastguard Worker }
177*795d594fSAndroid Build Coastguard Worker
FromRegisterPair(RegisterPair r)178*795d594fSAndroid Build Coastguard Worker static constexpr X86ManagedRegister FromRegisterPair(RegisterPair r) {
179*795d594fSAndroid Build Coastguard Worker CHECK_NE(r, kNoRegisterPair);
180*795d594fSAndroid Build Coastguard Worker return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
181*795d594fSAndroid Build Coastguard Worker kNumberOfX87RegIds));
182*795d594fSAndroid Build Coastguard Worker }
183*795d594fSAndroid Build Coastguard Worker
184*795d594fSAndroid Build Coastguard Worker private:
IsValidManagedRegister()185*795d594fSAndroid Build Coastguard Worker constexpr bool IsValidManagedRegister() const {
186*795d594fSAndroid Build Coastguard Worker return (0 <= id_) && (id_ < kNumberOfRegIds);
187*795d594fSAndroid Build Coastguard Worker }
188*795d594fSAndroid Build Coastguard Worker
RegId()189*795d594fSAndroid Build Coastguard Worker constexpr int RegId() const {
190*795d594fSAndroid Build Coastguard Worker CHECK(!IsNoRegister());
191*795d594fSAndroid Build Coastguard Worker return id_;
192*795d594fSAndroid Build Coastguard Worker }
193*795d594fSAndroid Build Coastguard Worker
AllocId()194*795d594fSAndroid Build Coastguard Worker int AllocId() const {
195*795d594fSAndroid Build Coastguard Worker CHECK(IsValidManagedRegister() && !IsRegisterPair());
196*795d594fSAndroid Build Coastguard Worker CHECK_LT(id_, kNumberOfAllocIds);
197*795d594fSAndroid Build Coastguard Worker return id_;
198*795d594fSAndroid Build Coastguard Worker }
199*795d594fSAndroid Build Coastguard Worker
200*795d594fSAndroid Build Coastguard Worker int AllocIdLow() const;
201*795d594fSAndroid Build Coastguard Worker int AllocIdHigh() const;
202*795d594fSAndroid Build Coastguard Worker
203*795d594fSAndroid Build Coastguard Worker friend class ManagedRegister;
204*795d594fSAndroid Build Coastguard Worker
X86ManagedRegister(int reg_id)205*795d594fSAndroid Build Coastguard Worker explicit constexpr X86ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
206*795d594fSAndroid Build Coastguard Worker
FromRegId(int reg_id)207*795d594fSAndroid Build Coastguard Worker static constexpr X86ManagedRegister FromRegId(int reg_id) {
208*795d594fSAndroid Build Coastguard Worker X86ManagedRegister reg(reg_id);
209*795d594fSAndroid Build Coastguard Worker CHECK(reg.IsValidManagedRegister());
210*795d594fSAndroid Build Coastguard Worker return reg;
211*795d594fSAndroid Build Coastguard Worker }
212*795d594fSAndroid Build Coastguard Worker };
213*795d594fSAndroid Build Coastguard Worker
214*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const X86ManagedRegister& reg);
215*795d594fSAndroid Build Coastguard Worker
216*795d594fSAndroid Build Coastguard Worker } // namespace x86
217*795d594fSAndroid Build Coastguard Worker
AsX86()218*795d594fSAndroid Build Coastguard Worker constexpr x86::X86ManagedRegister ManagedRegister::AsX86() const {
219*795d594fSAndroid Build Coastguard Worker x86::X86ManagedRegister reg(id_);
220*795d594fSAndroid Build Coastguard Worker CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
221*795d594fSAndroid Build Coastguard Worker return reg;
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker
224*795d594fSAndroid Build Coastguard Worker } // namespace art
225*795d594fSAndroid Build Coastguard Worker
226*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_UTILS_X86_MANAGED_REGISTER_X86_H_
227