Merge pull request #6993 from lioncash/nan

Interpreter_FPUtils: Set VXSNAN if any input operands are a signaling NaN in remaining NI_* functions
This commit is contained in:
Léo Lam 2018-05-28 18:49:13 +02:00 committed by GitHub
commit a9f022a067
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -113,13 +113,18 @@ inline double NI_mul(double a, double b)
inline double NI_div(double a, double b) inline double NI_div(double a, double b)
{ {
double t = a / b; const double t = a / b;
if (std::isnan(t)) if (std::isnan(t))
{ {
if (Common::IsSNAN(a) || Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
if (std::isnan(a)) if (std::isnan(a))
return MakeQuiet(a); return MakeQuiet(a);
if (std::isnan(b)) if (std::isnan(b))
return MakeQuiet(b); return MakeQuiet(b);
if (b == 0.0) if (b == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(FPSCR_ZX);
@ -130,8 +135,10 @@ inline double NI_div(double a, double b)
{ {
SetFPException(FPSCR_VXIDI); SetFPException(FPSCR_VXIDI);
} }
return PPC_NAN; return PPC_NAN;
} }
return t; return t;
} }
@ -158,16 +165,22 @@ inline double NI_add(double a, double b)
inline double NI_sub(double a, double b) inline double NI_sub(double a, double b)
{ {
double t = a - b; const double t = a - b;
if (std::isnan(t)) if (std::isnan(t))
{ {
if (Common::IsSNAN(a) || Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
if (std::isnan(a)) if (std::isnan(a))
return MakeQuiet(a); return MakeQuiet(a);
if (std::isnan(b)) if (std::isnan(b))
return MakeQuiet(b); return MakeQuiet(b);
SetFPException(FPSCR_VXISI); SetFPException(FPSCR_VXISI);
return PPC_NAN; return PPC_NAN;
} }
return t; return t;
} }
@ -177,51 +190,74 @@ inline double NI_sub(double a, double b)
inline double NI_madd(double a, double c, double b) inline double NI_madd(double a, double c, double b)
{ {
double t = a * c; double t = a * c;
if (std::isnan(t)) if (std::isnan(t))
{ {
if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c))
SetFPException(FPSCR_VXSNAN);
if (std::isnan(a)) if (std::isnan(a))
return MakeQuiet(a); return MakeQuiet(a);
if (std::isnan(b)) if (std::isnan(b))
return MakeQuiet(b); // ! return MakeQuiet(b); // !
if (std::isnan(c)) if (std::isnan(c))
return MakeQuiet(c); return MakeQuiet(c);
SetFPException(FPSCR_VXIMZ); SetFPException(FPSCR_VXIMZ);
return PPC_NAN; return PPC_NAN;
} }
t += b; t += b;
if (std::isnan(t)) if (std::isnan(t))
{ {
if (Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
if (std::isnan(b)) if (std::isnan(b))
return MakeQuiet(b); return MakeQuiet(b);
SetFPException(FPSCR_VXISI); SetFPException(FPSCR_VXISI);
return PPC_NAN; return PPC_NAN;
} }
return t; return t;
} }
inline double NI_msub(double a, double c, double b) inline double NI_msub(double a, double c, double b)
{ {
double t = a * c; double t = a * c;
if (std::isnan(t)) if (std::isnan(t))
{ {
if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c))
SetFPException(FPSCR_VXSNAN);
if (std::isnan(a)) if (std::isnan(a))
return MakeQuiet(a); return MakeQuiet(a);
if (std::isnan(b)) if (std::isnan(b))
return MakeQuiet(b); // ! return MakeQuiet(b); // !
if (std::isnan(c)) if (std::isnan(c))
return MakeQuiet(c); return MakeQuiet(c);
SetFPException(FPSCR_VXIMZ); SetFPException(FPSCR_VXIMZ);
return PPC_NAN; return PPC_NAN;
} }
t -= b; t -= b;
if (std::isnan(t)) if (std::isnan(t))
{ {
if (Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
if (std::isnan(b)) if (std::isnan(b))
return MakeQuiet(b); return MakeQuiet(b);
SetFPException(FPSCR_VXISI); SetFPException(FPSCR_VXISI);
return PPC_NAN; return PPC_NAN;
} }
return t; return t;
} }