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 "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