Merge pull request #7053 from lioncash/frfi
Interpreter_FPUtils/FloatingPoint/Paired: Amend cases where FPSCR.FR and FPSCR.FI should be unset
This commit is contained in:
commit
c22205cd7e
|
@ -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
|
||||||
|
|
|
@ -103,7 +103,10 @@ inline double NI_mul(double a, double b)
|
||||||
if (std::isnan(t))
|
if (std::isnan(t))
|
||||||
{
|
{
|
||||||
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||||
|
{
|
||||||
SetFPException(FPSCR_VXSNAN);
|
SetFPException(FPSCR_VXSNAN);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
|
}
|
||||||
|
|
||||||
if (std::isnan(a))
|
if (std::isnan(a))
|
||||||
return MakeQuiet(a);
|
return MakeQuiet(a);
|
||||||
|
@ -111,6 +114,7 @@ inline double NI_mul(double a, double b)
|
||||||
return MakeQuiet(b);
|
return MakeQuiet(b);
|
||||||
|
|
||||||
SetFPException(FPSCR_VXIMZ);
|
SetFPException(FPSCR_VXIMZ);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
return PPC_NAN;
|
return PPC_NAN;
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
|
@ -123,7 +127,10 @@ inline double NI_div(double a, double b)
|
||||||
if (std::isnan(t))
|
if (std::isnan(t))
|
||||||
{
|
{
|
||||||
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||||
|
{
|
||||||
SetFPException(FPSCR_VXSNAN);
|
SetFPException(FPSCR_VXSNAN);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
|
}
|
||||||
|
|
||||||
if (std::isnan(a))
|
if (std::isnan(a))
|
||||||
return MakeQuiet(a);
|
return MakeQuiet(a);
|
||||||
|
@ -135,17 +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.ClearFIFR();
|
||||||
}
|
}
|
||||||
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.ClearFIFR();
|
||||||
}
|
}
|
||||||
|
|
||||||
return PPC_NAN;
|
return PPC_NAN;
|
||||||
|
@ -161,7 +169,10 @@ inline double NI_add(double a, double b)
|
||||||
if (std::isnan(t))
|
if (std::isnan(t))
|
||||||
{
|
{
|
||||||
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||||
|
{
|
||||||
SetFPException(FPSCR_VXSNAN);
|
SetFPException(FPSCR_VXSNAN);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
|
}
|
||||||
|
|
||||||
if (std::isnan(a))
|
if (std::isnan(a))
|
||||||
return MakeQuiet(a);
|
return MakeQuiet(a);
|
||||||
|
@ -169,6 +180,7 @@ inline double NI_add(double a, double b)
|
||||||
return MakeQuiet(b);
|
return MakeQuiet(b);
|
||||||
|
|
||||||
SetFPException(FPSCR_VXISI);
|
SetFPException(FPSCR_VXISI);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
return PPC_NAN;
|
return PPC_NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +194,10 @@ inline double NI_sub(double a, double b)
|
||||||
if (std::isnan(t))
|
if (std::isnan(t))
|
||||||
{
|
{
|
||||||
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||||
|
{
|
||||||
SetFPException(FPSCR_VXSNAN);
|
SetFPException(FPSCR_VXSNAN);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
|
}
|
||||||
|
|
||||||
if (std::isnan(a))
|
if (std::isnan(a))
|
||||||
return MakeQuiet(a);
|
return MakeQuiet(a);
|
||||||
|
@ -190,6 +205,7 @@ inline double NI_sub(double a, double b)
|
||||||
return MakeQuiet(b);
|
return MakeQuiet(b);
|
||||||
|
|
||||||
SetFPException(FPSCR_VXISI);
|
SetFPException(FPSCR_VXISI);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
return PPC_NAN;
|
return PPC_NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +222,10 @@ inline double NI_madd(double a, double c, double b)
|
||||||
if (std::isnan(t))
|
if (std::isnan(t))
|
||||||
{
|
{
|
||||||
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.ClearFIFR();
|
||||||
|
}
|
||||||
|
|
||||||
if (std::isnan(a))
|
if (std::isnan(a))
|
||||||
return MakeQuiet(a);
|
return MakeQuiet(a);
|
||||||
|
@ -216,6 +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.ClearFIFR();
|
||||||
return PPC_NAN;
|
return PPC_NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,12 +244,16 @@ inline double NI_madd(double a, double c, double b)
|
||||||
if (std::isnan(t))
|
if (std::isnan(t))
|
||||||
{
|
{
|
||||||
if (Common::IsSNAN(b))
|
if (Common::IsSNAN(b))
|
||||||
|
{
|
||||||
SetFPException(FPSCR_VXSNAN);
|
SetFPException(FPSCR_VXSNAN);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
|
}
|
||||||
|
|
||||||
if (std::isnan(b))
|
if (std::isnan(b))
|
||||||
return MakeQuiet(b);
|
return MakeQuiet(b);
|
||||||
|
|
||||||
SetFPException(FPSCR_VXISI);
|
SetFPException(FPSCR_VXISI);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
return PPC_NAN;
|
return PPC_NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +267,10 @@ inline double NI_msub(double a, double c, double b)
|
||||||
if (std::isnan(t))
|
if (std::isnan(t))
|
||||||
{
|
{
|
||||||
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.ClearFIFR();
|
||||||
|
}
|
||||||
|
|
||||||
if (std::isnan(a))
|
if (std::isnan(a))
|
||||||
return MakeQuiet(a);
|
return MakeQuiet(a);
|
||||||
|
@ -253,6 +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.ClearFIFR();
|
||||||
return PPC_NAN;
|
return PPC_NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,12 +289,16 @@ inline double NI_msub(double a, double c, double b)
|
||||||
if (std::isnan(t))
|
if (std::isnan(t))
|
||||||
{
|
{
|
||||||
if (Common::IsSNAN(b))
|
if (Common::IsSNAN(b))
|
||||||
|
{
|
||||||
SetFPException(FPSCR_VXSNAN);
|
SetFPException(FPSCR_VXSNAN);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
|
}
|
||||||
|
|
||||||
if (std::isnan(b))
|
if (std::isnan(b))
|
||||||
return MakeQuiet(b);
|
return MakeQuiet(b);
|
||||||
|
|
||||||
SetFPException(FPSCR_VXISI);
|
SetFPException(FPSCR_VXISI);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
return PPC_NAN;
|
return PPC_NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,6 +394,7 @@ void Interpreter::fresx(UGeckoInstruction inst)
|
||||||
if (b == 0.0)
|
if (b == 0.0)
|
||||||
{
|
{
|
||||||
SetFPException(FPSCR_ZX);
|
SetFPException(FPSCR_ZX);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
|
|
||||||
if (FPSCR.ZE == 0)
|
if (FPSCR.ZE == 0)
|
||||||
compute_result(b);
|
compute_result(b);
|
||||||
|
@ -404,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);
|
||||||
|
@ -432,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);
|
||||||
|
@ -441,6 +437,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
|
||||||
else if (b == 0.0)
|
else if (b == 0.0)
|
||||||
{
|
{
|
||||||
SetFPException(FPSCR_ZX);
|
SetFPException(FPSCR_ZX);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
|
|
||||||
if (FPSCR.ZE == 0)
|
if (FPSCR.ZE == 0)
|
||||||
compute_result(b);
|
compute_result(b);
|
||||||
|
@ -448,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);
|
||||||
|
|
|
@ -115,12 +115,19 @@ void Interpreter::ps_div(UGeckoInstruction inst)
|
||||||
void Interpreter::ps_res(UGeckoInstruction inst)
|
void Interpreter::ps_res(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
// this code is based on the real hardware tests
|
// this code is based on the real hardware tests
|
||||||
double a = rPS0(inst.FB);
|
const double a = rPS0(inst.FB);
|
||||||
double b = rPS1(inst.FB);
|
const double b = rPS1(inst.FB);
|
||||||
|
|
||||||
if (a == 0.0 || b == 0.0)
|
if (a == 0.0 || b == 0.0)
|
||||||
{
|
{
|
||||||
SetFPException(FPSCR_ZX);
|
SetFPException(FPSCR_ZX);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Common::IsSNAN(a) || Common::IsSNAN(b))
|
||||||
|
{
|
||||||
|
SetFPException(FPSCR_VXSNAN);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
}
|
}
|
||||||
|
|
||||||
rPS0(inst.FD) = Common::ApproximateReciprocal(a);
|
rPS0(inst.FD) = Common::ApproximateReciprocal(a);
|
||||||
|
@ -133,18 +140,29 @@ void Interpreter::ps_res(UGeckoInstruction inst)
|
||||||
|
|
||||||
void Interpreter::ps_rsqrte(UGeckoInstruction inst)
|
void Interpreter::ps_rsqrte(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
if (rPS0(inst.FB) == 0.0 || rPS1(inst.FB) == 0.0)
|
const double ps0 = rPS0(inst.FB);
|
||||||
|
const double ps1 = rPS1(inst.FB);
|
||||||
|
|
||||||
|
if (ps0 == 0.0 || ps1 == 0.0)
|
||||||
{
|
{
|
||||||
SetFPException(FPSCR_ZX);
|
SetFPException(FPSCR_ZX);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rPS0(inst.FB) < 0.0 || rPS1(inst.FB) < 0.0)
|
if (ps0 < 0.0 || ps1 < 0.0)
|
||||||
{
|
{
|
||||||
SetFPException(FPSCR_VXSQRT);
|
SetFPException(FPSCR_VXSQRT);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
}
|
}
|
||||||
|
|
||||||
rPS0(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(rPS0(inst.FB)));
|
if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1))
|
||||||
rPS1(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(rPS1(inst.FB)));
|
{
|
||||||
|
SetFPException(FPSCR_VXSNAN);
|
||||||
|
FPSCR.ClearFIFR();
|
||||||
|
}
|
||||||
|
|
||||||
|
rPS0(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps0));
|
||||||
|
rPS1(inst.FD) = ForceSingle(Common::ApproximateReciprocalSquareRoot(ps1));
|
||||||
|
|
||||||
PowerPC::UpdateFPRF(rPS0(inst.FD));
|
PowerPC::UpdateFPRF(rPS0(inst.FD));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue