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   constexpr CpuRegister AsCpuRegister() const {
92     CHECK(IsCpuRegister());
93     return CpuRegister(static_cast<Register>(id_));
94   }
95 
AsXmmRegister()96   constexpr XmmRegister AsXmmRegister() const {
97     CHECK(IsXmmRegister());
98     return XmmRegister(static_cast<FloatRegister>(id_ - kNumberOfCpuRegIds));
99   }
100 
AsX87Register()101   constexpr X87Register AsX87Register() const {
102     CHECK(IsX87Register());
103     return static_cast<X87Register>(id_ -
104                                     (kNumberOfCpuRegIds + kNumberOfXmmRegIds));
105   }
106 
AsRegisterPairLow()107   constexpr 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   constexpr 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   constexpr bool IsCpuRegister() const {
120     CHECK(IsValidManagedRegister());
121     return (0 <= id_) && (id_ < kNumberOfCpuRegIds);
122   }
123 
IsXmmRegister()124   constexpr bool IsXmmRegister() const {
125     CHECK(IsValidManagedRegister());
126     const int test = id_ - kNumberOfCpuRegIds;
127     return (0 <= test) && (test < kNumberOfXmmRegIds);
128   }
129 
IsX87Register()130   constexpr bool IsX87Register() const {
131     CHECK(IsValidManagedRegister());
132     const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds);
133     return (0 <= test) && (test < kNumberOfX87RegIds);
134   }
135 
IsRegisterPair()136   constexpr 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 constexpr X86_64ManagedRegister FromCpuRegister(Register r) {
151     CHECK_NE(r, kNoRegister);
152     return FromRegId(r);
153   }
154 
FromXmmRegister(FloatRegister r)155   static constexpr X86_64ManagedRegister FromXmmRegister(FloatRegister r) {
156     return FromRegId(r + kNumberOfCpuRegIds);
157   }
158 
FromX87Register(X87Register r)159   static constexpr X86_64ManagedRegister FromX87Register(X87Register r) {
160     CHECK_NE(r, kNoX87Register);
161     return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds);
162   }
163 
FromRegisterPair(RegisterPair r)164   static constexpr X86_64ManagedRegister FromRegisterPair(RegisterPair r) {
165     CHECK_NE(r, kNoRegisterPair);
166     return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
167                           kNumberOfX87RegIds));
168   }
169 
170  private:
IsValidManagedRegister()171   constexpr bool IsValidManagedRegister() const {
172     return (0 <= id_) && (id_ < kNumberOfRegIds);
173   }
174 
RegId()175   constexpr 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 constexpr X86_64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
192 
FromRegId(int reg_id)193   static constexpr 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 constexpr 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