Home | History | Annotate | Download | only in x86
      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_X86_MANAGED_REGISTER_X86_H_
     18 #define ART_COMPILER_UTILS_X86_MANAGED_REGISTER_X86_H_
     19 
     20 #include "constants_x86.h"
     21 #include "debug/dwarf/register.h"
     22 #include "utils/managed_register.h"
     23 
     24 namespace art {
     25 namespace x86 {
     26 
     27 // Values for register pairs.
     28 // The registers in kReservedCpuRegistersArray in x86.cc are not used in pairs.
     29 // The table kRegisterPairs in x86.cc must be kept in sync with this enum.
     30 enum RegisterPair {
     31   EAX_EDX = 0,
     32   EAX_ECX = 1,
     33   EAX_EBX = 2,
     34   EAX_EDI = 3,
     35   EDX_ECX = 4,
     36   EDX_EBX = 5,
     37   EDX_EDI = 6,
     38   ECX_EBX = 7,
     39   ECX_EDI = 8,
     40   EBX_EDI = 9,
     41   ECX_EDX = 10,  // Dalvik style passing
     42   kNumberOfRegisterPairs = 11,
     43   kNoRegisterPair = -1,
     44 };
     45 
     46 std::ostream& operator<<(std::ostream& os, const RegisterPair& reg);
     47 
     48 const int kNumberOfCpuRegIds = kNumberOfCpuRegisters;
     49 const int kNumberOfCpuAllocIds = kNumberOfCpuRegisters;
     50 
     51 const int kNumberOfXmmRegIds = kNumberOfXmmRegisters;
     52 const int kNumberOfXmmAllocIds = kNumberOfXmmRegisters;
     53 
     54 const int kNumberOfX87RegIds = kNumberOfX87Registers;
     55 const int kNumberOfX87AllocIds = kNumberOfX87Registers;
     56 
     57 const int kNumberOfPairRegIds = kNumberOfRegisterPairs;
     58 
     59 const int kNumberOfRegIds = kNumberOfCpuRegIds + kNumberOfXmmRegIds +
     60     kNumberOfX87RegIds + kNumberOfPairRegIds;
     61 const int kNumberOfAllocIds = kNumberOfCpuAllocIds + kNumberOfXmmAllocIds +
     62     kNumberOfX87RegIds;
     63 
     64 // Register ids map:
     65 //   [0..R[  cpu registers (enum Register)
     66 //   [R..X[  xmm registers (enum XmmRegister)
     67 //   [X..S[  x87 registers (enum X87Register)
     68 //   [S..P[  register pairs (enum RegisterPair)
     69 // where
     70 //   R = kNumberOfCpuRegIds
     71 //   X = R + kNumberOfXmmRegIds
     72 //   S = X + kNumberOfX87RegIds
     73 //   P = X + kNumberOfRegisterPairs
     74 
     75 // Allocation ids map:
     76 //   [0..R[  cpu registers (enum Register)
     77 //   [R..X[  xmm registers (enum XmmRegister)
     78 //   [X..S[  x87 registers (enum X87Register)
     79 // where
     80 //   R = kNumberOfCpuRegIds
     81 //   X = R + kNumberOfXmmRegIds
     82 //   S = X + kNumberOfX87RegIds
     83 
     84 
     85 // An instance of class 'ManagedRegister' represents a single cpu register (enum
     86 // Register), an xmm register (enum XmmRegister), or a pair of cpu registers
     87 // (enum RegisterPair).
     88 // 'ManagedRegister::NoRegister()' provides an invalid register.
     89 // There is a one-to-one mapping between ManagedRegister and register id.
     90 class X86ManagedRegister : public ManagedRegister {
     91  public:
     92   constexpr ByteRegister AsByteRegister() const {
     93     CHECK(IsCpuRegister());
     94     CHECK_LT(AsCpuRegister(), ESP);  // ESP, EBP, ESI and EDI cannot be encoded as byte registers.
     95     return static_cast<ByteRegister>(id_);
     96   }
     97 
     98   constexpr Register AsCpuRegister() const {
     99     CHECK(IsCpuRegister());
    100     return static_cast<Register>(id_);
    101   }
    102 
    103   constexpr XmmRegister AsXmmRegister() const {
    104     CHECK(IsXmmRegister());
    105     return static_cast<XmmRegister>(id_ - kNumberOfCpuRegIds);
    106   }
    107 
    108   constexpr X87Register AsX87Register() const {
    109     CHECK(IsX87Register());
    110     return static_cast<X87Register>(id_ -
    111                                     (kNumberOfCpuRegIds + kNumberOfXmmRegIds));
    112   }
    113 
    114   constexpr Register AsRegisterPairLow() const {
    115     CHECK(IsRegisterPair());
    116     // Appropriate mapping of register ids allows to use AllocIdLow().
    117     return FromRegId(AllocIdLow()).AsCpuRegister();
    118   }
    119 
    120   constexpr Register AsRegisterPairHigh() const {
    121     CHECK(IsRegisterPair());
    122     // Appropriate mapping of register ids allows to use AllocIdHigh().
    123     return FromRegId(AllocIdHigh()).AsCpuRegister();
    124   }
    125 
    126   constexpr RegisterPair AsRegisterPair() const {
    127     CHECK(IsRegisterPair());
    128     return static_cast<RegisterPair>(id_ -
    129         (kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds));
    130   }
    131 
    132   constexpr bool IsCpuRegister() const {
    133     CHECK(IsValidManagedRegister());
    134     return (0 <= id_) && (id_ < kNumberOfCpuRegIds);
    135   }
    136 
    137   constexpr bool IsXmmRegister() const {
    138     CHECK(IsValidManagedRegister());
    139     const int test = id_ - kNumberOfCpuRegIds;
    140     return (0 <= test) && (test < kNumberOfXmmRegIds);
    141   }
    142 
    143   constexpr bool IsX87Register() const {
    144     CHECK(IsValidManagedRegister());
    145     const int test = id_ - (kNumberOfCpuRegIds + kNumberOfXmmRegIds);
    146     return (0 <= test) && (test < kNumberOfX87RegIds);
    147   }
    148 
    149   constexpr bool IsRegisterPair() const {
    150     CHECK(IsValidManagedRegister());
    151     const int test = id_ -
    152         (kNumberOfCpuRegIds + kNumberOfXmmRegIds + kNumberOfX87RegIds);
    153     return (0 <= test) && (test < kNumberOfPairRegIds);
    154   }
    155 
    156   void Print(std::ostream& os) const;
    157 
    158   // Returns true if the two managed-registers ('this' and 'other') overlap.
    159   // Either managed-register may be the NoRegister. If both are the NoRegister
    160   // then false is returned.
    161   bool Overlaps(const X86ManagedRegister& other) const;
    162 
    163   static constexpr X86ManagedRegister FromCpuRegister(Register r) {
    164     CHECK_NE(r, kNoRegister);
    165     return FromRegId(r);
    166   }
    167 
    168   static constexpr X86ManagedRegister FromXmmRegister(XmmRegister r) {
    169     CHECK_NE(r, kNoXmmRegister);
    170     return FromRegId(r + kNumberOfCpuRegIds);
    171   }
    172 
    173   static constexpr X86ManagedRegister FromX87Register(X87Register r) {
    174     CHECK_NE(r, kNoX87Register);
    175     return FromRegId(r + kNumberOfCpuRegIds + kNumberOfXmmRegIds);
    176   }
    177 
    178   static constexpr X86ManagedRegister FromRegisterPair(RegisterPair r) {
    179     CHECK_NE(r, kNoRegisterPair);
    180     return FromRegId(r + (kNumberOfCpuRegIds + kNumberOfXmmRegIds +
    181                           kNumberOfX87RegIds));
    182   }
    183 
    184  private:
    185   constexpr bool IsValidManagedRegister() const {
    186     return (0 <= id_) && (id_ < kNumberOfRegIds);
    187   }
    188 
    189   constexpr int RegId() const {
    190     CHECK(!IsNoRegister());
    191     return id_;
    192   }
    193 
    194   int AllocId() const {
    195     CHECK(IsValidManagedRegister() && !IsRegisterPair());
    196     CHECK_LT(id_, kNumberOfAllocIds);
    197     return id_;
    198   }
    199 
    200   int AllocIdLow() const;
    201   int AllocIdHigh() const;
    202 
    203   friend class ManagedRegister;
    204 
    205   explicit constexpr X86ManagedRegister(int reg_id) : ManagedRegister(reg_id) {}
    206 
    207   static constexpr X86ManagedRegister FromRegId(int reg_id) {
    208     X86ManagedRegister reg(reg_id);
    209     CHECK(reg.IsValidManagedRegister());
    210     return reg;
    211   }
    212 };
    213 
    214 std::ostream& operator<<(std::ostream& os, const X86ManagedRegister& reg);
    215 
    216 }  // namespace x86
    217 
    218 constexpr inline x86::X86ManagedRegister ManagedRegister::AsX86() const {
    219   x86::X86ManagedRegister reg(id_);
    220   CHECK(reg.IsNoRegister() || reg.IsValidManagedRegister());
    221   return reg;
    222 }
    223 
    224 }  // namespace art
    225 
    226 #endif  // ART_COMPILER_UTILS_X86_MANAGED_REGISTER_X86_H_
    227