Skip to content

Commit 8bc76ac

Browse files
committed
Implement FMADD in terms of std::fma
1 parent 36b344c commit 8bc76ac

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

include/remill/Arch/Runtime/sysroot/cmath

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ constexpr long double sqrt(long double num) {
8080
return __builtin_sqrtl(num);
8181
}
8282

83+
// https://en.cppreference.com/w/cpp/numeric/math/fma.html
84+
constexpr float fma(float x, float y, float z) {
85+
return __builtin_fmaf(x, y, z);
86+
}
87+
88+
constexpr double fma(double x, double y, double z) {
89+
return __builtin_fma(x, y, z);
90+
}
91+
92+
constexpr long double fma(long double x, long double y, long double z) {
93+
return __builtin_fmal(x, y, z);
94+
}
95+
8396
// https://en.cppreference.com/w/cpp/numeric/math/isunordered
8497
constexpr bool isunordered(float x, float y) {
8598
return __builtin_isunordered(x, y);

lib/Arch/AArch64/Semantics/BINARY.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,7 @@ DEF_SEM(FMADD_S, V128W dst, V32 src1, V32 src2, V32 src3) {
274274

275275
__remill_fpu_exception_clear(kFPUExceptionAll);
276276
BarrierReorder();
277-
auto prod = FMul32(factor1, factor2);
278-
auto res = FAdd32(prod, add);
277+
auto res = std::fma(factor1, factor2, add);
279278
BarrierReorder();
280279
auto new_except = __remill_fpu_exception_test(kFPUExceptionAll);
281280
BarrierReorder();
@@ -301,8 +300,7 @@ DEF_SEM(FMADD_D, V128W dst, V64 src1, V64 src2, V64 src3) {
301300

302301
__remill_fpu_exception_clear(kFPUExceptionAll);
303302
BarrierReorder();
304-
auto prod = FMul64(factor1, factor2);
305-
auto res = FAdd64(prod, add);
303+
auto res = std::fma(factor1, factor2, add);
306304
BarrierReorder();
307305
auto except_new = __remill_fpu_exception_test(kFPUExceptionAll);
308306
SetFPSRStatusFlags(state, except_new);

tests/AArch64/Run.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,11 @@ static void RunWithFlags(const test::TestInfo *info, NZCV flags,
708708
auto lifted_state = reinterpret_cast<State *>(&gLiftedState);
709709
auto native_state = reinterpret_cast<State *>(&gNativeState);
710710

711+
// CRITICAL: Establish consistent FPU environment for both tests
712+
std::fesetenv(FE_DFL_ENV);
713+
std::feclearexcept(FE_ALL_EXCEPT);
714+
std::fesetround(FE_TONEAREST); // Explicit rounding mode
715+
711716
// Set up the run's info.
712717
gTestToRun = info->test_begin;
713718
gStackSwitcher = &(gLiftedStack._redzone2[0]);
@@ -719,6 +724,12 @@ static void RunWithFlags(const test::TestInfo *info, NZCV flags,
719724
auto native_test_faulted = false;
720725
if (!sigsetjmp(gJmpBuf, true)) {
721726
gInNativeTest = true;
727+
728+
// Reset FPU environment before native test
729+
std::fesetenv(FE_DFL_ENV);
730+
std::feclearexcept(FE_ALL_EXCEPT);
731+
std::fesetround(FE_TONEAREST);
732+
722733
asm("msr nzcv, %0" : : "r"(flags));
723734
InvokeTestCase(arg1, arg2, arg3);
724735
} else {
@@ -740,7 +751,11 @@ static void RunWithFlags(const test::TestInfo *info, NZCV flags,
740751
// native program state recorded before executing the native testcase,
741752
// but after swapping execution to operate on `gStack`.
742753
if (!sigsetjmp(gJmpBuf, true)) {
754+
// Reset FPU environment before lifted test (same as native)
743755
std::fesetenv(FE_DFL_ENV);
756+
std::feclearexcept(FE_ALL_EXCEPT);
757+
std::fesetround(FE_TONEAREST);
758+
744759
gInNativeTest = false;
745760
(void) lifted_func(*lifted_state, lifted_state->gpr.pc.aword, nullptr);
746761
} else {

0 commit comments

Comments
 (0)