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