mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 07:39:26 +01:00
UnitTests/PowerPC: Check FPSCR output for fres/frsqrte
No games are known to care about this, but since we've gone through the effort of implementing it, we should also go through the effort of testing it.
This commit is contained in:
parent
c528a70e64
commit
1a8619c85b
@ -64,20 +64,51 @@ TEST(Jit64, Frsqrte)
|
||||
Core::DeclareAsCPUThread();
|
||||
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
|
||||
|
||||
TestCommonAsmRoutines routines(Core::System::GetInstance());
|
||||
Core::System& system = Core::System::GetInstance();
|
||||
TestCommonAsmRoutines routines(system);
|
||||
|
||||
UReg_FPSCR fpscr;
|
||||
|
||||
for (const u64 ivalue : double_test_values)
|
||||
{
|
||||
SCOPED_TRACE(fmt::format("frsqrte input: {:016x}\n", ivalue));
|
||||
|
||||
double dvalue = std::bit_cast<double>(ivalue);
|
||||
|
||||
u64 expected = std::bit_cast<u64>(Common::ApproximateReciprocalSquareRoot(dvalue));
|
||||
|
||||
u64 actual = routines.wrapped_frsqrte(ivalue, fpscr);
|
||||
|
||||
fmt::print("{:016x} -> {:016x} == {:016x}\n", ivalue, actual, expected);
|
||||
|
||||
EXPECT_EQ(expected, actual);
|
||||
|
||||
for (u32 zx = 0; zx < 2; ++zx)
|
||||
{
|
||||
for (u32 vxsqrt = 0; vxsqrt < 2; ++vxsqrt)
|
||||
{
|
||||
fpscr = {};
|
||||
fpscr.ZX = zx;
|
||||
fpscr.VXSQRT = vxsqrt;
|
||||
|
||||
routines.wrapped_frsqrte(ivalue, fpscr);
|
||||
|
||||
const u32 value_class = Common::ClassifyDouble(dvalue);
|
||||
|
||||
const bool input_is_zero =
|
||||
value_class == Common::PPC_FPCLASS_NZ || value_class == Common::PPC_FPCLASS_PZ;
|
||||
const bool input_is_negative = value_class == Common::PPC_FPCLASS_NN ||
|
||||
value_class == Common::PPC_FPCLASS_ND ||
|
||||
value_class == Common::PPC_FPCLASS_NINF;
|
||||
|
||||
const bool zx_expected = input_is_zero || zx;
|
||||
const bool vxsqrt_expected = input_is_negative || vxsqrt;
|
||||
const bool fx_expected = (input_is_zero && !zx) || (input_is_negative && !vxsqrt);
|
||||
|
||||
const u32 fpscr_expected = (zx_expected ? FPSCR_ZX : 0) |
|
||||
(vxsqrt_expected ? FPSCR_VXSQRT : 0) |
|
||||
(fx_expected ? FPSCR_FX : 0);
|
||||
|
||||
EXPECT_EQ(fpscr_expected, fpscr.Hex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,18 +56,36 @@ TEST(JitArm64, Fres)
|
||||
Core::DeclareAsCPUThread();
|
||||
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
|
||||
|
||||
TestFres test(Core::System::GetInstance());
|
||||
Core::System& system = Core::System::GetInstance();
|
||||
TestFres test(system);
|
||||
|
||||
for (const u64 ivalue : double_test_values)
|
||||
{
|
||||
SCOPED_TRACE(fmt::format("fres input: {:016x}\n", ivalue));
|
||||
|
||||
const double dvalue = std::bit_cast<double>(ivalue);
|
||||
|
||||
const u64 expected = std::bit_cast<u64>(Common::ApproximateReciprocal(dvalue));
|
||||
const u64 actual = test.fres(ivalue);
|
||||
|
||||
if (expected != actual)
|
||||
fmt::print("{:016x} -> {:016x} == {:016x}\n", ivalue, actual, expected);
|
||||
|
||||
EXPECT_EQ(expected, actual);
|
||||
|
||||
for (u32 zx = 0; zx < 2; ++zx)
|
||||
{
|
||||
UReg_FPSCR& fpscr = system.GetPPCState().fpscr;
|
||||
fpscr = {};
|
||||
fpscr.ZX = zx;
|
||||
|
||||
test.fres(ivalue);
|
||||
|
||||
const bool input_is_zero = (ivalue & (Common::DOUBLE_EXP | Common::DOUBLE_FRAC)) == 0;
|
||||
|
||||
const bool zx_expected = input_is_zero || zx;
|
||||
const bool fx_expected = input_is_zero && !zx;
|
||||
|
||||
const u32 fpscr_expected = (zx_expected ? FPSCR_ZX : 0) | (fx_expected ? FPSCR_FX : 0);
|
||||
|
||||
EXPECT_EQ(fpscr_expected, fpscr.Hex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,18 +57,49 @@ TEST(JitArm64, Frsqrte)
|
||||
Core::DeclareAsCPUThread();
|
||||
Common::ScopeGuard cpu_thread_guard([] { Core::UndeclareAsCPUThread(); });
|
||||
|
||||
TestFrsqrte test(Core::System::GetInstance());
|
||||
Core::System& system = Core::System::GetInstance();
|
||||
TestFrsqrte test(system);
|
||||
|
||||
for (const u64 ivalue : double_test_values)
|
||||
{
|
||||
SCOPED_TRACE(fmt::format("frsqrte input: {:016x}\n", ivalue));
|
||||
|
||||
const double dvalue = std::bit_cast<double>(ivalue);
|
||||
|
||||
const u64 expected = std::bit_cast<u64>(Common::ApproximateReciprocalSquareRoot(dvalue));
|
||||
const u64 actual = test.frsqrte(ivalue);
|
||||
|
||||
if (expected != actual)
|
||||
fmt::print("{:016x} -> {:016x} == {:016x}\n", ivalue, actual, expected);
|
||||
|
||||
EXPECT_EQ(expected, actual);
|
||||
|
||||
for (u32 zx = 0; zx < 2; ++zx)
|
||||
{
|
||||
for (u32 vxsqrt = 0; vxsqrt < 2; ++vxsqrt)
|
||||
{
|
||||
UReg_FPSCR& fpscr = system.GetPPCState().fpscr;
|
||||
fpscr = {};
|
||||
fpscr.ZX = zx;
|
||||
fpscr.VXSQRT = vxsqrt;
|
||||
|
||||
test.frsqrte(ivalue);
|
||||
|
||||
const u32 value_class = Common::ClassifyDouble(dvalue);
|
||||
|
||||
const bool input_is_zero =
|
||||
value_class == Common::PPC_FPCLASS_NZ || value_class == Common::PPC_FPCLASS_PZ;
|
||||
const bool input_is_negative = value_class == Common::PPC_FPCLASS_NN ||
|
||||
value_class == Common::PPC_FPCLASS_ND ||
|
||||
value_class == Common::PPC_FPCLASS_NINF;
|
||||
|
||||
const bool zx_expected = input_is_zero || zx;
|
||||
const bool vxsqrt_expected = input_is_negative || vxsqrt;
|
||||
const bool fx_expected = (input_is_zero && !zx) || (input_is_negative && !vxsqrt);
|
||||
|
||||
const u32 fpscr_expected = (zx_expected ? FPSCR_ZX : 0) |
|
||||
(vxsqrt_expected ? FPSCR_VXSQRT : 0) |
|
||||
(fx_expected ? FPSCR_FX : 0);
|
||||
|
||||
EXPECT_EQ(fpscr_expected, fpscr.Hex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user