Interpreter_Paired: Handle signaling NaNs within ps_res and ps_rsqrte

Like regular fres and frsqrte, these also signal whether or not either
of the inputs are signaling NaNs.
This commit is contained in:
Lioncash 2018-06-02 20:47:16 -04:00
parent d05c2ef90d
commit d6bafbfaaf
1 changed files with 23 additions and 6 deletions

View File

@ -115,8 +115,8 @@ void Interpreter::ps_div(UGeckoInstruction inst)
void Interpreter::ps_res(UGeckoInstruction inst) void Interpreter::ps_res(UGeckoInstruction inst)
{ {
// this code is based on the real hardware tests // this code is based on the real hardware tests
double a = rPS0(inst.FB); const double a = rPS0(inst.FB);
double b = rPS1(inst.FB); const double b = rPS1(inst.FB);
if (a == 0.0 || b == 0.0) if (a == 0.0 || b == 0.0)
{ {
@ -125,6 +125,13 @@ void Interpreter::ps_res(UGeckoInstruction inst)
FPSCR.FR = 0; FPSCR.FR = 0;
} }
if (Common::IsSNAN(a) || Common::IsSNAN(b))
{
SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
rPS0(inst.FD) = Common::ApproximateReciprocal(a); rPS0(inst.FD) = Common::ApproximateReciprocal(a);
rPS1(inst.FD) = Common::ApproximateReciprocal(b); rPS1(inst.FD) = Common::ApproximateReciprocal(b);
PowerPC::UpdateFPRF(rPS0(inst.FD)); PowerPC::UpdateFPRF(rPS0(inst.FD));
@ -135,22 +142,32 @@ void Interpreter::ps_res(UGeckoInstruction inst)
void Interpreter::ps_rsqrte(UGeckoInstruction inst) void Interpreter::ps_rsqrte(UGeckoInstruction inst)
{ {
if (rPS0(inst.FB) == 0.0 || rPS1(inst.FB) == 0.0) const double ps0 = rPS0(inst.FB);
const double ps1 = rPS1(inst.FB);
if (ps0 == 0.0 || ps1 == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(FPSCR_ZX);
FPSCR.FI = 0; FPSCR.FI = 0;
FPSCR.FR = 0; FPSCR.FR = 0;
} }
if (rPS0(inst.FB) < 0.0 || rPS1(inst.FB) < 0.0) if (ps0 < 0.0 || ps1 < 0.0)
{ {
SetFPException(FPSCR_VXSQRT); SetFPException(FPSCR_VXSQRT);
FPSCR.FI = 0; FPSCR.FI = 0;
FPSCR.FR = 0; FPSCR.FR = 0;
} }
rPS0(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(rPS0(inst.FB))); if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1))
rPS1(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(rPS1(inst.FB))); {
SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
rPS0(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps0));
rPS1(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps1));
PowerPC::UpdateFPRF(rPS0(inst.FD)); PowerPC::UpdateFPRF(rPS0(inst.FD));