diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index ad5db1fa10..d9030116d8 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -153,9 +153,10 @@ public: void FinalizeSingleResult(Gen::X64Reg output, const Gen::OpArg& input, bool packed = true, bool duplicate = false); void FinalizeDoubleResult(Gen::X64Reg output, const Gen::OpArg& input); - void HandleNaNs(UGeckoInstruction inst, Gen::X64Reg xmm, Gen::X64Reg clobber, - std::optional Ra, std::optional Rb, - std::optional Rc); + [[nodiscard]] Gen::FixupBranch HandleNaNs(UGeckoInstruction inst, Gen::X64Reg xmm, + Gen::X64Reg clobber, std::optional Ra, + std::optional Rb, + std::optional Rc); void MultiplyImmediate(u32 imm, int a, int d, bool overflow); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp index 5e7802ff67..2ef3788d51 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -93,8 +93,9 @@ void Jit64::FinalizeDoubleResult(X64Reg output, const OpArg& input) SetFPRFIfNeeded(input, false); } -void Jit64::HandleNaNs(UGeckoInstruction inst, X64Reg xmm, X64Reg clobber, std::optional Ra, - std::optional Rb, std::optional Rc) +FixupBranch Jit64::HandleNaNs(UGeckoInstruction inst, X64Reg xmm, X64Reg clobber, + std::optional Ra, std::optional Rb, + std::optional Rc) { // | PowerPC | x86 // ---------------------+----------+--------- @@ -104,9 +105,6 @@ void Jit64::HandleNaNs(UGeckoInstruction inst, X64Reg xmm, X64Reg clobber, std:: // Dragon Ball: Revenge of King Piccolo requires generated NaNs // to be positive, so we'll have to handle them manually. - if (!m_accurate_nans) - return; - if (inst.OPCD != 4) { // not paired-single @@ -140,7 +138,7 @@ void Jit64::HandleNaNs(UGeckoInstruction inst, X64Reg xmm, X64Reg clobber, std:: FixupBranch done = J(Jump::Near); SwitchToNearCode(); - SetJumpTarget(done); + return done; } else { @@ -217,7 +215,7 @@ void Jit64::HandleNaNs(UGeckoInstruction inst, X64Reg xmm, X64Reg clobber, std:: FixupBranch done = J(Jump::Near); SwitchToNearCode(); - SetJumpTarget(done); + return done; } } @@ -329,14 +327,21 @@ void Jit64::fp_arith(UGeckoInstruction inst) } } - switch (inst.SUBOP5) + if (m_accurate_nans) { - case 18: - HandleNaNs(inst, dest, XMM0, Ra, Rarg2, std::nullopt); - break; - case 25: - HandleNaNs(inst, dest, XMM0, Ra, std::nullopt, Rarg2); - break; + std::optional handled_nans; + switch (inst.SUBOP5) + { + case 18: + handled_nans = HandleNaNs(inst, dest, XMM0, Ra, Rarg2, std::nullopt); + break; + case 25: + handled_nans = HandleNaNs(inst, dest, XMM0, Ra, std::nullopt, Rarg2); + break; + } + + if (handled_nans) + SetJumpTarget(*handled_nans); } if (single) @@ -585,8 +590,14 @@ void Jit64::fmaddXX(UGeckoInstruction inst) DEBUG_ASSERT(!preserve_d); } - // If packed, the clobber register must be XMM0. If not packed, the clobber register is unused. - HandleNaNs(inst, result_xmm, XMM0, Ra, Rb, madds_accurate_nans ? R(Rc_duplicated) : Rc); + if (m_accurate_nans) + { + // If packed, the clobber register must be XMM0. If not packed, the clobber register is unused. + const FixupBranch handled_nans = + HandleNaNs(inst, result_xmm, XMM0, Ra, Rb, madds_accurate_nans ? R(Rc_duplicated) : Rc); + + SetJumpTarget(handled_nans); + } if (single) FinalizeSingleResult(Rd, R(result_xmm), packed, true); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Paired.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Paired.cpp index 930757cdad..8e44eb78b4 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Paired.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Paired.cpp @@ -100,12 +100,19 @@ void Jit64::ps_muls(UGeckoInstruction inst) default: PanicAlertFmt("ps_muls WTF!!!"); } + if (round_input) Force25BitPrecision(XMM1, R(Rc_duplicated), XMM0); else if (XMM1 != Rc_duplicated) MOVAPD(XMM1, Rc_duplicated); MULPD(XMM1, Ra); - HandleNaNs(inst, XMM1, XMM0, Ra, std::nullopt, Rc_duplicated); + + if (m_accurate_nans) + { + const FixupBranch handled_nans = HandleNaNs(inst, XMM1, XMM0, Ra, std::nullopt, Rc_duplicated); + SetJumpTarget(handled_nans); + } + FinalizeSingleResult(Rd, R(XMM1)); }