Permalink
Browse files

Interpreter_FPUtils: Unset FPSCR.FI and FPSCR.FR if an invalid operat…

…ion occurs in NI_* functions

If an invalid operation occurs, FI and FR bits are defined to be cleared
to zero for arithmetic operations.
  • Loading branch information...
lioncash committed Jun 3, 2018
1 parent 0f7370a commit 468efb7243a50652bb17f68cd384523faa90f2ef
Showing with 50 additions and 0 deletions.
  1. +50 −0 Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h
@@ -103,14 +103,20 @@ inline double NI_mul(double a, double b)
if (std::isnan(t))
{
if (Common::IsSNAN(a) || Common::IsSNAN(b))
{
SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
if (std::isnan(a))
return MakeQuiet(a);
if (std::isnan(b))
return MakeQuiet(b);
SetFPException(FPSCR_VXIMZ);
FPSCR.FI = 0;
FPSCR.FR = 0;
return PPC_NAN;
}
return t;
@@ -123,7 +129,11 @@ inline double NI_div(double a, double b)
if (std::isnan(t))
{
if (Common::IsSNAN(a) || Common::IsSNAN(b))
{
SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
if (std::isnan(a))
return MakeQuiet(a);
@@ -135,6 +145,8 @@ inline double NI_div(double a, double b)
if (a == 0.0)
{
SetFPException(FPSCR_VXZDZ);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
else
{
@@ -146,6 +158,8 @@ inline double NI_div(double a, double b)
else if (std::isinf(a) && std::isinf(b))
{
SetFPException(FPSCR_VXIDI);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
return PPC_NAN;
@@ -161,14 +175,20 @@ inline double NI_add(double a, double b)
if (std::isnan(t))
{
if (Common::IsSNAN(a) || Common::IsSNAN(b))
{
SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
if (std::isnan(a))
return MakeQuiet(a);
if (std::isnan(b))
return MakeQuiet(b);
SetFPException(FPSCR_VXISI);
FPSCR.FI = 0;
FPSCR.FR = 0;
return PPC_NAN;
}
@@ -182,14 +202,20 @@ inline double NI_sub(double a, double b)
if (std::isnan(t))
{
if (Common::IsSNAN(a) || Common::IsSNAN(b))
{
SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
if (std::isnan(a))
return MakeQuiet(a);
if (std::isnan(b))
return MakeQuiet(b);
SetFPException(FPSCR_VXISI);
FPSCR.FI = 0;
FPSCR.FR = 0;
return PPC_NAN;
}
@@ -206,7 +232,11 @@ 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.FI = 0;
FPSCR.FR = 0;
}
if (std::isnan(a))
return MakeQuiet(a);
@@ -216,6 +246,8 @@ inline double NI_madd(double a, double c, double b)
return MakeQuiet(c);
SetFPException(FPSCR_VXIMZ);
FPSCR.FI = 0;
FPSCR.FR = 0;
return PPC_NAN;
}
@@ -224,12 +256,18 @@ inline double NI_madd(double a, double c, double b)
if (std::isnan(t))
{
if (Common::IsSNAN(b))
{
SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
if (std::isnan(b))
return MakeQuiet(b);
SetFPException(FPSCR_VXISI);
FPSCR.FI = 0;
FPSCR.FR = 0;
return PPC_NAN;
}
@@ -243,7 +281,11 @@ 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.FI = 0;
FPSCR.FR = 0;
}
if (std::isnan(a))
return MakeQuiet(a);
@@ -253,6 +295,8 @@ inline double NI_msub(double a, double c, double b)
return MakeQuiet(c);
SetFPException(FPSCR_VXIMZ);
FPSCR.FI = 0;
FPSCR.FR = 0;
return PPC_NAN;
}
@@ -261,12 +305,18 @@ inline double NI_msub(double a, double c, double b)
if (std::isnan(t))
{
if (Common::IsSNAN(b))
{
SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0;
FPSCR.FR = 0;
}
if (std::isnan(b))
return MakeQuiet(b);
SetFPException(FPSCR_VXISI);
FPSCR.FI = 0;
FPSCR.FR = 0;
return PPC_NAN;
}

0 comments on commit 468efb7

Please sign in to comment.