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
21namespace art {
22namespace 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
40struct RegisterPairDescriptor {
41  RegisterPair reg;  // Used to verify that the enum is in sync.
42  Register low;
43  Register high;
44};
45
46
47static 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
53std::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
62bool 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
80int 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
89int 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
98void 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
114std::ostream& operator<<(std::ostream& os, const X86ManagedRegister& reg) {
115  reg.Print(os);
116  return os;
117}
118
119}  // namespace x86
120}  // namespace art
121