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 #include "managed_register_x86.h"
18 
19 #include "base/globals.h"
20 
21 namespace art {
22 namespace x86 {
23 
24 // Define register pairs.
25 // This list must be kept in sync with the RegisterPair enum.
26 #define REGISTER_PAIR_LIST(P) \
27   P(EAX, EDX)                 \
28   P(EAX, ECX)                 \
29   P(EAX, EBX)                 \
30   P(EAX, EDI)                 \
31   P(EDX, ECX)                 \
32   P(EDX, EBX)                 \
33   P(EDX, EDI)                 \
34   P(ECX, EBX)                 \
35   P(ECX, EDI)                 \
36   P(EBX, EDI)                 \
37   P(ECX, EDX)
38 
39 
40 struct RegisterPairDescriptor {
41   RegisterPair reg;  // Used to verify that the enum is in sync.
42   Register low;
43   Register high;
44 };
45 
46 
47 static const RegisterPairDescriptor kRegisterPairs[] = {
48 #define REGISTER_PAIR_ENUMERATION(low, high) { low##_##high, low, high },
49   REGISTER_PAIR_LIST(REGISTER_PAIR_ENUMERATION)
50 #undef REGISTER_PAIR_ENUMERATION
51 };
52 
operator <<(std::ostream & os,const RegisterPair & reg)53 std::ostream& operator<<(std::ostream& os, const RegisterPair& reg) {
54   if (reg == kNoRegisterPair) {
55     os << "kNoRegisterPair";
56   } else {
57     os << X86ManagedRegister::FromRegisterPair(reg);
58   }
59   return os;
60 }
61 
Overlaps(const X86ManagedRegister & other) const62 bool X86ManagedRegister::Overlaps(const X86ManagedRegister& other) const {
63   if (IsNoRegister() || other.IsNoRegister()) return false;
64   CHECK(IsValidManagedRegister());
65   CHECK(other.IsValidManagedRegister());
66   if (Equals(other)) return true;
67   if (IsRegisterPair()) {
68     Register low = AsRegisterPairLow();
69     Register high = AsRegisterPairHigh();
70     return X86ManagedRegister::FromCpuRegister(low).Overlaps(other) ||
71         X86ManagedRegister::FromCpuRegister(high).Overlaps(other);
72   }
73   if (other.IsRegisterPair()) {
74     return other.Overlaps(*this);
75   }
76   return false;
77 }
78 
79 
AllocIdLow() const80 int X86ManagedRegister::AllocIdLow() const {
81   CHECK(IsRegisterPair());
82   const int r = RegId() - (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
83                            kNumberOfX87RegIds);
84   CHECK_EQ(r, kRegisterPairs[r].reg);
85   return kRegisterPairs[r].low;
86 }
87 
88 
AllocIdHigh() const89 int X86ManagedRegister::AllocIdHigh() const {
90   CHECK(IsRegisterPair());
91   const int r = RegId() - (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
92                            kNumberOfX87RegIds);
93   CHECK_EQ(r, kRegisterPairs[r].reg);
94   return kRegisterPairs[r].high;
95 }
96 
97 
Print(std::ostream & os) const98 void X86ManagedRegister::Print(std::ostream& os) const {
99   if (!IsValidManagedRegister()) {
100     os << "No Register";
101   } else if (IsXmmRegister()) {
102     os << "XMM: " << AsXmmRegister();
103   } else if (IsX87Register()) {
104     os << "X87: " << AsX87Register();
105   } else if (IsCpuRegister()) {
106     os << "CPU: " << AsCpuRegister();
107   } else if (IsRegisterPair()) {
108     os << "Pair: " << AsRegisterPairLow() << ", " << AsRegisterPairHigh();
109   } else {
110     os << "??: " << RegId();
111   }
112 }
113 
operator <<(std::ostream & os,const X86ManagedRegister & reg)114 std::ostream& operator<<(std::ostream& os, const X86ManagedRegister& reg) {
115   reg.Print(os);
116   return os;
117 }
118 
119 }  // namespace x86
120 }  // namespace art
121