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