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