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