1 /*
2 * Copyright (C) 2014 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_64_MANAGED_REGISTER_X86_64_H_
18 #define ART_COMPILER_UTILS_X86_64_MANAGED_REGISTER_X86_64_H_
19
20 #include "constants_x86_64.h"
21 #include "debug/dwarf/register.h"
22 #include "utils/managed_register.h"
23
24 namespace art {
25 namespace x86_64 {
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 RAX_RDX = 0,
32 RAX_RCX = 1,
33 RAX_RBX = 2,
34 RAX_RDI = 3,
35 RDX_RCX = 4,
36 RDX_RBX = 5,
37 RDX_RDI = 6,
38 RCX_RBX = 7,
39 RCX_RDI = 8,
40 RBX_RDI = 9,
41 kNumberOfRegisterPairs = 10,
42 kNoRegisterPair = -1,
43 };
44
45 std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
46
47 const int kNumberOfCpuRegIds = kNumberOfCpuRegisters;
48 const int kNumberOfCpuAllocIds = kNumberOfCpuRegisters;
49
50 const int kNumberOfXmmRegIds = kNumberOfFloatRegisters;
51 const int kNumberOfXmmAllocIds = kNumberOfFloatRegisters;
52
53 const int kNumberOfX87RegIds = kNumberOfX87Registers;
54 const int kNumberOfX87AllocIds = kNumberOfX87Registers;
55
56 const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
57
58 const int kNumberOfRegIds = kNumberOfCpuRegIds + kNumberOfXmmRegIds +
59 kNumberOfX87RegIds + kNumberOfPairRegIds;
60 const 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.
89 class X86_64ManagedRegister : public ManagedRegister {
90 public:
AsCpuRegister()91 CpuRegister AsCpuRegister() const {
92 CHECK(IsCpuRegister());
93 return CpuRegister(static_cast<Register>(id_));
94 }
95
AsXmmRegister()96 XmmRegister AsXmmRegister() const {
97 CHECK(IsXmmRegister());
98 return XmmRegister(static_cast<FloatRegister>(id_ - kNumberOfCpuRegIds));
99 }
100
AsX87Register()101 X87Register AsX87Register() const {
102 CHECK(IsX87Register());
103 return static_cast<X87Register>(id_ -
104 (kNumberOfCpuRegIds + kNumberOfXmmRegIds));
105 }
106
AsRegisterPairLow()107 CpuRegister AsRegisterPairLow() const {
108 CHECK(IsRegisterPair());
109 // Appropriate mapping of register ids allows to use AllocIdLow().
110 return FromRegId(AllocIdLow()).AsCpuRegister();
111 }
112
AsRegisterPairHigh()113 CpuRegister AsRegisterPairHigh() const {
114 CHECK(IsRegisterPair());
115 // Appropriate mapping of register ids allows to use AllocIdHigh().
116 return FromRegId(AllocIdHigh()).AsCpuRegister();
117 }
118
IsCpuRegister()119 bool IsCpuRegister() const {
120 CHECK(IsValidManagedRegister());
121 return (0 <= id_) && (id_ < kNumberOfCpuRegIds);
122 }
123
IsXmmRegister()124 bool IsXmmRegister() const {
125 CHECK(IsValidManagedRegister());
126 const int test = id_ - kNumberOfCpuRegIds;
127 return (0 <= test) && (test < kNumberOfXmmRegIds);
128 }
129
IsX87Register()130 bool IsX87Register() const {
131 CHECK(IsValidManagedRegister());
132 const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds);
133 return (0 <= test) && (test < kNumberOfX87RegIds);
134 }
135
IsRegisterPair()136 bool IsRegisterPair() const {
137 CHECK(IsValidManagedRegister());
138 const int test = id_ -
139 (kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds);
140 return (0 <= test) && (test < kNumberOfPairRegIds);
141 }
142
143 void Print(std::ostream& os) const;
144
145 // Returns true if the two managed-registers ('this' and 'other') overlap.
146 // Either managed-register may be the NoRegister. If both are the NoRegister
147 // then false is returned.
148 bool Overlaps(const X86_64ManagedRegister& other) const;
149
FromCpuRegister(Register r)150 static X86_64ManagedRegister FromCpuRegister(Register r) {
151 CHECK_NE(r, kNoRegister);
152 return FromRegId(r);
153 }
154
FromXmmRegister(FloatRegister r)155 static X86_64ManagedRegister FromXmmRegister(FloatRegister r) {
156 return FromRegId(r + kNumberOfCpuRegIds);
157 }
158
FromX87Register(X87Register r)159 static X86_64ManagedRegister FromX87Register(X87Register r) {
160 CHECK_NE(r, kNoX87Register);
161 return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds);
162 }
163
FromRegisterPair(RegisterPair r)164 static X86_64ManagedRegister FromRegisterPair(RegisterPair r) {
165 CHECK_NE(r, kNoRegisterPair);
166 return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
167 kNumberOfX87RegIds));
168 }
169
170 private:
IsValidManagedRegister()171 bool IsValidManagedRegister() const {
172 return (0 <= id_) && (id_ < kNumberOfRegIds);
173 }
174
RegId()175 int RegId() const {
176 CHECK(!IsNoRegister());
177 return id_;
178 }
179
AllocId()180 int AllocId() const {
181 CHECK(IsValidManagedRegister() && !IsRegisterPair());
182 CHECK_LT(id_, kNumberOfAllocIds);
183 return id_;
184 }
185
186 int AllocIdLow() const;
187 int AllocIdHigh() const;
188
189 friend class ManagedRegister;
190
X86_64ManagedRegister(int reg_id)191 explicit X86_64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
192
FromRegId(int reg_id)193 static X86_64ManagedRegister FromRegId(int reg_id) {
194 X86_64ManagedRegister reg(reg_id);
195 CHECK(reg.IsValidManagedRegister());
196 return reg;
197 }
198 };
199
200 std::ostream& operator<<(std::ostream& os, const X86_64ManagedRegister& reg);
201
202 } // namespace x86_64
203
AsX86_64()204 inline x86_64::X86_64ManagedRegister ManagedRegister::AsX86_64() const {
205 x86_64::X86_64ManagedRegister reg(id_);
206 CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
207 return reg;
208 }
209
210 } // namespace art
211
212 #endif // ART_COMPILER_UTILS_X86_64_MANAGED_REGISTER_X86_64_H_
213