diff options
| author | Mai M <mathew1800@gmail.com> | 2021-05-20 10:23:49 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-20 10:23:49 -0400 |
| commit | 6958df596706ec3090b102467b68274a08a5453f (patch) | |
| tree | 18156b037845c7dd14e5d58d38bbbec5b4c479ce /Source/UnitTests/Core | |
| parent | 539c2cb00ed920262a310868146368bb3b3ba4c9 (diff) | |
| parent | e5f2dcd891bc126b5e75e6858ae8040c67df509a (diff) | |
Merge pull request #9695 from JosJuice/jitarm64-fres
JitArm64: Implement fres and frsqrte
Diffstat (limited to 'Source/UnitTests/Core')
| -rw-r--r-- | Source/UnitTests/Core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | Source/UnitTests/Core/PowerPC/JitArm64/Fres.cpp | 66 | ||||
| -rw-r--r-- | Source/UnitTests/Core/PowerPC/JitArm64/Frsqrte.cpp | 66 | ||||
| -rw-r--r-- | Source/UnitTests/Core/PowerPC/TestValues.h | 22 |
4 files changed, 154 insertions, 2 deletions
diff --git a/Source/UnitTests/Core/CMakeLists.txt b/Source/UnitTests/Core/CMakeLists.txt index 6dd344e638..134f7da78b 100644 --- a/Source/UnitTests/Core/CMakeLists.txt +++ b/Source/UnitTests/Core/CMakeLists.txt @@ -25,6 +25,8 @@ elseif(_M_ARM_64) PowerPC/DivUtilsTest.cpp PowerPC/JitArm64/ConvertSingleDouble.cpp PowerPC/JitArm64/FPRF.cpp + PowerPC/JitArm64/Fres.cpp + PowerPC/JitArm64/Frsqrte.cpp PowerPC/JitArm64/MovI2R.cpp ) else() diff --git a/Source/UnitTests/Core/PowerPC/JitArm64/Fres.cpp b/Source/UnitTests/Core/PowerPC/JitArm64/Fres.cpp new file mode 100644 index 0000000000..027a3ac89f --- /dev/null +++ b/Source/UnitTests/Core/PowerPC/JitArm64/Fres.cpp @@ -0,0 +1,66 @@ +// Copyright 2021 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include <functional> + +#include "Common/Arm64Emitter.h" +#include "Common/BitUtils.h" +#include "Common/CommonTypes.h" +#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" +#include "Core/PowerPC/JitArm64/Jit.h" +#include "Core/PowerPC/PowerPC.h" + +#include "../TestValues.h" + +#include <gtest/gtest.h> + +namespace +{ +using namespace Arm64Gen; + +class TestFres : public JitArm64 +{ +public: + TestFres() + { + AllocCodeSpace(4096); + + const u8* raw_fres = GetCodePtr(); + GenerateFres(); + + fres = Common::BitCast<u64 (*)(u64)>(GetCodePtr()); + MOV(ARM64Reg::X15, ARM64Reg::X30); + MOV(ARM64Reg::X14, PPC_REG); + MOVP2R(PPC_REG, &PowerPC::ppcState); + MOV(ARM64Reg::X1, ARM64Reg::X0); + m_float_emit.FMOV(ARM64Reg::D0, ARM64Reg::X0); + m_float_emit.FRECPE(ARM64Reg::D0, ARM64Reg::D0); + BL(raw_fres); + MOV(ARM64Reg::X30, ARM64Reg::X15); + MOV(PPC_REG, ARM64Reg::X14); + RET(); + } + + std::function<u64(u64)> fres; +}; + +} // namespace + +TEST(JitArm64, Fres) +{ + TestFres test; + + for (const u64 ivalue : double_test_values) + { + const double dvalue = Common::BitCast<double>(ivalue); + + const u64 expected = Common::BitCast<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); + } +} diff --git a/Source/UnitTests/Core/PowerPC/JitArm64/Frsqrte.cpp b/Source/UnitTests/Core/PowerPC/JitArm64/Frsqrte.cpp new file mode 100644 index 0000000000..749b147dcb --- /dev/null +++ b/Source/UnitTests/Core/PowerPC/JitArm64/Frsqrte.cpp @@ -0,0 +1,66 @@ +// Copyright 2021 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include <functional> + +#include "Common/Arm64Emitter.h" +#include "Common/BitUtils.h" +#include "Common/CommonTypes.h" +#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" +#include "Core/PowerPC/JitArm64/Jit.h" +#include "Core/PowerPC/PowerPC.h" + +#include "../TestValues.h" + +#include <gtest/gtest.h> + +namespace +{ +using namespace Arm64Gen; + +class TestFrsqrte : public JitArm64 +{ +public: + TestFrsqrte() + { + AllocCodeSpace(4096); + + const u8* raw_frsqrte = GetCodePtr(); + GenerateFrsqrte(); + + frsqrte = Common::BitCast<u64 (*)(u64)>(GetCodePtr()); + MOV(ARM64Reg::X15, ARM64Reg::X30); + MOV(ARM64Reg::X14, PPC_REG); + MOVP2R(PPC_REG, &PowerPC::ppcState); + MOV(ARM64Reg::X1, ARM64Reg::X0); + m_float_emit.FMOV(ARM64Reg::D0, ARM64Reg::X0); + m_float_emit.FRSQRTE(ARM64Reg::D0, ARM64Reg::D0); + BL(raw_frsqrte); + MOV(ARM64Reg::X30, ARM64Reg::X15); + MOV(PPC_REG, ARM64Reg::X14); + RET(); + } + + std::function<u64(u64)> frsqrte; +}; + +} // namespace + +TEST(JitArm64, Frsqrte) +{ + TestFrsqrte test; + + for (const u64 ivalue : double_test_values) + { + const double dvalue = Common::BitCast<double>(ivalue); + + const u64 expected = Common::BitCast<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); + } +} diff --git a/Source/UnitTests/Core/PowerPC/TestValues.h b/Source/UnitTests/Core/PowerPC/TestValues.h index 20fbbe913c..a1df5b0ff5 100644 --- a/Source/UnitTests/Core/PowerPC/TestValues.h +++ b/Source/UnitTests/Core/PowerPC/TestValues.h @@ -8,7 +8,7 @@ #include "Common/CommonTypes.h" -constexpr std::array<u64, 49> double_test_values{ +constexpr std::array<u64, 57> double_test_values{ // Special values 0x0000'0000'0000'0000, // positive zero 0x0000'0000'0000'0001, // smallest positive denormal @@ -54,13 +54,25 @@ constexpr std::array<u64, 49> double_test_values{ 0x3680'1234'5678'9ABC, 0x36A0'1234'5678'9ABC, 0x36B0'1234'5678'9ABC, 0xB680'1234'5678'9ABC, 0xB6A0'1234'5678'9ABC, 0xB6B0'1234'5678'9ABC, + // (exp > 1148) Boundary case for fres + 0x47C0'0000'0000'0000, // 2^125 = fres result is non-zero + 0x47D0'0000'0000'0000, // 2^126 = fres result is zero + 0xC7C0'0000'0000'0000, // -2^125 = fres result is non-zero + 0xC7D0'0000'0000'0000, // -2^126 = fres result is zero + + // (exp < 895) Boundary case for fres + 0x37F0'0000'0000'0000, // 2^(-128) = fres result is non-max + 0x37E0'0000'0000'0000, // 2^(-129) = fres result is max + 0xB7F0'0000'0000'0000, // -2^(-128) = fres result is non-max + 0xB7E0'0000'0000'0000, // -2^(-129) = fres result is max + // Some typical numbers 0x3FF8'0000'0000'0000, // 1.5 0x408F'4000'0000'0000, // 1000 0xC008'0000'0000'0000, // -3 }; -constexpr std::array<u32, 29> single_test_values{ +constexpr std::array<u32, 33> single_test_values{ // Special values 0x0000'0000, // positive zero 0x0000'0001, // smallest positive denormal @@ -89,6 +101,12 @@ constexpr std::array<u32, 29> single_test_values{ 0xFFC0'0000, // first negative QNaN 0xFFFF'FFFF, // last negative QNaN + // (exp > 252) Boundary case for fres + 0x7E00'0000, // 2^125 = fres result is non-zero + 0x7E80'0000, // 2^126 = fres result is zero + 0xC7C0'0000, // -2^125 = fres result is non-zero + 0xC7D0'0000, // -2^126 = fres result is zero + // Some typical numbers 0x3FC0'0000, // 1.5 0x447A'0000, // 1000 |
