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   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   Register AsCpuRegister() const {
98     CHECK(IsCpuRegister());
99     return static_cast<Register>(id_);
100   }
101 
AsXmmRegister()102   XmmRegister AsXmmRegister() const {
103     CHECK(IsXmmRegister());
104     return static_cast<XmmRegister>(id_ - kNumberOfCpuRegIds);
105   }
106 
AsX87Register()107   X87Register AsX87Register() const {
108     CHECK(IsX87Register());
109     return static_cast<X87Register>(id_ -
110                                     (kNumberOfCpuRegIds + kNumberOfXmmRegIds));
111   }
112 
AsRegisterPairLow()113   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   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   RegisterPair AsRegisterPair() const {
126     CHECK(IsRegisterPair());
127     return static_cast<RegisterPair>(id_ -
128         (kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds));
129   }
130 
IsCpuRegister()131   bool IsCpuRegister() const {
132     CHECK(IsValidManagedRegister());
133     return (0 <= id_) && (id_ < kNumberOfCpuRegIds);
134   }
135 
IsXmmRegister()136   bool IsXmmRegister() const {
137     CHECK(IsValidManagedRegister());
138     const int test = id_ - kNumberOfCpuRegIds;
139     return (0 <= test) && (test < kNumberOfXmmRegIds);
140   }
141 
IsX87Register()142   bool IsX87Register() const {
143     CHECK(IsValidManagedRegister());
144     const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds);
145     return (0 <= test) && (test < kNumberOfX87RegIds);
146   }
147 
IsRegisterPair()148   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 X86ManagedRegister FromCpuRegister(Register r) {
163     CHECK_NE(r, kNoRegister);
164     return FromRegId(r);
165   }
166 
FromXmmRegister(XmmRegister r)167   static X86ManagedRegister FromXmmRegister(XmmRegister r) {
168     CHECK_NE(r, kNoXmmRegister);
169     return FromRegId(r + kNumberOfCpuRegIds);
170   }
171 
FromX87Register(X87Register r)172   static X86ManagedRegister FromX87Register(X87Register r) {
173     CHECK_NE(r, kNoX87Register);
174     return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds);
175   }
176 
FromRegisterPair(RegisterPair r)177   static X86ManagedRegister FromRegisterPair(RegisterPair r) {
178     CHECK_NE(r, kNoRegisterPair);
179     return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
180                           kNumberOfX87RegIds));
181   }
182 
183  private:
IsValidManagedRegister()184   bool IsValidManagedRegister() const {
185     return (0 <= id_) && (id_ < kNumberOfRegIds);
186   }
187 
RegId()188   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 X86ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
205 
FromRegId(int reg_id)206   static 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 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