diff options
| author | Tilka <tilkax@gmail.com> | 2020-01-25 19:10:37 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-25 19:10:37 +0000 |
| commit | 709862b818f4546fbe15978efafe467a0c08b0c4 (patch) | |
| tree | 431bf5f9e1b6436c5f2a72adf8c1100797e1cc62 /Source/UnitTests/Core/PowerPC/Jit64Common/ConvertDoubleToSingle.cpp | |
| parent | e3a7922e12977ec4a2ea93249568497f3f891e9f (diff) | |
| parent | f6afce781fa367f077e96da563edd0f349bdcd83 (diff) | |
Merge pull request #8120 from MerryMage/cdts
Jit64: Make DoubleToSingle a common asm routine
Diffstat (limited to 'Source/UnitTests/Core/PowerPC/Jit64Common/ConvertDoubleToSingle.cpp')
| -rw-r--r-- | Source/UnitTests/Core/PowerPC/Jit64Common/ConvertDoubleToSingle.cpp | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/Source/UnitTests/Core/PowerPC/Jit64Common/ConvertDoubleToSingle.cpp b/Source/UnitTests/Core/PowerPC/Jit64Common/ConvertDoubleToSingle.cpp new file mode 100644 index 0000000000..41ca31b273 --- /dev/null +++ b/Source/UnitTests/Core/PowerPC/Jit64Common/ConvertDoubleToSingle.cpp @@ -0,0 +1,116 @@ +// Copyright 2019 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include <cstring> +#include <tuple> +#include <vector> + +#include "Common/CommonTypes.h" +#include "Common/x64ABI.h" +#include "Core/PowerPC/Gekko.h" +#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h" +#include "Core/PowerPC/Jit64/Jit.h" +#include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h" +#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h" + +#include <gtest/gtest.h> + +namespace +{ +class TestCommonAsmRoutines : public CommonAsmRoutines +{ +public: + TestCommonAsmRoutines() : CommonAsmRoutines(jit) + { + using namespace Gen; + + AllocCodeSpace(4096); + m_const_pool.Init(AllocChildCodeSpace(1024), 1024); + + const auto raw_cdts = reinterpret_cast<double (*)(double)>(AlignCode4()); + GenConvertDoubleToSingle(); + + wrapped_cdts = reinterpret_cast<u32 (*)(u64)>(AlignCode4()); + ABI_PushRegistersAndAdjustStack(ABI_ALL_CALLEE_SAVED, 8, 16); + + // Call + MOVQ_xmm(XMM0, R(ABI_PARAM1)); + ABI_CallFunction(raw_cdts); + MOV(32, R(ABI_RETURN), R(RSCRATCH)); + + ABI_PopRegistersAndAdjustStack(ABI_ALL_CALLEE_SAVED, 8, 16); + RET(); + } + + u32 (*wrapped_cdts)(u64); + Jit64 jit; +}; +} // namespace + +TEST(Jit64, ConvertDoubleToSingle) +{ + TestCommonAsmRoutines routines; + + const std::vector<u64> input_values{ + // Special values + 0x0000'0000'0000'0000, // positive zero + 0x0000'0000'0000'0001, // smallest positive denormal + 0x0000'0000'0100'0000, + 0x000F'FFFF'FFFF'FFFF, // largest positive denormal + 0x0010'0000'0000'0000, // smallest positive normal + 0x0010'0000'0000'0002, + 0x3FF0'0000'0000'0000, // 1.0 + 0x7FEF'FFFF'FFFF'FFFF, // largest positive normal + 0x7FF0'0000'0000'0000, // positive infinity + 0x7FF0'0000'0000'0001, // first positive SNaN + 0x7FF7'FFFF'FFFF'FFFF, // last positive SNaN + 0x7FF8'0000'0000'0000, // first positive QNaN + 0x7FFF'FFFF'FFFF'FFFF, // last positive QNaN + 0x8000'0000'0000'0000, // negative zero + 0x8000'0000'0000'0001, // smallest negative denormal + 0x8000'0000'0100'0000, + 0x800F'FFFF'FFFF'FFFF, // largest negative denormal + 0x8010'0000'0000'0000, // smallest negative normal + 0x8010'0000'0000'0002, + 0xBFF0'0000'0000'0000, // -1.0 + 0xFFEF'FFFF'FFFF'FFFF, // largest negative normal + 0xFFF0'0000'0000'0000, // negative infinity + 0xFFF0'0000'0000'0001, // first negative SNaN + 0xFFF7'FFFF'FFFF'FFFF, // last negative SNaN + 0xFFF8'0000'0000'0000, // first negative QNaN + 0xFFFF'FFFF'FFFF'FFFF, // last negative QNaN + + // (exp > 896) Boundary Case + 0x3800'0000'0000'0000, // 2^(-127) = Denormal in single-prec + 0x3810'0000'0000'0000, // 2^(-126) = Smallest single-prec normal + 0xB800'0000'0000'0000, // -2^(-127) = Denormal in single-prec + 0xB810'0000'0000'0000, // -2^(-126) = Smallest single-prec normal + 0x3800'1234'5678'9ABC, 0x3810'1234'5678'9ABC, 0xB800'1234'5678'9ABC, 0xB810'1234'5678'9ABC, + + // (exp >= 874) Boundary Case + 0x3680'0000'0000'0000, // 2^(-150) = Unrepresentable in single-prec + 0x36A0'0000'0000'0000, // 2^(-149) = Smallest single-prec denormal + 0x36B0'0000'0000'0000, // 2^(-148) = Single-prec denormal + 0xB680'0000'0000'0000, // -2^(-150) = Unrepresentable in single-prec + 0xB6A0'0000'0000'0000, // -2^(-149) = Smallest single-prec denormal + 0xB6B0'0000'0000'0000, // -2^(-148) = Single-prec denormal + 0x3680'1234'5678'9ABC, 0x36A0'1234'5678'9ABC, 0x36B0'1234'5678'9ABC, 0xB680'1234'5678'9ABC, + 0xB6A0'1234'5678'9ABC, 0xB6B0'1234'5678'9ABC, + + // Some typical numbers + 0x3FF8'0000'0000'0000, // 1.5 + 0x408F'4000'0000'0000, // 1000 + 0xC008'0000'0000'0000, // -3 + }; + + for (const u64 input : input_values) + { + const u32 expected = ConvertToSingle(input); + const u32 actual = routines.wrapped_cdts(input); + + printf("%016llx -> %08x == %08x\n", input, actual, expected); + + EXPECT_EQ(expected, actual); + } +} |
