Permalink
Browse files

Merge pull request #7063 from lioncash/fifr

Interpreter: Unset FPSCR.FI and FPSCR.FR for QNaN and infinity input operands
  • Loading branch information...
leoetlino committed Jun 4, 2018
2 parents 6ce9c96 + 9068109 commit 5f29e891d369079d545c20c7a2e7e864c8c94c29
@@ -103,18 +103,16 @@ 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);
if (std::isnan(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,21 +163,22 @@ 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);
if (std::isnan(b))
return MakeQuiet(b);
SetFPException(FPSCR_VXISI);
FPSCR.ClearFIFR();
return PPC_NAN;
}
if (std::isinf(a) || std::isinf(b))
FPSCR.ClearFIFR();
return t;
}
@@ -194,21 +189,22 @@ 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);
if (std::isnan(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 (std::isnan(a) || std::isinf(a) || std::isnan(b) || std::isinf(b))
FPSCR.ClearFIFR();
if (Common::IsSNAN(a) || Common::IsSNAN(b))
{
SetFPException(FPSCR_VXSNAN);
FPSCR.ClearFIFR();
}
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 (std::isnan(ps0) || std::isinf(ps0) || std::isnan(ps1) || std::isinf(ps1))
FPSCR.ClearFIFR();
if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1))
{
SetFPException(FPSCR_VXSNAN);
FPSCR.ClearFIFR();
}
rPS0(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps0));
rPS1(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps1));

0 comments on commit 5f29e89

Please sign in to comment.