powerpc64: add single-instruction math functions
authorRich Felker <dalias@aerifal.cx>
Fri, 23 Jun 2017 20:01:00 +0000 (16:01 -0400)
committerRich Felker <dalias@aerifal.cx>
Fri, 23 Jun 2017 20:01:00 +0000 (16:01 -0400)
while the official elfv2 abi for "powerpc64le" sets power8 as the
baseline isa, we use it for both little and big endian powerpc64
targets and need to maintain compatibility with pre-power8 models. the
instructions for sqrt, fabs, and fma are in the baseline isa; support
for the rest is conditional via predefined isa-level macros.

patch by David Edelsohn.

22 files changed:
src/math/powerpc64/ceil.c [new file with mode: 0644]
src/math/powerpc64/ceilf.c [new file with mode: 0644]
src/math/powerpc64/fabs.c [new file with mode: 0644]
src/math/powerpc64/fabsf.c [new file with mode: 0644]
src/math/powerpc64/floor.c [new file with mode: 0644]
src/math/powerpc64/floorf.c [new file with mode: 0644]
src/math/powerpc64/fma.c [new file with mode: 0644]
src/math/powerpc64/fmaf.c [new file with mode: 0644]
src/math/powerpc64/fmax.c [new file with mode: 0644]
src/math/powerpc64/fmaxf.c [new file with mode: 0644]
src/math/powerpc64/fmin.c [new file with mode: 0644]
src/math/powerpc64/fminf.c [new file with mode: 0644]
src/math/powerpc64/lrint.c [new file with mode: 0644]
src/math/powerpc64/lrintf.c [new file with mode: 0644]
src/math/powerpc64/lround.c [new file with mode: 0644]
src/math/powerpc64/lroundf.c [new file with mode: 0644]
src/math/powerpc64/round.c [new file with mode: 0644]
src/math/powerpc64/roundf.c [new file with mode: 0644]
src/math/powerpc64/sqrt.c [new file with mode: 0644]
src/math/powerpc64/sqrtf.c [new file with mode: 0644]
src/math/powerpc64/trunc.c [new file with mode: 0644]
src/math/powerpc64/truncf.c [new file with mode: 0644]

