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