1 /* 2 * Copyright (C) 2014 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_ARM64_MANAGED_REGISTER_ARM64_H_ 18 #define ART_COMPILER_UTILS_ARM64_MANAGED_REGISTER_ARM64_H_ 19 20 #include "base/logging.h" 21 #include "constants_arm64.h" 22 #include "utils/managed_register.h" 23 24 namespace art { 25 namespace arm64 { 26 27 const int kNumberOfCoreRegIds = kNumberOfCoreRegisters; 28 const int kNumberOfWRegIds = kNumberOfWRegisters; 29 const int kNumberOfDRegIds = kNumberOfDRegisters; 30 const int kNumberOfSRegIds = kNumberOfSRegisters; 31 32 const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfWRegIds + 33 kNumberOfDRegIds + kNumberOfSRegIds; 34 35 // Register ids map: 36 // [0..X[ core registers 64bit (enum Register) 37 // [X..W[ core registers 32bit (enum WRegister) 38 // [W..D[ double precision VFP registers (enum DRegister) 39 // [D..S[ single precision VFP registers (enum SRegister) 40 // 41 // where: 42 // X = kNumberOfCoreRegIds 43 // W = X + kNumberOfWRegIds 44 // D = W + kNumberOfDRegIds 45 // S = D + kNumberOfSRegIds 46 // 47 // An instance of class 'ManagedRegister' represents a single Arm64 48 // register. A register can be one of the following: 49 // * core register 64bit context (enum Register) 50 // * core register 32bit context (enum WRegister) 51 // * VFP double precision register (enum DRegister) 52 // * VFP single precision register (enum SRegister) 53 // 54 // There is a one to one mapping between ManagedRegister and register id. 55 56 class Arm64ManagedRegister : public ManagedRegister { 57 public: 58 Register AsCoreRegister() const { 59 CHECK(IsCoreRegister()); 60 return static_cast<Register>(id_); 61 } 62 63 WRegister AsWRegister() const { 64 CHECK(IsWRegister()); 65 return static_cast<WRegister>(id_ - kNumberOfCoreRegIds); 66 } 67 68 DRegister AsDRegister() const { 69 CHECK(IsDRegister()); 70 return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfWRegIds); 71 } 72 73 SRegister AsSRegister() const { 74 CHECK(IsSRegister()); 75 return static_cast<SRegister>(id_ - kNumberOfCoreRegIds - kNumberOfWRegIds - 76 kNumberOfDRegIds); 77 } 78 79 WRegister AsOverlappingCoreRegisterLow() const { 80 CHECK(IsValidManagedRegister()); 81 if (IsZeroRegister()) return W31; 82 return static_cast<WRegister>(AsCoreRegister()); 83 } 84 85 // FIXME: Find better naming. 86 Register AsOverlappingWRegisterCore() const { 87 CHECK(IsValidManagedRegister()); 88 return static_cast<Register>(AsWRegister()); 89 } 90 91 SRegister AsOverlappingDRegisterLow() const { 92 CHECK(IsValidManagedRegister()); 93 return static_cast<SRegister>(AsDRegister()); 94 } 95 96 // FIXME: Find better naming. 97 DRegister AsOverlappingSRegisterD() const { 98 CHECK(IsValidManagedRegister()); 99 return static_cast<DRegister>(AsSRegister()); 100 } 101 102 bool IsCoreRegister() const { 103 CHECK(IsValidManagedRegister()); 104 return (0 <= id_) && (id_ < kNumberOfCoreRegIds); 105 } 106 107 bool IsWRegister() const { 108 CHECK(IsValidManagedRegister()); 109 const int test = id_ - kNumberOfCoreRegIds; 110 return (0 <= test) && (test < kNumberOfWRegIds); 111 } 112 113 bool IsDRegister() const { 114 CHECK(IsValidManagedRegister()); 115 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfWRegIds); 116 return (0 <= test) && (test < kNumberOfDRegIds); 117 } 118 119 bool IsSRegister() const { 120 CHECK(IsValidManagedRegister()); 121 const int test = id_ - (kNumberOfCoreRegIds + kNumberOfWRegIds + 122 kNumberOfDRegIds); 123 return (0 <= test) && (test < kNumberOfSRegIds); 124 } 125 126 bool IsGPRegister() const { 127 return IsCoreRegister() || IsWRegister(); 128 } 129 130 bool IsFPRegister() const { 131 return IsDRegister() || IsSRegister(); 132 } 133 134 bool IsSameType(Arm64ManagedRegister test) const { 135 CHECK(IsValidManagedRegister() && test.IsValidManagedRegister()); 136 return 137 (IsCoreRegister() && test.IsCoreRegister()) || 138 (IsWRegister() && test.IsWRegister()) || 139 (IsDRegister() && test.IsDRegister()) || 140 (IsSRegister() && test.IsSRegister()); 141 } 142 143 // Returns true if the two managed-registers ('this' and 'other') overlap. 144 // Either managed-register may be the NoRegister. If both are the NoRegister 145 // then false is returned. 146 bool Overlaps(const Arm64ManagedRegister& other) const; 147 148 void Print(std::ostream& os) const; 149 150 static Arm64ManagedRegister FromCoreRegister(Register r) { 151 CHECK_NE(r, kNoRegister); 152 return FromRegId(r); 153 } 154 155 static Arm64ManagedRegister FromWRegister(WRegister r) { 156 CHECK_NE(r, kNoWRegister); 157 return FromRegId(r + kNumberOfCoreRegIds); 158 } 159 160 static Arm64ManagedRegister FromDRegister(DRegister r) { 161 CHECK_NE(r, kNoDRegister); 162 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfWRegIds)); 163 } 164 165 static Arm64ManagedRegister FromSRegister(SRegister r) { 166 CHECK_NE(r, kNoSRegister); 167 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfWRegIds + 168 kNumberOfDRegIds)); 169 } 170 171 // Returns the X register overlapping W register r. 172 static Arm64ManagedRegister FromWRegisterCore(WRegister r) { 173 CHECK_NE(r, kNoWRegister); 174 return FromRegId(r); 175 } 176 177 // Return the D register overlapping S register r. 178 static Arm64ManagedRegister FromSRegisterD(SRegister r) { 179 CHECK_NE(r, kNoSRegister); 180 return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfWRegIds)); 181 } 182 183 private: 184 bool IsValidManagedRegister() const { 185 return (0 <= id_) && (id_ < kNumberOfRegIds); 186 } 187 188 bool IsStackPointer() const { 189 return IsCoreRegister() && (id_ == SP); 190 } 191 192 bool IsZeroRegister() const { 193 return IsCoreRegister() && (id_ == XZR); 194 } 195 196 int RegId() const { 197 CHECK(!IsNoRegister()); 198 return id_; 199 } 200 201 int RegNo() const; 202 int RegIdLow() const; 203 int RegIdHigh() const; 204 205 friend class ManagedRegister; 206 207 explicit Arm64ManagedRegister(int reg_id) : ManagedRegister(reg_id) {} 208 209 static Arm64ManagedRegister FromRegId(int reg_id) { 210 Arm64ManagedRegister reg(reg_id); 211 CHECK(reg.IsValidManagedRegister()); 212 return reg; 213 } 214 }; 215 216 std::ostream& operator<<(std::ostream& os, const Arm64ManagedRegister& reg); 217 218 } // namespace arm64 219 220 inline arm64::Arm64ManagedRegister ManagedRegister::AsArm64() const { 221 arm64::Arm64ManagedRegister reg(id_); 222 CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister()); 223 return reg; 224 } 225 226 } // namespace art 227 228 #endif // ART_COMPILER_UTILS_ARM64_MANAGED_REGISTER_ARM64_H_ 229