Gekko: Add helper function for clearing both FPSCR.FI and FPSCR.FR

This commit is contained in:
Lioncash
2018-06-03 07:51:03 -04:00
parent d6bafbfaaf
commit 3e63d71046
4 changed files with 37 additions and 62 deletions

View File

@@ -476,6 +476,12 @@ union UReg_FPSCR
UReg_FPSCR() = default; UReg_FPSCR() = default;
explicit UReg_FPSCR(u32 hex_) : Hex{hex_} {} explicit UReg_FPSCR(u32 hex_) : Hex{hex_} {}
void ClearFIFR()
{
FI = 0;
FR = 0;
}
}; };
// Hardware Implementation-Dependent Register 0 // Hardware Implementation-Dependent Register 0

View File

@@ -105,8 +105,7 @@ inline double NI_mul(double a, double b)
if (Common::IsSNAN(a) || Common::IsSNAN(b)) if (Common::IsSNAN(a) || Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (std::isnan(a)) if (std::isnan(a))
@@ -115,8 +114,7 @@ inline double NI_mul(double a, double b)
return MakeQuiet(b); return MakeQuiet(b);
SetFPException(FPSCR_VXIMZ); SetFPException(FPSCR_VXIMZ);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
return PPC_NAN; return PPC_NAN;
} }
return t; return t;
@@ -131,8 +129,7 @@ inline double NI_div(double a, double b)
if (Common::IsSNAN(a) || Common::IsSNAN(b)) if (Common::IsSNAN(a) || Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (std::isnan(a)) if (std::isnan(a))
@@ -145,21 +142,18 @@ inline double NI_div(double a, double b)
if (a == 0.0) if (a == 0.0)
{ {
SetFPException(FPSCR_VXZDZ); SetFPException(FPSCR_VXZDZ);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
else else
{ {
SetFPException(FPSCR_ZX); SetFPException(FPSCR_ZX);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
} }
else if (std::isinf(a) && std::isinf(b)) else if (std::isinf(a) && std::isinf(b))
{ {
SetFPException(FPSCR_VXIDI); SetFPException(FPSCR_VXIDI);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
return PPC_NAN; return PPC_NAN;
@@ -177,8 +171,7 @@ inline double NI_add(double a, double b)
if (Common::IsSNAN(a) || Common::IsSNAN(b)) if (Common::IsSNAN(a) || Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (std::isnan(a)) if (std::isnan(a))
@@ -187,8 +180,7 @@ inline double NI_add(double a, double b)
return MakeQuiet(b); return MakeQuiet(b);
SetFPException(FPSCR_VXISI); SetFPException(FPSCR_VXISI);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
return PPC_NAN; return PPC_NAN;
} }
@@ -204,8 +196,7 @@ inline double NI_sub(double a, double b)
if (Common::IsSNAN(a) || Common::IsSNAN(b)) if (Common::IsSNAN(a) || Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (std::isnan(a)) if (std::isnan(a))
@@ -214,8 +205,7 @@ inline double NI_sub(double a, double b)
return MakeQuiet(b); return MakeQuiet(b);
SetFPException(FPSCR_VXISI); SetFPException(FPSCR_VXISI);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
return PPC_NAN; return PPC_NAN;
} }
@@ -234,8 +224,7 @@ inline double NI_madd(double a, double c, double b)
if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c)) if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (std::isnan(a)) if (std::isnan(a))
@@ -246,8 +235,7 @@ inline double NI_madd(double a, double c, double b)
return MakeQuiet(c); return MakeQuiet(c);
SetFPException(FPSCR_VXIMZ); SetFPException(FPSCR_VXIMZ);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
return PPC_NAN; return PPC_NAN;
} }
@@ -258,16 +246,14 @@ inline double NI_madd(double a, double c, double b)
if (Common::IsSNAN(b)) if (Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (std::isnan(b)) if (std::isnan(b))
return MakeQuiet(b); return MakeQuiet(b);
SetFPException(FPSCR_VXISI); SetFPException(FPSCR_VXISI);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
return PPC_NAN; return PPC_NAN;
} }
@@ -283,8 +269,7 @@ inline double NI_msub(double a, double c, double b)
if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c)) if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (std::isnan(a)) if (std::isnan(a))
@@ -295,8 +280,7 @@ inline double NI_msub(double a, double c, double b)
return MakeQuiet(c); return MakeQuiet(c);
SetFPException(FPSCR_VXIMZ); SetFPException(FPSCR_VXIMZ);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
return PPC_NAN; return PPC_NAN;
} }
@@ -307,16 +291,14 @@ inline double NI_msub(double a, double c, double b)
if (Common::IsSNAN(b)) if (Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (std::isnan(b)) if (std::isnan(b))
return MakeQuiet(b); return MakeQuiet(b);
SetFPException(FPSCR_VXISI); SetFPException(FPSCR_VXISI);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
return PPC_NAN; return PPC_NAN;
} }

