1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * vim: set ts=8 sts=4 et sw=4 tw=99: 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 const 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 { 29 public: 30 enum ContentType { 31 Single, 32 Double, 33 NumTypes 34 }; 35 36 static const char* GetName(uint32_t i) { 37 MOZ_ASSERT(i < TotalPhys); 38 return FloatRegistersMIPSShared::GetName(Encoding(i)); 39 } 40 41 static Encoding FromName(const char* name); 42 43 static const uint32_t Total = 32 * NumTypes; 44 static const uint32_t Allocatable = 60; 45 // When saving all registers we only need to do is save double registers. 46 static const uint32_t TotalPhys = 32; 47 48 static_assert(sizeof(SetType) * 8 >= Total, 49 "SetType should be large enough to enumerate all registers."); 50 51 // Magic values which are used to duplicate a mask of physical register for 52 // a specific type of register. A multiplication is used to copy and shift 53 // the bits of the physical register mask. 54 static const SetType SpreadSingle = SetType(1) << (uint32_t(Single) * TotalPhys); 55 static const SetType SpreadDouble = SetType(1) << (uint32_t(Double) * TotalPhys); 56 static const SetType SpreadScalar = SpreadSingle | SpreadDouble; 57 static const SetType SpreadVector = 0; 58 static const SetType Spread = SpreadScalar | SpreadVector; 59 60 static const SetType AllPhysMask = ((SetType(1) << TotalPhys) - 1); 61 static const SetType AllMask = AllPhysMask * Spread; 62 static const SetType AllSingleMask = AllPhysMask * SpreadSingle; 63 static const SetType AllDoubleMask = AllPhysMask * SpreadDouble; 64 65 static const SetType NonVolatileMask = 66 ( (1U << FloatRegisters::f24) | 67 (1U << FloatRegisters::f25) | 68 (1U << FloatRegisters::f26) | 69 (1U << FloatRegisters::f27) | 70 (1U << FloatRegisters::f28) | 71 (1U << FloatRegisters::f29) | 72 (1U << FloatRegisters::f30) | 73 (1U << FloatRegisters::f31) 74 ) * SpreadScalar 75 | AllPhysMask * SpreadVector; 76 77 static const SetType VolatileMask = AllMask & ~NonVolatileMask; 78 79 static const SetType WrapperMask = VolatileMask; 80 81 static const SetType NonAllocatableMask = 82 ( // f21 and f23 are MIPS scratch float registers. 83 (1U << FloatRegisters::f21) | 84 (1U << FloatRegisters::f23) 85 ) * Spread; 86 87 // Registers that can be allocated without being saved, generally. 88 static const SetType TempMask = VolatileMask & ~NonAllocatableMask; 89 90 static const SetType AllocatableMask = AllMask & ~NonAllocatableMask; 91 }; 92 93 template <typename T> 94 class TypedRegisterSet; 95 96 class FloatRegister : public FloatRegisterMIPSShared 97 { 98 public: 99 typedef FloatRegisters Codes; 100 typedef size_t Code; 101 typedef Codes::Encoding Encoding; 102 typedef Codes::ContentType ContentType; 103 104 Encoding reg_: 6; 105 private: 106 ContentType kind_ : 3; 107 108 public: 109 constexpr FloatRegister(uint32_t r, ContentType kind = Codes::Double) 110 : reg_(Encoding(r)), kind_(kind) 111 { } 112 constexpr FloatRegister() 113 : reg_(Encoding(FloatRegisters::invalid_freg)), kind_(Codes::Double) 114 { } 115 116 bool operator==(const FloatRegister& other) const { 117 MOZ_ASSERT(!isInvalid()); 118 MOZ_ASSERT(!other.isInvalid()); 119 return kind_ == other.kind_ && reg_ == other.reg_; 120 } 121 bool equiv(const FloatRegister& other) const { return other.kind_ == kind_; } 122 size_t size() const { return (kind_ == Codes::Double) ? sizeof(double) : sizeof (float); } 123 bool isInvalid() const { 124 return reg_ == FloatRegisters::invalid_freg; 125 } 126 127 bool isSingle() const { return kind_ == Codes::Single; } 128 bool isDouble() const { return kind_ == Codes::Double; } 129 130 FloatRegister singleOverlay() const; 131 FloatRegister doubleOverlay() const; 132 133 FloatRegister asSingle() const { return singleOverlay(); } 134 FloatRegister asDouble() const { return doubleOverlay(); } 135 FloatRegister asSimd128() const { MOZ_CRASH("NYI"); } 136 137 Code code() const { 138 MOZ_ASSERT(!isInvalid()); 139 return Code(reg_ | (kind_ << 5)); 140 } 141 Encoding encoding() const { 142 MOZ_ASSERT(!isInvalid()); 143 MOZ_ASSERT(uint32_t(reg_) < Codes::TotalPhys); 144 return reg_; 145 } 146 uint32_t id() const { 147 return reg_; 148 } 149 static FloatRegister FromCode(uint32_t i) { 150 uint32_t code = i & 0x1f; 151 uint32_t kind = i >> 5; 152 return FloatRegister(Code(code), ContentType(kind)); 153 } 154 155 bool volatile_() const { 156 return !!((1 << reg_) & FloatRegisters::VolatileMask); 157 } 158 const char* name() const { 159 return FloatRegisters::GetName(reg_); 160 } 161 bool operator != (const FloatRegister& other) const { 162 return kind_ != other.kind_ || reg_ != other.reg_; 163 } 164 bool aliases(const FloatRegister& other) { 165 return reg_ == other.reg_; 166 } 167 uint32_t numAliased() const { 168 return 2; 169 } 170 void aliased(uint32_t aliasIdx, FloatRegister* ret) { 171 if (aliasIdx == 0) { 172 *ret = *this; 173 return; 174 } 175 MOZ_ASSERT(aliasIdx == 1); 176 if (isDouble()) 177 *ret = singleOverlay(); 178 else 179 *ret = doubleOverlay(); 180 } 181 uint32_t numAlignedAliased() const { 182 return 2; 183 } 184 void alignedAliased(uint32_t aliasIdx, FloatRegister* ret) { 185 MOZ_ASSERT(isDouble()); 186 if (aliasIdx == 0) { 187 *ret = *this; 188 return; 189 } 190 MOZ_ASSERT(aliasIdx == 1); 191 *ret = singleOverlay(); 192 } 193 194 SetType alignedOrDominatedAliasedSet() const { 195 return Codes::Spread << reg_; 196 } 197 198 static Code FromName(const char* name) { 199 return FloatRegisters::FromName(name); 200 } 201 static TypedRegisterSet<FloatRegister> ReduceSetForPush(const TypedRegisterSet<FloatRegister>& s); 202 static uint32_t GetPushSizeInBytes(const TypedRegisterSet<FloatRegister>& s); 203 uint32_t getRegisterDumpOffsetInBytes(); 204 }; 205 206 } // namespace jit 207 } // namespace js 208 209 #endif /* jit_mips64_Architecture_mips64_h */ 210