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