Home | History | Annotate | Download | only in arm
      1 /*
      2  * Copyright (C) 2011 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_ARM_MANAGED_REGISTER_ARM_H_
     18 #define ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_
     19 
     20 #include "base/logging.h"
     21 #include "constants_arm.h"
     22 #include "utils/managed_register.h"
     23 
     24 namespace art {
     25 namespace arm {
     26 
     27 // Values for register pairs.
     28 enum RegisterPair {
     29   R0_R1 = 0,
     30   R2_R3 = 1,
     31   R4_R5 = 2,
     32   R6_R7 = 3,
     33   R1_R2 = 4,  // Dalvik style passing
     34   kNumberOfRegisterPairs = 5,
     35   kNoRegisterPair = -1,
     36 };
     37 
     38 std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
     39 
     40 const int kNumberOfCoreRegIds = kNumberOfCoreRegisters;
     41 const int kNumberOfCoreAllocIds = kNumberOfCoreRegisters;
     42 
     43 const int kNumberOfSRegIds = kNumberOfSRegisters;
     44 const int kNumberOfSAllocIds = kNumberOfSRegisters;
     45 
     46 const int kNumberOfDRegIds = kNumberOfDRegisters;
     47 const int kNumberOfOverlappingDRegIds = kNumberOfOverlappingDRegisters;
     48 const int kNumberOfDAllocIds = kNumberOfDRegIds - kNumberOfOverlappingDRegIds;
     49 
     50 const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
     51 
     52 const int kNumberOfRegIds = kNumberOfCoreRegIds + kNumberOfSRegIds +
     53     kNumberOfDRegIds + kNumberOfPairRegIds;
     54 const int kNumberOfAllocIds =
     55     kNumberOfCoreAllocIds + kNumberOfSAllocIds + kNumberOfDAllocIds;
     56 
     57 // Register ids map:
     58 //   [0..R[  core registers (enum Register)
     59 //   [R..S[  single precision VFP registers (enum SRegister)
     60 //   [S..D[  double precision VFP registers (enum DRegister)
     61 //   [D..P[  core register pairs (enum RegisterPair)
     62 // where
     63 //   R = kNumberOfCoreRegIds
     64 //   S = R + kNumberOfSRegIds
     65 //   D = S + kNumberOfDRegIds
     66 //   P = D + kNumberOfRegisterPairs
     67 
     68 // Allocation ids map:
     69 //   [0..R[  core registers (enum Register)
     70 //   [R..S[  single precision VFP registers (enum SRegister)
     71 //   [S..N[  non-overlapping double precision VFP registers (16-31 in enum
     72 //           DRegister, VFPv3-D32 only)
     73 // where
     74 //   R = kNumberOfCoreAllocIds
     75 //   S = R + kNumberOfSAllocIds
     76 //   N = S + kNumberOfDAllocIds
     77 
     78 
     79 // An instance of class 'ManagedRegister' represents a single ARM register or a
     80 // pair of core ARM registers (enum RegisterPair). A single register is either a
     81 // core register (enum Register), a VFP single precision register
     82 // (enum SRegister), or a VFP double precision register (enum DRegister).
     83 // 'ManagedRegister::NoRegister()' returns an invalid ManagedRegister.
     84 // There is a one-to-one mapping between ManagedRegister and register id.
     85 class ArmManagedRegister : public ManagedRegister {
     86  public:
     87   Register AsCoreRegister() const {
     88     CHECK(IsCoreRegister());
     89     return static_cast<Register>(id_);
     90   }
     91 
     92   SRegister AsSRegister() const {
     93     CHECK(IsSRegister());
     94     return static_cast<SRegister>(id_ - kNumberOfCoreRegIds);
     95   }
     96 
     97   DRegister AsDRegister() const {
     98     CHECK(IsDRegister());
     99     return static_cast<DRegister>(id_ - kNumberOfCoreRegIds - kNumberOfSRegIds);
    100   }
    101 
    102   SRegister AsOverlappingDRegisterLow() const {
    103     CHECK(IsOverlappingDRegister());
    104     DRegister d_reg = AsDRegister();
    105     return static_cast<SRegister>(d_reg * 2);
    106   }
    107 
    108   SRegister AsOverlappingDRegisterHigh() const {
    109     CHECK(IsOverlappingDRegister());
    110     DRegister d_reg = AsDRegister();
    111     return static_cast<SRegister>(d_reg * 2 + 1);
    112   }
    113 
    114   RegisterPair AsRegisterPair() const {
    115     CHECK(IsRegisterPair());
    116     Register reg_low = AsRegisterPairLow();
    117     if (reg_low == R1) {
    118       return R1_R2;
    119     } else {
    120       return static_cast<RegisterPair>(reg_low / 2);
    121     }
    122   }
    123 
    124   Register AsRegisterPairLow() const {
    125     CHECK(IsRegisterPair());
    126     // Appropriate mapping of register ids allows to use AllocIdLow().
    127     return FromRegId(AllocIdLow()).AsCoreRegister();
    128   }
    129 
    130   Register AsRegisterPairHigh() const {
    131     CHECK(IsRegisterPair());
    132     // Appropriate mapping of register ids allows to use AllocIdHigh().
    133     return FromRegId(AllocIdHigh()).AsCoreRegister();
    134   }
    135 
    136   bool IsCoreRegister() const {
    137     CHECK(IsValidManagedRegister());
    138     return (0 <= id_) && (id_ < kNumberOfCoreRegIds);
    139   }
    140 
    141   bool IsSRegister() const {
    142     CHECK(IsValidManagedRegister());
    143     const int test = id_ - kNumberOfCoreRegIds;
    144     return (0 <= test) && (test < kNumberOfSRegIds);
    145   }
    146 
    147   bool IsDRegister() const {
    148     CHECK(IsValidManagedRegister());
    149     const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
    150     return (0 <= test) && (test < kNumberOfDRegIds);
    151   }
    152 
    153   // Returns true if this DRegister overlaps SRegisters.
    154   bool IsOverlappingDRegister() const {
    155     CHECK(IsValidManagedRegister());
    156     const int test = id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds);
    157     return (0 <= test) && (test < kNumberOfOverlappingDRegIds);
    158   }
    159 
    160   bool IsRegisterPair() const {
    161     CHECK(IsValidManagedRegister());
    162     const int test =
    163         id_ - (kNumberOfCoreRegIds + kNumberOfSRegIds + kNumberOfDRegIds);
    164     return (0 <= test) && (test < kNumberOfPairRegIds);
    165   }
    166 
    167   bool IsSameType(ArmManagedRegister test) const {
    168     CHECK(IsValidManagedRegister() && test.IsValidManagedRegister());
    169     return
    170       (IsCoreRegister() && test.IsCoreRegister()) ||
    171       (IsSRegister() && test.IsSRegister()) ||
    172       (IsDRegister() && test.IsDRegister()) ||
    173       (IsRegisterPair() && test.IsRegisterPair());
    174   }
    175 
    176 
    177   // Returns true if the two managed-registers ('this' and 'other') overlap.
    178   // Either managed-register may be the NoRegister. If both are the NoRegister
    179   // then false is returned.
    180   bool Overlaps(const ArmManagedRegister& other) const;
    181 
    182   void Print(std::ostream& os) const;
    183 
    184   static ArmManagedRegister FromCoreRegister(Register r) {
    185     CHECK_NE(r, kNoRegister);
    186     return FromRegId(r);
    187   }
    188 
    189   static ArmManagedRegister FromSRegister(SRegister r) {
    190     CHECK_NE(r, kNoSRegister);
    191     return FromRegId(r + kNumberOfCoreRegIds);
    192   }
    193 
    194   static ArmManagedRegister FromDRegister(DRegister r) {
    195     CHECK_NE(r, kNoDRegister);
    196     return FromRegId(r + (kNumberOfCoreRegIds + kNumberOfSRegIds));
    197   }
    198 
    199   static ArmManagedRegister FromRegisterPair(RegisterPair r) {
    200     CHECK_NE(r, kNoRegisterPair);
    201     return FromRegId(r + (kNumberOfCoreRegIds +
    202                           kNumberOfSRegIds + kNumberOfDRegIds));
    203   }
    204 
    205   // Return a RegisterPair consisting of Register r_low and r_low + 1.
    206   static ArmManagedRegister FromCoreRegisterPair(Register r_low) {
    207     if (r_low != R1) {  // not the dalvik special case
    208       CHECK_NE(r_low, kNoRegister);
    209       CHECK_EQ(0, (r_low % 2));
    210       const int r = r_low / 2;
    211       CHECK_LT(r, kNumberOfPairRegIds);
    212       return FromRegisterPair(static_cast<RegisterPair>(r));
    213     } else {
    214       return FromRegisterPair(R1_R2);
    215     }
    216   }
    217 
    218   // Return a DRegister overlapping SRegister r_low and r_low + 1.
    219   static ArmManagedRegister FromSRegisterPair(SRegister r_low) {
    220     CHECK_NE(r_low, kNoSRegister);
    221     CHECK_EQ(0, (r_low % 2));
    222     const int r = r_low / 2;
    223     CHECK_LT(r, kNumberOfOverlappingDRegIds);
    224     return FromDRegister(static_cast<DRegister>(r));
    225   }
    226 
    227  private:
    228   bool IsValidManagedRegister() const {
    229     return (0 <= id_) && (id_ < kNumberOfRegIds);
    230   }
    231 
    232   int RegId() const {
    233     CHECK(!IsNoRegister());
    234     return id_;
    235   }
    236 
    237   int AllocId() const {
    238     CHECK(IsValidManagedRegister() &&
    239            !IsOverlappingDRegister() && !IsRegisterPair());
    240     int r = id_;
    241     if ((kNumberOfDAllocIds > 0) && IsDRegister()) {  // VFPv3-D32 only.
    242       r -= kNumberOfOverlappingDRegIds;
    243     }
    244     CHECK_LT(r, kNumberOfAllocIds);
    245     return r;
    246   }
    247 
    248   int AllocIdLow() const;
    249   int AllocIdHigh() const;
    250 
    251   friend class ManagedRegister;
    252 
    253   explicit ArmManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
    254 
    255   static ArmManagedRegister FromRegId(int reg_id) {
    256     ArmManagedRegister reg(reg_id);
    257     CHECK(reg.IsValidManagedRegister());
    258     return reg;
    259   }
    260 };
    261 
    262 std::ostream& operator<<(std::ostream& os, const ArmManagedRegister& reg);
    263 
    264 }  // namespace arm
    265 
    266 inline arm::ArmManagedRegister ManagedRegister::AsArm() const {
    267   arm::ArmManagedRegister reg(id_);
    268   CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
    269   return reg;
    270 }
    271 
    272 }  // namespace art
    273 
    274 #endif  // ART_COMPILER_UTILS_ARM_MANAGED_REGISTER_ARM_H_
    275