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