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