summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2021-06-13 14:35:04 +0200
committerJosJuice <josjuice@gmail.com>2021-06-27 20:34:49 +0200
commitd56721ebb9910cd14115f778c57c58a6fd0ca366 (patch)
tree3781316ee3ae16e8d2ecf6b7d987533bb7f3444f /Source/Core
parentdef5666419a04c22c61925f96d2c970a0bb01d72 (diff)
Interpreter: Fix FPRF handling of denormal singles
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/FloatUtils.h1
-rw-r--r--Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp40
-rw-r--r--Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp32
-rw-r--r--Source/Core/Core/PowerPC/PowerPC.cpp7
-rw-r--r--Source/Core/Core/PowerPC/PowerPC.h3
5 files changed, 44 insertions, 39 deletions
diff --git a/Source/Core/Common/FloatUtils.h b/Source/Core/Common/FloatUtils.h
index 7fca042ace..7480cdcfea 100644
--- a/Source/Core/Common/FloatUtils.h
+++ b/Source/Core/Common/FloatUtils.h
@@ -87,7 +87,6 @@ enum PPCFpClass
// Uses PowerPC conventions for the return value, so it can be easily
// used directly in CPU emulation.
u32 ClassifyDouble(double dvalue);
-// More efficient float version.
u32 ClassifyFloat(float fvalue);
struct BaseAndDec
diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp
index 66ccff82af..d02e8ae71b 100644
--- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp
+++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp
@@ -302,7 +302,7 @@ void Interpreter::frspx(UGeckoInstruction inst) // round to single
if (!is_snan || FPSCR.VE == 0)
{
rPS(inst.FD).Fill(rounded);
- PowerPC::UpdateFPRF(b);
+ PowerPC::UpdateFPRFSingle(rounded);
}
FPSCR.ClearFIFR();
@@ -311,7 +311,7 @@ void Interpreter::frspx(UGeckoInstruction inst) // round to single
{
SetFI(&FPSCR, b != rounded);
FPSCR.FR = fabs(rounded) > fabs(b);
- PowerPC::UpdateFPRF(rounded);
+ PowerPC::UpdateFPRFSingle(rounded);
rPS(inst.FD).Fill(rounded);
}
@@ -333,7 +333,7 @@ void Interpreter::fmulx(UGeckoInstruction inst)
rPS(inst.FD).SetPS0(result);
FPSCR.FI = 0; // are these flags important?
FPSCR.FR = 0;
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFDouble(result);
}
if (inst.Rc)
@@ -354,7 +354,7 @@ void Interpreter::fmulsx(UGeckoInstruction inst)
rPS(inst.FD).Fill(result);
FPSCR.FI = 0;
FPSCR.FR = 0;
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFSingle(result);
}
if (inst.Rc)
@@ -372,7 +372,7 @@ void Interpreter::fmaddx(UGeckoInstruction inst)
{
const double result = ForceDouble(FPSCR, product.value);
rPS(inst.FD).SetPS0(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFDouble(result);
}
if (inst.Rc)
@@ -395,7 +395,7 @@ void Interpreter::fmaddsx(UGeckoInstruction inst)
rPS(inst.FD).Fill(result);
FPSCR.FI = d_value.value != result;
FPSCR.FR = 0;
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFSingle(result);
}
if (inst.Rc)
@@ -413,7 +413,7 @@ void Interpreter::faddx(UGeckoInstruction inst)
{
const double result = ForceDouble(FPSCR, sum.value);
rPS(inst.FD).SetPS0(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFDouble(result);
}
if (inst.Rc)
@@ -430,7 +430,7 @@ void Interpreter::faddsx(UGeckoInstruction inst)
{
const double result = ForceSingle(FPSCR, sum.value);
rPS(inst.FD).Fill(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFSingle(result);
}
if (inst.Rc)
@@ -450,7 +450,7 @@ void Interpreter::fdivx(UGeckoInstruction inst)
{
const double result = ForceDouble(FPSCR, quotient.value);
rPS(inst.FD).SetPS0(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFDouble(result);
}
// FR,FI,OX,UX???
@@ -470,7 +470,7 @@ void Interpreter::fdivsx(UGeckoInstruction inst)
{
const double result = ForceSingle(FPSCR, quotient.value);
rPS(inst.FD).Fill(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFSingle(result);
}
if (inst.Rc)
@@ -485,7 +485,7 @@ void Interpreter::fresx(UGeckoInstruction inst)
const auto compute_result = [inst](double value) {
const double result = Common::ApproximateReciprocal(value);
rPS(inst.FD).Fill(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFSingle(result);
};
if (b == 0.0)
@@ -523,7 +523,7 @@ void Interpreter::frsqrtex(UGeckoInstruction inst)
const auto compute_result = [inst](double value) {
const double result = Common::ApproximateReciprocalSquareRoot(value);
rPS(inst.FD).SetPS0(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFDouble(result);
};
if (b < 0.0)
@@ -574,7 +574,7 @@ void Interpreter::fmsubx(UGeckoInstruction inst)
{
const double result = ForceDouble(FPSCR, product.value);
rPS(inst.FD).SetPS0(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFDouble(result);
}
if (inst.Rc)
@@ -594,7 +594,7 @@ void Interpreter::fmsubsx(UGeckoInstruction inst)
{
const double result = ForceSingle(FPSCR, product.value);
rPS(inst.FD).Fill(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFSingle(result);
}
if (inst.Rc)
@@ -615,7 +615,7 @@ void Interpreter::fnmaddx(UGeckoInstruction inst)
const double result = std::isnan(tmp) ? tmp : -tmp;
rPS(inst.FD).SetPS0(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFDouble(result);
}
if (inst.Rc)
@@ -637,7 +637,7 @@ void Interpreter::fnmaddsx(UGeckoInstruction inst)
const double result = std::isnan(tmp) ? tmp : -tmp;
rPS(inst.FD).Fill(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFSingle(result);
}
if (inst.Rc)
@@ -658,7 +658,7 @@ void Interpreter::fnmsubx(UGeckoInstruction inst)
const double result = std::isnan(tmp) ? tmp : -tmp;
rPS(inst.FD).SetPS0(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFDouble(result);
}
if (inst.Rc)
@@ -680,7 +680,7 @@ void Interpreter::fnmsubsx(UGeckoInstruction inst)
const double result = std::isnan(tmp) ? tmp : -tmp;
rPS(inst.FD).Fill(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFSingle(result);
}
if (inst.Rc)
@@ -698,7 +698,7 @@ void Interpreter::fsubx(UGeckoInstruction inst)
{
const double result = ForceDouble(FPSCR, difference.value);
rPS(inst.FD).SetPS0(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFDouble(result);
}
if (inst.Rc)
@@ -716,7 +716,7 @@ void Interpreter::fsubsx(UGeckoInstruction inst)
{
const double result = ForceSingle(FPSCR, difference.value);
rPS(inst.FD).Fill(result);
- PowerPC::UpdateFPRF(result);
+ PowerPC::UpdateFPRFSingle(result);
}
if (inst.Rc)
diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp
index 89d51eabb7..140433892c 100644
--- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp
+++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Paired.cpp
@@ -117,7 +117,7 @@ void Interpreter::ps_div(UGeckoInstruction inst)
const double ps1 = ForceSingle(FPSCR, NI_div(&FPSCR, a.PS1AsDouble(), b.PS1AsDouble()).value);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
@@ -145,7 +145,7 @@ void Interpreter::ps_res(UGeckoInstruction inst)
const double ps1 = Common::ApproximateReciprocal(b);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
@@ -178,7 +178,7 @@ void Interpreter::ps_rsqrte(UGeckoInstruction inst)
const double dst_ps1 = ForceSingle(FPSCR, Common::ApproximateReciprocalSquareRoot(ps1));
rPS(inst.FD).SetBoth(dst_ps0, dst_ps1);
- PowerPC::UpdateFPRF(dst_ps0);
+ PowerPC::UpdateFPRFSingle(dst_ps0);
if (inst.Rc)
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);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
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);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
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);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
@@ -247,7 +247,7 @@ void Interpreter::ps_msub(UGeckoInstruction inst)
ForceSingle(FPSCR, NI_msub(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
@@ -268,7 +268,7 @@ void Interpreter::ps_madd(UGeckoInstruction inst)
ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
@@ -292,7 +292,7 @@ void Interpreter::ps_nmsub(UGeckoInstruction inst)
const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1;
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
@@ -316,7 +316,7 @@ void Interpreter::ps_nmadd(UGeckoInstruction inst)
const double ps1 = std::isnan(tmp1) ? tmp1 : -tmp1;
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
@@ -332,7 +332,7 @@ void Interpreter::ps_sum0(UGeckoInstruction inst)
const double ps1 = ForceSingle(FPSCR, c.PS1AsDouble());
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
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);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps1);
+ PowerPC::UpdateFPRFSingle(ps1);
if (inst.Rc)
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);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
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);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
@@ -399,7 +399,7 @@ void Interpreter::ps_madds0(UGeckoInstruction inst)
ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c0, b.PS1AsDouble()).value);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
@@ -418,7 +418,7 @@ void Interpreter::ps_madds1(UGeckoInstruction inst)
ForceSingle(FPSCR, NI_madd(&FPSCR, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
rPS(inst.FD).SetBoth(ps0, ps1);
- PowerPC::UpdateFPRF(ps0);
+ PowerPC::UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp
index 73eac23a94..817276f8d7 100644
--- a/Source/Core/Core/PowerPC/PowerPC.cpp
+++ b/Source/Core/Core/PowerPC/PowerPC.cpp
@@ -626,11 +626,16 @@ void PowerPCState::SetSR(u32 index, u32 value)
// FPSCR update functions
-void UpdateFPRF(double dvalue)
+void UpdateFPRFDouble(double dvalue)
{
FPSCR.FPRF = Common::ClassifyDouble(dvalue);
}
+void UpdateFPRFSingle(float fvalue)
+{
+ FPSCR.FPRF = Common::ClassifyFloat(fvalue);
+}
+
void RoundingModeUpdated()
{
// The rounding mode is separate for each thread, so this must run on the CPU thread
diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h
index 73919161f2..fdc0f16a09 100644
--- a/Source/Core/Core/PowerPC/PowerPC.h
+++ b/Source/Core/Core/PowerPC/PowerPC.h
@@ -304,7 +304,8 @@ inline void SetXER_OV(bool value)
SetXER_SO(value);
}
-void UpdateFPRF(double dvalue);
+void UpdateFPRFDouble(double dvalue);
+void UpdateFPRFSingle(float fvalue);
void RoundingModeUpdated();