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_MIPS_MANAGED_REGISTER_MIPS_H_ 18 #define ART_COMPILER_UTILS_MIPS_MANAGED_REGISTER_MIPS_H_ 19 20 #include "constants_mips.h" 21 #include "debug/dwarf/register.h" 22 #include "utils/managed_register.h" 23 24 namespace art { 25 namespace mips { 26 27 // Values for register pairs. 28 enum RegisterPair { 29 V0_V1 = 0, 30 A0_A1 = 1, 31 A2_A3 = 2, 32 T0_T1 = 3, 33 T2_T3 = 4, 34 T4_T5 = 5, 35 T6_T7 = 6, 36 S0_S1 = 7, 37 S2_S3 = 8, 38 S4_S5 = 9, 39 S6_S7 = 10, 40 A1_A2 = 11, // Dalvik style passing 41 kNumberOfRegisterPairs = 12, 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 kNumberOfFRegIds = kNumberOfFRegisters; 51 const int kNumberOfFAllocIds = kNumberOfFRegisters; 52 53 const int kNumberOfDRegIds = kNumberOfDRegisters; 54 const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters; 55 const int kNumberOfDAllocIds = kNumberOfDRegisters; 56 57 const int kNumberOfPairRegIds = kNumberOfRegisterPairs; 58 59 const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfFRegIds + 60 kNumberOfDRegIds + kNumberOfPairRegIds; 61 const int kNumberOfAllocIds = 62 kNumberOfCoreAllocIds + kNumberOfFAllocIds + kNumberOfDAllocIds; 63 64 // Register ids map: 65 // [0..R[ core registers (enum Register) 66 // [R..F[ single precision FP registers (enum FRegister) 67 // [F..D[ double precision FP registers (enum DRegister) 68 // [D..P[ core register pairs (enum RegisterPair) 69 // where 70 // R = kNumberOfCoreRegIds 71 // F = R + kNumberOfFRegIds 72 // D = F + kNumberOfDRegIds 73 // P = D + kNumberOfRegisterPairs 74 75 // Allocation ids map: 76 // [0..R[ core registers (enum Register) 77 // [R..F[ single precision FP registers (enum FRegister) 78 // where 79 // R = kNumberOfCoreRegIds 80 // F = R + kNumberOfFRegIds 81 82 83 // An instance of class 'ManagedRegister' represents a single core register (enum 84 // Register), a single precision FP register (enum FRegister), a double precision 85 // FP register (enum DRegister), or a pair of core registers (enum RegisterPair). 86 // 'ManagedRegister::NoRegister()' provides an invalid register. 87 // There is a one-to-one mapping between ManagedRegister and register id. 88 class MipsManagedRegister : public ManagedRegister { 89 public: 90 constexpr Register AsCoreRegister() const { 91 CHECK(IsCoreRegister()); 92 return static_cast<Register>(id_); 93 } 94 95 constexpr FRegister AsFRegister() const { 96 CHECK(IsFRegister()); 97 return static_cast<FRegister>(id_ - kNumberOfCoreRegIds); 98 } 99 100 constexpr DRegister AsDRegister() const { 101 CHECK(IsDRegister()); 102 return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfFRegIds); 103 } 104 105 constexpr FRegister AsOverlappingDRegisterLow() const { 106 CHECK(IsOverlappingDRegister()); 107 DRegister d_reg = AsDRegister(); 108 return static_cast<FRegister>(d_reg * 2); 109 } 110 111 constexpr FRegister AsOverlappingDRegisterHigh() const { 112 CHECK(IsOverlappingDRegister()); 113 DRegister d_reg = AsDRegister(); 114 return static_cast<FRegister>(d_reg * 2 + 1); 115 } 116 117 constexpr Register AsRegisterPairLow() const { 118 CHECK(IsRegisterPair()); 119 // Appropriate mapping of register ids allows to use AllocIdLow(). 120 return FromRegId(AllocIdLow()).AsCoreRegister(); 121 } 122 123 constexpr Register AsRegisterPairHigh() const { 124 CHECK(IsRegisterPair()); 125 // Appropriate mapping of register ids allows to use AllocIdHigh(). 126 return FromRegId(AllocIdHigh()).AsCoreRegister(); 127 } 128 129 constexpr bool IsCoreRegister() const { 130 CHECK(IsValidManagedRegister()); 131 return (0 <= id_) && (id_ < kNumberOfCoreRegIds); 132 } 133 134 constexpr bool IsFRegister() const { 135 CHECK(IsValidManagedRegister()); 136 const int test = id_ - kNumberOfCoreRegIds; 137 return (0 <= test) && (test < kNumberOfFRegIds); 138 } 139 140 constexpr bool IsDRegister() const { 141 CHECK(IsValidManagedRegister()); 142 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds); 143 return (0 <= test) && (test < kNumberOfDRegIds); 144 } 145 146 // Returns true if this DRegister overlaps FRegisters. 147 constexpr bool IsOverlappingDRegister() const { 148 CHECK(IsValidManagedRegister()); 149 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds); 150 return (0 <= test) && (test < kNumberOfOverlappingDRegIds); 151 } 152 153 constexpr bool IsRegisterPair() const { 154 CHECK(IsValidManagedRegister()); 155 const int test = 156 id_ - (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds); 157 return (0 <= test) && (test < kNumberOfPairRegIds); 158 } 159 160 void Print(std::ostream& os) const; 161 162 // Returns true if the two managed-registers ('this' and 'other') overlap. 163 // Either managed-register may be the NoRegister. If both are the NoRegister 164 // then false is returned. 165 bool Overlaps(const MipsManagedRegister& other) const; 166 167 static constexpr MipsManagedRegister FromCoreRegister(Register r) { 168 CHECK_NE(r, kNoRegister); 169 return FromRegId(r); 170 } 171 172 static constexpr MipsManagedRegister FromFRegister(FRegister r) { 173 CHECK_NE(r, kNoFRegister); 174 return FromRegId(r + kNumberOfCoreRegIds); 175 } 176 177 static constexpr MipsManagedRegister FromDRegister(DRegister r) { 178 CHECK_NE(r, kNoDRegister); 179 return FromRegId(r + kNumberOfCoreRegIds + kNumberOfFRegIds); 180 } 181 182 static constexpr MipsManagedRegister FromRegisterPair(RegisterPair r) { 183 CHECK_NE(r, kNoRegisterPair); 184 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfFRegIds + kNumberOfDRegIds)); 185 } 186 187 private: 188 constexpr bool IsValidManagedRegister() const { 189 return (0 <= id_) && (id_ < kNumberOfRegIds); 190 } 191 192 constexpr int RegId() const { 193 CHECK(!IsNoRegister()); 194 return id_; 195 } 196 197 int AllocId() const { 198 CHECK(IsValidManagedRegister() && !IsOverlappingDRegister() && !IsRegisterPair()); 199 CHECK_LT(id_, kNumberOfAllocIds); 200 return id_; 201 } 202 203 int AllocIdLow() const; 204 int AllocIdHigh() const; 205 206 friend class ManagedRegister; 207 208 explicit constexpr MipsManagedRegister(int reg_id) : ManagedRegister(reg_id) {} 209 210 static constexpr MipsManagedRegister FromRegId(int reg_id) { 211 MipsManagedRegister reg(reg_id); 212 CHECK(reg.IsValidManagedRegister()); 213 return reg; 214 } 215 }; 216 217 std::ostream& operator<<(std::ostream& os, const MipsManagedRegister& reg); 218 219 } // namespace mips 220 221 constexpr inline mips::MipsManagedRegister ManagedRegister::AsMips() const { 222 mips::MipsManagedRegister reg(id_); 223 CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister()); 224 return reg; 225 } 226 227 } // namespace art 228 229 #endif // ART_COMPILER_UTILS_MIPS_MANAGED_REGISTER_MIPS_H_ 230