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