View File

@@ -92,8 +92,7 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode)
const double di = i; const double di = i;
if (di == b) if (di == b)
{ {
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
else else
{ {
@@ -105,8 +104,7 @@ void ConvertToInteger(UGeckoInstruction inst, RoundingMode rounding_mode)
if (exception_occurred) if (exception_occurred)
{ {
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (!exception_occurred || FPSCR.VE == 0) if (!exception_occurred || FPSCR.VE == 0)
@@ -285,8 +283,7 @@ void Interpreter::frspx(UGeckoInstruction inst) // round to single
PowerPC::UpdateFPRF(b); PowerPC::UpdateFPRF(b);
} }
SetFI(0); FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
else else
{ {
@@ -397,8 +394,7 @@ void Interpreter::fresx(UGeckoInstruction inst)
if (b == 0.0) if (b == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(FPSCR_ZX);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
if (FPSCR.ZE == 0) if (FPSCR.ZE == 0)
compute_result(b); compute_result(b);
@@ -406,8 +402,7 @@ void Interpreter::fresx(UGeckoInstruction inst)
else if (Common::IsSNAN(b)) else if (Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
if (FPSCR.VE == 0) if (FPSCR.VE == 0)
compute_result(b); compute_result(b);
@@ -434,8 +429,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
if (b < 0.0) if (b < 0.0)
{ {
SetFPException(FPSCR_VXSQRT); SetFPException(FPSCR_VXSQRT);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
if (FPSCR.VE == 0) if (FPSCR.VE == 0)
compute_result(b); compute_result(b);
@@ -443,8 +437,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
else if (b == 0.0) else if (b == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(FPSCR_ZX);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
if (FPSCR.ZE == 0) if (FPSCR.ZE == 0)
compute_result(b); compute_result(b);
@@ -452,8 +445,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
else if (Common::IsSNAN(b)) else if (Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
if (FPSCR.VE == 0) if (FPSCR.VE == 0)
compute_result(b); compute_result(b);

View File

@@ -121,15 +121,13 @@ void Interpreter::ps_res(UGeckoInstruction inst)
if (a == 0.0 || b == 0.0) if (a == 0.0 || b == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(FPSCR_ZX);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (Common::IsSNAN(a) || Common::IsSNAN(b)) if (Common::IsSNAN(a) || Common::IsSNAN(b))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
rPS0(inst.FD) = Common::ApproximateReciprocal(a); rPS0(inst.FD) = Common::ApproximateReciprocal(a);
@@ -148,22 +146,19 @@ void Interpreter::ps_rsqrte(UGeckoInstruction inst)
if (ps0 == 0.0 || ps1 == 0.0) if (ps0 == 0.0 || ps1 == 0.0)
{ {
SetFPException(FPSCR_ZX); SetFPException(FPSCR_ZX);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (ps0 < 0.0 || ps1 < 0.0) if (ps0 < 0.0 || ps1 < 0.0)
{ {
SetFPException(FPSCR_VXSQRT); SetFPException(FPSCR_VXSQRT);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1)) if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1))
{ {
SetFPException(FPSCR_VXSNAN); SetFPException(FPSCR_VXSNAN);
FPSCR.FI = 0; FPSCR.ClearFIFR();
FPSCR.FR = 0;
} }
rPS0(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps0)); rPS0(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps0));