mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 13:27:45 -07:00
Jit64: Skip HandleNaNs for operations that can't generate NaN
Operations that have two operands and can't generate a default NaN, i.e. addition and subtraction, already have the desired NaN handling on x86. We just need to make sure to not reverse the operands. This fixes ps_sum0/ps_sum1 outputting NaNs in cases where they shouldn't. (HandleNaNs assumes that a NaN in a ps0 input always results in a NaN in the ps0 output, and correspondingly for ps1.)
This commit is contained in:
parent
cbceae9176
commit
2f1a8ee1b9
@ -236,8 +236,7 @@ void Jit64::fp_arith(UGeckoInstruction inst)
|
||||
|
||||
bool single = inst.OPCD == 4 || inst.OPCD == 59;
|
||||
// If both the inputs are known to have identical top and bottom halves, we can skip the MOVDDUP
|
||||
// at the end by
|
||||
// using packed arithmetic instead.
|
||||
// at the end by using packed arithmetic instead.
|
||||
bool packed = inst.OPCD == 4 ||
|
||||
(inst.OPCD == 59 && js.op->fprIsDuplicated[a] && js.op->fprIsDuplicated[arg2]);
|
||||
// Packed divides are slower than scalar divides on basically all x86, so this optimization isn't
|
||||
@ -249,10 +248,12 @@ void Jit64::fp_arith(UGeckoInstruction inst)
|
||||
void (XEmitter::*avxOp)(X64Reg, X64Reg, const OpArg&) = nullptr;
|
||||
void (XEmitter::*sseOp)(X64Reg, const OpArg&) = nullptr;
|
||||
bool reversible = false;
|
||||
bool roundRHS = false;
|
||||
bool round_rhs = false;
|
||||
bool preserve_inputs = false;
|
||||
switch (inst.SUBOP5)
|
||||
{
|
||||
case 18:
|
||||
preserve_inputs = m_accurate_nans;
|
||||
avxOp = packed ? &XEmitter::VDIVPD : &XEmitter::VDIVSD;
|
||||
sseOp = packed ? &XEmitter::DIVPD : &XEmitter::DIVSD;
|
||||
break;
|
||||
@ -261,13 +262,14 @@ void Jit64::fp_arith(UGeckoInstruction inst)
|
||||
sseOp = packed ? &XEmitter::SUBPD : &XEmitter::SUBSD;
|
||||
break;
|
||||
case 21:
|
||||
reversible = true;
|
||||
reversible = !m_accurate_nans;
|
||||
avxOp = packed ? &XEmitter::VADDPD : &XEmitter::VADDSD;
|
||||
sseOp = packed ? &XEmitter::ADDPD : &XEmitter::ADDSD;
|
||||
break;
|
||||
case 25:
|
||||
reversible = true;
|
||||
roundRHS = single && !js.op->fprIsSingle[c];
|
||||
round_rhs = single && !js.op->fprIsSingle[c];
|
||||
preserve_inputs = m_accurate_nans;
|
||||
avxOp = packed ? &XEmitter::VMULPD : &XEmitter::VMULSD;
|
||||
sseOp = packed ? &XEmitter::MULPD : &XEmitter::MULSD;
|
||||
break;
|
||||
@ -280,9 +282,8 @@ void Jit64::fp_arith(UGeckoInstruction inst)
|
||||
RCOpArg Rarg2 = fpr.Use(arg2, RCMode::Read);
|
||||
RegCache::Realize(Rd, Ra, Rarg2);
|
||||
|
||||
bool preserve_inputs = m_accurate_nans;
|
||||
X64Reg dest = preserve_inputs ? XMM1 : static_cast<X64Reg>(Rd);
|
||||
if (roundRHS)
|
||||
if (round_rhs)
|
||||
{
|
||||
if (a == d && !preserve_inputs)
|
||||
{
|
||||
@ -300,10 +301,15 @@ void Jit64::fp_arith(UGeckoInstruction inst)
|
||||
avx_op(avxOp, sseOp, dest, Ra, Rarg2, packed, reversible);
|
||||
}
|
||||
|
||||
if (inst.SUBOP5 != 25)
|
||||
switch (inst.SUBOP5)
|
||||
{
|
||||
case 18:
|
||||
HandleNaNs(inst, dest, XMM0, Ra, Rarg2, std::nullopt);
|
||||
else
|
||||
break;
|
||||
case 25:
|
||||
HandleNaNs(inst, dest, XMM0, Ra, std::nullopt, Rarg2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (single)
|
||||
FinalizeSingleResult(Rd, R(dest), packed, true);
|
||||
|
@ -79,7 +79,8 @@ void Jit64::ps_sum(UGeckoInstruction inst)
|
||||
default:
|
||||
PanicAlertFmt("ps_sum WTF!!!");
|
||||
}
|
||||
HandleNaNs(inst, tmp, tmp == XMM1 ? XMM0 : XMM1, Ra, Rb, Rc);
|
||||
// We're intentionally not calling HandleNaNs here.
|
||||
// For addition and subtraction specifically, x86's NaN behavior matches PPC's.
|
||||
FinalizeSingleResult(Rd, R(tmp));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user