managed_register_x86.h revision 166db04e259ca51838c311891598664deeed85ad
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
23namespace art {
24namespace 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.
29enum 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
44std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
45
46const int kNumberOfCpuRegIds = kNumberOfCpuRegisters;
47const int kNumberOfCpuAllocIds = kNumberOfCpuRegisters;
48
49const int kNumberOfXmmRegIds = kNumberOfXmmRegisters;
50const int kNumberOfXmmAllocIds = kNumberOfXmmRegisters;
51
52const int kNumberOfX87RegIds = kNumberOfX87Registers;
53const int kNumberOfX87AllocIds = kNumberOfX87Registers;
54
55const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
56
57const int kNumberOfRegIds = kNumberOfCpuRegIds + kNumberOfXmmRegIds +
58    kNumberOfX87RegIds + kNumberOfPairRegIds;
59const 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.
88class X86ManagedRegister : public ManagedRegister {
89 public:
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
96  Register AsCpuRegister() const {
97    CHECK(IsCpuRegister());
98    return static_cast<Register>(id_);
99  }
100
101  XmmRegister AsXmmRegister() const {
102    CHECK(IsXmmRegister());
103    return static_cast<XmmRegister>(id_ - kNumberOfCpuRegIds);
104  }
105
106  X87Register AsX87Register() const {
107    CHECK(IsX87Register());
108    return static_cast<X87Register>(id_ -
109                                    (kNumberOfCpuRegIds + kNumberOfXmmRegIds));
110  }
111
112  Register AsRegisterPairLow() const {
113    CHECK(IsRegisterPair());
114    // Appropriate mapping of register ids allows to use AllocIdLow().
115    return FromRegId(AllocIdLow()).AsCpuRegister();
116  }
117
118  Register AsRegisterPairHigh() const {
119    CHECK(IsRegisterPair());
120    // Appropriate mapping of register ids allows to use AllocIdHigh().
121    return FromRegId(AllocIdHigh()).AsCpuRegister();
122  }
123
124  bool IsCpuRegister() const {
125    CHECK(IsValidManagedRegister());
126    return (0 <= id_) && (id_ < kNumberOfCpuRegIds);
127  }
128
129  bool IsXmmRegister() const {
130    CHECK(IsValidManagedRegister());
131    const int test = id_ - kNumberOfCpuRegIds;
132    return (0 <= test) && (test < kNumberOfXmmRegIds);
133  }
134
135  bool IsX87Register() const {
136    CHECK(IsValidManagedRegister());
137    const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds);
138    return (0 <= test) && (test < kNumberOfX87RegIds);
139  }
140
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
155  static X86ManagedRegister FromCpuRegister(Register r) {
156    CHECK_NE(r, kNoRegister);
157    return FromRegId(r);
158  }
159
160  static X86ManagedRegister FromXmmRegister(XmmRegister r) {
161    CHECK_NE(r, kNoXmmRegister);
162    return FromRegId(r + kNumberOfCpuRegIds);
163  }
164
165  static X86ManagedRegister FromX87Register(X87Register r) {
166    CHECK_NE(r, kNoX87Register);
167    return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds);
168  }
169
170  static X86ManagedRegister FromRegisterPair(RegisterPair r) {
171    CHECK_NE(r, kNoRegisterPair);
172    return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
173                          kNumberOfX87RegIds));
174  }
175
176 private:
177  bool IsValidManagedRegister() const {
178    return (0 <= id_) && (id_ < kNumberOfRegIds);
179  }
180
181  int RegId() const {
182    CHECK(!IsNoRegister());
183    return id_;
184  }
185
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
197  explicit X86ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
198
199  static X86ManagedRegister FromRegId(int reg_id) {
200    X86ManagedRegister reg(reg_id);
201    CHECK(reg.IsValidManagedRegister());
202    return reg;
203  }
204};
205
206std::ostream& operator<<(std::ostream& os, const X86ManagedRegister& reg);
207
208}  // namespace x86
209
210inline 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