Merge pull request #7063 from lioncash/fifr
Interpreter: Unset FPSCR.FI and FPSCR.FR for QNaN and infinity input operands
This commit is contained in:
commit
5f29e891d3
|
@ -103,10 +103,9 @@ inline double NI_mul(double a, double b)
|
|||
if (std::isnan(t))
|
||||
{
|
||||
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
if (std::isnan(a))
|
||||
return MakeQuiet(a);
|
||||
|
@ -114,7 +113,6 @@ inline double NI_mul(double a, double b)
|
|||
return MakeQuiet(b);
|
||||
|
||||
SetFPException(FPSCR_VXIMZ);
|
||||
FPSCR.ClearFIFR();
|
||||
return PPC_NAN;
|
||||
}
|
||||
return t;
|
||||
|
@ -127,10 +125,9 @@ inline double NI_div(double a, double b)
|
|||
if (std::isnan(t))
|
||||
{
|
||||
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
if (std::isnan(a))
|
||||
return MakeQuiet(a);
|
||||
|
@ -142,18 +139,15 @@ inline double NI_div(double a, double b)
|
|||
if (a == 0.0)
|
||||
{
|
||||
SetFPException(FPSCR_VXZDZ);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFPException(FPSCR_ZX);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
}
|
||||
else if (std::isinf(a) && std::isinf(b))
|
||||
{
|
||||
SetFPException(FPSCR_VXIDI);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
return PPC_NAN;
|
||||
|
@ -169,10 +163,9 @@ inline double NI_add(double a, double b)
|
|||
if (std::isnan(t))
|
||||
{
|
||||
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
if (std::isnan(a))
|
||||
return MakeQuiet(a);
|
||||
|
@ -180,10 +173,12 @@ inline double NI_add(double a, double b)
|
|||
return MakeQuiet(b);
|
||||
|
||||
SetFPException(FPSCR_VXISI);
|
||||
FPSCR.ClearFIFR();
|
||||
return PPC_NAN;
|
||||
}
|
||||
|
||||
if (std::isinf(a) || std::isinf(b))
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -194,10 +189,9 @@ inline double NI_sub(double a, double b)
|
|||
if (std::isnan(t))
|
||||
{
|
||||
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
if (std::isnan(a))
|
||||
return MakeQuiet(a);
|
||||
|
@ -205,10 +199,12 @@ inline double NI_sub(double a, double b)
|
|||
return MakeQuiet(b);
|
||||
|
||||
SetFPException(FPSCR_VXISI);
|
||||
FPSCR.ClearFIFR();
|
||||
return PPC_NAN;
|
||||
}
|
||||
|
||||
if (std::isinf(a) || std::isinf(b))
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -222,10 +218,9 @@ inline double NI_madd(double a, double c, double b)
|
|||
if (std::isnan(t))
|
||||
{
|
||||
if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
if (std::isnan(a))
|
||||
return MakeQuiet(a);
|
||||
|
@ -235,7 +230,6 @@ inline double NI_madd(double a, double c, double b)
|
|||
return MakeQuiet(c);
|
||||
|
||||
SetFPException(FPSCR_VXIMZ);
|
||||
FPSCR.ClearFIFR();
|
||||
return PPC_NAN;
|
||||
}
|
||||
|
||||
|
@ -244,19 +238,20 @@ inline double NI_madd(double a, double c, double b)
|
|||
if (std::isnan(t))
|
||||
{
|
||||
if (Common::IsSNAN(b))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
if (std::isnan(b))
|
||||
return MakeQuiet(b);
|
||||
|
||||
SetFPException(FPSCR_VXISI);
|
||||
FPSCR.ClearFIFR();
|
||||
return PPC_NAN;
|
||||
}
|
||||
|
||||
if (std::isinf(a) || std::isinf(b) || std::isinf(c))
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -267,10 +262,9 @@ inline double NI_msub(double a, double c, double b)
|
|||
if (std::isnan(t))
|
||||
{
|
||||
if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
if (std::isnan(a))
|
||||
return MakeQuiet(a);
|
||||
|
@ -280,7 +274,6 @@ inline double NI_msub(double a, double c, double b)
|
|||
return MakeQuiet(c);
|
||||
|
||||
SetFPException(FPSCR_VXIMZ);
|
||||
FPSCR.ClearFIFR();
|
||||
return PPC_NAN;
|
||||
}
|
||||
|
||||
|
@ -289,19 +282,20 @@ inline double NI_msub(double a, double c, double b)
|
|||
if (std::isnan(t))
|
||||
{
|
||||
if (Common::IsSNAN(b))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
if (std::isnan(b))
|
||||
return MakeQuiet(b);
|
||||
|
||||
SetFPException(FPSCR_VXISI);
|
||||
FPSCR.ClearFIFR();
|
||||
return PPC_NAN;
|
||||
}
|
||||
|
||||
if (std::isinf(a) || std::isinf(b) || std::isinf(c))
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
|
|
@ -409,6 +409,9 @@ void Interpreter::fresx(UGeckoInstruction inst)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (std::isnan(b) || std::isinf(b))
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
compute_result(b);
|
||||
}
|
||||
|
||||
|
@ -452,6 +455,9 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (std::isnan(b) || std::isinf(b))
|
||||
FPSCR.ClearFIFR();
|
||||
|
||||
compute_result(b);
|
||||
}
|
||||
|
||||
|
|
|
@ -124,11 +124,11 @@ void Interpreter::ps_res(UGeckoInstruction inst)
|
|||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
if (std::isnan(a) || std::isinf(a) || std::isnan(b) || std::isinf(b))
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
|
||||
rPS0(inst.FD) = Common::ApproximateReciprocal(a);
|
||||
rPS1(inst.FD) = Common::ApproximateReciprocal(b);
|
||||
|
@ -155,11 +155,11 @@ void Interpreter::ps_rsqrte(UGeckoInstruction inst)
|
|||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
if (std::isnan(ps0) || std::isinf(ps0) || std::isnan(ps1) || std::isinf(ps1))
|
||||
FPSCR.ClearFIFR();
|
||||
}
|
||||
|
||||
if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1))
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
|
||||
rPS0(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps0));
|
||||
rPS1(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps1));
|
||||
|
|
Loading…
Reference in New Issue