summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2021-05-23 21:15:07 +0200
committerJosJuice <josjuice@gmail.com>2021-05-25 10:54:00 +0200
commit9bc5bd83a990bf15e0a95b0944166264d2bde58a (patch)
tree6cc01da510924c962d2a5c9e5fc44d8ffef47089 /Source/Core
parentff08b85740f52394433ebc2a49c22b324c858dc7 (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.h48
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;
}