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