diff options
| author | JosJuice <josjuice@gmail.com> | 2021-05-23 21:15:07 +0200 |
|---|---|---|
| committer | JosJuice <josjuice@gmail.com> | 2021-05-25 10:54:00 +0200 |
| commit | 9bc5bd83a990bf15e0a95b0944166264d2bde58a (patch) | |
| tree | 6cc01da510924c962d2a5c9e5fc44d8ffef47089 /Source/Core | |
| parent | ff08b85740f52394433ebc2a49c22b324c858dc7 (diff) | |
Interpreter: Use std::fma for emulating FMA
This is more accurate to the original hardware's rounding behavior.
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Core/PowerPC/Interpreter/Interpreter_FPUtils.h | 48 |
1 files 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; } |
