From 4f3ef50d5c6e3bb4ee0753e7161b9e0ce010d4b8 Mon Sep 17 00:00:00 2001 From: Merry Date: Sun, 15 Jan 2023 23:59:27 +0000 Subject: [PATCH] fp: Fix FPToFixed for borderline values --- src/dynarmic/common/fp/op/FPToFixed.cpp | 3 ++- tests/fp/FPToFixed.cpp | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/dynarmic/common/fp/op/FPToFixed.cpp b/src/dynarmic/common/fp/op/FPToFixed.cpp index adb90180..b1a57d31 100644 --- a/src/dynarmic/common/fp/op/FPToFixed.cpp +++ b/src/dynarmic/common/fp/op/FPToFixed.cpp @@ -5,6 +5,7 @@ #include "dynarmic/common/fp/op/FPToFixed.h" +#include #include #include #include @@ -75,7 +76,7 @@ u64 FPToFixed(size_t ibits, FPT op, size_t fbits, bool unsigned_, FPCR fpcr, Rou } // Detect Overflow - const int min_exponent_for_overflow = static_cast(ibits) - static_cast(mcl::bit::highest_set_bit(value.mantissa + (round_up ? 1 : 0))) - (unsigned_ ? 0 : 1); + const int min_exponent_for_overflow = static_cast(ibits) - static_cast(mcl::bit::highest_set_bit(value.mantissa + (round_up ? Safe::LogicalShiftRight(1, exponent) : 0))) - (unsigned_ ? 0 : 1); if (exponent >= min_exponent_for_overflow) { // Positive overflow if (unsigned_ || !sign) { diff --git a/tests/fp/FPToFixed.cpp b/tests/fp/FPToFixed.cpp index 2d1deb5e..31a684a6 100644 --- a/tests/fp/FPToFixed.cpp +++ b/tests/fp/FPToFixed.cpp @@ -38,3 +38,20 @@ TEST_CASE("FPToFixed", "[fp]") { REQUIRE(fpsr.Value() == expected_fpsr); } } + +TEST_CASE("FPToFixed edge cases", "[fp]") { + const std::vector> test_cases{ + {0x41dffffffffffffe, 0x7fffffff, false, FP::RoundingMode::ToNearest_TieEven}, + {0x41dffffffffffffe, 0x7fffffff, false, FP::RoundingMode::TowardsPlusInfinity}, + {0x41dffffffffffffe, 0x7fffffff, false, FP::RoundingMode::TowardsMinusInfinity}, + {0x41dffffffffffffe, 0x7fffffff, false, FP::RoundingMode::TowardsZero}, + {0x41dffffffffffffe, 0x7fffffff, false, FP::RoundingMode::ToNearest_TieAwayFromZero}, + }; + + const FPCR fpcr; + FPSR fpsr; + for (auto [input, expected_output, unsigned_, rounding_mode] : test_cases) { + const u64 output = FPToFixed(32, input, 0, unsigned_, fpcr, rounding_mode, fpsr); + REQUIRE(output == expected_output); + } +}