Interpreter: Fix FPRF handling of denormal singles
This commit is contained in:
parent
def5666419
commit
d56721ebb9
|
@ -87,7 +87,6 @@ enum PPCFpClass
|
||||||
// Uses PowerPC conventions for the return value, so it can be easily
|
// Uses PowerPC conventions for the return value, so it can be easily
|
||||||
// used directly in CPU emulation.
|
// used directly in CPU emulation.
|
||||||
u32 ClassifyDouble(double dvalue);
|
u32 ClassifyDouble(double dvalue);
|
||||||
// More efficient float version.
|
|
||||||
u32 ClassifyFloat(float fvalue);
|
u32 ClassifyFloat(float fvalue);
|
||||||
|
|
||||||
struct BaseAndDec
|
struct BaseAndDec
|
||||||
|
|
|
@ -302,7 +302,7 @@ void Interpreter::frspx(UGeckoInstruction inst) // round to single
|
||||||
if (!is_snan || FPSCR.VE == 0)
|
if (!is_snan || FPSCR.VE == 0)
|
||||||
{
|
{
|
||||||
rPS(inst.FD).Fill(rounded);
|
rPS(inst.FD).Fill(rounded);
|
||||||
PowerPC::UpdateFPRF(b);
|
PowerPC::UpdateFPRFSingle(rounded);
|
||||||
}
|
}
|
||||||
|
|
||||||
FPSCR.ClearFIFR();
|
FPSCR.ClearFIFR();
|
||||||
|
@ -311,7 +311,7 @@ void Interpreter::frspx(UGeckoInstruction inst) // round to single
|
||||||
{
|
{
|
||||||
SetFI(&FPSCR, b != rounded);
|
SetFI(&FPSCR, b != rounded);
|
||||||
FPSCR.FR = fabs(rounded) > fabs(b);
|
FPSCR.FR = fabs(rounded) > fabs(b);
|
||||||
PowerPC::UpdateFPRF(rounded);
|
PowerPC::UpdateFPRFSingle(rounded);
|
||||||
rPS(inst.FD).Fill(rounded);
|
rPS(inst.FD).Fill(rounded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,7 +333,7 @@ void Interpreter::fmulx(UGeckoInstruction inst)
|
||||||
rPS(inst.FD).SetPS0(result);
|
rPS(inst.FD).SetPS0(result);
|
||||||
FPSCR.FI = 0; // are these flags important?
|
FPSCR.FI = 0; // are these flags important?
|
||||||
FPSCR.FR = 0;
|
FPSCR.FR = 0;
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFDouble(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -354,7 +354,7 @@ void Interpreter::fmulsx(UGeckoInstruction inst)
|
||||||
rPS(inst.FD).Fill(result);
|
rPS(inst.FD).Fill(result);
|
||||||
FPSCR.FI = 0;
|
FPSCR.FI = 0;
|
||||||
FPSCR.FR = 0;
|
FPSCR.FR = 0;
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFSingle(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -372,7 +372,7 @@ void Interpreter::fmaddx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
const double result = ForceDouble(FPSCR, product.value);
|
const double result = ForceDouble(FPSCR, product.value);
|
||||||
rPS(inst.FD).SetPS0(result);
|
rPS(inst.FD).SetPS0(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFDouble(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -395,7 +395,7 @@ void Interpreter::fmaddsx(UGeckoInstruction inst)
|
||||||
rPS(inst.FD).Fill(result);
|
rPS(inst.FD).Fill(result);
|
||||||
FPSCR.FI = d_value.value != result;
|
FPSCR.FI = d_value.value != result;
|
||||||
FPSCR.FR = 0;
|
FPSCR.FR = 0;
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFSingle(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -413,7 +413,7 @@ void Interpreter::faddx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
const double result = ForceDouble(FPSCR, sum.value);
|
const double result = ForceDouble(FPSCR, sum.value);
|
||||||
rPS(inst.FD).SetPS0(result);
|
rPS(inst.FD).SetPS0(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFDouble(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -430,7 +430,7 @@ void Interpreter::faddsx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
const double result = ForceSingle(FPSCR, sum.value);
|
const double result = ForceSingle(FPSCR, sum.value);
|
||||||
rPS(inst.FD).Fill(result);
|
rPS(inst.FD).Fill(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFSingle(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -450,7 +450,7 @@ void Interpreter::fdivx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
const double result = ForceDouble(FPSCR, quotient.value);
|
const double result = ForceDouble(FPSCR, quotient.value);
|
||||||
rPS(inst.FD).SetPS0(result);
|
rPS(inst.FD).SetPS0(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFDouble(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FR,FI,OX,UX???
|
// FR,FI,OX,UX???
|
||||||
|
@ -470,7 +470,7 @@ void Interpreter::fdivsx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
const double result = ForceSingle(FPSCR, quotient.value);
|
const double result = ForceSingle(FPSCR, quotient.value);
|
||||||
rPS(inst.FD).Fill(result);
|
rPS(inst.FD).Fill(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFSingle(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -485,7 +485,7 @@ void Interpreter::fresx(UGeckoInstruction inst)
|
||||||
const auto compute_result = [inst](double value) {
|
const auto compute_result = [inst](double value) {
|
||||||
const double result = Common::ApproximateReciprocal(value);
|
const double result = Common::ApproximateReciprocal(value);
|
||||||
rPS(inst.FD).Fill(result);
|
rPS(inst.FD).Fill(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFSingle(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (b == 0.0)
|
if (b == 0.0)
|
||||||
|
@ -523,7 +523,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
|
||||||
const auto compute_result = [inst](double value) {
|
const auto compute_result = [inst](double value) {
|
||||||
const double result = Common::ApproximateReciprocalSquareRoot(value);
|
const double result = Common::ApproximateReciprocalSquareRoot(value);
|
||||||
rPS(inst.FD).SetPS0(result);
|
rPS(inst.FD).SetPS0(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFDouble(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (b < 0.0)
|
if (b < 0.0)
|
||||||
|
@ -574,7 +574,7 @@ void Interpreter::fmsubx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
const double result = ForceDouble(FPSCR, product.value);
|
const double result = ForceDouble(FPSCR, product.value);
|
||||||
rPS(inst.FD).SetPS0(result);
|
rPS(inst.FD).SetPS0(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFDouble(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -594,7 +594,7 @@ void Interpreter::fmsubsx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
const double result = ForceSingle(FPSCR, product.value);
|
const double result = ForceSingle(FPSCR, product.value);
|
||||||
rPS(inst.FD).Fill(result);
|
rPS(inst.FD).Fill(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFSingle(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -615,7 +615,7 @@ void Interpreter::fnmaddx(UGeckoInstruction inst)
|
||||||
const double result = std::isnan(tmp) ? tmp : -tmp;
|
const double result = std::isnan(tmp) ? tmp : -tmp;
|
||||||
|
|
||||||
rPS(inst.FD).SetPS0(result);
|
rPS(inst.FD).SetPS0(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFDouble(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -637,7 +637,7 @@ void Interpreter::fnmaddsx(UGeckoInstruction inst)
|
||||||
const double result = std::isnan(tmp) ? tmp : -tmp;
|
const double result = std::isnan(tmp) ? tmp : -tmp;
|
||||||
|
|
||||||
rPS(inst.FD).Fill(result);
|
rPS(inst.FD).Fill(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFSingle(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -658,7 +658,7 @@ void Interpreter::fnmsubx(UGeckoInstruction inst)
|
||||||
const double result = std::isnan(tmp) ? tmp : -tmp;
|
const double result = std::isnan(tmp) ? tmp : -tmp;
|
||||||
|
|
||||||
rPS(inst.FD).SetPS0(result);
|
rPS(inst.FD).SetPS0(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFDouble(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -680,7 +680,7 @@ void Interpreter::fnmsubsx(UGeckoInstruction inst)
|
||||||
const double result = std::isnan(tmp) ? tmp : -tmp;
|
const double result = std::isnan(tmp) ? tmp : -tmp;
|
||||||
|
|
||||||
rPS(inst.FD).Fill(result);
|
rPS(inst.FD).Fill(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFSingle(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -698,7 +698,7 @@ void Interpreter::fsubx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
const double result = ForceDouble(FPSCR, difference.value);
|
const double result = ForceDouble(FPSCR, difference.value);
|
||||||
rPS(inst.FD).SetPS0(result);
|
rPS(inst.FD).SetPS0(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFDouble(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
@ -716,7 +716,7 @@ void Interpreter::fsubsx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
const double result = ForceSingle(FPSCR, difference.value);
|
const double result = ForceSingle(FPSCR, difference.value);
|
||||||
rPS(inst.FD).Fill(result);
|
rPS(inst.FD).Fill(result);
|
||||||
PowerPC::UpdateFPRF(result);
|
PowerPC::UpdateFPRFSingle(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
|
|
|
@ -117,7 +117,7 @@ void Interpreter::ps_div(UGeckoInstruction inst)
|
||||||
const double ps1 = ForceSingle(FPSCR, NI_div(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value);
|
const double ps1 = ForceSingle(FPSCR, NI_div(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -145,7 +145,7 @@ void Interpreter::ps_res(UGeckoInstruction inst)
|
||||||
const double ps1 = Common::ApproximateReciprocal(b);
|
const double ps1 = Common::ApproximateReciprocal(b);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -178,7 +178,7 @@ void Interpreter::ps_rsqrte(UGeckoInstruction inst)
|
||||||
const double dst_ps1 = ForceSingle(FPSCR, Common::ApproximateReciprocalSquareRoot(ps1));
|
const double dst_ps1 = ForceSingle(FPSCR, Common::ApproximateReciprocalSquareRoot(ps1));
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(dst_ps0, dst_ps1);
|
rPS(inst.FD).SetBoth(dst_ps0, dst_ps1);
|
||||||
PowerPC::UpdateFPRF(dst_ps0);
|
PowerPC::UpdateFPRFSingle(dst_ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -193,7 +193,7 @@ void Interpreter::ps_sub(UGeckoInstruction inst)
|
||||||
const double ps1 = ForceSingle(FPSCR, NI_sub(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value);
|
const double ps1 = ForceSingle(FPSCR, NI_sub(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -208,7 +208,7 @@ void Interpreter::ps_add(UGeckoInstruction inst)
|
||||||
const double ps1 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value);
|
const double ps1 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -226,7 +226,7 @@ void Interpreter::ps_mul(UGeckoInstruction inst)
|
||||||
const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c1).value);
|
const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c1).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -247,7 +247,7 @@ void Interpreter::ps_msub(UGeckoInstruction inst)
|
||||||
ForceSingle(FPSCR, NI_msub(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
|
ForceSingle(FPSCR, NI_msub(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -268,7 +268,7 @@ void Interpreter::ps_madd(UGeckoInstruction inst)
|
||||||
ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
|
ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -292,7 +292,7 @@ void Interpreter::ps_nmsub(UGeckoInstruction inst)
|
||||||
const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1;
|
const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1;
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -316,7 +316,7 @@ void Interpreter::ps_nmadd(UGeckoInstruction inst)
|
||||||
const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1;
|
const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1;
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -332,7 +332,7 @@ void Interpreter::ps_sum0(UGeckoInstruction inst)
|
||||||
const double ps1 = ForceSingle(FPSCR, c.PS1AsDouble());
|
const double ps1 = ForceSingle(FPSCR, c.PS1AsDouble());
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -348,7 +348,7 @@ void Interpreter::ps_sum1(UGeckoInstruction inst)
|
||||||
const double ps1 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS0AsDouble(), b.PS1AsDouble()).value);
|
const double ps1 = ForceSingle(FPSCR, NI_add(&FPSCR, a.PS0AsDouble(), b.PS1AsDouble()).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps1);
|
PowerPC::UpdateFPRFSingle(ps1);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -364,7 +364,7 @@ void Interpreter::ps_muls0(UGeckoInstruction inst)
|
||||||
const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c0).value);
|
const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c0).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -380,7 +380,7 @@ void Interpreter::ps_muls1(UGeckoInstruction inst)
|
||||||
const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c1).value);
|
const double ps1 = ForceSingle(FPSCR, NI_mul(&FPSCR, a.PS1AsDouble(), c1).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -399,7 +399,7 @@ void Interpreter::ps_madds0(UGeckoInstruction inst)
|
||||||
ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c0, b.PS1AsDouble()).value);
|
ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c0, b.PS1AsDouble()).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
@ -418,7 +418,7 @@ void Interpreter::ps_madds1(UGeckoInstruction inst)
|
||||||
ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
|
ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
|
||||||
|
|
||||||
rPS(inst.FD).SetBoth(ps0, ps1);
|
rPS(inst.FD).SetBoth(ps0, ps1);
|
||||||
PowerPC::UpdateFPRF(ps0);
|
PowerPC::UpdateFPRFSingle(ps0);
|
||||||
|
|
||||||
if (inst.Rc)
|
if (inst.Rc)
|
||||||
PowerPC::ppcState.UpdateCR1();
|
PowerPC::ppcState.UpdateCR1();
|
||||||
|
|
|
@ -626,11 +626,16 @@ void PowerPCState::SetSR(u32 index, u32 value)
|
||||||
|
|
||||||
// FPSCR update functions
|
// FPSCR update functions
|
||||||
|
|
||||||
void UpdateFPRF(double dvalue)
|
void UpdateFPRFDouble(double dvalue)
|
||||||
{
|
{
|
||||||
FPSCR.FPRF = Common::ClassifyDouble(dvalue);
|
FPSCR.FPRF = Common::ClassifyDouble(dvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateFPRFSingle(float fvalue)
|
||||||
|
{
|
||||||
|
FPSCR.FPRF = Common::ClassifyFloat(fvalue);
|
||||||
|
}
|
||||||
|
|
||||||
void RoundingModeUpdated()
|
void RoundingModeUpdated()
|
||||||
{
|
{
|
||||||
// The rounding mode is separate for each thread, so this must run on the CPU thread
|
// The rounding mode is separate for each thread, so this must run on the CPU thread
|
||||||
|
|
|
@ -304,7 +304,8 @@ inline void SetXER_OV(bool value)
|
||||||
SetXER_SO(value);
|
SetXER_SO(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateFPRF(double dvalue);
|
void UpdateFPRFDouble(double dvalue);
|
||||||
|
void UpdateFPRFSingle(float fvalue);
|
||||||
|
|
||||||
void RoundingModeUpdated();
|
void RoundingModeUpdated();
|
||||||
|
|
||||||
|
|
|
@ -74,14 +74,14 @@ TEST(JitArm64, FPRF)
|
||||||
for (const u64 double_input : double_test_values)
|
for (const u64 double_input : double_test_values)
|
||||||
{
|
{
|
||||||
const u32 expected_double =
|
const u32 expected_double =
|
||||||
RunUpdateFPRF([&] { PowerPC::UpdateFPRF(Common::BitCast<double>(double_input)); });
|
RunUpdateFPRF([&] { PowerPC::UpdateFPRFDouble(Common::BitCast<double>(double_input)); });
|
||||||
const u32 actual_double = RunUpdateFPRF([&] { test.fprf_double(double_input); });
|
const u32 actual_double = RunUpdateFPRF([&] { test.fprf_double(double_input); });
|
||||||
EXPECT_EQ(expected_double, actual_double);
|
EXPECT_EQ(expected_double, actual_double);
|
||||||
|
|
||||||
const u32 single_input = ConvertToSingle(double_input);
|
const u32 single_input = ConvertToSingle(double_input);
|
||||||
|
|
||||||
const u32 expected_single = RunUpdateFPRF(
|
const u32 expected_single =
|
||||||
[&] { PowerPC::UpdateFPRF(Common::BitCast<double>(ConvertToDouble(single_input))); });
|
RunUpdateFPRF([&] { PowerPC::UpdateFPRFSingle(Common::BitCast<float>(single_input)); });
|
||||||
const u32 actual_single = RunUpdateFPRF([&] { test.fprf_single(single_input); });
|
const u32 actual_single = RunUpdateFPRF([&] { test.fprf_single(single_input); });
|
||||||
EXPECT_EQ(expected_single, actual_single);
|
EXPECT_EQ(expected_single, actual_single);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue