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_ARM_MANAGED_REGISTER_ARM_H_ 18 #define ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_ 19 20 #include "base/logging.h" 21 #include "constants_arm.h" 22 #include "debug/dwarf/register.h" 23 #include "utils/managed_register.h" 24 25 namespace art { 26 namespace arm { 27 28 // Values for register pairs. 29 enum RegisterPair { 30 R0_R1 = 0, 31 R2_R3 = 1, 32 R4_R5 = 2, 33 R6_R7 = 3, 34 R1_R2 = 4, // Dalvik style passing 35 kNumberOfRegisterPairs = 5, 36 kNoRegisterPair = -1, 37 }; 38 39 std::ostream& operator<<(std::ostream& os, const RegisterPair& reg); 40 41 const int kNumberOfCoreRegIds = kNumberOfCoreRegisters; 42 const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters; 43 44 const int kNumberOfSRegIds = kNumberOfSRegisters; 45 const int kNumberOfSAllocIds = kNumberOfSRegisters; 46 47 const int kNumberOfDRegIds = kNumberOfDRegisters; 48 const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters; 49 const int kNumberOfDAllocIds = kNumberOfDRegIds - kNumberOfOverlappingDRegIds; 50 51 const int kNumberOfPairRegIds = kNumberOfRegisterPairs; 52 53 const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfSRegIds + 54 kNumberOfDRegIds + kNumberOfPairRegIds; 55 const int kNumberOfAllocIds = 56 kNumberOfCoreAllocIds + kNumberOfSAllocIds + kNumberOfDAllocIds; 57 58 // Register ids map: 59 // [0..R[ core registers (enum Register) 60 // [R..S[ single precision VFP registers (enum SRegister) 61 // [S..D[ double precision VFP registers (enum DRegister) 62 // [D..P[ core register pairs (enum RegisterPair) 63 // where 64 // R = kNumberOfCoreRegIds 65 // S = R + kNumberOfSRegIds 66 // D = S + kNumberOfDRegIds 67 // P = D + kNumberOfRegisterPairs 68 69 // Allocation ids map: 70 // [0..R[ core registers (enum Register) 71 // [R..S[ single precision VFP registers (enum SRegister) 72 // [S..N[ non-overlapping double precision VFP registers (16-31 in enum 73 // DRegister, VFPv3-D32 only) 74 // where 75 // R = kNumberOfCoreAllocIds 76 // S = R + kNumberOfSAllocIds 77 // N = S + kNumberOfDAllocIds 78 79 80 // An instance of class 'ManagedRegister' represents a single ARM register or a 81 // pair of core ARM registers (enum RegisterPair). A single register is either a 82 // core register (enum Register), a VFP single precision register 83 // (enum SRegister), or a VFP double precision register (enum DRegister). 84 // 'ManagedRegister::NoRegister()' returns an invalid ManagedRegister. 85 // There is a one-to-one mapping between ManagedRegister and register id. 86 class ArmManagedRegister : public ManagedRegister { 87 public: 88 Register AsCoreRegister() const { 89 CHECK(IsCoreRegister()); 90 return static_cast<Register>(id_); 91 } 92 93 SRegister AsSRegister() const { 94 CHECK(IsSRegister()); 95 return static_cast<SRegister>(id_ - kNumberOfCoreRegIds); 96 } 97 98 DRegister AsDRegister() const { 99 CHECK(IsDRegister()); 100 return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds); 101 } 102 103 SRegister AsOverlappingDRegisterLow() const { 104 CHECK(IsOverlappingDRegister()); 105 DRegister d_reg = AsDRegister(); 106 return static_cast<SRegister>(d_reg * 2); 107 } 108 109 SRegister AsOverlappingDRegisterHigh() const { 110 CHECK(IsOverlappingDRegister()); 111 DRegister d_reg = AsDRegister(); 112 return static_cast<SRegister>(d_reg * 2 + 1); 113 } 114 115 RegisterPair AsRegisterPair() const { 116 CHECK(IsRegisterPair()); 117 Register reg_low = AsRegisterPairLow(); 118 if (reg_low == R1) { 119 return R1_R2; 120 } else { 121 return static_cast<RegisterPair>(reg_low / 2); 122 } 123 } 124 125 Register AsRegisterPairLow() const { 126 CHECK(IsRegisterPair()); 127 // Appropriate mapping of register ids allows to use AllocIdLow(). 128 return FromRegId(AllocIdLow()).AsCoreRegister(); 129 } 130 131 Register AsRegisterPairHigh() const { 132 CHECK(IsRegisterPair()); 133 // Appropriate mapping of register ids allows to use AllocIdHigh(). 134 return FromRegId(AllocIdHigh()).AsCoreRegister(); 135 } 136 137 bool IsCoreRegister() const { 138 CHECK(IsValidManagedRegister()); 139 return (0 <= id_) && (id_ < kNumberOfCoreRegIds); 140 } 141 142 bool IsSRegister() const { 143 CHECK(IsValidManagedRegister()); 144 const int test = id_ - kNumberOfCoreRegIds; 145 return (0 <= test) && (test < kNumberOfSRegIds); 146 } 147 148 bool IsDRegister() const { 149 CHECK(IsValidManagedRegister()); 150 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds); 151 return (0 <= test) && (test < kNumberOfDRegIds); 152 } 153 154 // Returns true if this DRegister overlaps SRegisters. 155 bool IsOverlappingDRegister() const { 156 CHECK(IsValidManagedRegister()); 157 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds); 158 return (0 <= test) && (test < kNumberOfOverlappingDRegIds); 159 } 160 161 bool IsRegisterPair() const { 162 CHECK(IsValidManagedRegister()); 163 const int test = 164 id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds); 165 return (0 <= test) && (test < kNumberOfPairRegIds); 166 } 167 168 bool IsSameType(ArmManagedRegister test) const { 169 CHECK(IsValidManagedRegister() && test.IsValidManagedRegister()); 170 return 171 (IsCoreRegister() && test.IsCoreRegister()) || 172 (IsSRegister() && test.IsSRegister()) || 173 (IsDRegister() && test.IsDRegister()) || 174 (IsRegisterPair() && test.IsRegisterPair()); 175 } 176 177 178 // Returns true if the two managed-registers ('this' and 'other') overlap. 179 // Either managed-register may be the NoRegister. If both are the NoRegister 180 // then false is returned. 181 bool Overlaps(const ArmManagedRegister& other) const; 182 183 void Print(std::ostream& os) const; 184 185 static ArmManagedRegister FromCoreRegister(Register r) { 186 CHECK_NE(r, kNoRegister); 187 return FromRegId(r); 188 } 189 190 static ArmManagedRegister FromSRegister(SRegister r) { 191 CHECK_NE(r, kNoSRegister); 192 return FromRegId(r + kNumberOfCoreRegIds); 193 } 194 195 static ArmManagedRegister FromDRegister(DRegister r) { 196 CHECK_NE(r, kNoDRegister); 197 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds)); 198 } 199 200 static ArmManagedRegister FromRegisterPair(RegisterPair r) { 201 CHECK_NE(r, kNoRegisterPair); 202 return FromRegId(r + (kNumberOfCoreRegIds + 203 kNumberOfSRegIds + kNumberOfDRegIds)); 204 } 205 206 // Return a RegisterPair consisting of Register r_low and r_low + 1. 207 static ArmManagedRegister FromCoreRegisterPair(Register r_low) { 208 if (r_low != R1) { // not the dalvik special case 209 CHECK_NE(r_low, kNoRegister); 210 CHECK_EQ(0, (r_low % 2)); 211 const int r = r_low / 2; 212 CHECK_LT(r, kNumberOfPairRegIds); 213 return FromRegisterPair(static_cast<RegisterPair>(r)); 214 } else { 215 return FromRegisterPair(R1_R2); 216 } 217 } 218 219 // Return a DRegister overlapping SRegister r_low and r_low + 1. 220 static ArmManagedRegister FromSRegisterPair(SRegister r_low) { 221 CHECK_NE(r_low, kNoSRegister); 222 CHECK_EQ(0, (r_low % 2)); 223 const int r = r_low / 2; 224 CHECK_LT(r, kNumberOfOverlappingDRegIds); 225 return FromDRegister(static_cast<DRegister>(r)); 226 } 227 228 private: 229 bool IsValidManagedRegister() const { 230 return (0 <= id_) && (id_ < kNumberOfRegIds); 231 } 232 233 int RegId() const { 234 CHECK(!IsNoRegister()); 235 return id_; 236 } 237 238 int AllocId() const { 239 CHECK(IsValidManagedRegister() && 240 !IsOverlappingDRegister() && !IsRegisterPair()); 241 int r = id_; 242 if ((kNumberOfDAllocIds > 0) && IsDRegister()) { // VFPv3-D32 only. 243 r -= kNumberOfOverlappingDRegIds; 244 } 245 CHECK_LT(r, kNumberOfAllocIds); 246 return r; 247 } 248 249 int AllocIdLow() const; 250 int AllocIdHigh() const; 251 252 friend class ManagedRegister; 253 254 explicit ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {} 255 256 static ArmManagedRegister FromRegId(int reg_id) { 257 ArmManagedRegister reg(reg_id); 258 CHECK(reg.IsValidManagedRegister()); 259 return reg; 260 } 261 }; 262 263 std::ostream& operator<<(std::ostream& os, const ArmManagedRegister& reg); 264 265 } // namespace arm 266 267 inline arm::ArmManagedRegister ManagedRegister::AsArm() const { 268 arm::ArmManagedRegister reg(id_); 269 CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister()); 270 return reg; 271 } 272 273 } // namespace art 274 275 #endif // ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_ 276