diff --git a/js/src/jit/JitFrames.cpp b/js/src/jit/JitFrames.cpp index 7011ad84dfc8..ffac8bd51a68 100644 --- a/js/src/jit/JitFrames.cpp +++ b/js/src/jit/JitFrames.cpp @@ -2242,9 +2242,14 @@ MachineState::FromBailout(RegisterDump::GPRArray& regs, RegisterDump::FPUArray& for (unsigned i = 0; i < FloatRegisters::TotalSingle; i++) machine.setRegisterLocation(FloatRegister(i, FloatRegister::Single), (double*)&fbase[i]); #elif defined(JS_CODEGEN_MIPS32) - for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) { - machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Double), &fpregs[i]); - machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Single), &fpregs[i]); + float* fbase = (float*)&fpregs[0]; + for (unsigned i = 0; i < FloatRegisters::TotalDouble; i++) { + machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Double), + &fpregs[i].d); + } + for (unsigned i = 0; i < FloatRegisters::TotalSingle; i++) { + machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Single), + (double*)&fbase[i]); } #elif defined(JS_CODEGEN_MIPS64) for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) { diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index daf69ae0f25a..504976e4f33e 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -1967,7 +1967,7 @@ MacroAssembler::convertValueToFloatingPoint(ValueOperand value, FloatRegister ou jump(&done); bind(&isDouble); - FloatRegister tmp = output.asDouble(); + FloatRegister tmp = output; if (outputType == MIRType::Float32 && hasMultiAlias()) tmp = ScratchDoubleReg; diff --git a/js/src/jit/mips-shared/Architecture-mips-shared.h b/js/src/jit/mips-shared/Architecture-mips-shared.h index 8c41cf23c384..0d5f61e76428 100644 --- a/js/src/jit/mips-shared/Architecture-mips-shared.h +++ b/js/src/jit/mips-shared/Architecture-mips-shared.h @@ -266,7 +266,7 @@ class FloatRegistersMIPSShared f31, invalid_freg }; - typedef uint32_t Code; + typedef FPRegisterID Code; typedef FPRegisterID Encoding; // Content spilled during bailouts. @@ -274,7 +274,7 @@ class FloatRegistersMIPSShared double d; }; - static const char* GetName(Encoding code) { + static const char* GetName(Code code) { static const char * const Names[] = { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", @@ -283,13 +283,9 @@ class FloatRegistersMIPSShared return Names[code]; } - static const Encoding Invalid = invalid_freg; + static const Code Invalid = invalid_freg; -#if defined(JS_CODEGEN_MIPS32) - typedef uint32_t SetType; -#elif defined(JS_CODEGEN_MIPS64) typedef uint64_t SetType; -#endif }; template @@ -302,33 +298,16 @@ class FloatRegisterMIPSShared typedef FloatRegistersMIPSShared::SetType SetType; -#if defined(JS_CODEGEN_MIPS32) static uint32_t SetSize(SetType x) { - static_assert(sizeof(SetType) == 4, "SetType must be 32 bits"); + static_assert(sizeof(SetType) == 8, "SetType must be 64 bits"); return mozilla::CountPopulation32(x); } static uint32_t FirstBit(SetType x) { - static_assert(sizeof(SetType) == 4, "SetType must be 32 bits"); - return mozilla::CountTrailingZeroes32(x); - } - static uint32_t LastBit(SetType x) { - static_assert(sizeof(SetType) == 4, "SetType must be 32 bits"); - return 31 - mozilla::CountLeadingZeroes32(x); - } -#elif defined(JS_CODEGEN_MIPS64) - static uint32_t SetSize(SetType x) { - static_assert(sizeof(SetType) == 8, "SetType must be 64 bits"); - return mozilla::CountPopulation64(x); - } - static uint32_t FirstBit(SetType x) { - static_assert(sizeof(SetType) == 8, "SetType must be 64 bits"); return mozilla::CountTrailingZeroes64(x); } static uint32_t LastBit(SetType x) { - static_assert(sizeof(SetType) == 8, "SetType must be 64 bits"); return 63 - mozilla::CountLeadingZeroes64(x); } -#endif }; namespace mips_private { @@ -349,12 +328,12 @@ hasUnaliasedDouble() { return false; } -// MIPS64 doesn't support it and on MIPS32 we don't allocate odd single fp -// registers thus not exposing multi aliasing to the jit. -// See comments in Arhitecture-mips32.h. +// On MIPS, fn-double aliases both fn-float32 and fn+1-float32, so if you need +// to convert a float32 to a double as a temporary, you need a temporary +// double register. inline bool hasMultiAlias() { - return false; + return true; } } // namespace jit diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.cpp b/js/src/jit/mips-shared/Assembler-mips-shared.cpp index 825c9039e7e4..0f1f02b1bab1 100644 --- a/js/src/jit/mips-shared/Assembler-mips-shared.cpp +++ b/js/src/jit/mips-shared/Assembler-mips-shared.cpp @@ -58,13 +58,6 @@ js::jit::SA(uint32_t value) return value << SAShift; } -uint32_t -js::jit::FS(uint32_t value) -{ - MOZ_ASSERT(value < 32); - return value << FSShift; -} - Register js::jit::toRS(Instruction& i) { @@ -1348,15 +1341,15 @@ AssemblerMIPSShared::as_movd(FloatRegister fd, FloatRegister fs) BufferOffset AssemblerMIPSShared::as_ctc1(Register rt, FPControl fc) { - spew("ctc1 %3s,%d", rt.name(), fc); - return writeInst(InstReg(op_cop1, rs_ctc1, rt, (uint32_t)fc).encode()); + spew("ctc1 %3s,%3s", rt.name(), FloatRegister(fc).name()); + return writeInst(InstReg(op_cop1, rs_ctc1, rt, FloatRegister(fc)).encode()); } BufferOffset AssemblerMIPSShared::as_cfc1(Register rt, FPControl fc) { - spew("cfc1 %3s,%d", rt.name(), fc); - return writeInst(InstReg(op_cop1, rs_cfc1, rt, (uint32_t)fc).encode()); + spew("cfc1 %3s,%3s", rt.name(), FloatRegister(fc).name()); + return writeInst(InstReg(op_cop1, rs_cfc1, rt, FloatRegister(fc)).encode()); } BufferOffset diff --git a/js/src/jit/mips-shared/Assembler-mips-shared.h b/js/src/jit/mips-shared/Assembler-mips-shared.h index 283e71ae63f7..cc4614f9f404 100644 --- a/js/src/jit/mips-shared/Assembler-mips-shared.h +++ b/js/src/jit/mips-shared/Assembler-mips-shared.h @@ -219,14 +219,15 @@ class InstJump; uint32_t RS(Register r); uint32_t RT(Register r); +uint32_t RT(uint32_t regCode); uint32_t RT(FloatRegister r); uint32_t RD(Register r); uint32_t RD(FloatRegister r); +uint32_t RD(uint32_t regCode); uint32_t RZ(Register r); uint32_t RZ(FloatRegister r); uint32_t SA(uint32_t value); uint32_t SA(FloatRegister r); -uint32_t FS(uint32_t value); Register toRS (Instruction& i); Register toRT (Instruction& i); @@ -1421,9 +1422,6 @@ class InstReg : public Instruction : Instruction(op | code | ff) { } // for float point - InstReg(Opcode op, RSField rs, Register rt, uint32_t fs) - : Instruction(op | rs | RT(rt) | FS(fs)) - { } InstReg(Opcode op, RSField rs, Register rt, FloatRegister rd) : Instruction(op | rs | RT(rt) | RD(rd)) { } diff --git a/js/src/jit/mips32/Architecture-mips32.cpp b/js/src/jit/mips32/Architecture-mips32.cpp index 049143dc73a2..9aca3f831b49 100644 --- a/js/src/jit/mips32/Architecture-mips32.cpp +++ b/js/src/jit/mips32/Architecture-mips32.cpp @@ -28,33 +28,38 @@ const Registers::SetType Registers::CallMask = (1 << Registers::v0) | (1 << Registers::v1); // used for double-size returns -FloatRegisters::Encoding +FloatRegisters::Code FloatRegisters::FromName(const char* name) { - for (size_t i = 0; i < RegisterIdLimit; i++) { + for (size_t i = 0; i < Total; i++) { if (strcmp(GetName(i), name) == 0) - return Encoding(i); + return Code(i); } return Invalid; } FloatRegister -FloatRegister::doubleOverlay() const +FloatRegister::doubleOverlay(unsigned int which) const { - MOZ_ASSERT(isNotOdd()); - if (isSingle()) - return FloatRegister(code_, Double); + MOZ_ASSERT(!isInvalid()); + if (kind_ != Double) + return FloatRegister(code_ & ~1, Double); return *this; } FloatRegister -FloatRegister::singleOverlay() const +FloatRegister::singleOverlay(unsigned int which) const { - MOZ_ASSERT(isNotOdd()); - if (isDouble()) - return FloatRegister(code_, Single); - return *this; + MOZ_ASSERT(!isInvalid()); + if (kind_ == Double) { + // Only even registers are double + MOZ_ASSERT(code_ % 2 == 0); + MOZ_ASSERT(which < 2); + return FloatRegister(code_ + which, Single); + } + MOZ_ASSERT(which == 0); + return FloatRegister(code_, Single); } FloatRegisterSet @@ -62,8 +67,12 @@ FloatRegister::ReduceSetForPush(const FloatRegisterSet& s) { LiveFloatRegisterSet mod; for (FloatRegisterIterator iter(s); iter.more(); ++iter) { - // Even for single size registers save complete double register. - mod.addUnchecked((*iter).doubleOverlay()); + if ((*iter).isSingle()) { + // Even for single size registers save complete double register. + mod.addUnchecked((*iter).doubleOverlay()); + } else { + mod.addUnchecked(*iter); + } } return mod.set(); } @@ -74,21 +83,18 @@ FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s) FloatRegisterSet ss = s.reduceSetForPush(); uint64_t bits = ss.bits(); // We are only pushing double registers. - MOZ_ASSERT((bits & 0xFFFF) == 0); - uint32_t ret = mozilla::CountPopulation32(bits) * sizeof(double); - - // Additional space needed by MacroAssembler::PushRegsInMask to ensure - // correct alignment of double values. - if (ret) - ret += sizeof(double); - + MOZ_ASSERT((bits & 0xffffffff) == 0); + uint32_t ret = mozilla::CountPopulation32(bits >> 32) * sizeof(double); return ret; } uint32_t FloatRegister::getRegisterDumpOffsetInBytes() { - MOZ_ASSERT(isNotOdd()); - return id() * sizeof(float); + if (isSingle()) + return id() * sizeof(float); + if (isDouble()) + return id() * sizeof(double); + MOZ_CRASH(); } } // namespace ion diff --git a/js/src/jit/mips32/Architecture-mips32.h b/js/src/jit/mips32/Architecture-mips32.h index 517b63b68fc7..55086a4e31d3 100644 --- a/js/src/jit/mips32/Architecture-mips32.h +++ b/js/src/jit/mips32/Architecture-mips32.h @@ -19,6 +19,7 @@ namespace js { namespace jit { +// Shadow stack space is not required on MIPS. static const uint32_t ShadowStackSpace = 4 * sizeof(uintptr_t); // These offsets are specific to nunboxing, and capture offsets into the @@ -31,66 +32,88 @@ static const int32_t NUNBOX32_PAYLOAD_OFFSET = 0; // For MIPS this is 2 instructions relative call. static const uint32_t BAILOUT_TABLE_ENTRY_SIZE = 2 * sizeof(void*); -// MIPS32 can have two types of floating-point coprocessors modes: -// - FR=0 mode/ 32-bit FPRs - Historical default, there are 32 single +// MIPS32 can have two types of floating-point coprocessors: +// - 32 bit floating-point coprocessor - In this case, there are 32 single // precision registers and pairs of even and odd float registers are used as // double precision registers. Example: f0 (double) is composed of -// f0 and f1 (single). Loongson3A FPU running in this mode doesn't allow -// use of odd registers for single precision arithmetic. -// - FR=1 mode/ 64-bit FPRs - In this case, there are 32 double precision register -// which can also be used as single precision registers. -// More info https://dmz-portal.imgtec.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking - -// Currently we enable 16 even single precision registers which can be also can be used -// as double precision registers. It enables jit code to run even on Loongson3A. -// It does not support FR=1 mode because MacroAssembler threats odd single precision -// registers as high parts of even double precision registers. -#ifdef __mips_fpr -static_assert(__mips_fpr == 32, "MIPS32 jit only supports FR=0 fpu mode."); -#endif +// f0 and f1 (single). +// - 64 bit floating-point coprocessor - In this case, there are 32 double +// precision register which can also be used as single precision registers. +// When using O32 ABI, floating-point coprocessor is 32 bit. +// When using N32 ABI, floating-point coprocessor is 64 bit. class FloatRegisters : public FloatRegistersMIPSShared { public: static const char* GetName(uint32_t i) { - MOZ_ASSERT(i < RegisterIdLimit); - return FloatRegistersMIPSShared::GetName(Encoding(i % 32)); + MOZ_ASSERT(i < Total); + return FloatRegistersMIPSShared::GetName(Code(i % 32)); } - static Encoding FromName(const char* name); + static Code FromName(const char* name); - static const uint32_t Total = 32; + static const uint32_t Total = 64; static const uint32_t TotalDouble = 16; + static const uint32_t RegisterIdLimit = 32; + // Workarounds: On Loongson CPU-s the odd FP registers behave differently + // in fp-32 mode than standard MIPS. +#if defined(_MIPS_ARCH_LOONGSON3A) static const uint32_t TotalSingle = 16; - static const uint32_t Allocatable = 28; - static const SetType AllSingleMask = (1ULL << TotalSingle) - 1; - - static const SetType AllDoubleMask = ((1ULL << TotalDouble) - 1) << TotalSingle; - static const SetType AllMask = AllDoubleMask | AllSingleMask; - + static const SetType AllSingleMask = 0x55555555ULL; +#else + static const uint32_t TotalSingle = 32; + static const uint32_t Allocatable = 42; + static const SetType AllSingleMask = (1ULL << 32) - 1; +#endif // When saving all registers we only need to do is save double registers. static const uint32_t TotalPhys = 16; - static const uint32_t RegisterIdLimit = 32; static_assert(sizeof(SetType) * 8 >= Total, "SetType should be large enough to enumerate all registers."); + static const SetType AllDoubleMask = 0x55555555ULL << 32; + static const SetType AllMask = AllDoubleMask | AllSingleMask; + + static const SetType NonVolatileDoubleMask = + ((1ULL << FloatRegisters::f20) | + (1ULL << FloatRegisters::f22) | + (1ULL << FloatRegisters::f24) | + (1ULL << FloatRegisters::f26) | + (1ULL << FloatRegisters::f28) | + (1ULL << FloatRegisters::f30)) << 32; + + // f20-single and f21-single alias f20-double ... static const SetType NonVolatileMask = - ((SetType(1) << (FloatRegisters::f20 >> 1)) | - (SetType(1) << (FloatRegisters::f22 >> 1)) | - (SetType(1) << (FloatRegisters::f24 >> 1)) | - (SetType(1) << (FloatRegisters::f26 >> 1)) | - (SetType(1) << (FloatRegisters::f28 >> 1)) | - (SetType(1) << (FloatRegisters::f30 >> 1))) * ((1 << TotalSingle) + 1); + NonVolatileDoubleMask | + (1ULL << FloatRegisters::f20) | + (1ULL << FloatRegisters::f21) | + (1ULL << FloatRegisters::f22) | + (1ULL << FloatRegisters::f23) | + (1ULL << FloatRegisters::f24) | + (1ULL << FloatRegisters::f25) | + (1ULL << FloatRegisters::f26) | + (1ULL << FloatRegisters::f27) | + (1ULL << FloatRegisters::f28) | + (1ULL << FloatRegisters::f29) | + (1ULL << FloatRegisters::f30) | + (1ULL << FloatRegisters::f31); static const SetType VolatileMask = AllMask & ~NonVolatileMask; + static const SetType VolatileDoubleMask = AllDoubleMask & ~NonVolatileDoubleMask; static const SetType WrapperMask = VolatileMask; + static const SetType NonAllocatableDoubleMask = + ((1ULL << FloatRegisters::f16) | + (1ULL << FloatRegisters::f18)) << 32; + // f16-single and f17-single alias f16-double ... static const SetType NonAllocatableMask = - ((SetType(1) << (FloatRegisters::f16 >> 1)) | - (SetType(1) << (FloatRegisters::f18 >> 1))) * ((1 << TotalSingle) + 1); + NonAllocatableDoubleMask | + (1ULL << FloatRegisters::f16) | + (1ULL << FloatRegisters::f17) | + (1ULL << FloatRegisters::f18) | + (1ULL << FloatRegisters::f19); // Registers that can be allocated without being saved, generally. static const SetType TempMask = VolatileMask & ~NonAllocatableMask; @@ -110,16 +133,16 @@ class FloatRegister : public FloatRegisterMIPSShared typedef Codes::Code Code; typedef Codes::Encoding Encoding; - Encoding code_ : 6; + uint32_t code_ : 6; protected: RegType kind_ : 1; public: constexpr FloatRegister(uint32_t code, RegType kind = Double) - : code_ (Encoding(code)), kind_(kind) + : code_ (Code(code)), kind_(kind) { } constexpr FloatRegister() - : code_(FloatRegisters::invalid_freg), kind_(Double) + : code_(Code(FloatRegisters::invalid_freg)), kind_(Double) { } bool operator==(const FloatRegister& other) const { @@ -133,43 +156,52 @@ class FloatRegister : public FloatRegisterMIPSShared return code_ == FloatRegisters::invalid_freg; } - bool isNotOdd() const { return !isInvalid() && ((code_ & 1) == 0); } - bool isSingle() const { return kind_ == Single; } bool isDouble() const { return kind_ == Double; } - FloatRegister doubleOverlay() const; - FloatRegister singleOverlay() const; + FloatRegister doubleOverlay(unsigned int which = 0) const; + FloatRegister singleOverlay(unsigned int which = 0) const; + FloatRegister sintOverlay(unsigned int which = 0) const; + FloatRegister uintOverlay(unsigned int which = 0) const; FloatRegister asSingle() const { return singleOverlay(); } FloatRegister asDouble() const { return doubleOverlay(); } FloatRegister asSimd128() const { MOZ_CRASH("NYI"); } Code code() const { - MOZ_ASSERT(isNotOdd()); - return Code((code_ >> 1) | (kind_ << 4)); + MOZ_ASSERT(!isInvalid()); + return Code(code_ | (kind_ << 5)); } Encoding encoding() const { MOZ_ASSERT(!isInvalid()); - return code_; + return Encoding(code_); } uint32_t id() const { - MOZ_ASSERT(!isInvalid()); return code_; } static FloatRegister FromCode(uint32_t i) { - uint32_t code = i & 15; - uint32_t kind = i >> 4; - return FloatRegister(Encoding(code << 1), RegType(kind)); + uint32_t code = i & 31; + uint32_t kind = i >> 5; + return FloatRegister(code, RegType(kind)); } - + // This is similar to FromCode except for double registers on O32. static FloatRegister FromIndex(uint32_t index, RegType kind) { - MOZ_ASSERT(index < 16); - return FloatRegister(Encoding(index << 1), kind); +#if defined(USES_O32_ABI) + // Only even FP registers are avaiable for Loongson on O32. +# if defined(_MIPS_ARCH_LOONGSON3A) + return FloatRegister(index * 2, kind); +# else + if (kind == Double) + return FloatRegister(index * 2, kind); +# endif +#endif + return FloatRegister(index, kind); } bool volatile_() const { - return !!((SetType(1) << code()) & FloatRegisters::VolatileMask); + if (isDouble()) + return !!((1ULL << code_) & FloatRegisters::VolatileMask); + return !!((1ULL << (code_ & ~1)) & FloatRegisters::VolatileMask); } const char* name() const { return FloatRegisters::GetName(code_); @@ -178,49 +210,61 @@ class FloatRegister : public FloatRegisterMIPSShared return other.kind_ != kind_ || code_ != other.code_; } bool aliases(const FloatRegister& other) { - MOZ_ASSERT(isNotOdd()); - return code_ == other.code_; + if (kind_ == other.kind_) + return code_ == other.code_; + return doubleOverlay() == other.doubleOverlay(); } uint32_t numAliased() const { - MOZ_ASSERT(isNotOdd()); + if (isDouble()) { + MOZ_ASSERT((code_ & 1) == 0); + return 3; + } return 2; } void aliased(uint32_t aliasIdx, FloatRegister* ret) { - MOZ_ASSERT(isNotOdd()); - if (aliasIdx == 0) { *ret = *this; return; } - MOZ_ASSERT(aliasIdx == 1); if (isDouble()) { - *ret = singleOverlay(); - } else { - *ret = doubleOverlay(); + MOZ_ASSERT((code_ & 1) == 0); + MOZ_ASSERT(aliasIdx <= 2); + *ret = singleOverlay(aliasIdx - 1); + return; } + MOZ_ASSERT(aliasIdx == 1); + *ret = doubleOverlay(aliasIdx - 1); } uint32_t numAlignedAliased() const { - MOZ_ASSERT(isNotOdd()); - return 2; + if (isDouble()) { + MOZ_ASSERT((code_ & 1) == 0); + return 2; + } + // f1-float32 has 0 other aligned aliases, 1 total. + // f0-float32 has 1 other aligned alias, 2 total. + return 2 - (code_ & 1); } + // | f0-double | + // | f0-float32 | f1-float32 | + // We only push double registers on MIPS. So, if we've stored f0-double + // we also want to f0-float32 is stored there. void alignedAliased(uint32_t aliasIdx, FloatRegister* ret) { - MOZ_ASSERT(isNotOdd()); - + MOZ_ASSERT(isDouble()); + MOZ_ASSERT((code_ & 1) == 0); if (aliasIdx == 0) { *ret = *this; return; } MOZ_ASSERT(aliasIdx == 1); - if (isDouble()) { - *ret = singleOverlay(); - } else { - *ret = doubleOverlay(); - } + *ret = singleOverlay(aliasIdx - 1); } SetType alignedOrDominatedAliasedSet() const { - MOZ_ASSERT(isNotOdd()); - return (SetType(1) << (code_ >> 1)) * ((1 << FloatRegisters::TotalSingle) + 1); + if (isSingle()) + return SetType(1) << code_; + + MOZ_ASSERT(isDouble()); + return SetType(0b11) << code_; } static constexpr RegTypeName DefaultType = RegTypeName::Float64; @@ -262,21 +306,6 @@ FloatRegister::LiveAsIndexableSet(SetType set) return set; } -template <> inline FloatRegister::SetType -FloatRegister::AllocatableAsIndexableSet(SetType set) -{ - // Single registers are not dominating any smaller registers, thus masking - // is enough to convert an allocatable set into a set of register list all - // single register available. - return set & FloatRegisters::AllSingleMask; -} - -template <> inline FloatRegister::SetType -FloatRegister::AllocatableAsIndexableSet(SetType set) -{ - return set & FloatRegisters::AllDoubleMask; -} - // In order to handle functions such as int(*)(int, double) where the first // argument is a general purpose register, and the second argument is a floating // point register, we have to store the double content into 2 general purpose diff --git a/js/src/jit/mips32/Assembler-mips32.h b/js/src/jit/mips32/Assembler-mips32.h index 03cb048bd2ac..43aa97cb6ac0 100644 --- a/js/src/jit/mips32/Assembler-mips32.h +++ b/js/src/jit/mips32/Assembler-mips32.h @@ -157,9 +157,7 @@ class Assembler : public AssemblerMIPSShared // precision registers that make one double register. FloatRegister getOddPair(FloatRegister reg) { MOZ_ASSERT(reg.isDouble()); - MOZ_ASSERT(reg.id() % 2 == 0); - FloatRegister odd(reg.id() | 1, FloatRegister::Single); - return odd; + return reg.singleOverlay(1); } public: diff --git a/js/src/jit/mips32/CodeGenerator-mips32.cpp b/js/src/jit/mips32/CodeGenerator-mips32.cpp index 1b08334a3fc6..f44716154edc 100644 --- a/js/src/jit/mips32/CodeGenerator-mips32.cpp +++ b/js/src/jit/mips32/CodeGenerator-mips32.cpp @@ -826,5 +826,6 @@ CodeGeneratorMIPS::setReturnDoubleRegs(LiveRegisterSet* regs) { MOZ_ASSERT(ReturnFloat32Reg.code_ == ReturnDoubleReg.code_); regs->add(ReturnFloat32Reg); + regs->add(ReturnDoubleReg.singleOverlay(1)); regs->add(ReturnDoubleReg); } \ No newline at end of file diff --git a/js/src/jit/mips32/MacroAssembler-mips32.cpp b/js/src/jit/mips32/MacroAssembler-mips32.cpp index af0b379c9bba..1d4c4ea84c1d 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32.cpp +++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp @@ -751,7 +751,7 @@ MacroAssemblerMIPS::ma_ss(FloatRegister ft, Address address) void MacroAssemblerMIPS::ma_pop(FloatRegister fs) { - ma_ld(fs.doubleOverlay(), Address(StackPointer, 0)); + ma_ld(fs.doubleOverlay(0), Address(StackPointer, 0)); as_addiu(StackPointer, StackPointer, sizeof(double)); } @@ -759,7 +759,7 @@ void MacroAssemblerMIPS::ma_push(FloatRegister fs) { as_addiu(StackPointer, StackPointer, -sizeof(double)); - ma_sd(fs.doubleOverlay(), Address(StackPointer, 0)); + ma_sd(fs.doubleOverlay(0), Address(StackPointer, 0)); } bool @@ -2110,22 +2110,18 @@ MacroAssembler::PushRegsInMask(LiveRegisterSet set) } MOZ_ASSERT(diffG == 0); - if (diffF > 0) { - // Double values have to be aligned. We reserve extra space so that we can - // start writing from the first aligned location. - // We reserve a whole extra double so that the buffer has even size. - ma_and(SecondScratchReg, sp, Imm32(~(ABIStackAlignment - 1))); - reserveStack(diffF); + // Double values have to be aligned. We reserve extra space so that we can + // start writing from the first aligned location. + // We reserve a whole extra double so that the buffer has even size. + ma_and(SecondScratchReg, sp, Imm32(~(ABIStackAlignment - 1))); + reserveStack(diffF + sizeof(double)); - diffF -= sizeof(double); - - for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) { + for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) { + if ((*iter).code() % 2 == 0) as_sd(*iter, SecondScratchReg, -diffF); - diffF -= sizeof(double); - } - - MOZ_ASSERT(diffF == 0); + diffF -= sizeof(double); } + MOZ_ASSERT(diffF == 0); } void @@ -2136,22 +2132,18 @@ MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) const int32_t reservedG = diffG; const int32_t reservedF = diffF; - if (reservedF > 0) { - // Read the buffer form the first aligned location. - ma_addu(SecondScratchReg, sp, Imm32(reservedF)); - ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(ABIStackAlignment - 1))); + // Read the buffer form the first aligned location. + ma_addu(SecondScratchReg, sp, Imm32(reservedF + sizeof(double))); + ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(ABIStackAlignment - 1))); + for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) { + if (!ignore.has(*iter) && ((*iter).code() % 2 == 0)) + // Use assembly l.d because we have alligned the stack. + as_ld(*iter, SecondScratchReg, -diffF); diffF -= sizeof(double); - - LiveFloatRegisterSet fpignore(ignore.fpus().reduceSetForPush()); - for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) { - if (!ignore.has(*iter)) - as_ld(*iter, SecondScratchReg, -diffF); - diffF -= sizeof(double); - } - freeStack(reservedF); - MOZ_ASSERT(diffF == 0); } + freeStack(reservedF + sizeof(double)); + MOZ_ASSERT(diffF == 0); for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); ++iter) { diffG -= sizeof(intptr_t); @@ -2163,13 +2155,14 @@ MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore) } void -MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register scratch) +MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register) { - int32_t diffF = set.fpus().getPushSizeInBytes(); + FloatRegisterSet fpuSet(set.fpus().reduceSetForPush()); + unsigned numFpu = fpuSet.size(); + int32_t diffF = fpuSet.getPushSizeInBytes(); int32_t diffG = set.gprs().size() * sizeof(intptr_t); MOZ_ASSERT(dest.offset >= diffG + diffF); - MOZ_ASSERT(dest.base == StackPointer); for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); ++iter) { diffG -= sizeof(intptr_t); @@ -2178,19 +2171,21 @@ MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register scra } MOZ_ASSERT(diffG == 0); - if (diffF > 0) { - - computeEffectiveAddress(dest, scratch); - ma_and(scratch, scratch, Imm32(~(ABIStackAlignment - 1))); - - diffF -= sizeof(double); - - for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) { - as_sd(*iter, scratch, -diffF); - diffF -= sizeof(double); - } - MOZ_ASSERT(diffF == 0); + for (FloatRegisterBackwardIterator iter(fpuSet); iter.more(); ++iter) { + FloatRegister reg = *iter; + diffF -= reg.size(); + numFpu -= 1; + dest.offset -= reg.size(); + if (reg.isDouble()) + storeDouble(reg, dest); + else if (reg.isSingle()) + storeFloat32(reg, dest); + else + MOZ_CRASH("Unknown register type."); } + MOZ_ASSERT(numFpu == 0); + diffF -= diffF % sizeof(uintptr_t); + MOZ_ASSERT(diffF == 0); } // =============================================================== // ABI function calls. diff --git a/js/src/wasm/WasmStubs.cpp b/js/src/wasm/WasmStubs.cpp index 512aefba660e..50c960000968 100644 --- a/js/src/wasm/WasmStubs.cpp +++ b/js/src/wasm/WasmStubs.cpp @@ -239,7 +239,11 @@ static const LiveRegisterSet NonVolatileRegs = FloatRegisterSet(FloatRegisters::NonVolatileMask)); #endif -#if defined(JS_CODEGEN_NONE) +#if defined(JS_CODEGEN_MIPS32) +static const unsigned NonVolatileRegsPushSize = NonVolatileRegs.gprs().size() * sizeof(intptr_t) + + NonVolatileRegs.fpus().getPushSizeInBytes() + + sizeof(double); +#elif defined(JS_CODEGEN_NONE) static const unsigned NonVolatileRegsPushSize = 0; #else static const unsigned NonVolatileRegsPushSize = NonVolatileRegs.gprs().size() * sizeof(intptr_t) +