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: 91 CpuRegister AsCpuRegister() const { 92 CHECK(IsCpuRegister()); 93 return CpuRegister(static_cast<Register>(id_)); 94 } 95 96 XmmRegister AsXmmRegister() const { 97 CHECK(IsXmmRegister()); 98 return XmmRegister(static_cast<FloatRegister>(id_ - kNumberOfCpuRegIds)); 99 } 100 101 X87Register AsX87Register() const { 102 CHECK(IsX87Register()); 103 return static_cast<X87Register>(id_ - 104 (kNumberOfCpuRegIds + kNumberOfXmmRegIds)); 105 } 106 107 CpuRegister AsRegisterPairLow() const { 108 CHECK(IsRegisterPair()); 109 // Appropriate mapping of register ids allows to use AllocIdLow(). 110 return FromRegId(AllocIdLow()).AsCpuRegister(); 111 } 112 113 CpuRegister AsRegisterPairHigh() const { 114 CHECK(IsRegisterPair()); 115 // Appropriate mapping of register ids allows to use AllocIdHigh(). 116 return FromRegId(AllocIdHigh()).AsCpuRegister(); 117 } 118 119 bool IsCpuRegister() const { 120 CHECK(IsValidManagedRegister()); 121 return (0 <= id_) && (id_ < kNumberOfCpuRegIds); 122 } 123 124 bool IsXmmRegister() const { 125 CHECK(IsValidManagedRegister()); 126 const int test = id_ - kNumberOfCpuRegIds; 127 return (0 <= test) && (test < kNumberOfXmmRegIds); 128 } 129 130 bool IsX87Register() const { 131 CHECK(IsValidManagedRegister()); 132 const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds); 133 return (0 <= test) && (test < kNumberOfX87RegIds); 134 } 135 136 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 150 static X86_64ManagedRegister FromCpuRegister(Register r) { 151 CHECK_NE(r, kNoRegister); 152 return FromRegId(r); 153 } 154 155 static X86_64ManagedRegister FromXmmRegister(FloatRegister r) { 156 return FromRegId(r + kNumberOfCpuRegIds); 157 } 158 159 static X86_64ManagedRegister FromX87Register(X87Register r) { 160 CHECK_NE(r, kNoX87Register); 161 return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds); 162 } 163 164 static X86_64ManagedRegister FromRegisterPair(RegisterPair r) { 165 CHECK_NE(r, kNoRegisterPair); 166 return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds + 167 kNumberOfX87RegIds)); 168 } 169 170 private: 171 bool IsValidManagedRegister() const { 172 return (0 <= id_) && (id_ < kNumberOfRegIds); 173 } 174 175 int RegId() const { 176 CHECK(!IsNoRegister()); 177 return id_; 178 } 179 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 191 explicit X86_64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {} 192 193 static 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 204 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