diff --git a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp index 1f31d8199746..c1b40dbebdb1 100644 --- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp +++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp @@ -214,47 +214,13 @@ CodeGeneratorMIPSShared::visitMinMaxD(LMinMaxD* ins) { FloatRegister first = ToFloatRegister(ins->first()); FloatRegister second = ToFloatRegister(ins->second()); - FloatRegister output = ToFloatRegister(ins->output()); - MOZ_ASSERT(first == output); + MOZ_ASSERT(first == ToFloatRegister(ins->output())); - Assembler::DoubleCondition cond = ins->mir()->isMax() - ? Assembler::DoubleLessThanOrEqual - : Assembler::DoubleGreaterThanOrEqual; - Label nan, equal, returnSecond, done; - - // First or second is NaN, result is NaN. - masm.ma_bc1d(first, second, &nan, Assembler::DoubleUnordered, ShortJump); - // Make sure we handle -0 and 0 right. - masm.ma_bc1d(first, second, &equal, Assembler::DoubleEqual, ShortJump); - masm.ma_bc1d(first, second, &returnSecond, cond, ShortJump); - masm.ma_b(&done, ShortJump); - - // Check for zero. - masm.bind(&equal); - masm.loadConstantDouble(0.0, ScratchDoubleReg); - // First wasn't 0 or -0, so just return it. - masm.ma_bc1d(first, ScratchDoubleReg, &done, Assembler::DoubleNotEqualOrUnordered, ShortJump); - - // So now both operands are either -0 or 0. - if (ins->mir()->isMax()) { - // -0 + -0 = -0 and -0 + 0 = 0. - masm.addDouble(second, first); - } else { - masm.negateDouble(first); - masm.subDouble(second, first); - masm.negateDouble(first); - } - masm.ma_b(&done, ShortJump); - - masm.bind(&nan); - masm.loadConstantDouble(GenericNaN(), output); - masm.ma_b(&done, ShortJump); - - masm.bind(&returnSecond); - masm.moveDouble(second, output); - - masm.bind(&done); + if (ins->mir()->isMax()) + masm.maxDouble(second, first, true); + else + masm.minDouble(second, first, true); } void @@ -262,46 +228,13 @@ CodeGeneratorMIPSShared::visitMinMaxF(LMinMaxF* ins) { FloatRegister first = ToFloatRegister(ins->first()); FloatRegister second = ToFloatRegister(ins->second()); - FloatRegister output = ToFloatRegister(ins->output()); - MOZ_ASSERT(first == output); + MOZ_ASSERT(first == ToFloatRegister(ins->output())); - Assembler::DoubleCondition cond = ins->mir()->isMax() - ? Assembler::DoubleLessThanOrEqual - : Assembler::DoubleGreaterThanOrEqual; - Label nan, equal, returnSecond, done; - - // First or second is NaN, result is NaN. - masm.ma_bc1s(first, second, &nan, Assembler::DoubleUnordered, ShortJump); - // Make sure we handle -0 and 0 right. - masm.ma_bc1s(first, second, &equal, Assembler::DoubleEqual, ShortJump); - masm.ma_bc1s(first, second, &returnSecond, cond, ShortJump); - masm.ma_b(&done, ShortJump); - - // Check for zero. - masm.bind(&equal); - masm.loadConstantFloat32(0.0f, ScratchFloat32Reg); - // First wasn't 0 or -0, so just return it. - masm.ma_bc1s(first, ScratchFloat32Reg, &done, Assembler::DoubleNotEqualOrUnordered, ShortJump); - - // So now both operands are either -0 or 0. - if (ins->mir()->isMax()) { - // -0 + -0 = -0 and -0 + 0 = 0. - masm.as_adds(first, first, second); - } else { - masm.as_negs(first, first); - masm.as_subs(first, first, second); - masm.as_negs(first, first); - } - masm.ma_b(&done, ShortJump); - - masm.bind(&nan); - masm.loadConstantFloat32(GenericNaN(), output); - masm.ma_b(&done, ShortJump); - masm.bind(&returnSecond); - masm.as_movs(output, second); - - masm.bind(&done); + if (ins->mir()->isMax()) + masm.maxFloat32(second, first, true); + else + masm.minFloat32(second, first, true); } void diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp index 0b630790f10d..cf11fd4338dc 100644 --- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp +++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp @@ -815,6 +815,96 @@ MacroAssemblerMIPSShared::ma_bc1d(FloatRegister lhs, FloatRegister rhs, Label* l asMasm().branchWithCode(getBranchCode(testKind, fcc), label, jumpKind); } +void +MacroAssemblerMIPSShared::minMaxDouble(FloatRegister srcDest, FloatRegister second, + bool handleNaN, bool isMax) +{ + FloatRegister first = srcDest; + + Assembler::DoubleCondition cond = isMax + ? Assembler::DoubleLessThanOrEqual + : Assembler::DoubleGreaterThanOrEqual; + Label nan, equal, returnSecond, done; + + // First or second is NaN, result is NaN. + ma_bc1d(first, second, &nan, Assembler::DoubleUnordered, ShortJump); + // Make sure we handle -0 and 0 right. + ma_bc1d(first, second, &equal, Assembler::DoubleEqual, ShortJump); + ma_bc1d(first, second, &returnSecond, cond, ShortJump); + ma_b(&done, ShortJump); + + // Check for zero. + bind(&equal); + asMasm().loadConstantDouble(0.0, ScratchDoubleReg); + // First wasn't 0 or -0, so just return it. + ma_bc1d(first, ScratchDoubleReg, &done, Assembler::DoubleNotEqualOrUnordered, ShortJump); + + // So now both operands are either -0 or 0. + if (isMax) { + // -0 + -0 = -0 and -0 + 0 = 0. + as_addd(first, first, second); + } else { + as_negd(first, first); + as_subd(first, first, second); + as_negd(first, first); + } + ma_b(&done, ShortJump); + + bind(&nan); + asMasm().loadConstantDouble(JS::GenericNaN(), srcDest); + ma_b(&done, ShortJump); + + bind(&returnSecond); + as_movd(srcDest, second); + + bind(&done); +} + +void +MacroAssemblerMIPSShared::minMaxFloat32(FloatRegister srcDest, FloatRegister second, + bool handleNaN, bool isMax) +{ + FloatRegister first = srcDest; + + Assembler::DoubleCondition cond = isMax + ? Assembler::DoubleLessThanOrEqual + : Assembler::DoubleGreaterThanOrEqual; + Label nan, equal, returnSecond, done; + + // First or second is NaN, result is NaN. + ma_bc1s(first, second, &nan, Assembler::DoubleUnordered, ShortJump); + // Make sure we handle -0 and 0 right. + ma_bc1s(first, second, &equal, Assembler::DoubleEqual, ShortJump); + ma_bc1s(first, second, &returnSecond, cond, ShortJump); + ma_b(&done, ShortJump); + + // Check for zero. + bind(&equal); + asMasm().loadConstantFloat32(0.0f, ScratchFloat32Reg); + // First wasn't 0 or -0, so just return it. + ma_bc1s(first, ScratchFloat32Reg, &done, Assembler::DoubleNotEqualOrUnordered, ShortJump); + + // So now both operands are either -0 or 0. + if (isMax) { + // -0 + -0 = -0 and -0 + 0 = 0. + as_adds(first, first, second); + } else { + as_negs(first, first); + as_subs(first, first, second); + as_negs(first, first); + } + ma_b(&done, ShortJump); + + bind(&nan); + asMasm().loadConstantFloat32(JS::GenericNaN(), srcDest); + ma_b(&done, ShortJump); + + bind(&returnSecond); + as_movs(srcDest, second); + + bind(&done); +} + void MacroAssemblerMIPSShared::ma_call(ImmPtr dest) { diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h index 278d848430de..4cfd227a0378 100644 --- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h +++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h @@ -190,6 +190,11 @@ class MacroAssemblerMIPSShared : public Assembler as_mfc1(dest, src); } + // Evaluate srcDest = minmax{Float32,Double}(srcDest, other). + // Handle NaN specially if handleNaN is true. + void minMaxDouble(FloatRegister srcDest, FloatRegister other, bool handleNaN, bool isMax); + void minMaxFloat32(FloatRegister srcDest, FloatRegister other, bool handleNaN, bool isMax); + private: void atomicEffectOpMIPSr2(int nbytes, AtomicOp op, const Register& value, const Register& addr, Register flagTemp, Register valueTemp, Register offsetTemp, Register maskTemp);