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