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:
1 parent
d5067b6276
commit
6ac7ffcdd7
3 files changed
+39
-20
No files matched your search
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user