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