xref: /aosp_15_r20/art/compiler/utils/x86/managed_register_x86.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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