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 committed 2026-01-18 20:02:49 +01:00
1 parent d5067b6276
commit 6ac7ffcdd7
3 files changed
+39 -20

No files matched your search

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