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