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