Home | History | Annotate | Download | only in arm64
      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 
     26 namespace art {
     27 namespace arm64 {
     28 
     29 const int kNumberOfXRegIds = kNumberOfXRegisters;
     30 const int kNumberOfWRegIds = kNumberOfWRegisters;
     31 const int kNumberOfDRegIds = kNumberOfDRegisters;
     32 const int kNumberOfSRegIds = kNumberOfSRegisters;
     33 
     34 const 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 
     58 class 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 
    215 std::ostream& operator<<(std::ostream& os, const Arm64ManagedRegister& reg);
    216 
    217 }  // namespace arm64
    218 
    219 constexpr 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