diff --git a/src/math/powerpc64/ceil.c b/src/math/powerpc64/ceil.c
new file mode 100644 (file)
index 0000000..4b01133
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef _ARCH_PWR5X
+
+double ceil(double x)
+{
+       __asm__ ("frip %0, %1" : "=d"(x) : "d"(x));
+       return x;
+}
+
+#else
+
+#include "../ceil.c"
+
+#endif
diff --git a/src/math/powerpc64/ceilf.c b/src/math/powerpc64/ceilf.c
new file mode 100644 (file)
index 0000000..59ba396
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef _ARCH_PWR5X
+
+float ceilf(float x)
+{
+       __asm__ ("frip %0, %1" : "=f"(x) : "f"(x));
+       return x;
+}
+
+#else
+
+#include "../ceilf.c"
+
+#endif
diff --git a/src/math/powerpc64/fabs.c b/src/math/powerpc64/fabs.c
new file mode 100644 (file)
index 0000000..6123c75
--- /dev/null
@@ -0,0 +1,7 @@
+#include <math.h>
+
+double fabs(double x)
+{
+       __asm__ ("fabs %0, %1" : "=d"(x) : "d"(x));
+       return x;
+}
diff --git a/src/math/powerpc64/fabsf.c b/src/math/powerpc64/fabsf.c
new file mode 100644 (file)
index 0000000..e9e4564
--- /dev/null
@@ -0,0 +1,7 @@
+#include <math.h>
+
+float fabsf(float x)
+{
+       __asm__ ("fabs %0, %1" : "=f"(x) : "f"(x));
+       return x;
+}
diff --git a/src/math/powerpc64/floor.c b/src/math/powerpc64/floor.c
new file mode 100644 (file)
index 0000000..4e68044
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef _ARCH_PWR5X
+
+double floor(double x)
+{
+       __asm__ ("frim %0, %1" : "=d"(x) : "d"(x));
+       return x;
+}
+
+#else
+
+#include "../floor.c"
+
+#endif
diff --git a/src/math/powerpc64/floorf.c b/src/math/powerpc64/floorf.c
new file mode 100644 (file)
index 0000000..e1031ef
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef _ARCH_PWR5X
+
+float floorf(float x)
+{
+       __asm__ ("frim %0, %1" : "=f"(x) : "f"(x));
+       return x;
+}
+
+#else
+
+#include "../floorf.c"
+
+#endif
diff --git a/src/math/powerpc64/fma.c b/src/math/powerpc64/fma.c
new file mode 100644 (file)
index 0000000..5aebd1a
--- /dev/null
@@ -0,0 +1,7 @@
+#include <math.h>
+
+double fma(double x, double y, double z)
+{
+       __asm__ ("fmadd %0, %1, %2, %3" : "=d"(x) : "d"(x), "d"(y), "d"(z));
+       return x;
+}
diff --git a/src/math/powerpc64/fmaf.c b/src/math/powerpc64/fmaf.c
new file mode 100644 (file)
index 0000000..c678fef
--- /dev/null
@@ -0,0 +1,7 @@
+#include <math.h>
+
+float fmaf(float x, float y, float z)
+{
+       __asm__ ("fmadds %0, %1, %2, %3" : "=f"(x) : "f"(x), "f"(y), "f"(z));
+       return x;
+}
diff --git a/src/math/powerpc64/fmax.c b/src/math/powerpc64/fmax.c
new file mode 100644 (file)
index 0000000..992df7f
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef __VSX__
+
+double fmax(double x, double y)
+{
+       __asm__ ("xsmaxdp %x0, %x1, %x2" : "=ws"(x) : "ws"(x), "ws"(y));
+       return x;
+}
+
+#else
+
+#include "../fmax.c"
+
+#endif
diff --git a/src/math/powerpc64/fmaxf.c b/src/math/powerpc64/fmaxf.c
new file mode 100644 (file)
index 0000000..345a234
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef __VSX__
+
+float fmaxf(float x, float y)
+{
+       __asm__ ("xsmaxdp %x0, %x1, %x2" : "=ww"(x) : "ww"(x), "ww"(y));
+       return x;
+}
+
+#else
+
+#include "../fmaxf.c"
+
+#endif
diff --git a/src/math/powerpc64/fmin.c b/src/math/powerpc64/fmin.c
new file mode 100644 (file)
index 0000000..adf71ba
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef __VSX__
+
+double fmin(double x, double y)
+{
+       __asm__ ("xsmindp %x0, %x1, %x2" : "=ws"(x) : "ws"(x), "ws"(y));
+       return x;
+}
+
+#else
+
+#include "../fmin.c"
+
+#endif
diff --git a/src/math/powerpc64/fminf.c b/src/math/powerpc64/fminf.c
new file mode 100644 (file)
index 0000000..faf0e47
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef __VSX__
+
+float fminf(float x, float y)
+{
+       __asm__ ("xsmindp %x0, %x1, %x2" : "=ww"(x) : "ww"(x), "ww"(y));
+       return x;
+}
+
+#else
+
+#include "../fminf.c"
+
+#endif
diff --git a/src/math/powerpc64/lrint.c b/src/math/powerpc64/lrint.c
new file mode 100644 (file)
index 0000000..4e4b2e0
--- /dev/null
@@ -0,0 +1,16 @@
+#include <math.h>
+
+#ifdef _ARCH_PWR5X
+
+long lrint(double x)
+{
+       long n;
+       __asm__ ("fctid %0, %1" : "=d"(n) : "d"(x));
+       return n;
+}
+
+#else
+
+#include "../lrint.c"
+
+#endif
diff --git a/src/math/powerpc64/lrintf.c b/src/math/powerpc64/lrintf.c
new file mode 100644 (file)
index 0000000..9070fc0
--- /dev/null
@@ -0,0 +1,16 @@
+#include <math.h>
+
+#ifdef _ARCH_PWR5X
+
+long lrintf(float x)
+{
+       long n;
+       __asm__ ("fctid %0, %1" : "=d"(n) : "f"(x));
+       return n;
+}
+
+#else
+
+#include "../lrintf.c"
+
+#endif
diff --git a/src/math/powerpc64/lround.c b/src/math/powerpc64/lround.c
new file mode 100644 (file)
index 0000000..ee4d114
--- /dev/null
@@ -0,0 +1,18 @@
+#include <math.h>
+
+#ifdef __VSX__
+
+long lround(double x)
+{
+       long n;
+       __asm__ (
+               "xsrdpi %1, %1\n"
+               "fctid %0, %1\n" : "=d"(n), "+d"(x));
+       return n;
+}
+
+#else
+
+#include "../lround.c"
+
+#endif
diff --git a/src/math/powerpc64/lroundf.c b/src/math/powerpc64/lroundf.c
new file mode 100644 (file)
index 0000000..033094f
--- /dev/null
@@ -0,0 +1,18 @@
+#include <math.h>
+
+#ifdef __VSX__
+
+long lroundf(float x)
+{
+       long n;
+       __asm__ (
+               "xsrdpi %1, %1\n"
+               "fctid %0, %1\n" : "=d"(n), "+f"(x));
+       return n;
+}
+
+#else
+
+#include "../lroundf.c"
+
+#endif
diff --git a/src/math/powerpc64/round.c b/src/math/powerpc64/round.c
new file mode 100644 (file)
index 0000000..4b9318e
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef _ARCH_PWR5X
+
+double round(double x)
+{
+       __asm__ ("frin %0, %1" : "=d"(x) : "d"(x));
+       return x;
+}
+
+#else
+
+#include "../round.c"
+
+#endif
diff --git a/src/math/powerpc64/roundf.c b/src/math/powerpc64/roundf.c
new file mode 100644 (file)
index 0000000..ae93f99
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef _ARCH_PWR5X
+
+float roundf(float x)
+{
+       __asm__ ("frin %0, %1" : "=f"(x) : "f"(x));
+       return x;
+}
+
+#else
+
+#include "../roundf.c"
+
+#endif
diff --git a/src/math/powerpc64/sqrt.c b/src/math/powerpc64/sqrt.c
new file mode 100644 (file)
index 0000000..13bb98d
--- /dev/null
@@ -0,0 +1,7 @@
+#include <math.h>
+
+double sqrt(double x)
+{
+       __asm__ ("fsqrt %0, %1" : "=d"(x) : "d"(x));
+       return x;
+}
diff --git a/src/math/powerpc64/sqrtf.c b/src/math/powerpc64/sqrtf.c
new file mode 100644 (file)
index 0000000..b6ecb10
--- /dev/null
@@ -0,0 +1,7 @@
+#include <math.h>
+
+float sqrtf(float x)
+{
+       __asm__ ("fsqrts %0, %1" : "=f"(x) : "f"(x));
+       return x;
+}
diff --git a/src/math/powerpc64/trunc.c b/src/math/powerpc64/trunc.c
new file mode 100644 (file)
index 0000000..5791854
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef _ARCH_PWR5X
+
+double trunc(double x)
+{
+       __asm__ ("friz %0, %1" : "=d"(x) : "d"(x));
+       return x;
+}
+
+#else
+
+#include "../trunc.c"
+
+#endif
diff --git a/src/math/powerpc64/truncf.c b/src/math/powerpc64/truncf.c
new file mode 100644 (file)
index 0000000..94e638f
--- /dev/null
@@ -0,0 +1,15 @@
+#include <math.h>
+
+#ifdef _ARCH_PWR5X
+
+float truncf(float x)
+{
+       __asm__ ("friz %0, %1" : "=f"(x) : "f"(x));
+       return x;
+}
+
+#else
+
+#include "../truncf.c"
+
+#endif