diff options
Diffstat (limited to 'js/src/jit/mips64/Architecture-mips64.h')
-rw-r--r-- | js/src/jit/mips64/Architecture-mips64.h | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/js/src/jit/mips64/Architecture-mips64.h b/js/src/jit/mips64/Architecture-mips64.h new file mode 100644 index 0000000000..d3db37ea2c --- /dev/null +++ b/js/src/jit/mips64/Architecture-mips64.h @@ -0,0 +1,233 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_mips64_Architecture_mips64_h +#define jit_mips64_Architecture_mips64_h + +#include "mozilla/MathAlgorithms.h" + +#include <limits.h> +#include <stdint.h> + +#include "jit/mips-shared/Architecture-mips-shared.h" + +#include "js/Utility.h" + +namespace js { +namespace jit { + +// Shadow stack space is not required on MIPS64. +static const uint32_t ShadowStackSpace = 0; + +// MIPS64 have 64 bit floating-point coprocessor. There are 32 double +// precision register which can also be used as single precision registers. +class FloatRegisters : public FloatRegistersMIPSShared { + public: + enum ContentType { Single, Double, NumTypes }; + + static const char* GetName(uint32_t i) { + MOZ_ASSERT(i < TotalPhys); + return FloatRegistersMIPSShared::GetName(Encoding(i)); + } + + static Encoding FromName(const char* name); + + static const uint32_t Total = 32 * NumTypes; +#ifdef MIPSR6 + static const uint32_t Allocatable = 60; +#else + static const uint32_t Allocatable = 62; +#endif + // When saving all registers we only need to do is save double registers. + static const uint32_t TotalPhys = 32; + + static_assert(sizeof(SetType) * 8 >= Total, + "SetType should be large enough to enumerate all registers."); + + // Magic values which are used to duplicate a mask of physical register for + // a specific type of register. A multiplication is used to copy and shift + // the bits of the physical register mask. + static const SetType SpreadSingle = SetType(1) + << (uint32_t(Single) * TotalPhys); + static const SetType SpreadDouble = SetType(1) + << (uint32_t(Double) * TotalPhys); + static const SetType SpreadScalar = SpreadSingle | SpreadDouble; + static const SetType SpreadVector = 0; + static const SetType Spread = SpreadScalar | SpreadVector; + + static const SetType AllPhysMask = ((SetType(1) << TotalPhys) - 1); + static const SetType AllMask = AllPhysMask * Spread; + static const SetType AllSingleMask = AllPhysMask * SpreadSingle; + static const SetType AllDoubleMask = AllPhysMask * SpreadDouble; + + static const SetType NonVolatileMask = + ((1U << FloatRegisters::f24) | (1U << FloatRegisters::f25) | + (1U << FloatRegisters::f26) | (1U << FloatRegisters::f27) | + (1U << FloatRegisters::f28) | (1U << FloatRegisters::f29) | + (1U << FloatRegisters::f30) | (1U << FloatRegisters::f31)) * + SpreadScalar | + AllPhysMask * SpreadVector; + + static const SetType VolatileMask = AllMask & ~NonVolatileMask; + + static const SetType WrapperMask = VolatileMask; + +#ifdef MIPSR6 + static const SetType NonAllocatableMask = + ((1U << FloatRegisters::f23) | (1U << FloatRegisters::f24)) * Spread; +#else + static const SetType NonAllocatableMask = + (1U << FloatRegisters::f23) * Spread; +#endif + + static const SetType AllocatableMask = AllMask & ~NonAllocatableMask; +}; + +template <typename T> +class TypedRegisterSet; + +class FloatRegister : public FloatRegisterMIPSShared { + public: + typedef FloatRegisters Codes; + typedef size_t Code; + typedef Codes::Encoding Encoding; + typedef Codes::ContentType ContentType; + + Encoding reg_ : 6; + + private: + ContentType kind_ : 3; + + public: + constexpr FloatRegister(uint32_t r, ContentType kind = Codes::Double) + : reg_(Encoding(r)), kind_(kind) {} + constexpr FloatRegister() + : reg_(Encoding(FloatRegisters::invalid_freg)), kind_(Codes::Double) {} + + static uint32_t SetSize(SetType x) { + // Count the number of non-aliased registers. + x |= x >> Codes::TotalPhys; + x &= Codes::AllPhysMask; + static_assert(Codes::AllPhysMask <= 0xffffffff, + "We can safely use CountPopulation32"); + return mozilla::CountPopulation32(x); + } + + bool operator==(const FloatRegister& other) const { + MOZ_ASSERT(!isInvalid()); + MOZ_ASSERT(!other.isInvalid()); + return kind_ == other.kind_ && reg_ == other.reg_; + } + bool equiv(const FloatRegister& other) const { return other.kind_ == kind_; } + size_t size() const { + return (kind_ == Codes::Double) ? sizeof(double) : sizeof(float); + } + // Always push doubles to maintain 8-byte stack alignment. + size_t pushSize() const { return sizeof(double); } + bool isInvalid() const { return reg_ == FloatRegisters::invalid_freg; } + + bool isSingle() const { return kind_ == Codes::Single; } + bool isDouble() const { return kind_ == Codes::Double; } + bool isSimd128() const { return false; } + + FloatRegister singleOverlay() const; + FloatRegister doubleOverlay() const; + + FloatRegister asSingle() const { return singleOverlay(); } + FloatRegister asDouble() const { return doubleOverlay(); } + FloatRegister asSimd128() const { MOZ_CRASH("NYI"); } + + Code code() const { + MOZ_ASSERT(!isInvalid()); + return Code(reg_ | (kind_ << 5)); + } + Encoding encoding() const { + MOZ_ASSERT(!isInvalid()); + MOZ_ASSERT(uint32_t(reg_) < Codes::TotalPhys); + return reg_; + } + uint32_t id() const { return reg_; } + static FloatRegister FromCode(uint32_t i) { + uint32_t code = i & 0x1f; + uint32_t kind = i >> 5; + return FloatRegister(Code(code), ContentType(kind)); + } + + bool volatile_() const { + return !!((1 << reg_) & FloatRegisters::VolatileMask); + } + const char* name() const { return FloatRegisters::GetName(reg_); } + bool operator!=(const FloatRegister& other) const { + return kind_ != other.kind_ || reg_ != other.reg_; + } + bool aliases(const FloatRegister& other) { return reg_ == other.reg_; } + uint32_t numAliased() const { return 2; } + FloatRegister aliased(uint32_t aliasIdx) { + if (aliasIdx == 0) { + return *this; + } + MOZ_ASSERT(aliasIdx == 1); + if (isDouble()) { + return singleOverlay(); + } + return doubleOverlay(); + } + uint32_t numAlignedAliased() const { return 2; } + FloatRegister alignedAliased(uint32_t aliasIdx) { + MOZ_ASSERT(isDouble()); + if (aliasIdx == 0) { + return *this; + } + MOZ_ASSERT(aliasIdx == 1); + return singleOverlay(); + } + + SetType alignedOrDominatedAliasedSet() const { return Codes::Spread << reg_; } + + static constexpr RegTypeName DefaultType = RegTypeName::Float64; + + template <RegTypeName = DefaultType> + static SetType LiveAsIndexableSet(SetType s) { + return SetType(0); + } + + template <RegTypeName Name = DefaultType> + static SetType AllocatableAsIndexableSet(SetType s) { + static_assert(Name != RegTypeName::Any, "Allocatable set are not iterable"); + return LiveAsIndexableSet<Name>(s); + } + + static Code FromName(const char* name) { + return FloatRegisters::FromName(name); + } + static TypedRegisterSet<FloatRegister> ReduceSetForPush( + const TypedRegisterSet<FloatRegister>& s); + static uint32_t GetPushSizeInBytes(const TypedRegisterSet<FloatRegister>& s); + uint32_t getRegisterDumpOffsetInBytes(); +}; + +template <> +inline FloatRegister::SetType +FloatRegister::LiveAsIndexableSet<RegTypeName::Float32>(SetType set) { + return set & FloatRegisters::AllSingleMask; +} + +template <> +inline FloatRegister::SetType +FloatRegister::LiveAsIndexableSet<RegTypeName::Float64>(SetType set) { + return set & FloatRegisters::AllDoubleMask; +} + +template <> +inline FloatRegister::SetType +FloatRegister::LiveAsIndexableSet<RegTypeName::Any>(SetType set) { + return set; +} + +} // namespace jit +} // namespace js + +#endif /* jit_mips64_Architecture_mips64_h */ |