From 9bc5bd83a990bf15e0a95b0944166264d2bde58a Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 23 May 2021 21:15:07 +0200 Subject: [PATCH] Interpreter: Use std::fma for emulating FMA This is more accurate to the original hardware's rounding behavior. --- .../PowerPC/Interpreter/Interpreter_FPUtils.h | 48 ++----------------- 1 file changed, 4 insertions(+), 44 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h index 70978cf0d3..bedc3085d3 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -238,7 +238,7 @@ inline FPResult NI_sub(UReg_FPSCR* fpscr, double a, double b) // inputs are checked for NaN is still a, b, c. inline FPResult NI_madd(UReg_FPSCR* fpscr, double a, double c, double b) { - FPResult result{a * c}; + FPResult result{std::fma(a, c, b)}; if (std::isnan(result.value)) { @@ -263,27 +263,7 @@ inline FPResult NI_madd(UReg_FPSCR* fpscr, double a, double c, double b) return result; } - result.SetException(fpscr, FPSCR_VXIMZ); - result.value = PPC_NAN; - return result; - } - - result.value += b; - - if (std::isnan(result.value)) - { - if (Common::IsSNAN(b)) - result.SetException(fpscr, FPSCR_VXSNAN); - - fpscr->ClearFIFR(); - - if (std::isnan(b)) - { - result.value = MakeQuiet(b); - return result; - } - - result.SetException(fpscr, FPSCR_VXISI); + result.SetException(fpscr, std::isnan(a * c) ? FPSCR_VXIMZ : FPSCR_VXISI); result.value = PPC_NAN; return result; } @@ -296,7 +276,7 @@ inline FPResult NI_madd(UReg_FPSCR* fpscr, double a, double c, double b) inline FPResult NI_msub(UReg_FPSCR* fpscr, double a, double c, double b) { - FPResult result{a * c}; + FPResult result{std::fma(a, c, -b)}; if (std::isnan(result.value)) { @@ -321,27 +301,7 @@ inline FPResult NI_msub(UReg_FPSCR* fpscr, double a, double c, double b) return result; } - result.SetException(fpscr, FPSCR_VXIMZ); - result.value = PPC_NAN; - return result; - } - - result.value -= b; - - if (std::isnan(result.value)) - { - if (Common::IsSNAN(b)) - result.SetException(fpscr, FPSCR_VXSNAN); - - fpscr->ClearFIFR(); - - if (std::isnan(b)) - { - result.value = MakeQuiet(b); - return result; - } - - result.SetException(fpscr, FPSCR_VXISI); + result.SetException(fpscr, std::isnan(a * c) ? FPSCR_VXIMZ : FPSCR_VXISI); result.value = PPC_NAN; return result; }