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
24namespace art {
25namespace 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.
30enum 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
46std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
47
48const int kNumberOfCpuRegIds = kNumberOfCpuRegisters;
49const int kNumberOfCpuAllocIds = kNumberOfCpuRegisters;
50
51const int kNumberOfXmmRegIds = kNumberOfXmmRegisters;
52const int kNumberOfXmmAllocIds = kNumberOfXmmRegisters;
53
54const int kNumberOfX87RegIds = kNumberOfX87Registers;
55const int kNumberOfX87AllocIds = kNumberOfX87Registers;
56
57const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
58
59const int kNumberOfRegIds = kNumberOfCpuRegIds + kNumberOfXmmRegIds +
60    kNumberOfX87RegIds + kNumberOfPairRegIds;
61const 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.
90class X86ManagedRegister : public ManagedRegister {
91 public:
92  constexpr 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
98  constexpr Register AsCpuRegister() const {
99    CHECK(IsCpuRegister());
100    return static_cast<Register>(id_);
101  }
102
103  constexpr XmmRegister AsXmmRegister() const {
104    CHECK(IsXmmRegister());
105    return static_cast<XmmRegister>(id_ - kNumberOfCpuRegIds);
106  }
107
108  constexpr X87Register AsX87Register() const {
109    CHECK(IsX87Register());
110    return static_cast<X87Register>(id_ -
111                                    (kNumberOfCpuRegIds + kNumberOfXmmRegIds));
112  }
113
114  constexpr Register AsRegisterPairLow() const {
115    CHECK(IsRegisterPair());
116    // Appropriate mapping of register ids allows to use AllocIdLow().
117    return FromRegId(AllocIdLow()).AsCpuRegister();
118  }
119
120  constexpr Register AsRegisterPairHigh() const {
121    CHECK(IsRegisterPair());
122    // Appropriate mapping of register ids allows to use AllocIdHigh().
123    return FromRegId(AllocIdHigh()).AsCpuRegister();
124  }
125
126  constexpr RegisterPair AsRegisterPair() const {
127    CHECK(IsRegisterPair());
128    return static_cast<RegisterPair>(id_ -
129        (kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds));
130  }
131
132  constexpr bool IsCpuRegister() const {
133    CHECK(IsValidManagedRegister());
134    return (0 <= id_) && (id_ < kNumberOfCpuRegIds);
135  }
136
137  constexpr bool IsXmmRegister() const {
138    CHECK(IsValidManagedRegister());
139    const int test = id_ - kNumberOfCpuRegIds;
140    return (0 <= test) && (test < kNumberOfXmmRegIds);
141  }
142
143  constexpr bool IsX87Register() const {
144    CHECK(IsValidManagedRegister());
145    const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds);
146    return (0 <= test) && (test < kNumberOfX87RegIds);
147  }
148
149  constexpr 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
163  static constexpr X86ManagedRegister FromCpuRegister(Register r) {
164    CHECK_NE(r, kNoRegister);
165    return FromRegId(r);
166  }
167
168  static constexpr X86ManagedRegister FromXmmRegister(XmmRegister r) {
169    CHECK_NE(r, kNoXmmRegister);
170    return FromRegId(r + kNumberOfCpuRegIds);
171  }
172
173  static constexpr X86ManagedRegister FromX87Register(X87Register r) {
174    CHECK_NE(r, kNoX87Register);
175    return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds);
176  }
177
178  static constexpr X86ManagedRegister FromRegisterPair(RegisterPair r) {
179    CHECK_NE(r, kNoRegisterPair);
180    return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
181                          kNumberOfX87RegIds));
182  }
183
184 private:
185  constexpr bool IsValidManagedRegister() const {
186    return (0 <= id_) && (id_ < kNumberOfRegIds);
187  }
188
189  constexpr int RegId() const {
190    CHECK(!IsNoRegister());
191    return id_;
192  }
193
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
205  explicit constexpr X86ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
206
207  static constexpr X86ManagedRegister FromRegId(int reg_id) {
208    X86ManagedRegister reg(reg_id);
209    CHECK(reg.IsValidManagedRegister());
210    return reg;
211  }
212};
213
214std::ostream& operator<<(std::ostream& os, const X86ManagedRegister& reg);
215
216}  // namespace x86
217
218constexpr 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