summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLioncash <mathew1800@gmail.com>2018-06-02 20:13:30 -0400
committerLioncash <mathew1800@gmail.com>2018-06-02 20:18:51 -0400
commit468efb7243a50652bb17f68cd384523faa90f2ef (patch)
treeb630a4b08ec4604a1dbc41e5247495fac3bf2f4a /Source/Core
parent0f7370a22c67bf668fff165ac0bcff2dfc0eceb8 (diff)
Interpreter_FPUtils: Unset FPSCR.FI and FPSCR.FR if an invalid operation occurs in NI_* functions
If an invalid operation occurs, FI and FR bits are defined to be cleared to zero for arithmetic operations.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h50
1 files changed, 50 insertions, 0 deletions
diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h
index abc798d220..666ca2bffb 100644
--- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h
+++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h
@@ -103,7 +103,11 @@ 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);
@@ -111,6 +115,8 @@ inline double NI_mul(double a, double 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,7 +175,11 @@ 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);
@@ -169,6 +187,8 @@ inline double NI_add(double a, double b)
return MakeQuiet(b);
SetFPException(FPSCR_VXISI);
+ FPSCR.FI = 0;
+ FPSCR.FR = 0;
return PPC_NAN;
}
@@ -182,7 +202,11 @@ 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);
@@ -190,6 +214,8 @@ inline double NI_sub(double a, double 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;
}