Jit64: Return FixupBranch from HandleNaNs

This will be used in the next commit to skip running code that's
unnecessary when the result is NaN.
This commit is contained in:
JosJuice 2025-08-23 15:18:54 +02:00
parent d5067b6276
commit 6ac7ffcdd7
3 changed files with 39 additions and 20 deletions

View File

@ -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<Gen::OpArg> Ra, std::optional<Gen::OpArg> Rb,
std::optional<Gen::OpArg> Rc);
[[nodiscard]] Gen::FixupBranch HandleNaNs(UGeckoInstruction inst, Gen::X64Reg xmm,
Gen::X64Reg clobber, std::optional<Gen::OpArg> Ra,
std::optional<Gen::OpArg> Rb,
std::optional<Gen::OpArg> Rc);
void MultiplyImmediate(u32 imm, int a, int d, bool overflow);

View File

@ -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<OpArg> Ra,
std::optional<OpArg> Rb, std::optional<OpArg> Rc)
FixupBranch Jit64::HandleNaNs(UGeckoInstruction inst, X64Reg xmm, X64Reg clobber,
std::optional<OpArg> Ra, std::optional<OpArg> Rb,
std::optional<OpArg> 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<FixupBranch> 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);

View File

@ -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));
}