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 "base/logging.h"
     21 #include "constants_arm64.h"
     22 #include "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