Merge pull request #7141 from lioncash/fp

Interpreter_FPUtils: Handle the FPSCR.ZE and FPSCR.VE flags with arithmetic instructions
This commit is contained in:
Mat M 2018-07-04 22:26:24 -04:00 committed by GitHub
commit 9ea3e833ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 334 additions and 165 deletions

View File

@ -97,206 +97,280 @@ inline double MakeQuiet(double d)
// these functions allow globally modify operations behaviour
// also, these may be used to set flags like FR, FI, OX, UX
inline double NI_mul(double a, double b)
struct FPResult
{
const double t = a * b;
if (std::isnan(t))
bool HasNoInvalidExceptions() const { return (exception & FPSCR_VX_ANY) == 0; }
void SetException(FPSCRExceptionFlag flag)
{
exception = flag;
SetFPException(flag);
}
double value = 0.0;
FPSCRExceptionFlag exception{};
};
inline FPResult NI_mul(double a, double b)
{
FPResult result{a * b};
if (std::isnan(result.value))
{
if (Common::IsSNAN(a) || Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
{
result.SetException(FPSCR_VXSNAN);
}
FPSCR.ClearFIFR();
if (std::isnan(a))
return MakeQuiet(a);
{
result.value = MakeQuiet(a);
return result;
}
if (std::isnan(b))
return MakeQuiet(b);
{
result.value = MakeQuiet(b);
return result;
}
SetFPException(FPSCR_VXIMZ);
return PPC_NAN;
result.value = PPC_NAN;
result.SetException(FPSCR_VXIMZ);
return result;
}
return t;
return result;
}
inline double NI_div(double a, double b)
inline FPResult NI_div(double a, double b)
{
const double t = a / b;
FPResult result{a / b};
if (std::isnan(t))
if (std::isnan(result.value))
{
if (Common::IsSNAN(a) || Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
result.SetException(FPSCR_VXSNAN);
FPSCR.ClearFIFR();
if (std::isnan(a))
return MakeQuiet(a);
{
result.value = MakeQuiet(a);
return result;
}
if (std::isnan(b))
return MakeQuiet(b);
{
result.value = MakeQuiet(b);
return result;
}
if (b == 0.0)
{
if (a == 0.0)
{
SetFPException(FPSCR_VXZDZ);
result.SetException(FPSCR_VXZDZ);
}
else
{
SetFPException(FPSCR_ZX);
result.SetException(FPSCR_ZX);
}
}
else if (std::isinf(a) && std::isinf(b))
{
SetFPException(FPSCR_VXIDI);
result.SetException(FPSCR_VXIDI);
}
return PPC_NAN;
result.value = PPC_NAN;
return result;
}
return t;
return result;
}
inline double NI_add(double a, double b)
inline FPResult NI_add(double a, double b)
{
const double t = a + b;
FPResult result{a + b};
if (std::isnan(t))
if (std::isnan(result.value))
{
if (Common::IsSNAN(a) || Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
result.SetException(FPSCR_VXSNAN);
FPSCR.ClearFIFR();
if (std::isnan(a))
return MakeQuiet(a);
{
result.value = MakeQuiet(a);
return result;
}
if (std::isnan(b))
return MakeQuiet(b);
{
result.value = MakeQuiet(b);
return result;
}
SetFPException(FPSCR_VXISI);
return PPC_NAN;
result.SetException(FPSCR_VXISI);
result.value = PPC_NAN;
return result;
}
if (std::isinf(a) || std::isinf(b))
FPSCR.ClearFIFR();
return t;
return result;
}
inline double NI_sub(double a, double b)
inline FPResult NI_sub(double a, double b)
{
const double t = a - b;
FPResult result{a - b};
if (std::isnan(t))
if (std::isnan(result.value))
{
if (Common::IsSNAN(a) || Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
result.SetException(FPSCR_VXSNAN);
FPSCR.ClearFIFR();
if (std::isnan(a))
return MakeQuiet(a);
{
result.value = MakeQuiet(a);
return result;
}
if (std::isnan(b))
return MakeQuiet(b);
{
result.value = MakeQuiet(b);
return result;
}
SetFPException(FPSCR_VXISI);
return PPC_NAN;
result.SetException(FPSCR_VXISI);
result.value = PPC_NAN;
return result;
}
if (std::isinf(a) || std::isinf(b))
FPSCR.ClearFIFR();
return t;
return result;
}
// FMA instructions on PowerPC are weird:
// They calculate (a * c) + b, but the order in which
// inputs are checked for NaN is still a, b, c.
inline double NI_madd(double a, double c, double b)
inline FPResult NI_madd(double a, double c, double b)
{
double t = a * c;
FPResult result{a * c};
if (std::isnan(t))
if (std::isnan(result.value))
{
if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c))
SetFPException(FPSCR_VXSNAN);
result.SetException(FPSCR_VXSNAN);
FPSCR.ClearFIFR();
if (std::isnan(a))
return MakeQuiet(a);
{
result.value = MakeQuiet(a);
return result;
}
if (std::isnan(b))
return MakeQuiet(b); // !
{
result.value = MakeQuiet(b); // !
return result;
}
if (std::isnan(c))
return MakeQuiet(c);
{
result.value = MakeQuiet(c);
return result;
}
SetFPException(FPSCR_VXIMZ);
return PPC_NAN;
result.SetException(FPSCR_VXIMZ);
result.value = PPC_NAN;
return result;
}
t += b;
result.value += b;
if (std::isnan(t))
if (std::isnan(result.value))
{
if (Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
result.SetException(FPSCR_VXSNAN);
FPSCR.ClearFIFR();
if (std::isnan(b))
return MakeQuiet(b);
{
result.value = MakeQuiet(b);
return result;
}
SetFPException(FPSCR_VXISI);
return PPC_NAN;
result.SetException(FPSCR_VXISI);
result.value = PPC_NAN;
return result;
}
if (std::isinf(a) || std::isinf(b) || std::isinf(c))
FPSCR.ClearFIFR();
return t;
return result;
}
inline double NI_msub(double a, double c, double b)
inline FPResult NI_msub(double a, double c, double b)
{
double t = a * c;
FPResult result{a * c};
if (std::isnan(t))
if (std::isnan(result.value))
{
if (Common::IsSNAN(a) || Common::IsSNAN(b) || Common::IsSNAN(c))
SetFPException(FPSCR_VXSNAN);
result.SetException(FPSCR_VXSNAN);
FPSCR.ClearFIFR();
if (std::isnan(a))
return MakeQuiet(a);
{
result.value = MakeQuiet(a);
return result;
}
if (std::isnan(b))
return MakeQuiet(b); // !
{
result.value = MakeQuiet(b); // !
return result;
}
if (std::isnan(c))
return MakeQuiet(c);
{
result.value = MakeQuiet(c);
return result;
}
SetFPException(FPSCR_VXIMZ);
return PPC_NAN;
result.SetException(FPSCR_VXIMZ);
result.value = PPC_NAN;
return result;
}
t -= b;
result.value -= b;
if (std::isnan(t))
if (std::isnan(result.value))
{
if (Common::IsSNAN(b))
SetFPException(FPSCR_VXSNAN);
result.SetException(FPSCR_VXSNAN);
FPSCR.ClearFIFR();
if (std::isnan(b))
return MakeQuiet(b);
{
result.value = MakeQuiet(b);
return result;
}
SetFPException(FPSCR_VXISI);
return PPC_NAN;
result.SetException(FPSCR_VXISI);
result.value = PPC_NAN;
return result;
}
if (std::isinf(a) || std::isinf(b) || std::isinf(c))
FPSCR.ClearFIFR();
return t;
return result;
}
// used by stfsXX instructions and ps_rsqrte

View File

@ -300,23 +300,35 @@ void Interpreter::frspx(UGeckoInstruction inst) // round to single
void Interpreter::fmulx(UGeckoInstruction inst)
{
rPS0(inst.FD) = ForceDouble(NI_mul(rPS0(inst.FA), rPS0(inst.FC)));
FPSCR.FI = 0; // are these flags important?
FPSCR.FR = 0;
PowerPC::UpdateFPRF(rPS0(inst.FD));
const FPResult product = NI_mul(rPS0(inst.FA), rPS0(inst.FC));
if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{
const double result = ForceDouble(product.value);
rPS0(inst.FD) = result;
FPSCR.FI = 0; // are these flags important?
FPSCR.FR = 0;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();
}
void Interpreter::fmulsx(UGeckoInstruction inst)
{
double c_value = Force25Bit(rPS0(inst.FC));
double d_value = NI_mul(rPS0(inst.FA), c_value);
rPS0(inst.FD) = rPS1(inst.FD) = ForceSingle(d_value);
// FPSCR.FI = d_value != rPS0(_inst.FD);
FPSCR.FI = 0;
FPSCR.FR = 0;
PowerPC::UpdateFPRF(rPS0(inst.FD));
const double c_value = Force25Bit(rPS0(inst.FC));
const FPResult d_value = NI_mul(rPS0(inst.FA), c_value);
if (FPSCR.VE == 0 || d_value.HasNoInvalidExceptions())
{
const double result = ForceSingle(d_value.value);
rPS0(inst.FD) = rPS1(inst.FD) = result;
FPSCR.FI = 0;
FPSCR.FR = 0;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();
@ -324,9 +336,14 @@ void Interpreter::fmulsx(UGeckoInstruction inst)
void Interpreter::fmaddx(UGeckoInstruction inst)
{
double result = ForceDouble(NI_madd(rPS0(inst.FA), rPS0(inst.FC), rPS0(inst.FB)));
rPS0(inst.FD) = result;
PowerPC::UpdateFPRF(result);
const FPResult product = NI_madd(rPS0(inst.FA), rPS0(inst.FC), rPS0(inst.FB));
if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{
const double result = ForceDouble(product.value);
rPS0(inst.FD) = result;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();
@ -334,12 +351,18 @@ void Interpreter::fmaddx(UGeckoInstruction inst)
void Interpreter::fmaddsx(UGeckoInstruction inst)
{
double c_value = Force25Bit(rPS0(inst.FC));
double d_value = NI_madd(rPS0(inst.FA), c_value, rPS0(inst.FB));
rPS0(inst.FD) = rPS1(inst.FD) = ForceSingle(d_value);
FPSCR.FI = d_value != rPS0(inst.FD);
FPSCR.FR = 0;
PowerPC::UpdateFPRF(rPS0(inst.FD));
const double c_value = Force25Bit(rPS0(inst.FC));
const FPResult d_value = NI_madd(rPS0(inst.FA), c_value, rPS0(inst.FB));
if (FPSCR.VE == 0 || d_value.HasNoInvalidExceptions())
{
const double result = ForceSingle(d_value.value);
rPS0(inst.FD) = rPS1(inst.FD) = result;
FPSCR.FI = d_value.value != result;
FPSCR.FR = 0;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();
@ -347,16 +370,28 @@ void Interpreter::fmaddsx(UGeckoInstruction inst)
void Interpreter::faddx(UGeckoInstruction inst)
{
rPS0(inst.FD) = ForceDouble(NI_add(rPS0(inst.FA), rPS0(inst.FB)));
PowerPC::UpdateFPRF(rPS0(inst.FD));
const FPResult sum = NI_add(rPS0(inst.FA), rPS0(inst.FB));
if (FPSCR.VE == 0 || sum.HasNoInvalidExceptions())
{
const double result = ForceDouble(sum.value);
rPS0(inst.FD) = result;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();
}
void Interpreter::faddsx(UGeckoInstruction inst)
{
rPS0(inst.FD) = rPS1(inst.FD) = ForceSingle(NI_add(rPS0(inst.FA), rPS0(inst.FB)));
PowerPC::UpdateFPRF(rPS0(inst.FD));
const FPResult sum = NI_add(rPS0(inst.FA), rPS0(inst.FB));
if (FPSCR.VE == 0 || sum.HasNoInvalidExceptions())
{
const double result = ForceSingle(sum.value);
rPS0(inst.FD) = rPS1(inst.FD) = result;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();
@ -364,8 +399,16 @@ void Interpreter::faddsx(UGeckoInstruction inst)
void Interpreter::fdivx(UGeckoInstruction inst)
{
rPS0(inst.FD) = ForceDouble(NI_div(rPS0(inst.FA), rPS0(inst.FB)));
PowerPC::UpdateFPRF(rPS0(inst.FD));
const FPResult quotient = NI_div(rPS0(inst.FA), rPS0(inst.FB));
const bool not_divide_by_zero = FPSCR.ZE == 0 || quotient.exception != FPSCR_ZX;
const bool not_invalid = FPSCR.VE == 0 || quotient.HasNoInvalidExceptions();
if (not_divide_by_zero && not_invalid)
{
const double result = ForceDouble(quotient.value);
rPS0(inst.FD) = result;
PowerPC::UpdateFPRF(result);
}
// FR,FI,OX,UX???
if (inst.Rc)
@ -373,8 +416,16 @@ void Interpreter::fdivx(UGeckoInstruction inst)
}
void Interpreter::fdivsx(UGeckoInstruction inst)
{
rPS0(inst.FD) = rPS1(inst.FD) = ForceSingle(NI_div(rPS0(inst.FA), rPS0(inst.FB)));
PowerPC::UpdateFPRF(rPS0(inst.FD));
const FPResult quotient = NI_div(rPS0(inst.FA), rPS0(inst.FB));
const bool not_divide_by_zero = FPSCR.ZE == 0 || quotient.exception != FPSCR_ZX;
const bool not_invalid = FPSCR.VE == 0 || quotient.HasNoInvalidExceptions();
if (not_divide_by_zero && not_invalid)
{
const double result = ForceSingle(quotient.value);
rPS0(inst.FD) = rPS1(inst.FD) = result;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();
@ -465,20 +516,32 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
Helper_UpdateCR1();
}
void Interpreter::fmsubx(UGeckoInstruction _inst)
void Interpreter::fmsubx(UGeckoInstruction inst)
{
rPS0(_inst.FD) = ForceDouble(NI_msub(rPS0(_inst.FA), rPS0(_inst.FC), rPS0(_inst.FB)));
PowerPC::UpdateFPRF(rPS0(_inst.FD));
const FPResult product = NI_msub(rPS0(inst.FA), rPS0(inst.FC), rPS0(inst.FB));
if (_inst.Rc)
if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{
const double result = ForceDouble(product.value);
rPS0(inst.FD) = result;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();
}
void Interpreter::fmsubsx(UGeckoInstruction inst)
{
double c_value = Force25Bit(rPS0(inst.FC));
rPS0(inst.FD) = rPS1(inst.FD) = ForceSingle(NI_msub(rPS0(inst.FA), c_value, rPS0(inst.FB)));
PowerPC::UpdateFPRF(rPS0(inst.FD));
const double c_value = Force25Bit(rPS0(inst.FC));
const FPResult product = NI_msub(rPS0(inst.FA), c_value, rPS0(inst.FB));
if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{
const double result = ForceSingle(product.value);
rPS0(inst.FD) = rPS1(inst.FD) = result;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();
@ -486,9 +549,14 @@ void Interpreter::fmsubsx(UGeckoInstruction inst)
void Interpreter::fnmaddx(UGeckoInstruction inst)
{
double result = ForceDouble(NI_madd(rPS0(inst.FA), rPS0(inst.FC), rPS0(inst.FB)));
rPS0(inst.FD) = std::isnan(result) ? result : -result;
PowerPC::UpdateFPRF(rPS0(inst.FD));
const FPResult product = NI_madd(rPS0(inst.FA), rPS0(inst.FC), rPS0(inst.FB));
if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{
const double result = ForceDouble(product.value);
rPS0(inst.FD) = std::isnan(result) ? result : -result;
PowerPC::UpdateFPRF(rPS0(inst.FD));
}
if (inst.Rc)
Helper_UpdateCR1();
@ -496,10 +564,15 @@ void Interpreter::fnmaddx(UGeckoInstruction inst)
void Interpreter::fnmaddsx(UGeckoInstruction inst)
{
double c_value = Force25Bit(rPS0(inst.FC));
double result = ForceSingle(NI_madd(rPS0(inst.FA), c_value, rPS0(inst.FB)));
rPS0(inst.FD) = rPS1(inst.FD) = std::isnan(result) ? result : -result;
PowerPC::UpdateFPRF(rPS0(inst.FD));
const double c_value = Force25Bit(rPS0(inst.FC));
const FPResult product = NI_madd(rPS0(inst.FA), c_value, rPS0(inst.FB));
if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{
const double result = ForceSingle(product.value);
rPS0(inst.FD) = rPS1(inst.FD) = std::isnan(result) ? result : -result;
PowerPC::UpdateFPRF(rPS0(inst.FD));
}
if (inst.Rc)
Helper_UpdateCR1();
@ -507,9 +580,14 @@ void Interpreter::fnmaddsx(UGeckoInstruction inst)
void Interpreter::fnmsubx(UGeckoInstruction inst)
{
double result = ForceDouble(NI_msub(rPS0(inst.FA), rPS0(inst.FC), rPS0(inst.FB)));
rPS0(inst.FD) = std::isnan(result) ? result : -result;
PowerPC::UpdateFPRF(rPS0(inst.FD));
const FPResult product = NI_msub(rPS0(inst.FA), rPS0(inst.FC), rPS0(inst.FB));
if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{
const double result = ForceDouble(product.value);
rPS0(inst.FD) = std::isnan(result) ? result : -result;
PowerPC::UpdateFPRF(rPS0(inst.FD));
}
if (inst.Rc)
Helper_UpdateCR1();
@ -517,10 +595,15 @@ void Interpreter::fnmsubx(UGeckoInstruction inst)
void Interpreter::fnmsubsx(UGeckoInstruction inst)
{
double c_value = Force25Bit(rPS0(inst.FC));
double result = ForceSingle(NI_msub(rPS0(inst.FA), c_value, rPS0(inst.FB)));
rPS0(inst.FD) = rPS1(inst.FD) = std::isnan(result) ? result : -result;
PowerPC::UpdateFPRF(rPS0(inst.FD));
const double c_value = Force25Bit(rPS0(inst.FC));
const FPResult product = NI_msub(rPS0(inst.FA), c_value, rPS0(inst.FB));
if (FPSCR.VE == 0 || product.HasNoInvalidExceptions())
{
const double result = ForceSingle(product.value);
rPS0(inst.FD) = rPS1(inst.FD) = std::isnan(result) ? result : -result;
PowerPC::UpdateFPRF(rPS0(inst.FD));
}
if (inst.Rc)
Helper_UpdateCR1();
@ -528,8 +611,14 @@ void Interpreter::fnmsubsx(UGeckoInstruction inst)
void Interpreter::fsubx(UGeckoInstruction inst)
{
rPS0(inst.FD) = ForceDouble(NI_sub(rPS0(inst.FA), rPS0(inst.FB)));
PowerPC::UpdateFPRF(rPS0(inst.FD));
const FPResult difference = NI_sub(rPS0(inst.FA), rPS0(inst.FB));
if (FPSCR.VE == 0 || difference.HasNoInvalidExceptions())
{
const double result = ForceDouble(difference.value);
rPS0(inst.FD) = result;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();
@ -537,8 +626,14 @@ void Interpreter::fsubx(UGeckoInstruction inst)
void Interpreter::fsubsx(UGeckoInstruction inst)
{
rPS0(inst.FD) = rPS1(inst.FD) = ForceSingle(NI_sub(rPS0(inst.FA), rPS0(inst.FB)));
PowerPC::UpdateFPRF(rPS0(inst.FD));
const FPResult difference = NI_sub(rPS0(inst.FA), rPS0(inst.FB));
if (FPSCR.VE == 0 || difference.HasNoInvalidExceptions())
{
const double result = ForceSingle(difference.value);
rPS0(inst.FD) = rPS1(inst.FD) = result;
PowerPC::UpdateFPRF(result);
}
if (inst.Rc)
Helper_UpdateCR1();

View File

@ -104,8 +104,8 @@ void Interpreter::ps_merge11(UGeckoInstruction inst)
// From here on, the real deal.
void Interpreter::ps_div(UGeckoInstruction inst)
{
rPS0(inst.FD) = ForceSingle(NI_div(rPS0(inst.FA), rPS0(inst.FB)));
rPS1(inst.FD) = ForceSingle(NI_div(rPS1(inst.FA), rPS1(inst.FB)));
rPS0(inst.FD) = ForceSingle(NI_div(rPS0(inst.FA), rPS0(inst.FB)).value);
rPS1(inst.FD) = ForceSingle(NI_div(rPS1(inst.FA), rPS1(inst.FB)).value);
PowerPC::UpdateFPRF(rPS0(inst.FD));
if (inst.Rc)
@ -172,8 +172,8 @@ void Interpreter::ps_rsqrte(UGeckoInstruction inst)
void Interpreter::ps_sub(UGeckoInstruction inst)
{
rPS0(inst.FD) = ForceSingle(NI_sub(rPS0(inst.FA), rPS0(inst.FB)));
rPS1(inst.FD) = ForceSingle(NI_sub(rPS1(inst.FA), rPS1(inst.FB)));
rPS0(inst.FD) = ForceSingle(NI_sub(rPS0(inst.FA), rPS0(inst.FB)).value);
rPS1(inst.FD) = ForceSingle(NI_sub(rPS1(inst.FA), rPS1(inst.FB)).value);
PowerPC::UpdateFPRF(rPS0(inst.FD));
if (inst.Rc)
@ -182,8 +182,8 @@ void Interpreter::ps_sub(UGeckoInstruction inst)
void Interpreter::ps_add(UGeckoInstruction inst)
{
rPS0(inst.FD) = ForceSingle(NI_add(rPS0(inst.FA), rPS0(inst.FB)));
rPS1(inst.FD) = ForceSingle(NI_add(rPS1(inst.FA), rPS1(inst.FB)));
rPS0(inst.FD) = ForceSingle(NI_add(rPS0(inst.FA), rPS0(inst.FB)).value);
rPS1(inst.FD) = ForceSingle(NI_add(rPS1(inst.FA), rPS1(inst.FB)).value);
PowerPC::UpdateFPRF(rPS0(inst.FD));
if (inst.Rc)
@ -192,10 +192,10 @@ void Interpreter::ps_add(UGeckoInstruction inst)
void Interpreter::ps_mul(UGeckoInstruction inst)
{
double c0 = Force25Bit(rPS0(inst.FC));
double c1 = Force25Bit(rPS1(inst.FC));
rPS0(inst.FD) = ForceSingle(NI_mul(rPS0(inst.FA), c0));
rPS1(inst.FD) = ForceSingle(NI_mul(rPS1(inst.FA), c1));
const double c0 = Force25Bit(rPS0(inst.FC));
const double c1 = Force25Bit(rPS1(inst.FC));
rPS0(inst.FD) = ForceSingle(NI_mul(rPS0(inst.FA), c0).value);
rPS1(inst.FD) = ForceSingle(NI_mul(rPS1(inst.FA), c1).value);
PowerPC::UpdateFPRF(rPS0(inst.FD));
if (inst.Rc)
@ -204,10 +204,10 @@ void Interpreter::ps_mul(UGeckoInstruction inst)
void Interpreter::ps_msub(UGeckoInstruction inst)
{
double c0 = Force25Bit(rPS0(inst.FC));
double c1 = Force25Bit(rPS1(inst.FC));
rPS0(inst.FD) = ForceSingle(NI_msub(rPS0(inst.FA), c0, rPS0(inst.FB)));
rPS1(inst.FD) = ForceSingle(NI_msub(rPS1(inst.FA), c1, rPS1(inst.FB)));
const double c0 = Force25Bit(rPS0(inst.FC));
const double c1 = Force25Bit(rPS1(inst.FC));
rPS0(inst.FD) = ForceSingle(NI_msub(rPS0(inst.FA), c0, rPS0(inst.FB)).value);
rPS1(inst.FD) = ForceSingle(NI_msub(rPS1(inst.FA), c1, rPS1(inst.FB)).value);
PowerPC::UpdateFPRF(rPS0(inst.FD));
if (inst.Rc)
@ -216,10 +216,10 @@ void Interpreter::ps_msub(UGeckoInstruction inst)
void Interpreter::ps_madd(UGeckoInstruction inst)
{
double c0 = Force25Bit(rPS0(inst.FC));
double c1 = Force25Bit(rPS1(inst.FC));
rPS0(inst.FD) = ForceSingle(NI_madd(rPS0(inst.FA), c0, rPS0(inst.FB)));
rPS1(inst.FD) = ForceSingle(NI_madd(rPS1(inst.FA), c1, rPS1(inst.FB)));
const double c0 = Force25Bit(rPS0(inst.FC));
const double c1 = Force25Bit(rPS1(inst.FC));
rPS0(inst.FD) = ForceSingle(NI_madd(rPS0(inst.FA), c0, rPS0(inst.FB)).value);
rPS1(inst.FD) = ForceSingle(NI_madd(rPS1(inst.FA), c1, rPS1(inst.FB)).value);
PowerPC::UpdateFPRF(rPS0(inst.FD));
if (inst.Rc)
@ -228,10 +228,10 @@ void Interpreter::ps_madd(UGeckoInstruction inst)
void Interpreter::ps_nmsub(UGeckoInstruction inst)
{
double c0 = Force25Bit(rPS0(inst.FC));
double c1 = Force25Bit(rPS1(inst.FC));
double result0 = ForceSingle(NI_msub(rPS0(inst.FA), c0, rPS0(inst.FB)));
double result1 = ForceSingle(NI_msub(rPS1(inst.FA), c1, rPS1(inst.FB)));
const double c0 = Force25Bit(rPS0(inst.FC));
const double c1 = Force25Bit(rPS1(inst.FC));
const double result0 = ForceSingle(NI_msub(rPS0(inst.FA), c0, rPS0(inst.FB)).value);
const double result1 = ForceSingle(NI_msub(rPS1(inst.FA), c1, rPS1(inst.FB)).value);
rPS0(inst.FD) = std::isnan(result0) ? result0 : -result0;
rPS1(inst.FD) = std::isnan(result1) ? result1 : -result1;
PowerPC::UpdateFPRF(rPS0(inst.FD));
@ -242,10 +242,10 @@ void Interpreter::ps_nmsub(UGeckoInstruction inst)
void Interpreter::ps_nmadd(UGeckoInstruction inst)
{
double c0 = Force25Bit(rPS0(inst.FC));
double c1 = Force25Bit(rPS1(inst.FC));
double result0 = ForceSingle(NI_madd(rPS0(inst.FA), c0, rPS0(inst.FB)));
double result1 = ForceSingle(NI_madd(rPS1(inst.FA), c1, rPS1(inst.FB)));
const double c0 = Force25Bit(rPS0(inst.FC));
const double c1 = Force25Bit(rPS1(inst.FC));
const double result0 = ForceSingle(NI_madd(rPS0(inst.FA), c0, rPS0(inst.FB)).value);
const double result1 = ForceSingle(NI_madd(rPS1(inst.FA), c1, rPS1(inst.FB)).value);
rPS0(inst.FD) = std::isnan(result0) ? result0 : -result0;
rPS1(inst.FD) = std::isnan(result1) ? result1 : -result1;
PowerPC::UpdateFPRF(rPS0(inst.FD));
@ -256,8 +256,8 @@ void Interpreter::ps_nmadd(UGeckoInstruction inst)
void Interpreter::ps_sum0(UGeckoInstruction inst)
{
double p0 = ForceSingle(NI_add(rPS0(inst.FA), rPS1(inst.FB)));
double p1 = ForceSingle(rPS1(inst.FC));
const double p0 = ForceSingle(NI_add(rPS0(inst.FA), rPS1(inst.FB)).value);
const double p1 = ForceSingle(rPS1(inst.FC));
rPS0(inst.FD) = p0;
rPS1(inst.FD) = p1;
PowerPC::UpdateFPRF(rPS0(inst.FD));
@ -268,8 +268,8 @@ void Interpreter::ps_sum0(UGeckoInstruction inst)
void Interpreter::ps_sum1(UGeckoInstruction inst)
{
double p0 = ForceSingle(rPS0(inst.FC));
double p1 = ForceSingle(NI_add(rPS0(inst.FA), rPS1(inst.FB)));
const double p0 = ForceSingle(rPS0(inst.FC));
const double p1 = ForceSingle(NI_add(rPS0(inst.FA), rPS1(inst.FB)).value);
rPS0(inst.FD) = p0;
rPS1(inst.FD) = p1;
PowerPC::UpdateFPRF(rPS1(inst.FD));
@ -280,9 +280,9 @@ void Interpreter::ps_sum1(UGeckoInstruction inst)
void Interpreter::ps_muls0(UGeckoInstruction inst)
{
double c0 = Force25Bit(rPS0(inst.FC));
double p0 = ForceSingle(NI_mul(rPS0(inst.FA), c0));
double p1 = ForceSingle(NI_mul(rPS1(inst.FA), c0));
const double c0 = Force25Bit(rPS0(inst.FC));
const double p0 = ForceSingle(NI_mul(rPS0(inst.FA), c0).value);
const double p1 = ForceSingle(NI_mul(rPS1(inst.FA), c0).value);
rPS0(inst.FD) = p0;
rPS1(inst.FD) = p1;
PowerPC::UpdateFPRF(rPS0(inst.FD));
@ -293,9 +293,9 @@ void Interpreter::ps_muls0(UGeckoInstruction inst)
void Interpreter::ps_muls1(UGeckoInstruction inst)
{
double c1 = Force25Bit(rPS1(inst.FC));
double p0 = ForceSingle(NI_mul(rPS0(inst.FA), c1));
double p1 = ForceSingle(NI_mul(rPS1(inst.FA), c1));
const double c1 = Force25Bit(rPS1(inst.FC));
const double p0 = ForceSingle(NI_mul(rPS0(inst.FA), c1).value);
const double p1 = ForceSingle(NI_mul(rPS1(inst.FA), c1).value);
rPS0(inst.FD) = p0;
rPS1(inst.FD) = p1;
PowerPC::UpdateFPRF(rPS0(inst.FD));
@ -306,9 +306,9 @@ void Interpreter::ps_muls1(UGeckoInstruction inst)
void Interpreter::ps_madds0(UGeckoInstruction inst)
{
double c0 = Force25Bit(rPS0(inst.FC));
double p0 = ForceSingle(NI_madd(rPS0(inst.FA), c0, rPS0(inst.FB)));
double p1 = ForceSingle(NI_madd(rPS1(inst.FA), c0, rPS1(inst.FB)));
const double c0 = Force25Bit(rPS0(inst.FC));
const double p0 = ForceSingle(NI_madd(rPS0(inst.FA), c0, rPS0(inst.FB)).value);
const double p1 = ForceSingle(NI_madd(rPS1(inst.FA), c0, rPS1(inst.FB)).value);
rPS0(inst.FD) = p0;
rPS1(inst.FD) = p1;
PowerPC::UpdateFPRF(rPS0(inst.FD));
@ -319,9 +319,9 @@ void Interpreter::ps_madds0(UGeckoInstruction inst)
void Interpreter::ps_madds1(UGeckoInstruction inst)
{
double c1 = Force25Bit(rPS1(inst.FC));
double p0 = ForceSingle(NI_madd(rPS0(inst.FA), c1, rPS0(inst.FB)));
double p1 = ForceSingle(NI_madd(rPS1(inst.FA), c1, rPS1(inst.FB)));
const double c1 = Force25Bit(rPS1(inst.FC));
const double p0 = ForceSingle(NI_madd(rPS0(inst.FA), c1, rPS0(inst.FB)).value);
const double p1 = ForceSingle(NI_madd(rPS1(inst.FA), c1, rPS1(inst.FB)).value);
rPS0(inst.FD) = p0;
rPS1(inst.FD) = p1;
PowerPC::UpdateFPRF(rPS0(inst.FD));