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