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#ifndef ART_COMPILER_UTILS_X86_MANAGED_REGISTER_X86_H_ 18#define ART_COMPILER_UTILS_X86_MANAGED_REGISTER_X86_H_ 19 20#include "constants_x86.h" 21#include "debug/dwarf/register.h" 22#include "utils/managed_register.h" 23 24namespace art { 25namespace x86 { 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. 30enum RegisterPair { 31 EAX_EDX = 0, 32 EAX_ECX = 1, 33 EAX_EBX = 2, 34 EAX_EDI = 3, 35 EDX_ECX = 4, 36 EDX_EBX = 5, 37 EDX_EDI = 6, 38 ECX_EBX = 7, 39 ECX_EDI = 8, 40 EBX_EDI = 9, 41 ECX_EDX = 10, // Dalvik style passing 42 kNumberOfRegisterPairs = 11, 43 kNoRegisterPair = -1, 44}; 45 46std::ostream& operator<<(std::ostream& os, const RegisterPair& reg); 47 48const int kNumberOfCpuRegIds = kNumberOfCpuRegisters; 49const int kNumberOfCpuAllocIds = kNumberOfCpuRegisters; 50 51const int kNumberOfXmmRegIds = kNumberOfXmmRegisters; 52const int kNumberOfXmmAllocIds = kNumberOfXmmRegisters; 53 54const int kNumberOfX87RegIds = kNumberOfX87Registers; 55const int kNumberOfX87AllocIds = kNumberOfX87Registers; 56 57const int kNumberOfPairRegIds = kNumberOfRegisterPairs; 58 59const int kNumberOfRegIds = kNumberOfCpuRegIds + kNumberOfXmmRegIds + 60 kNumberOfX87RegIds + kNumberOfPairRegIds; 61const int kNumberOfAllocIds = kNumberOfCpuAllocIds + kNumberOfXmmAllocIds + 62 kNumberOfX87RegIds; 63 64// Register ids map: 65// [0..R[ cpu registers (enum Register) 66// [R..X[ xmm registers (enum XmmRegister) 67// [X..S[ x87 registers (enum X87Register) 68// [S..P[ register pairs (enum RegisterPair) 69// where 70// R = kNumberOfCpuRegIds 71// X = R + kNumberOfXmmRegIds 72// S = X + kNumberOfX87RegIds 73// P = X + kNumberOfRegisterPairs 74 75// Allocation ids map: 76// [0..R[ cpu registers (enum Register) 77// [R..X[ xmm registers (enum XmmRegister) 78// [X..S[ x87 registers (enum X87Register) 79// where 80// R = kNumberOfCpuRegIds 81// X = R + kNumberOfXmmRegIds 82// S = X + kNumberOfX87RegIds 83 84 85// An instance of class 'ManagedRegister' represents a single cpu register (enum 86// Register), an xmm register (enum XmmRegister), or a pair of cpu registers 87// (enum RegisterPair). 88// 'ManagedRegister::NoRegister()' provides an invalid register. 89// There is a one-to-one mapping between ManagedRegister and register id. 90class X86ManagedRegister : public ManagedRegister { 91 public: 92 constexpr ByteRegister AsByteRegister() const { 93 CHECK(IsCpuRegister()); 94 CHECK_LT(AsCpuRegister(), ESP); // ESP, EBP, ESI and EDI cannot be encoded as byte registers. 95 return static_cast<ByteRegister>(id_); 96 } 97 98 constexpr Register AsCpuRegister() const { 99 CHECK(IsCpuRegister()); 100 return static_cast<Register>(id_); 101 } 102 103 constexpr XmmRegister AsXmmRegister() const { 104 CHECK(IsXmmRegister()); 105 return static_cast<XmmRegister>(id_ - kNumberOfCpuRegIds); 106 } 107 108 constexpr X87Register AsX87Register() const { 109 CHECK(IsX87Register()); 110 return static_cast<X87Register>(id_ - 111 (kNumberOfCpuRegIds + kNumberOfXmmRegIds)); 112 } 113 114 constexpr Register AsRegisterPairLow() const { 115 CHECK(IsRegisterPair()); 116 // Appropriate mapping of register ids allows to use AllocIdLow(). 117 return FromRegId(AllocIdLow()).AsCpuRegister(); 118 } 119 120 constexpr Register AsRegisterPairHigh() const { 121 CHECK(IsRegisterPair()); 122 // Appropriate mapping of register ids allows to use AllocIdHigh(). 123 return FromRegId(AllocIdHigh()).AsCpuRegister(); 124 } 125 126 constexpr RegisterPair AsRegisterPair() const { 127 CHECK(IsRegisterPair()); 128 return static_cast<RegisterPair>(id_ - 129 (kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds)); 130 } 131 132 constexpr bool IsCpuRegister() const { 133 CHECK(IsValidManagedRegister()); 134 return (0 <= id_) && (id_ < kNumberOfCpuRegIds); 135 } 136 137 constexpr bool IsXmmRegister() const { 138 CHECK(IsValidManagedRegister()); 139 const int test = id_ - kNumberOfCpuRegIds; 140 return (0 <= test) && (test < kNumberOfXmmRegIds); 141 } 142 143 constexpr bool IsX87Register() const { 144 CHECK(IsValidManagedRegister()); 145 const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds); 146 return (0 <= test) && (test < kNumberOfX87RegIds); 147 } 148 149 constexpr bool IsRegisterPair() const { 150 CHECK(IsValidManagedRegister()); 151 const int test = id_ - 152 (kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds); 153 return (0 <= test) && (test < kNumberOfPairRegIds); 154 } 155 156 void Print(std::ostream& os) const; 157 158 // Returns true if the two managed-registers ('this' and 'other') overlap. 159 // Either managed-register may be the NoRegister. If both are the NoRegister 160 // then false is returned. 161 bool Overlaps(const X86ManagedRegister& other) const; 162 163 static constexpr X86ManagedRegister FromCpuRegister(Register r) { 164 CHECK_NE(r, kNoRegister); 165 return FromRegId(r); 166 } 167 168 static constexpr X86ManagedRegister FromXmmRegister(XmmRegister r) { 169 CHECK_NE(r, kNoXmmRegister); 170 return FromRegId(r + kNumberOfCpuRegIds); 171 } 172 173 static constexpr X86ManagedRegister FromX87Register(X87Register r) { 174 CHECK_NE(r, kNoX87Register); 175 return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds); 176 } 177 178 static constexpr X86ManagedRegister FromRegisterPair(RegisterPair r) { 179 CHECK_NE(r, kNoRegisterPair); 180 return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds + 181 kNumberOfX87RegIds)); 182 } 183 184 private: 185 constexpr bool IsValidManagedRegister() const { 186 return (0 <= id_) && (id_ < kNumberOfRegIds); 187 } 188 189 constexpr int RegId() const { 190 CHECK(!IsNoRegister()); 191 return id_; 192 } 193 194 int AllocId() const { 195 CHECK(IsValidManagedRegister() && !IsRegisterPair()); 196 CHECK_LT(id_, kNumberOfAllocIds); 197 return id_; 198 } 199 200 int AllocIdLow() const; 201 int AllocIdHigh() const; 202 203 friend class ManagedRegister; 204 205 explicit constexpr X86ManagedRegister(int reg_id) : ManagedRegister(reg_id) {} 206 207 static constexpr X86ManagedRegister FromRegId(int reg_id) { 208 X86ManagedRegister reg(reg_id); 209 CHECK(reg.IsValidManagedRegister()); 210 return reg; 211 } 212}; 213 214std::ostream& operator<<(std::ostream& os, const X86ManagedRegister& reg); 215 216} // namespace x86 217 218constexpr inline x86::X86ManagedRegister ManagedRegister::AsX86() const { 219 x86::X86ManagedRegister reg(id_); 220 CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister()); 221 return reg; 222} 223 224} // namespace art 225 226#endif // ART_COMPILER_UTILS_X86_MANAGED_REGISTER_X86_H_ 227