[PATCH] Fix ARM optimized fma & fmaf implementations
Mickaël Thomas <[email protected]>
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
The vfma.f32|64 z, x, y instruction performs the operation
z += x * y without intermediate rounding.
The register used for z is both read and written by the instruction.
The inline assembly must therefore use the "+" constraint modifier.
Using "=" the generated assembly gives an incorrect result.
Current (incorrect) implementation:
In archive arm-none-eabi/thumb/v8-m.main+dp/hard/newlib/libm.a:
<fma>:
eea0 0b01 vfma.f64 d0, d0, d1
4770 bx lr
<fmaf>:
eea0 0a20 vfma.f32 s0, s0, s1
4770 bx lr
Correct implementation:
<fma>:
eea0 2b01 vfma.f64 d2, d0, d1
eeb0 0b42 vmov.f64 d0, d2
4770 bx lr
<fmaf>:
eea0 1a20 vfma.f32 s2, s0, s1
eeb0 0a41 vmov.f32 s0, s2
4770 bx lr
---
newlib/libm/machine/arm/s_fma_arm.c | 2 +-
newlib/libm/machine/arm/sf_fma_arm.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/newlib/libm/machine/arm/s_fma_arm.c b/newlib/libm/machine/arm/s_fma_arm.c
index f945419b5..6a2b403e1 100644
--- a/newlib/libm/machine/arm/s_fma_arm.c
+++ b/newlib/libm/machine/arm/s_fma_arm.c
@@ -41,7 +41,7 @@
double
fma (double x, double y, double z)
{
- asm ("vfma.f64 %P0, %P1, %P2" : "=w" (z) : "w" (x), "w" (y));
+ asm ("vfma.f64 %P0, %P1, %P2" : "+w" (z) : "w" (x), "w" (y));
return z;
}
diff --git a/newlib/libm/machine/arm/sf_fma_arm.c b/newlib/libm/machine/arm/sf_fma_arm.c
index 4befd9017..8d1b63d99 100644
--- a/newlib/libm/machine/arm/sf_fma_arm.c
+++ b/newlib/libm/machine/arm/sf_fma_arm.c
@@ -41,7 +41,7 @@
float
fmaf (float x, float y, float z)
{
- asm ("vfma.f32 %0, %1, %2" : "=t" (z) : "t" (x), "t" (y));
+ asm ("vfma.f32 %0, %1, %2" : "+t" (z) : "t" (x), "t" (y));
return z;
}
--
2.45.2