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 "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