tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Architecture-mips64.h (7667B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef jit_mips64_Architecture_mips64_h
      8 #define jit_mips64_Architecture_mips64_h
      9 
     10 #include "mozilla/MathAlgorithms.h"
     11 
     12 #include <limits.h>
     13 #include <stdint.h>
     14 
     15 #include "jit/mips-shared/Architecture-mips-shared.h"
     16 
     17 #include "js/Utility.h"
     18 
     19 namespace js {
     20 namespace jit {
     21 
     22 // Shadow stack space is not required on MIPS64.
     23 static constexpr uint32_t ShadowStackSpace = 0;
     24 
     25 // MIPS64 have 64 bit floating-point coprocessor. There are 32 double
     26 // precision register which can also be used as single precision registers.
     27 class FloatRegisters : public FloatRegistersMIPSShared {
     28 public:
     29  enum ContentType { Single, Double, NumTypes };
     30 
     31  static const char* GetName(uint32_t i) {
     32    MOZ_ASSERT(i < TotalPhys);
     33    return FloatRegistersMIPSShared::GetName(Encoding(i));
     34  }
     35 
     36  static Encoding FromName(const char* name);
     37 
     38  static const uint32_t Total = 32 * NumTypes;
     39 #ifdef MIPSR6
     40  static const uint32_t Allocatable = 60;
     41 #else
     42  static const uint32_t Allocatable = 62;
     43 #endif
     44  // When saving all registers we only need to do is save double registers.
     45  static const uint32_t TotalPhys = 32;
     46 
     47  static_assert(sizeof(SetType) * 8 >= Total,
     48                "SetType should be large enough to enumerate all registers.");
     49 
     50  // Magic values which are used to duplicate a mask of physical register for
     51  // a specific type of register. A multiplication is used to copy and shift
     52  // the bits of the physical register mask.
     53  static const SetType SpreadSingle = SetType(1)
     54                                      << (uint32_t(Single) * TotalPhys);
     55  static const SetType SpreadDouble = SetType(1)
     56                                      << (uint32_t(Double) * TotalPhys);
     57  static const SetType SpreadScalar = SpreadSingle | SpreadDouble;
     58  static const SetType SpreadVector = 0;
     59  static const SetType Spread = SpreadScalar | SpreadVector;
     60 
     61  static const SetType AllPhysMask = ((SetType(1) << TotalPhys) - 1);
     62  static const SetType AllMask = AllPhysMask * Spread;
     63  static const SetType AllSingleMask = AllPhysMask * SpreadSingle;
     64  static const SetType AllDoubleMask = AllPhysMask * SpreadDouble;
     65 
     66  static const SetType NonVolatileMask =
     67      ((1U << FloatRegisters::f24) | (1U << FloatRegisters::f25) |
     68       (1U << FloatRegisters::f26) | (1U << FloatRegisters::f27) |
     69       (1U << FloatRegisters::f28) | (1U << FloatRegisters::f29) |
     70       (1U << FloatRegisters::f30) | (1U << FloatRegisters::f31)) *
     71          SpreadScalar |
     72      AllPhysMask * SpreadVector;
     73 
     74  static const SetType VolatileMask = AllMask & ~NonVolatileMask;
     75 
     76  static const SetType WrapperMask = VolatileMask;
     77 
     78 #ifdef MIPSR6
     79  static const SetType NonAllocatableMask =
     80      ((1U << FloatRegisters::f23) | (1U << FloatRegisters::f24)) * Spread;
     81 #else
     82  static const SetType NonAllocatableMask =
     83      (1U << FloatRegisters::f23) * Spread;
     84 #endif
     85 
     86  static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
     87 };
     88 
     89 template <typename T>
     90 class TypedRegisterSet;
     91 
     92 class FloatRegister : public FloatRegisterMIPSShared {
     93 public:
     94  typedef FloatRegisters Codes;
     95  typedef size_t Code;
     96  typedef Codes::Encoding Encoding;
     97  typedef Codes::ContentType ContentType;
     98 
     99  Encoding reg_ : 6;
    100 
    101 private:
    102  ContentType kind_ : 3;
    103 
    104 public:
    105  constexpr explicit FloatRegister(uint32_t r, ContentType kind = Codes::Double)
    106      : reg_(Encoding(r)), kind_(kind) {}
    107  constexpr FloatRegister()
    108      : reg_(Encoding(FloatRegisters::invalid_freg)), kind_(Codes::Double) {}
    109 
    110  static uint32_t SetSize(SetType x) {
    111    // Count the number of non-aliased registers.
    112    x |= x >> Codes::TotalPhys;
    113    x &= Codes::AllPhysMask;
    114    static_assert(Codes::AllPhysMask <= 0xffffffff,
    115                  "We can safely use CountPopulation32");
    116    return mozilla::CountPopulation32(x);
    117  }
    118 
    119  bool operator==(const FloatRegister& other) const {
    120    MOZ_ASSERT(!isInvalid());
    121    MOZ_ASSERT(!other.isInvalid());
    122    return kind_ == other.kind_ && reg_ == other.reg_;
    123  }
    124  bool equiv(const FloatRegister& other) const { return other.kind_ == kind_; }
    125  size_t size() const {
    126    return (kind_ == Codes::Double) ? sizeof(double) : sizeof(float);
    127  }
    128  // Always push doubles to maintain 8-byte stack alignment.
    129  size_t pushSize() const { return sizeof(double); }
    130  bool isInvalid() const { return reg_ == FloatRegisters::invalid_freg; }
    131 
    132  bool isSingle() const { return kind_ == Codes::Single; }
    133  bool isDouble() const { return kind_ == Codes::Double; }
    134  bool isSimd128() const { return false; }
    135 
    136  FloatRegister singleOverlay() const;
    137  FloatRegister doubleOverlay() const;
    138 
    139  FloatRegister asSingle() const { return singleOverlay(); }
    140  FloatRegister asDouble() const { return doubleOverlay(); }
    141  FloatRegister asSimd128() const { MOZ_CRASH("NYI"); }
    142 
    143  Code code() const {
    144    MOZ_ASSERT(!isInvalid());
    145    return Code(reg_ | (kind_ << 5));
    146  }
    147  Encoding encoding() const {
    148    MOZ_ASSERT(!isInvalid());
    149    MOZ_ASSERT(uint32_t(reg_) < Codes::TotalPhys);
    150    return reg_;
    151  }
    152  uint32_t id() const { return reg_; }
    153  static FloatRegister FromCode(uint32_t i) {
    154    uint32_t code = i & 0x1f;
    155    uint32_t kind = i >> 5;
    156    return FloatRegister(Code(code), ContentType(kind));
    157  }
    158 
    159  bool volatile_() const {
    160    return !!((1 << reg_) & FloatRegisters::VolatileMask);
    161  }
    162  const char* name() const { return FloatRegisters::GetName(reg_); }
    163  bool operator!=(const FloatRegister& other) const {
    164    return kind_ != other.kind_ || reg_ != other.reg_;
    165  }
    166  bool aliases(const FloatRegister& other) { return reg_ == other.reg_; }
    167  uint32_t numAliased() const { return 2; }
    168  FloatRegister aliased(uint32_t aliasIdx) {
    169    if (aliasIdx == 0) {
    170      return *this;
    171    }
    172    MOZ_ASSERT(aliasIdx == 1);
    173    if (isDouble()) {
    174      return singleOverlay();
    175    }
    176    return doubleOverlay();
    177  }
    178  uint32_t numAlignedAliased() const { return 2; }
    179  FloatRegister alignedAliased(uint32_t aliasIdx) {
    180    MOZ_ASSERT(isDouble());
    181    if (aliasIdx == 0) {
    182      return *this;
    183    }
    184    MOZ_ASSERT(aliasIdx == 1);
    185    return singleOverlay();
    186  }
    187 
    188  SetType alignedOrDominatedAliasedSet() const { return Codes::Spread << reg_; }
    189 
    190  static constexpr RegTypeName DefaultType = RegTypeName::Float64;
    191 
    192  template <RegTypeName = DefaultType>
    193  static SetType LiveAsIndexableSet(SetType s) {
    194    return SetType(0);
    195  }
    196 
    197  template <RegTypeName Name = DefaultType>
    198  static SetType AllocatableAsIndexableSet(SetType s) {
    199    static_assert(Name != RegTypeName::Any, "Allocatable set are not iterable");
    200    return LiveAsIndexableSet<Name>(s);
    201  }
    202 
    203  static Code FromName(const char* name) {
    204    return FloatRegisters::FromName(name);
    205  }
    206  static TypedRegisterSet<FloatRegister> ReduceSetForPush(
    207      const TypedRegisterSet<FloatRegister>& s);
    208  static uint32_t GetPushSizeInBytes(const TypedRegisterSet<FloatRegister>& s);
    209  uint32_t getRegisterDumpOffsetInBytes();
    210 };
    211 
    212 template <>
    213 inline FloatRegister::SetType
    214 FloatRegister::LiveAsIndexableSet<RegTypeName::Float32>(SetType set) {
    215  return set & FloatRegisters::AllSingleMask;
    216 }
    217 
    218 template <>
    219 inline FloatRegister::SetType
    220 FloatRegister::LiveAsIndexableSet<RegTypeName::Float64>(SetType set) {
    221  return set & FloatRegisters::AllDoubleMask;
    222 }
    223 
    224 template <>
    225 inline FloatRegister::SetType
    226 FloatRegister::LiveAsIndexableSet<RegTypeName::Any>(SetType set) {
    227  return set;
    228 }
    229 
    230 }  // namespace jit
    231 }  // namespace js
    232 
    233 #endif /* jit_mips64_Architecture_mips64_h */