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