tor-browser

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

commit b180a2213ed62ad35eb058d0689de6523122267f
parent 196222acb31580987d9be5ad9cc68045ee330b45
Author: André Bargull <andre.bargull@gmail.com>
Date:   Wed, 22 Oct 2025 09:51:57 +0000

Bug 1995387: Change division and remainder MacroAssembler method to be three-operand instructions. r=spidermonkey-reviewers,jandem

Change the flexible div/mod instructions to use three operands, so that callers
don't first need to move the left-hand side operand into the destination register.

Drive-by changes:
- arm32: Avoid two division instructions in `flexibleDivMod32` by inlining `quotient32`.
- x86-shared: Avoid unnecessary `push`/`pop` instructions in `flexible{Quotient,Remainder}32`.
- Some code clean-ups to improve readability.

Differential Revision: https://phabricator.services.mozilla.com/D269278

Diffstat:
Mjs/src/jit/CacheIRCompiler.cpp | 17+++++++----------
Mjs/src/jit/MacroAssembler.cpp | 3+--
Mjs/src/jit/MacroAssembler.h | 59++++++++++++++++++++++++++++++++---------------------------
Mjs/src/jit/arm/MacroAssembler-arm-inl.h | 12++++++------
Mjs/src/jit/arm/MacroAssembler-arm.cpp | 59++++++++++++++++++++++++++++++-----------------------------
Mjs/src/jit/arm64/MacroAssembler-arm64-inl.h | 43++++++++++++++++++-------------------------
Mjs/src/jit/arm64/MacroAssembler-arm64.cpp | 45++++++++++++++++++++++-----------------------
Mjs/src/jit/loong64/MacroAssembler-loong64-inl.h | 24++++++++++++------------
Mjs/src/jit/loong64/MacroAssembler-loong64.cpp | 41++++++++++++++++++++++-------------------
Mjs/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h | 44++++++++++++++++++++------------------------
Mjs/src/jit/mips-shared/MacroAssembler-mips-shared.cpp | 50+++++++++++++++++++++++---------------------------
Mjs/src/jit/mips64/MacroAssembler-mips64-inl.h | 44++++++++++++++++++++------------------------
Mjs/src/jit/mips64/MacroAssembler-mips64.cpp | 8++++----
Mjs/src/jit/riscv64/MacroAssembler-riscv64-inl.h | 24++++++++++++------------
Mjs/src/jit/riscv64/MacroAssembler-riscv64.cpp | 43++++++++++++++++++++++++-------------------
Mjs/src/jit/wasm32/MacroAssembler-wasm32-inl.h | 4++--
Mjs/src/jit/wasm32/MacroAssembler-wasm32.cpp | 13+++++++------
Mjs/src/jit/x64/MacroAssembler-x64.cpp | 38+++++++++++++++++++++-----------------
Mjs/src/jit/x64/MacroAssembler-x64.h | 4++--
Mjs/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h | 8++++----
Mjs/src/jit/x86-shared/MacroAssembler-x86-shared.cpp | 107+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mjs/src/jit/x86/MacroAssembler-x86.cpp | 8++++----
Mjs/src/jsapi-tests/testJitMacroAssembler.cpp | 265+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mjs/src/wasm/WasmBaselineCompile.cpp | 72++++++++----------------------------------------------------------------
24 files changed, 524 insertions(+), 511 deletions(-)

diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp @@ -3433,8 +3433,7 @@ bool CacheIRCompiler::emitInt32DivResult(Int32OperandId lhsId, masm.branchTest32(Assembler::Signed, rhs, rhs, failure->label()); masm.bind(&notZero); - masm.mov(lhs, scratch); - masm.flexibleDivMod32(rhs, scratch, rem, false, liveVolatileRegs()); + masm.flexibleDivMod32(lhs, rhs, scratch, rem, false, liveVolatileRegs()); // A remainder implies a double result. masm.branchTest32(Assembler::NonZero, rem, rem, failure->label()); @@ -3467,8 +3466,7 @@ bool CacheIRCompiler::emitInt32ModResult(Int32OperandId lhsId, masm.branch32(Assembler::Equal, rhs, Imm32(-1), failure->label()); masm.bind(&notOverflow); - masm.mov(lhs, scratch); - masm.flexibleRemainder32(rhs, scratch, false, liveVolatileRegs()); + masm.flexibleRemainder32(lhs, rhs, scratch, false, liveVolatileRegs()); // Modulo takes the sign of the dividend; we can't return negative zero here. Label notZero; @@ -4013,8 +4011,7 @@ bool CacheIRCompiler::emitBigIntPtrDiv(IntPtrOperandId lhsId, LiveRegisterSet volatileRegs(GeneralRegisterSet::Volatile(), liveVolatileFloatRegs()); - masm.movePtr(lhs, output); - masm.flexibleQuotientPtr(rhs, output, false, volatileRegs); + masm.flexibleQuotientPtr(lhs, rhs, output, false, volatileRegs); return true; } @@ -4038,18 +4035,18 @@ bool CacheIRCompiler::emitBigIntPtrMod(IntPtrOperandId lhsId, // Prevent division by 0. masm.branchTestPtr(Assembler::Zero, rhs, rhs, failure->label()); - masm.movePtr(lhs, output); - // Prevent INTPTR_MIN / -1. - Label notOverflow; + Label notOverflow, done; masm.branchPtr(Assembler::NotEqual, lhs, ImmWord(DigitMin), &notOverflow); masm.branchPtr(Assembler::NotEqual, rhs, Imm32(-1), &notOverflow); masm.movePtr(ImmWord(0), output); + masm.jump(&done); masm.bind(&notOverflow); LiveRegisterSet volatileRegs(GeneralRegisterSet::Volatile(), liveVolatileFloatRegs()); - masm.flexibleRemainderPtr(rhs, output, false, volatileRegs); + masm.flexibleRemainderPtr(lhs, rhs, output, false, volatileRegs); + masm.bind(&done); return true; } diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp @@ -1996,8 +1996,7 @@ void MacroAssembler::loadInt32ToStringWithBase( branch32(Assembler::AboveOrEqual, input, scratch1, fail); { // Compute |scratch1 = input / base| and |scratch2 = input % base|. - move32(input, scratch1); - flexibleDivMod32(base, scratch1, scratch2, true, volatileRegs); + flexibleDivMod32(input, base, scratch1, scratch2, true, volatileRegs); // Compute the digits of the divisor and remainder. toChar(scratch1); diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h @@ -1212,41 +1212,46 @@ class MacroAssembler : public MacroAssemblerSpecific { // zero. rhs must not be zero, and the division must not overflow. // // On ARM, the chip must have hardware division instructions. - inline void quotient32(Register rhs, Register srcDest, bool isUnsigned) + inline void quotient32(Register lhs, Register rhs, Register dest, + bool isUnsigned) DEFINED_ON(mips64, arm, arm64, loong64, riscv64, wasm32); - inline void quotient64(Register rhs, Register srcDest, bool isUnsigned) + inline void quotient64(Register lhs, Register rhs, Register dest, + bool isUnsigned) DEFINED_ON(arm64, loong64, mips64, riscv64); - // As above, but srcDest must be eax and tempEdx must be edx. - inline void quotient32(Register rhs, Register srcDest, Register tempEdx, - bool isUnsigned) DEFINED_ON(x86_shared); + // As above, but lhs and dest must be eax and tempEdx must be edx. + inline void quotient32(Register lhs, Register rhs, Register dest, + Register tempEdx, bool isUnsigned) + DEFINED_ON(x86_shared); // Perform an integer division, returning the remainder part. // rhs must not be zero, and the division must not overflow. // // On ARM, the chip must have hardware division instructions. - inline void remainder32(Register rhs, Register srcDest, bool isUnsigned) + inline void remainder32(Register lhs, Register rhs, Register dest, + bool isUnsigned) DEFINED_ON(mips64, arm, arm64, loong64, riscv64, wasm32); - inline void remainder64(Register rhs, Register srcDest, bool isUnsigned) + inline void remainder64(Register lhs, Register rhs, Register dest, + bool isUnsigned) DEFINED_ON(arm64, loong64, mips64, riscv64); - // As above, but srcDest must be eax and tempEdx must be edx. - inline void remainder32(Register rhs, Register srcDest, Register tempEdx, - bool isUnsigned) DEFINED_ON(x86_shared); + // As above, but lhs and dest must be eax and tempEdx must be edx. + inline void remainder32(Register lhs, Register rhs, Register dest, + Register tempEdx, bool isUnsigned) + DEFINED_ON(x86_shared); // Perform an integer division, returning the integer part rounded toward // zero. rhs must not be zero, and the division must not overflow. // // This variant preserves registers, and doesn't require hardware division // instructions on ARM (will call out to a runtime routine). - // - // rhs is preserved, srdDest is clobbered. - void flexibleRemainder32(Register rhs, Register srcDest, bool isUnsigned, - const LiveRegisterSet& volatileLiveRegs) - PER_SHARED_ARCH; - void flexibleRemainderPtr(Register rhs, Register srcDest, bool isUnsigned, + void flexibleRemainder32( + Register lhs, Register rhs, Register dest, bool isUnsigned, + const LiveRegisterSet& volatileLiveRegs) PER_SHARED_ARCH; + void flexibleRemainderPtr(Register lhs, Register rhs, Register dest, + bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) PER_ARCH; // Perform an integer division, returning the integer part rounded toward @@ -1254,25 +1259,25 @@ class MacroAssembler : public MacroAssemblerSpecific { // // This variant preserves registers, and doesn't require hardware division // instructions on ARM (will call out to a runtime routine). - // - // rhs is preserved, srdDest is clobbered. - void flexibleQuotient32(Register rhs, Register srcDest, bool isUnsigned, - const LiveRegisterSet& volatileLiveRegs) - PER_SHARED_ARCH; - void flexibleQuotientPtr(Register rhs, Register srcDest, bool isUnsigned, + void flexibleQuotient32( + Register lhs, Register rhs, Register dest, bool isUnsigned, + const LiveRegisterSet& volatileLiveRegs) PER_SHARED_ARCH; + void flexibleQuotientPtr(Register lhs, Register rhs, Register dest, + bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) PER_ARCH; // Perform an integer division, returning the integer part rounded toward - // zero. rhs must not be zero, and the division must not overflow. The - // remainder is stored into the third argument register here. + // zero in the third argument register. rhs must not be zero, and the division + // must not overflow. The remainder is stored into the fourth argument + // register here. // // This variant preserves registers, and doesn't require hardware division // instructions on ARM (will call out to a runtime routine). // - // rhs is preserved, srdDest and remOutput are clobbered. + // lhs and rhs are preserved, divOutput and remOutput are clobbered. void flexibleDivMod32( - Register rhs, Register srcDest, Register remOutput, bool isUnsigned, - const LiveRegisterSet& volatileLiveRegs) PER_SHARED_ARCH; + Register lhs, Register rhs, Register divOutput, Register remOutput, + bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) PER_SHARED_ARCH; inline void divFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH; inline void divDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH; diff --git a/js/src/jit/arm/MacroAssembler-arm-inl.h b/js/src/jit/arm/MacroAssembler-arm-inl.h @@ -564,25 +564,25 @@ void MacroAssembler::mulDoublePtr(ImmPtr imm, Register temp, mulDouble(scratchDouble, dest); } -void MacroAssembler::quotient32(Register rhs, Register srcDest, +void MacroAssembler::quotient32(Register lhs, Register rhs, Register dest, bool isUnsigned) { MOZ_ASSERT(ARMFlags::HasIDIV()); if (isUnsigned) { - ma_udiv(srcDest, rhs, srcDest); + ma_udiv(lhs, rhs, dest); } else { - ma_sdiv(srcDest, rhs, srcDest); + ma_sdiv(lhs, rhs, dest); } } -void MacroAssembler::remainder32(Register rhs, Register srcDest, +void MacroAssembler::remainder32(Register lhs, Register rhs, Register dest, bool isUnsigned) { MOZ_ASSERT(ARMFlags::HasIDIV()); ScratchRegisterScope scratch(*this); if (isUnsigned) { - ma_umod(srcDest, rhs, srcDest, scratch); + ma_umod(lhs, rhs, dest, scratch); } else { - ma_smod(srcDest, rhs, srcDest, scratch); + ma_smod(lhs, rhs, dest, scratch); } } diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -6004,18 +6004,15 @@ extern MOZ_EXPORT int64_t __aeabi_idivmod(int, int); extern MOZ_EXPORT int64_t __aeabi_uidivmod(int, int); } -inline void EmitRemainderOrQuotient(bool isRemainder, MacroAssembler& masm, - Register rhs, Register lhsOutput, +static void EmitRemainderOrQuotient(bool isRemainder, MacroAssembler& masm, + Register lhs, Register rhs, Register output, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - // Currently this helper can't handle this situation. - MOZ_ASSERT(lhsOutput != rhs); - if (ARMFlags::HasIDIV()) { if (isRemainder) { - masm.remainder32(rhs, lhsOutput, isUnsigned); + masm.remainder32(lhs, rhs, output, isUnsigned); } else { - masm.quotient32(rhs, lhsOutput, isUnsigned); + masm.quotient32(lhs, rhs, output, isUnsigned); } } else { // Ensure that the output registers are saved and restored properly. @@ -6030,7 +6027,7 @@ inline void EmitRemainderOrQuotient(bool isRemainder, MacroAssembler& masm, ScratchRegisterScope scratch(masm); masm.setupUnalignedABICall(scratch); } - masm.passABIArg(lhsOutput); + masm.passABIArg(lhs); masm.passABIArg(rhs); if (isUnsigned) { masm.callWithABI<Fn, __aeabi_uidivmod>( @@ -6040,53 +6037,57 @@ inline void EmitRemainderOrQuotient(bool isRemainder, MacroAssembler& masm, ABIType::Int64, CheckUnsafeCallWithABI::DontCheckOther); } if (isRemainder) { - masm.mov(ReturnRegVal1, lhsOutput); + masm.mov(ReturnRegVal1, output); } else { - masm.mov(ReturnRegVal0, lhsOutput); + masm.mov(ReturnRegVal0, output); } LiveRegisterSet ignore; - ignore.add(lhsOutput); + ignore.add(output); masm.PopRegsInMaskIgnore(liveRegs, ignore); } } void MacroAssembler::flexibleQuotient32( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - EmitRemainderOrQuotient(false, *this, rhs, srcDest, isUnsigned, + EmitRemainderOrQuotient(false, *this, lhs, rhs, dest, isUnsigned, volatileLiveRegs); } void MacroAssembler::flexibleQuotientPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - flexibleQuotient32(rhs, srcDest, isUnsigned, volatileLiveRegs); + flexibleQuotient32(lhs, rhs, dest, isUnsigned, volatileLiveRegs); } void MacroAssembler::flexibleRemainder32( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - EmitRemainderOrQuotient(true, *this, rhs, srcDest, isUnsigned, + EmitRemainderOrQuotient(true, *this, lhs, rhs, dest, isUnsigned, volatileLiveRegs); } void MacroAssembler::flexibleRemainderPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - flexibleRemainder32(rhs, srcDest, isUnsigned, volatileLiveRegs); + flexibleRemainder32(lhs, rhs, dest, isUnsigned, volatileLiveRegs); } -void MacroAssembler::flexibleDivMod32(Register rhs, Register lhsOutput, - Register remOutput, bool isUnsigned, +void MacroAssembler::flexibleDivMod32(Register lhs, Register rhs, + Register divOutput, Register remOutput, + bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - // Currently this helper can't handle this situation. - MOZ_ASSERT(lhsOutput != rhs); + MOZ_ASSERT(lhs != divOutput && lhs != remOutput, "lhs is preserved"); + MOZ_ASSERT(rhs != divOutput && rhs != remOutput, "rhs is preserved"); if (ARMFlags::HasIDIV()) { - mov(lhsOutput, remOutput); - remainder32(rhs, remOutput, isUnsigned); - quotient32(rhs, lhsOutput, isUnsigned); + if (isUnsigned) { + as_udiv(divOutput, lhs, rhs); + } else { + as_sdiv(divOutput, lhs, rhs); + } + as_mls(remOutput, lhs, divOutput, rhs); } else { // Ensure that the output registers are saved and restored properly. LiveRegisterSet liveRegs = volatileLiveRegs; @@ -6100,7 +6101,7 @@ void MacroAssembler::flexibleDivMod32(Register rhs, Register lhsOutput, ScratchRegisterScope scratch(*this); setupUnalignedABICall(scratch); } - passABIArg(lhsOutput); + passABIArg(lhs); passABIArg(rhs); if (isUnsigned) { callWithABI<Fn, __aeabi_uidivmod>(ABIType::Int64, @@ -6109,11 +6110,11 @@ void MacroAssembler::flexibleDivMod32(Register rhs, Register lhsOutput, callWithABI<Fn, __aeabi_idivmod>(ABIType::Int64, CheckUnsafeCallWithABI::DontCheckOther); } - moveRegPair(ReturnRegVal0, ReturnRegVal1, lhsOutput, remOutput); + moveRegPair(ReturnRegVal0, ReturnRegVal1, divOutput, remOutput); LiveRegisterSet ignore; ignore.add(remOutput); - ignore.add(lhsOutput); + ignore.add(divOutput); PopRegsInMaskIgnore(liveRegs, ignore); } } diff --git a/js/src/jit/arm64/MacroAssembler-arm64-inl.h b/js/src/jit/arm64/MacroAssembler-arm64-inl.h @@ -561,62 +561,55 @@ void MacroAssembler::mulDoublePtr(ImmPtr imm, Register temp, fmul(ARMFPRegister(dest, 64), ARMFPRegister(dest, 64), scratchDouble); } -void MacroAssembler::quotient32(Register rhs, Register srcDest, +void MacroAssembler::quotient32(Register lhs, Register rhs, Register dest, bool isUnsigned) { if (isUnsigned) { - Udiv(ARMRegister(srcDest, 32), ARMRegister(srcDest, 32), - ARMRegister(rhs, 32)); + Udiv(ARMRegister(dest, 32), ARMRegister(lhs, 32), ARMRegister(rhs, 32)); } else { - Sdiv(ARMRegister(srcDest, 32), ARMRegister(srcDest, 32), - ARMRegister(rhs, 32)); + Sdiv(ARMRegister(dest, 32), ARMRegister(lhs, 32), ARMRegister(rhs, 32)); } } -void MacroAssembler::quotient64(Register rhs, Register srcDest, +void MacroAssembler::quotient64(Register lhs, Register rhs, Register dest, bool isUnsigned) { if (isUnsigned) { - Udiv(ARMRegister(srcDest, 64), ARMRegister(srcDest, 64), - ARMRegister(rhs, 64)); + Udiv(ARMRegister(dest, 64), ARMRegister(lhs, 64), ARMRegister(rhs, 64)); } else { - Sdiv(ARMRegister(srcDest, 64), ARMRegister(srcDest, 64), - ARMRegister(rhs, 64)); + Sdiv(ARMRegister(dest, 64), ARMRegister(lhs, 64), ARMRegister(rhs, 64)); } } // This does not deal with x % 0 or INT_MIN % -1, the caller needs to filter // those cases when they may occur. -void MacroAssembler::remainder32(Register rhs, Register srcDest, +void MacroAssembler::remainder32(Register lhs, Register rhs, Register dest, bool isUnsigned) { vixl::UseScratchRegisterScope temps(this); ARMRegister scratch = temps.AcquireW(); if (isUnsigned) { - Udiv(scratch, ARMRegister(srcDest, 32), ARMRegister(rhs, 32)); + Udiv(scratch, ARMRegister(lhs, 32), ARMRegister(rhs, 32)); } else { - Sdiv(scratch, ARMRegister(srcDest, 32), ARMRegister(rhs, 32)); + Sdiv(scratch, ARMRegister(lhs, 32), ARMRegister(rhs, 32)); } - // Compute the remainder: srcDest = srcDest - (scratch * rhs). - Msub(/* result= */ ARMRegister(srcDest, 32), scratch, ARMRegister(rhs, 32), - ARMRegister(srcDest, 32)); + // Compute the remainder: dest = lhs - (scratch * rhs). + Msub(/* result= */ ARMRegister(dest, 32), scratch, ARMRegister(rhs, 32), + ARMRegister(lhs, 32)); } -void MacroAssembler::remainder64(Register rhs, Register srcDest, +void MacroAssembler::remainder64(Register lhs, Register rhs, Register dest, bool isUnsigned) { - const ARMRegister dividend64(srcDest, 64); - const ARMRegister divisor64(rhs, 64); - vixl::UseScratchRegisterScope temps(this); ARMRegister scratch64 = temps.AcquireX(); if (isUnsigned) { - Udiv(scratch64, ARMRegister(srcDest, 64), ARMRegister(rhs, 64)); + Udiv(scratch64, ARMRegister(lhs, 64), ARMRegister(rhs, 64)); } else { - Sdiv(scratch64, ARMRegister(srcDest, 64), ARMRegister(rhs, 64)); + Sdiv(scratch64, ARMRegister(lhs, 64), ARMRegister(rhs, 64)); } - // Compute the remainder: srcDest = srcDest - (scratch * rhs). - Msub(/* result= */ ARMRegister(srcDest, 64), scratch64, ARMRegister(rhs, 64), - ARMRegister(srcDest, 64)); + // Compute the remainder: dest = lhs - (scratch64 * rhs). + Msub(/* result= */ ARMRegister(dest, 64), scratch64, ARMRegister(rhs, 64), + ARMRegister(lhs, 64)); } void MacroAssembler::divFloat32(FloatRegister src, FloatRegister dest) { diff --git a/js/src/jit/arm64/MacroAssembler-arm64.cpp b/js/src/jit/arm64/MacroAssembler-arm64.cpp @@ -3274,48 +3274,47 @@ void MacroAssembler::atomicEffectOpJS(Scalar::Type arrayType, void MacroAssembler::atomicPause() { Isb(); } -void MacroAssembler::flexibleQuotient32(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleQuotient32(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - quotient32(rhs, srcDest, isUnsigned); + quotient32(lhs, rhs, dest, isUnsigned); } void MacroAssembler::flexibleQuotientPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - quotient64(rhs, srcDest, isUnsigned); + quotient64(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleRemainder32(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleRemainder32(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - remainder32(rhs, srcDest, isUnsigned); + remainder32(lhs, rhs, dest, isUnsigned); } void MacroAssembler::flexibleRemainderPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - remainder64(rhs, srcDest, isUnsigned); + remainder64(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleDivMod32(Register rhs, Register srcDest, - Register remOutput, bool isUnsigned, - const LiveRegisterSet&) { - vixl::UseScratchRegisterScope temps(this); - ARMRegister src = temps.AcquireW(); - - // Preserve src for remainder computation - Mov(src, ARMRegister(srcDest, 32)); +void MacroAssembler::flexibleDivMod32(Register lhs, Register rhs, + Register divOutput, Register remOutput, + bool isUnsigned, const LiveRegisterSet&) { + MOZ_ASSERT(lhs != divOutput && lhs != remOutput, "lhs is preserved"); + MOZ_ASSERT(rhs != divOutput && rhs != remOutput, "rhs is preserved"); if (isUnsigned) { - Udiv(ARMRegister(srcDest, 32), src, ARMRegister(rhs, 32)); + Udiv(ARMRegister(divOutput, 32), ARMRegister(lhs, 32), + ARMRegister(rhs, 32)); } else { - Sdiv(ARMRegister(srcDest, 32), src, ARMRegister(rhs, 32)); + Sdiv(ARMRegister(divOutput, 32), ARMRegister(lhs, 32), + ARMRegister(rhs, 32)); } - // Compute the remainder: remOutput = src - (srcDest * rhs). - Msub(/* result= */ ARMRegister(remOutput, 32), ARMRegister(srcDest, 32), - ARMRegister(rhs, 32), src); + // Compute the remainder: remOutput = lhs - (divOutput * rhs). + Msub(/* result= */ ARMRegister(remOutput, 32), ARMRegister(divOutput, 32), + ARMRegister(rhs, 32), ARMRegister(lhs, 32)); } CodeOffset MacroAssembler::moveNearAddressWithPatch(Register dest) { diff --git a/js/src/jit/loong64/MacroAssembler-loong64-inl.h b/js/src/jit/loong64/MacroAssembler-loong64-inl.h @@ -593,39 +593,39 @@ void MacroAssembler::inc64(AbsoluteAddress dest) { as_st_d(scratch2, scratch, 0); } -void MacroAssembler::quotient32(Register rhs, Register srcDest, +void MacroAssembler::quotient32(Register lhs, Register rhs, Register dest, bool isUnsigned) { if (isUnsigned) { - as_div_wu(srcDest, srcDest, rhs); + as_div_wu(dest, lhs, rhs); } else { - as_div_w(srcDest, srcDest, rhs); + as_div_w(dest, lhs, rhs); } } -void MacroAssembler::quotient64(Register rhs, Register srcDest, +void MacroAssembler::quotient64(Register lhs, Register rhs, Register dest, bool isUnsigned) { if (isUnsigned) { - as_div_du(srcDest, srcDest, rhs); + as_div_du(dest, lhs, rhs); } else { - as_div_d(srcDest, srcDest, rhs); + as_div_d(dest, lhs, rhs); } } -void MacroAssembler::remainder32(Register rhs, Register srcDest, +void MacroAssembler::remainder32(Register lhs, Register rhs, Register dest, bool isUnsigned) { if (isUnsigned) { - as_mod_wu(srcDest, srcDest, rhs); + as_mod_wu(dest, lhs, rhs); } else { - as_mod_w(srcDest, srcDest, rhs); + as_mod_w(dest, lhs, rhs); } } -void MacroAssembler::remainder64(Register rhs, Register srcDest, +void MacroAssembler::remainder64(Register lhs, Register rhs, Register dest, bool isUnsigned) { if (isUnsigned) { - as_mod_du(srcDest, srcDest, rhs); + as_mod_du(dest, lhs, rhs); } else { - as_mod_d(srcDest, srcDest, rhs); + as_mod_d(dest, lhs, rhs); } } diff --git a/js/src/jit/loong64/MacroAssembler-loong64.cpp b/js/src/jit/loong64/MacroAssembler-loong64.cpp @@ -4600,39 +4600,42 @@ void MacroAssembler::atomicPause() { nop(); } -void MacroAssembler::flexibleQuotient32(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleQuotient32(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - quotient32(rhs, srcDest, isUnsigned); + quotient32(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleQuotientPtr(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleQuotientPtr(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - quotient64(rhs, srcDest, isUnsigned); + quotient64(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleRemainder32(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleRemainder32(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - remainder32(rhs, srcDest, isUnsigned); + remainder32(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleRemainderPtr(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleRemainderPtr(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - remainder64(rhs, srcDest, isUnsigned); + remainder64(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleDivMod32(Register rhs, Register srcDest, - Register remOutput, bool isUnsigned, - const LiveRegisterSet&) { +void MacroAssembler::flexibleDivMod32(Register lhs, Register rhs, + Register divOutput, Register remOutput, + bool isUnsigned, const LiveRegisterSet&) { + MOZ_ASSERT(lhs != divOutput && lhs != remOutput, "lhs is preserved"); + MOZ_ASSERT(rhs != divOutput && rhs != remOutput, "rhs is preserved"); + if (isUnsigned) { - as_mod_wu(remOutput, srcDest, rhs); - as_div_wu(srcDest, srcDest, rhs); + as_div_wu(divOutput, lhs, rhs); + as_mod_wu(remOutput, lhs, rhs); } else { - as_mod_w(remOutput, srcDest, rhs); - as_div_w(srcDest, srcDest, rhs); + as_div_w(divOutput, lhs, rhs); + as_mod_w(remOutput, lhs, rhs); } } diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h b/js/src/jit/mips-shared/MacroAssembler-mips-shared-inl.h @@ -247,43 +247,39 @@ void MacroAssembler::mulDoublePtr(ImmPtr imm, Register temp, mulDouble(ScratchDoubleReg, dest); } -void MacroAssembler::quotient32(Register rhs, Register srcDest, +void MacroAssembler::quotient32(Register lhs, Register rhs, Register dest, bool isUnsigned) { - if (isUnsigned) { #ifdef MIPSR6 - as_divu(srcDest, srcDest, rhs); -#else - as_divu(srcDest, rhs); -#endif + if (isUnsigned) { + as_divu(dest, lhs, rhs); } else { -#ifdef MIPSR6 - as_div(srcDest, srcDest, rhs); + as_div(dest, lhs, rhs); + } #else - as_div(srcDest, rhs); -#endif + if (isUnsigned) { + as_divu(lhs, rhs); + } else { + as_div(lhs, rhs); } -#ifndef MIPSR6 - as_mflo(srcDest); + as_mflo(dest); #endif } -void MacroAssembler::remainder32(Register rhs, Register srcDest, +void MacroAssembler::remainder32(Register lhs, Register rhs, Register dest, bool isUnsigned) { - if (isUnsigned) { #ifdef MIPSR6 - as_modu(srcDest, srcDest, rhs); -#else - as_divu(srcDest, rhs); -#endif + if (isUnsigned) { + as_modu(dest, lhs, rhs); } else { -#ifdef MIPSR6 - as_mod(srcDest, srcDest, rhs); + as_mod(dest, lhs, rhs); + } #else - as_div(srcDest, rhs); -#endif + if (isUnsigned) { + as_divu(lhs, rhs); + } else { + as_div(lhs, rhs); } -#ifndef MIPSR6 - as_mfhi(srcDest); + as_mfhi(dest); #endif } diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp @@ -3105,44 +3105,40 @@ void MacroAssembler::atomicEffectOpJS(Scalar::Type arrayType, void MacroAssembler::atomicPause() { as_sync(); } -void MacroAssembler::flexibleQuotient32(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleQuotient32(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - quotient32(rhs, srcDest, isUnsigned); + quotient32(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleRemainder32(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleRemainder32(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - remainder32(rhs, srcDest, isUnsigned); + remainder32(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleDivMod32(Register rhs, Register srcDest, - Register remOutput, bool isUnsigned, - const LiveRegisterSet&) { - UseScratchRegisterScope temps(*this); - if (isUnsigned) { +void MacroAssembler::flexibleDivMod32(Register lhs, Register rhs, + Register divOutput, Register remOutput, + bool isUnsigned, const LiveRegisterSet&) { + MOZ_ASSERT(lhs != divOutput && lhs != remOutput, "lhs is preserved"); + MOZ_ASSERT(rhs != divOutput && rhs != remOutput, "rhs is preserved"); + #ifdef MIPSR6 - Register scratch = temps.Acquire(); - as_divu(scratch, srcDest, rhs); - as_modu(remOutput, srcDest, rhs); - ma_move(srcDest, scratch); -#else - as_divu(srcDest, rhs); -#endif + if (isUnsigned) { + as_divu(divOutput, lhs, rhs); + as_modu(remOutput, rhs, rhs); } else { -#ifdef MIPSR6 - Register scratch = temps.Acquire(); - as_div(scratch, srcDest, rhs); - as_mod(remOutput, srcDest, rhs); - ma_move(srcDest, scratch); + as_div(divOutput, lhs, rhs); + as_mod(remOutput, lhs, rhs); + } #else - as_div(srcDest, rhs); -#endif + if (isUnsigned) { + as_divu(lhs, rhs); + } else { + as_div(lhs, rhs); } -#ifndef MIPSR6 as_mfhi(remOutput); - as_mflo(srcDest); + as_mflo(divOutput); #endif } diff --git a/js/src/jit/mips64/MacroAssembler-mips64-inl.h b/js/src/jit/mips64/MacroAssembler-mips64-inl.h @@ -361,43 +361,39 @@ void MacroAssembler::inc64(AbsoluteAddress dest) { as_sd(scratch2, scratch, 0); } -void MacroAssembler::quotient64(Register rhs, Register srcDest, +void MacroAssembler::quotient64(Register lhs, Register rhs, Register dest, bool isUnsigned) { - if (isUnsigned) { #ifdef MIPSR6 - as_ddivu(srcDest, srcDest, rhs); -#else - as_ddivu(srcDest, rhs); -#endif + if (isUnsigned) { + as_ddivu(dest, lhs, rhs); } else { -#ifdef MIPSR6 - as_ddiv(srcDest, srcDest, rhs); + as_ddiv(dest, lhs, rhs); + } #else - as_ddiv(srcDest, rhs); -#endif + if (isUnsigned) { + as_ddivu(lhs, rhs); + } else { + as_ddiv(lhs, rhs); } -#ifndef MIPSR6 - as_mflo(srcDest); + as_mflo(dest); #endif } -void MacroAssembler::remainder64(Register rhs, Register srcDest, +void MacroAssembler::remainder64(Register lhs, Register rhs, Register dest, bool isUnsigned) { - if (isUnsigned) { #ifdef MIPSR6 - as_dmodu(srcDest, srcDest, rhs); -#else - as_ddivu(srcDest, rhs); -#endif + if (isUnsigned) { + as_dmodu(dest, lhs, rhs); } else { -#ifdef MIPSR6 - as_dmod(srcDest, srcDest, rhs); + as_dmod(dest, lhs, rhs); + } #else - as_ddiv(srcDest, rhs); -#endif + if (isUnsigned) { + as_ddivu(lhs, rhs); + } else { + as_ddiv(lhs, rhs); } -#ifndef MIPSR6 - as_mfhi(srcDest); + as_mfhi(dest); #endif } diff --git a/js/src/jit/mips64/MacroAssembler-mips64.cpp b/js/src/jit/mips64/MacroAssembler-mips64.cpp @@ -3363,15 +3363,15 @@ void MacroAssembler::convertUInt64ToFloat32(Register64 src_, FloatRegister dest, } void MacroAssembler::flexibleQuotientPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - quotient64(rhs, srcDest, isUnsigned); + quotient64(lhs, rhs, dest, isUnsigned); } void MacroAssembler::flexibleRemainderPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - remainder64(rhs, srcDest, isUnsigned); + remainder64(lhs, rhs, dest, isUnsigned); } void MacroAssembler::wasmMarkCallAsSlow() { mov(ra, ra); } diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64-inl.h b/js/src/jit/riscv64/MacroAssembler-riscv64-inl.h @@ -1922,39 +1922,39 @@ void MacroAssembler::popcnt64(Register64 input, Register64 output, Register tmp) { Popcnt64(output.reg, input.reg, tmp); } -void MacroAssembler::quotient32(Register rhs, Register srcDest, +void MacroAssembler::quotient32(Register lhs, Register rhs, Register dest, bool isUnsigned) { if (isUnsigned) { - ma_divu32(srcDest, srcDest, rhs); + ma_divu32(dest, lhs, rhs); } else { - ma_div32(srcDest, srcDest, rhs); + ma_div32(dest, lhs, rhs); } } -void MacroAssembler::quotient64(Register rhs, Register srcDest, +void MacroAssembler::quotient64(Register lhs, Register rhs, Register dest, bool isUnsigned) { if (isUnsigned) { - ma_divu64(srcDest, srcDest, rhs); + ma_divu64(dest, lhs, rhs); } else { - ma_div64(srcDest, srcDest, rhs); + ma_div64(dest, lhs, rhs); } } -void MacroAssembler::remainder32(Register rhs, Register srcDest, +void MacroAssembler::remainder32(Register lhs, Register rhs, Register dest, bool isUnsigned) { if (isUnsigned) { - ma_modu32(srcDest, srcDest, rhs); + ma_modu32(dest, lhs, rhs); } else { - ma_mod32(srcDest, srcDest, rhs); + ma_mod32(dest, lhs, rhs); } } -void MacroAssembler::remainder64(Register rhs, Register srcDest, +void MacroAssembler::remainder64(Register lhs, Register rhs, Register dest, bool isUnsigned) { if (isUnsigned) { - ma_modu64(srcDest, srcDest, rhs); + ma_modu64(dest, lhs, rhs); } else { - ma_mod64(srcDest, srcDest, rhs); + ma_mod64(dest, lhs, rhs); } } diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64.cpp b/js/src/jit/riscv64/MacroAssembler-riscv64.cpp @@ -3554,39 +3554,44 @@ void MacroAssembler::patchSub32FromMemAndBranchIfNegative(CodeOffset offset, inst->SetInstructionBits(((uint32_t)inst->InstructionBits() & ~kImm12Mask) | (((uint32_t)(-val) & 0xfff) << kImm12Shift)); } -void MacroAssembler::flexibleDivMod32(Register rhs, Register srcDest, - Register remOutput, bool isUnsigned, - const LiveRegisterSet&) { +void MacroAssembler::flexibleDivMod32(Register lhs, Register rhs, + Register divOutput, Register remOutput, + bool isUnsigned, const LiveRegisterSet&) { + MOZ_ASSERT(lhs != divOutput && lhs != remOutput, "lhs is preserved"); + MOZ_ASSERT(rhs != divOutput && rhs != remOutput, "rhs is preserved"); + + // The recommended code sequence to obtain both the quotient and remainder + // is div[u] followed by mod[u]. if (isUnsigned) { - ma_modu32(remOutput, srcDest, rhs); - ma_divu32(srcDest, srcDest, rhs); + ma_divu32(divOutput, lhs, rhs); + ma_modu32(remOutput, lhs, rhs); } else { - ma_mod32(remOutput, srcDest, rhs); - ma_div32(srcDest, srcDest, rhs); + ma_div32(divOutput, lhs, rhs); + ma_mod32(remOutput, lhs, rhs); } } -void MacroAssembler::flexibleQuotient32(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleQuotient32(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - quotient32(rhs, srcDest, isUnsigned); + quotient32(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleQuotientPtr(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleQuotientPtr(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - quotient64(rhs, srcDest, isUnsigned); + quotient64(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleRemainder32(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleRemainder32(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - remainder32(rhs, srcDest, isUnsigned); + remainder32(lhs, rhs, dest, isUnsigned); } -void MacroAssembler::flexibleRemainderPtr(Register rhs, Register srcDest, - bool isUnsigned, +void MacroAssembler::flexibleRemainderPtr(Register lhs, Register rhs, + Register dest, bool isUnsigned, const LiveRegisterSet&) { - remainder64(rhs, srcDest, isUnsigned); + remainder64(lhs, rhs, dest, isUnsigned); } void MacroAssembler::floorDoubleToInt32(FloatRegister src, Register dest, diff --git a/js/src/jit/wasm32/MacroAssembler-wasm32-inl.h b/js/src/jit/wasm32/MacroAssembler-wasm32-inl.h @@ -1127,12 +1127,12 @@ void MacroAssembler::branchAdd64(Condition cond, Imm64 imm, Register64 dest, MOZ_CRASH(); } -void MacroAssembler::quotient32(Register rhs, Register srcDest, +void MacroAssembler::quotient32(Register lhs, Register rhs, Register dest, bool isUnsigned) { MOZ_CRASH(); } -void MacroAssembler::remainder32(Register rhs, Register srcDest, +void MacroAssembler::remainder32(Register lhs, Register rhs, Register dest, bool isUnsigned) { MOZ_CRASH(); } diff --git a/js/src/jit/wasm32/MacroAssembler-wasm32.cpp b/js/src/jit/wasm32/MacroAssembler-wasm32.cpp @@ -48,32 +48,33 @@ void MacroAssembler::PopStackPtr() { MOZ_CRASH(); } void MacroAssembler::freeStackTo(uint32_t framePushed) { MOZ_CRASH(); } -void MacroAssembler::flexibleDivMod32(Register rhs, Register srcDest, - Register remOutput, bool isUnsigned, +void MacroAssembler::flexibleDivMod32(Register lhs, Register rhs, + Register divOutput, Register remOutput, + bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { MOZ_CRASH(); } void MacroAssembler::flexibleQuotient32( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { MOZ_CRASH(); } void MacroAssembler::flexibleQuotientPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { MOZ_CRASH(); } void MacroAssembler::flexibleRemainder32( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { MOZ_CRASH(); } void MacroAssembler::flexibleRemainderPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { MOZ_CRASH(); } diff --git a/js/src/jit/x64/MacroAssembler-x64.cpp b/js/src/jit/x64/MacroAssembler-x64.cpp @@ -858,9 +858,10 @@ void MacroAssemblerX64::convertDoubleToPtr(FloatRegister src, Register dest, } // This operation really consists of five phases, in order to enforce the -// restriction that on x64, srcDest must be rax and rdx will be clobbered. +// restriction that on x64, the dividend must be rax and both rax and rdx will +// be clobbered. // -// Input: { rhs, lhsOutput } +// Input: { lhs, rhs } // // [PUSH] Preserve registers // [MOVE] Generate moves to specific registers @@ -868,16 +869,17 @@ void MacroAssemblerX64::convertDoubleToPtr(FloatRegister src, Register dest, // [DIV] Input: { regForRhs, RAX } // [DIV] extend RAX into RDX // [DIV] x64 Division operator -// [DIV] Ouptut: { RAX, RDX } +// [DIV] Output: { RAX, RDX } // // [MOVE] Move specific registers to outputs // [POP] Restore registers // -// Output: { lhsOutput, remainderOutput } -void MacroAssemblerX64::flexibleDivMod64(Register rhs, Register lhsOutput, - bool isUnsigned, bool isDiv) { - if (lhsOutput == rhs) { - movq(ImmWord(isDiv ? 1 : 0), lhsOutput); +// Output: { output } +void MacroAssemblerX64::flexibleDivMod64(Register lhs, Register rhs, + Register output, bool isUnsigned, + bool isDiv) { + if (lhs == rhs) { + movq(ImmWord(isDiv ? 1 : 0), output); return; } @@ -890,14 +892,16 @@ void MacroAssemblerX64::flexibleDivMod64(Register rhs, Register lhsOutput, LiveGeneralRegisterSet preserve; preserve.add(rdx); preserve.add(rax); - preserve.add(regForRhs); + if (rhs != regForRhs) { + preserve.add(regForRhs); + } - preserve.takeUnchecked(lhsOutput); + preserve.takeUnchecked(output); asMasm().PushRegsInMask(preserve); // Shuffle input into place. - asMasm().moveRegPair(lhsOutput, rhs, rax, regForRhs); + asMasm().moveRegPair(lhs, rhs, rax, regForRhs); if (oom()) { return; } @@ -912,8 +916,8 @@ void MacroAssemblerX64::flexibleDivMod64(Register rhs, Register lhsOutput, } Register result = isDiv ? rax : rdx; - if (result != lhsOutput) { - movq(result, lhsOutput); + if (result != output) { + movq(result, output); } asMasm().PopRegsInMask(preserve); @@ -1048,15 +1052,15 @@ void MacroAssembler::moveValue(const Value& src, const ValueOperand& dest) { // Arithmetic functions void MacroAssembler::flexibleQuotientPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - flexibleDivMod64(rhs, srcDest, isUnsigned, /* isDiv= */ true); + flexibleDivMod64(lhs, rhs, dest, isUnsigned, /* isDiv= */ true); } void MacroAssembler::flexibleRemainderPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - flexibleDivMod64(rhs, srcDest, isUnsigned, /* isDiv= */ false); + flexibleDivMod64(lhs, rhs, dest, isUnsigned, /* isDiv= */ false); } // =============================================================== diff --git a/js/src/jit/x64/MacroAssembler-x64.h b/js/src/jit/x64/MacroAssembler-x64.h @@ -76,8 +76,8 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared { X86Encoding::XMMRegisterID destId)); protected: - void flexibleDivMod64(Register rhs, Register lhsOutput, bool isUnsigned, - bool isDiv); + void flexibleDivMod64(Register lhs, Register rhs, Register output, + bool isUnsigned, bool isDiv); public: using MacroAssemblerX86Shared::load32; diff --git a/js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h b/js/src/jit/x86-shared/MacroAssembler-x86-shared-inl.h @@ -252,9 +252,9 @@ void MacroAssembler::mulDouble(FloatRegister src, FloatRegister dest) { vmulsd(src, dest, dest); } -void MacroAssembler::quotient32(Register rhs, Register srcDest, +void MacroAssembler::quotient32(Register lhs, Register rhs, Register dest, Register tempEdx, bool isUnsigned) { - MOZ_ASSERT(srcDest == eax && tempEdx == edx); + MOZ_ASSERT(lhs == eax && dest == eax && tempEdx == edx); // Sign extend eax into edx to make (edx:eax): idiv/udiv are 64-bit. if (isUnsigned) { @@ -266,9 +266,9 @@ void MacroAssembler::quotient32(Register rhs, Register srcDest, } } -void MacroAssembler::remainder32(Register rhs, Register srcDest, +void MacroAssembler::remainder32(Register lhs, Register rhs, Register dest, Register tempEdx, bool isUnsigned) { - MOZ_ASSERT(srcDest == eax && tempEdx == edx); + MOZ_ASSERT(lhs == eax && dest == eax && tempEdx == edx); // Sign extend eax into edx to make (edx:eax): idiv/udiv are 64-bit. if (isUnsigned) { diff --git a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp @@ -352,10 +352,10 @@ void MacroAssembler::flush() {} void MacroAssembler::comment(const char* msg) { masm.comment(msg); } // This operation really consists of five phases, in order to enforce the -// restriction that on x86_shared, srcDest must be eax and edx will be -// clobbered. +// restriction that on x86_shared, the dividend must be eax and both eax and edx +// will be clobbered. // -// Input: { rhs, lhsOutput } +// Input: { lhs, rhs } // // [PUSH] Preserve registers // [MOVE] Generate moves to specific registers @@ -363,20 +363,26 @@ void MacroAssembler::comment(const char* msg) { masm.comment(msg); } // [DIV] Input: { regForRhs, EAX } // [DIV] extend EAX into EDX // [DIV] x86 Division operator -// [DIV] Ouptut: { EAX, EDX } +// [DIV] Output: { EAX, EDX } // // [MOVE] Move specific registers to outputs // [POP] Restore registers // -// Output: { lhsOutput, remainderOutput } -void MacroAssembler::flexibleDivMod32(Register rhs, Register lhsOutput, - Register remOutput, bool isUnsigned, - const LiveRegisterSet&) { - // Currently this helper can't handle this situation. - MOZ_ASSERT(lhsOutput != rhs); - MOZ_ASSERT(lhsOutput != remOutput); - - // Choose a register that is not edx, or eax to hold the rhs; +// Output: { quotientOutput, remainderOutput } +static void EmitDivMod32(MacroAssembler& masm, Register lhs, Register rhs, + Register divOutput, Register remOutput, + bool isUnsigned) { + if (lhs == rhs) { + if (divOutput != Register::Invalid()) { + masm.movl(Imm32(1), divOutput); + } + if (remOutput != Register::Invalid()) { + masm.movl(Imm32(0), remOutput); + } + return; + } + + // Choose a register that is not edx or eax to hold the rhs; // ebx is chosen arbitrarily, and will be preserved if necessary. Register regForRhs = (rhs == eax || rhs == edx) ? ebx : rhs; @@ -385,61 +391,64 @@ void MacroAssembler::flexibleDivMod32(Register rhs, Register lhsOutput, LiveRegisterSet preserve; preserve.add(edx); preserve.add(eax); - preserve.add(regForRhs); + if (rhs != regForRhs) { + preserve.add(regForRhs); + } - preserve.takeUnchecked(lhsOutput); - preserve.takeUnchecked(remOutput); + if (divOutput != Register::Invalid()) { + preserve.takeUnchecked(divOutput); + } + if (remOutput != Register::Invalid()) { + preserve.takeUnchecked(remOutput); + } - PushRegsInMask(preserve); + masm.PushRegsInMask(preserve); // Shuffle input into place. - moveRegPair(lhsOutput, rhs, eax, regForRhs); + masm.moveRegPair(lhs, rhs, eax, regForRhs); // Sign extend eax into edx to make (edx:eax): idiv/udiv are 64-bit. if (isUnsigned) { - mov(ImmWord(0), edx); - udiv(regForRhs); + masm.mov(ImmWord(0), edx); + masm.udiv(regForRhs); } else { - cdq(); - idiv(regForRhs); + masm.cdq(); + masm.idiv(regForRhs); } - moveRegPair(eax, edx, lhsOutput, remOutput); + if (divOutput != Register::Invalid() && remOutput != Register::Invalid()) { + masm.moveRegPair(eax, edx, divOutput, remOutput); + } else { + if (divOutput != Register::Invalid() && divOutput != eax) { + masm.mov(eax, divOutput); + } + if (remOutput != Register::Invalid() && remOutput != edx) { + masm.mov(edx, remOutput); + } + } - PopRegsInMask(preserve); + masm.PopRegsInMask(preserve); +} + +void MacroAssembler::flexibleDivMod32(Register lhs, Register rhs, + Register divOutput, Register remOutput, + bool isUnsigned, const LiveRegisterSet&) { + MOZ_ASSERT(lhs != divOutput && lhs != remOutput, "lhs is preserved"); + MOZ_ASSERT(rhs != divOutput && rhs != remOutput, "rhs is preserved"); + + EmitDivMod32(*this, lhs, rhs, divOutput, remOutput, isUnsigned); } void MacroAssembler::flexibleQuotient32( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - // Choose an arbitrary register that isn't eax, edx, rhs or srcDest; - AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All()); - regs.takeUnchecked(eax); - regs.takeUnchecked(edx); - regs.takeUnchecked(rhs); - regs.takeUnchecked(srcDest); - - Register remOut = regs.takeAny(); - push(remOut); - flexibleDivMod32(rhs, srcDest, remOut, isUnsigned, volatileLiveRegs); - pop(remOut); + EmitDivMod32(*this, lhs, rhs, dest, Register::Invalid(), isUnsigned); } void MacroAssembler::flexibleRemainder32( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - // Choose an arbitrary register that isn't eax, edx, rhs or srcDest - AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All()); - regs.takeUnchecked(eax); - regs.takeUnchecked(edx); - regs.takeUnchecked(rhs); - regs.takeUnchecked(srcDest); - - Register remOut = regs.takeAny(); - push(remOut); - flexibleDivMod32(rhs, srcDest, remOut, isUnsigned, volatileLiveRegs); - mov(remOut, srcDest); - pop(remOut); + EmitDivMod32(*this, lhs, rhs, Register::Invalid(), dest, isUnsigned); } // =============================================================== diff --git a/js/src/jit/x86/MacroAssembler-x86.cpp b/js/src/jit/x86/MacroAssembler-x86.cpp @@ -959,15 +959,15 @@ void MacroAssembler::moveValue(const Value& src, const ValueOperand& dest) { // Arithmetic functions void MacroAssembler::flexibleQuotientPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - flexibleQuotient32(rhs, srcDest, isUnsigned, volatileLiveRegs); + flexibleQuotient32(lhs, rhs, dest, isUnsigned, volatileLiveRegs); } void MacroAssembler::flexibleRemainderPtr( - Register rhs, Register srcDest, bool isUnsigned, + Register lhs, Register rhs, Register dest, bool isUnsigned, const LiveRegisterSet& volatileLiveRegs) { - flexibleRemainder32(rhs, srcDest, isUnsigned, volatileLiveRegs); + flexibleRemainder32(lhs, rhs, dest, isUnsigned, volatileLiveRegs); } // =============================================================== diff --git a/js/src/jsapi-tests/testJitMacroAssembler.cpp b/js/src/jsapi-tests/testJitMacroAssembler.cpp @@ -5,6 +5,8 @@ * 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/. */ +#include "mozilla/Sprintf.h" + #include "jit/IonAnalysis.h" #include "jit/Linker.h" #include "jit/MacroAssembler.h" @@ -35,48 +37,80 @@ BEGIN_TEST(testJitMacroAssembler_flexibleDivMod) { PrepareJit(masm); // Test case divides 9/2; - const uintptr_t quotient_result = 4; - const uintptr_t remainder_result = 1; const uintptr_t dividend = 9; const uintptr_t divisor = 2; + const uintptr_t quotient_result = 4; + const uintptr_t remainder_result = 1; - AllocatableGeneralRegisterSet leftOutputHandSides(GeneralRegisterSet::All()); - - while (!leftOutputHandSides.empty()) { - Register lhsOutput = leftOutputHandSides.takeAny(); + AllocatableGeneralRegisterSet leftHandSides(GeneralRegisterSet::All()); + while (!leftHandSides.empty()) { + Register lhs = leftHandSides.takeAny(); AllocatableGeneralRegisterSet rightHandSides(GeneralRegisterSet::All()); while (!rightHandSides.empty()) { Register rhs = rightHandSides.takeAny(); - AllocatableGeneralRegisterSet remainders(GeneralRegisterSet::All()); - while (!remainders.empty()) { - Register remainderOutput = remainders.takeAny(); - if (lhsOutput == rhs || lhsOutput == remainderOutput || - rhs == remainderOutput) { - continue; + AllocatableGeneralRegisterSet quotients(GeneralRegisterSet::All()); + while (!quotients.empty()) { + Register quotientOutput = quotients.takeAny(); + + AllocatableGeneralRegisterSet remainders(GeneralRegisterSet::All()); + while (!remainders.empty()) { + Register remainderOutput = remainders.takeAny(); + + // lhs and rhs are preserved by |flexibleDivMod32|, so neither can be + // an output register. + if (lhs == quotientOutput || lhs == remainderOutput) { + continue; + } + if (rhs == quotientOutput || rhs == remainderOutput) { + continue; + } + + // Output registers must be distinct. + if (quotientOutput == remainderOutput) { + continue; + } + + AllocatableRegisterSet regs(RegisterSet::Volatile()); + LiveRegisterSet save(regs.asLiveSet()); + + Label next, fail; + masm.mov(ImmWord(dividend), lhs); + masm.mov(ImmWord(divisor), rhs); + masm.flexibleDivMod32(lhs, rhs, quotientOutput, remainderOutput, + false, save); + masm.branchPtr(Assembler::NotEqual, quotientOutput, + ImmWord(lhs != rhs ? quotient_result : 1), &fail); + masm.branchPtr(Assembler::NotEqual, remainderOutput, + ImmWord(lhs != rhs ? remainder_result : 0), &fail); + // Ensure LHS was not clobbered + masm.branchPtr(Assembler::NotEqual, lhs, + ImmWord(lhs != rhs ? dividend : divisor), &fail); + // Ensure RHS was not clobbered + masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(divisor), &fail); + masm.jump(&next); + masm.bind(&fail); + masm.printf("Failed\n"); + + char buffer[128]; + SprintfLiteral( + buffer, + "\tlhs = %s, rhs = %s, quotientOutput = %s, remainderOutput " + "= %s\n", + lhs.name(), rhs.name(), quotientOutput.name(), + remainderOutput.name()); + + masm.printf(buffer); + masm.printf("\tlhs = %d\n", lhs); + masm.printf("\trhs = %d\n", rhs); + masm.printf("\tquotientOutput = %d\n", quotientOutput); + masm.printf("\tremainderOutput = %d\n", remainderOutput); + + masm.breakpoint(); + + masm.bind(&next); } - - AllocatableRegisterSet regs(RegisterSet::Volatile()); - LiveRegisterSet save(regs.asLiveSet()); - - Label next, fail; - masm.mov(ImmWord(dividend), lhsOutput); - masm.mov(ImmWord(divisor), rhs); - masm.flexibleDivMod32(rhs, lhsOutput, remainderOutput, false, save); - masm.branch32(Assembler::NotEqual, AbsoluteAddress(&quotient_result), - lhsOutput, &fail); - masm.branch32(Assembler::NotEqual, AbsoluteAddress(&remainder_result), - remainderOutput, &fail); - // Ensure RHS was not clobbered - masm.branch32(Assembler::NotEqual, AbsoluteAddress(&divisor), rhs, - &fail); - masm.jump(&next); - masm.bind(&fail); - masm.printf("Failed"); - masm.breakpoint(); - - masm.bind(&next); } } } @@ -98,36 +132,53 @@ BEGIN_TEST(testJitMacroAssembler_flexibleRemainder) { const uintptr_t divisor = 2; const uintptr_t remainder_result = 1; - AllocatableGeneralRegisterSet leftOutputHandSides(GeneralRegisterSet::All()); - - while (!leftOutputHandSides.empty()) { - Register lhsOutput = leftOutputHandSides.takeAny(); + AllocatableGeneralRegisterSet leftHandSides(GeneralRegisterSet::All()); + while (!leftHandSides.empty()) { + Register lhs = leftHandSides.takeAny(); AllocatableGeneralRegisterSet rightHandSides(GeneralRegisterSet::All()); while (!rightHandSides.empty()) { Register rhs = rightHandSides.takeAny(); - if (lhsOutput == rhs) { - continue; - } + AllocatableGeneralRegisterSet outputs(GeneralRegisterSet::All()); + while (!outputs.empty()) { + Register output = outputs.takeAny(); - AllocatableRegisterSet regs(RegisterSet::Volatile()); - LiveRegisterSet save(regs.asLiveSet()); - - Label next, fail; - masm.mov(ImmWord(dividend), lhsOutput); - masm.mov(ImmWord(divisor), rhs); - masm.flexibleRemainder32(rhs, lhsOutput, false, save); - masm.branch32(Assembler::NotEqual, AbsoluteAddress(&remainder_result), - lhsOutput, &fail); - // Ensure RHS was not clobbered - masm.branch32(Assembler::NotEqual, AbsoluteAddress(&divisor), rhs, &fail); - masm.jump(&next); - masm.bind(&fail); - masm.printf("Failed\n"); - masm.breakpoint(); + AllocatableRegisterSet regs(RegisterSet::Volatile()); + LiveRegisterSet save(regs.asLiveSet()); - masm.bind(&next); + Label next, fail; + masm.mov(ImmWord(dividend), lhs); + masm.mov(ImmWord(divisor), rhs); + masm.flexibleRemainder32(lhs, rhs, output, false, save); + masm.branchPtr(Assembler::NotEqual, output, + ImmWord(lhs != rhs ? remainder_result : 0), &fail); + // Ensure LHS was not clobbered + if (lhs != output) { + masm.branchPtr(Assembler::NotEqual, lhs, + ImmWord(lhs != rhs ? dividend : divisor), &fail); + } + // Ensure RHS was not clobbered + if (rhs != output) { + masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(divisor), &fail); + } + masm.jump(&next); + masm.bind(&fail); + masm.printf("Failed\n"); + + char buffer[128]; + SprintfLiteral(buffer, "\tlhs = %s, rhs = %s, output = %s\n", + lhs.name(), rhs.name(), output.name()); + + masm.printf(buffer); + masm.printf("\tlhs = %d\n", lhs); + masm.printf("\trhs = %d\n", rhs); + masm.printf("\toutput = %d\n", output); + + masm.breakpoint(); + + masm.bind(&next); + } } } @@ -148,36 +199,53 @@ BEGIN_TEST(testJitMacroAssembler_flexibleQuotient) { const uintptr_t divisor = 2; const uintptr_t quotient_result = 4; - AllocatableGeneralRegisterSet leftOutputHandSides(GeneralRegisterSet::All()); - - while (!leftOutputHandSides.empty()) { - Register lhsOutput = leftOutputHandSides.takeAny(); + AllocatableGeneralRegisterSet leftHandSides(GeneralRegisterSet::All()); + while (!leftHandSides.empty()) { + Register lhs = leftHandSides.takeAny(); AllocatableGeneralRegisterSet rightHandSides(GeneralRegisterSet::All()); while (!rightHandSides.empty()) { Register rhs = rightHandSides.takeAny(); - if (lhsOutput == rhs) { - continue; - } + AllocatableGeneralRegisterSet outputs(GeneralRegisterSet::All()); + while (!outputs.empty()) { + Register output = outputs.takeAny(); - AllocatableRegisterSet regs(RegisterSet::Volatile()); - LiveRegisterSet save(regs.asLiveSet()); - - Label next, fail; - masm.mov(ImmWord(dividend), lhsOutput); - masm.mov(ImmWord(divisor), rhs); - masm.flexibleQuotient32(rhs, lhsOutput, false, save); - masm.branch32(Assembler::NotEqual, AbsoluteAddress(&quotient_result), - lhsOutput, &fail); - // Ensure RHS was not clobbered - masm.branch32(Assembler::NotEqual, AbsoluteAddress(&divisor), rhs, &fail); - masm.jump(&next); - masm.bind(&fail); - masm.printf("Failed\n"); - masm.breakpoint(); + AllocatableRegisterSet regs(RegisterSet::Volatile()); + LiveRegisterSet save(regs.asLiveSet()); - masm.bind(&next); + Label next, fail; + masm.mov(ImmWord(dividend), lhs); + masm.mov(ImmWord(divisor), rhs); + masm.flexibleQuotient32(lhs, rhs, output, false, save); + masm.branchPtr(Assembler::NotEqual, output, + ImmWord(lhs != rhs ? quotient_result : 1), &fail); + // Ensure LHS was not clobbered + if (lhs != output) { + masm.branchPtr(Assembler::NotEqual, lhs, + ImmWord(lhs != rhs ? dividend : divisor), &fail); + } + // Ensure RHS was not clobbered + if (rhs != output) { + masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(divisor), &fail); + } + masm.jump(&next); + masm.bind(&fail); + masm.printf("Failed\n"); + + char buffer[128]; + SprintfLiteral(buffer, "\tlhs = %s, rhs = %s, output = %s\n", + lhs.name(), rhs.name(), output.name()); + + masm.printf(buffer); + masm.printf("\tlhs = %d\n", lhs); + masm.printf("\trhs = %d\n", rhs); + masm.printf("\toutput = %d\n", output); + + masm.breakpoint(); + + masm.bind(&next); + } } } @@ -185,14 +253,9 @@ BEGIN_TEST(testJitMacroAssembler_flexibleQuotient) { } END_TEST(testJitMacroAssembler_flexibleQuotient) -// To make sure ecx isn't being clobbered; globally scoped to ensure it has the -// right lifetime. -const uintptr_t guardEcx = 0xfeedbad; - bool shiftTest(JSContext* cx, const char* name, void (*operation)(StackMacroAssembler& masm, Register, Register), - const uintptr_t* lhsInput, const uintptr_t* rhsInput, - const uintptr_t* result) { + uintptr_t lhsInput, uintptr_t rhsInput, uintptr_t result) { TempAllocator tempAlloc(&cx->tempLifoAlloc()); JitContext jcx(cx); StackMacroAssembler masm(cx, tempAlloc); @@ -200,6 +263,8 @@ bool shiftTest(JSContext* cx, const char* name, PrepareJit(masm); + const uintptr_t guardEcx = 0xfeedbad; + JS::AutoSuppressGCAnalysis suppress; AllocatableGeneralRegisterSet leftOutputHandSides(GeneralRegisterSet::All()); @@ -211,33 +276,33 @@ bool shiftTest(JSContext* cx, const char* name, Register rhs = rightHandSides.takeAny(); // You can only use shift as the same reg if the values are the same - if (lhsOutput == rhs && *lhsInput != *rhsInput) { + if (lhsOutput == rhs && lhsInput != rhsInput) { continue; } Label next, outputFail, clobberRhs, clobberEcx, dump; masm.mov(ImmWord(guardEcx), ecx); - masm.mov(ImmWord(*lhsInput), lhsOutput); - masm.mov(ImmWord(*rhsInput), rhs); + masm.mov(ImmWord(lhsInput), lhsOutput); + masm.mov(ImmWord(rhsInput), rhs); operation(masm, rhs, lhsOutput); // Ensure Result is correct - masm.branch32(Assembler::NotEqual, AbsoluteAddress(result), lhsOutput, - &outputFail); + masm.branchPtr(Assembler::NotEqual, lhsOutput, ImmWord(result), + &outputFail); // Ensure RHS was not clobbered, unless it's also the output register. if (lhsOutput != rhs) { - masm.branch32(Assembler::NotEqual, AbsoluteAddress(rhsInput), rhs, - &clobberRhs); + masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(rhsInput), + &clobberRhs); } if (lhsOutput != ecx && rhs != ecx) { // If neither lhsOutput nor rhs is ecx, make sure ecx has been // preserved, otherwise it's expected to be covered by the RHS clobber // check above, or intentionally clobbered as the output. - masm.branch32(Assembler::NotEqual, AbsoluteAddress(&guardEcx), ecx, - &clobberEcx); + masm.branchPtr(Assembler::NotEqual, ecx, ImmWord(guardEcx), + &clobberEcx); } masm.jump(&next); @@ -282,7 +347,7 @@ BEGIN_TEST(testJitMacroAssembler_flexibleRshift) { [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) { masm.flexibleRshift32(rhs, lhsOutput); }, - &lhsInput, &rhsInput, &result); + lhsInput, rhsInput, result); if (!res) { return false; } @@ -300,7 +365,7 @@ BEGIN_TEST(testJitMacroAssembler_flexibleRshift) { [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) { masm.flexibleRshift32(rhs, lhsOutput); }, - &lhsInput, &rhsInput, &result); + lhsInput, rhsInput, result); if (!res) { return false; } @@ -321,7 +386,7 @@ BEGIN_TEST(testJitMacroAssembler_flexibleRshiftArithmetic) { [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) { masm.flexibleRshift32Arithmetic(rhs, lhsOutput); }, - &lhsInput, &rhsInput, &result); + lhsInput, rhsInput, result); if (!res) { return false; } @@ -339,7 +404,7 @@ BEGIN_TEST(testJitMacroAssembler_flexibleRshiftArithmetic) { [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) { masm.flexibleRshift32Arithmetic(rhs, lhsOutput); }, - &lhsInput, &rhsInput, &result); + lhsInput, rhsInput, result); if (!res) { return false; } @@ -361,7 +426,7 @@ BEGIN_TEST(testJitMacroAssembler_flexibleLshift) { [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) { masm.flexibleLshift32(rhs, lhsOutput); }, - &lhsInput, &rhsInput, &result); + lhsInput, rhsInput, result); if (!res) { return false; } @@ -378,7 +443,7 @@ BEGIN_TEST(testJitMacroAssembler_flexibleLshift) { [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) { masm.flexibleLshift32(rhs, lhsOutput); }, - &lhsInput, &rhsInput, &result); + lhsInput, rhsInput, result); if (!res) { return false; } diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp @@ -2382,18 +2382,18 @@ void BaseCompiler::popAndAllocateForDivAndRemI32(RegI32* r0, RegI32* r1, static void QuotientI32(MacroAssembler& masm, RegI32 rs, RegI32 rsd, RegI32 reserved, IsUnsigned isUnsigned) { #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) - masm.quotient32(rs, rsd, reserved, isUnsigned); + masm.quotient32(rsd, rs, rsd, reserved, isUnsigned); #else - masm.quotient32(rs, rsd, isUnsigned); + masm.quotient32(rsd, rs, rsd, isUnsigned); #endif } static void RemainderI32(MacroAssembler& masm, RegI32 rs, RegI32 rsd, RegI32 reserved, IsUnsigned isUnsigned) { #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) - masm.remainder32(rs, rsd, reserved, isUnsigned); + masm.remainder32(rsd, rs, rsd, reserved, isUnsigned); #else - masm.remainder32(rs, rsd, isUnsigned); + masm.remainder32(rsd, rs, rsd, isUnsigned); #endif } @@ -2457,35 +2457,8 @@ static void QuotientI64(MacroAssembler& masm, RegI64 rhs, RegI64 srcDest, masm.cqo(); masm.idivq(rhs.reg); } -# elif defined(JS_CODEGEN_MIPS64) - MOZ_ASSERT(reserved.isInvalid()); - if (isUnsigned) { - masm.as_ddivu(srcDest.reg, rhs.reg); - } else { - masm.as_ddiv(srcDest.reg, rhs.reg); - } - masm.as_mflo(srcDest.reg); -# elif defined(JS_CODEGEN_ARM64) - MOZ_ASSERT(reserved.isInvalid()); - ARMRegister sd(srcDest.reg, 64); - ARMRegister r(rhs.reg, 64); - if (isUnsigned) { - masm.Udiv(sd, sd, r); - } else { - masm.Sdiv(sd, sd, r); - } -# elif defined(JS_CODEGEN_LOONG64) - if (isUnsigned) { - masm.as_div_du(srcDest.reg, srcDest.reg, rhs.reg); - } else { - masm.as_div_d(srcDest.reg, srcDest.reg, rhs.reg); - } -# elif defined(JS_CODEGEN_RISCV64) - if (isUnsigned) { - masm.divu(srcDest.reg, srcDest.reg, rhs.reg); - } else { - masm.div(srcDest.reg, srcDest.reg, rhs.reg); - } +# elif !defined(JS_CODEGEN_NONE) && !defined(JS_CODEGEN_WASM32) + masm.quotient64(srcDest.reg, rhs.reg, srcDest.reg, isUnsigned); # else MOZ_CRASH("BaseCompiler platform hook: quotientI64"); # endif @@ -2506,37 +2479,8 @@ static void RemainderI64(MacroAssembler& masm, RegI64 rhs, RegI64 srcDest, masm.idivq(rhs.reg); } masm.movq(rdx, rax); -# elif defined(JS_CODEGEN_MIPS64) - MOZ_ASSERT(reserved.isInvalid()); - if (isUnsigned) { - masm.as_ddivu(srcDest.reg, rhs.reg); - } else { - masm.as_ddiv(srcDest.reg, rhs.reg); - } - masm.as_mfhi(srcDest.reg); -# elif defined(JS_CODEGEN_ARM64) - ARMRegister sd(srcDest.reg, 64); - ARMRegister r(rhs.reg, 64); - ARMRegister t(reserved.reg, 64); - if (isUnsigned) { - masm.Udiv(t, sd, r); - } else { - masm.Sdiv(t, sd, r); - } - masm.Mul(t, t, r); - masm.Sub(sd, sd, t); -# elif defined(JS_CODEGEN_LOONG64) - if (isUnsigned) { - masm.as_mod_du(srcDest.reg, srcDest.reg, rhs.reg); - } else { - masm.as_mod_d(srcDest.reg, srcDest.reg, rhs.reg); - } -# elif defined(JS_CODEGEN_RISCV64) - if (isUnsigned) { - masm.remu(srcDest.reg, srcDest.reg, rhs.reg); - } else { - masm.rem(srcDest.reg, srcDest.reg, rhs.reg); - } +# elif !defined(JS_CODEGEN_NONE) && !defined(JS_CODEGEN_WASM32) + masm.remainder64(srcDest.reg, rhs.reg, srcDest.reg, isUnsigned); # else MOZ_CRASH("BaseCompiler platform hook: remainderI64"); # endif