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