crt: arm: Use a bit twiddling implementation of rint*
Split the implementation file per architecture, and use a BSD/Sun
implementation of rint/rintf for arm, as the previous arm
implementation used signed 32 bit integer intermediates.
Signed-off-by: Martin Storsjö <martin@martin.st>
diff --git a/mingw-w64-crt/math/arm/s_rint.c b/mingw-w64-crt/math/arm/s_rint.c
new file mode 100644
index 0000000..823a2e0
--- /dev/null
+++ b/mingw-w64-crt/math/arm/s_rint.c
@@ -0,0 +1,86 @@
+/* @(#)s_rint.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/cdefs.h>
+
+/*
+ * rint(x)
+ * Return x rounded to integral value according to the prevailing
+ * rounding mode.
+ * Method:
+ * Using floating addition.
+ * Exception:
+ * Inexact flag raised if x not equal to rint(x).
+ */
+
+#include <float.h>
+
+#include "../bsd_private_base.h"
+
+static const double
+TWO52[2]={
+ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
+ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
+};
+
+double
+rint(double x)
+{
+ int32_t i0,j0,sx;
+ u_int32_t i,i1;
+ double w,t;
+ EXTRACT_WORDS(i0,i1,x);
+ sx = (i0>>31)&1;
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) {
+ if(((i0&0x7fffffff)|i1)==0) return x;
+ i1 |= (i0&0x0fffff);
+ i0 &= 0xfffe0000;
+ i0 |= ((i1|-i1)>>12)&0x80000;
+ SET_HIGH_WORD(x,i0);
+ STRICT_ASSIGN(double,w,TWO52[sx]+x);
+ t = w-TWO52[sx];
+ GET_HIGH_WORD(i0,t);
+ SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31));
+ return t;
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ i>>=1;
+ if(((i0&i)|i1)!=0) {
+ /*
+ * Some bit is set after the 0.5 bit. To avoid the
+ * possibility of errors from double rounding in
+ * w = TWO52[sx]+x, adjust the 0.25 bit to a lower
+ * guard bit. We do this for all j0<=51. The
+ * adjustment is trickiest for j0==18 and j0==19
+ * since then it spans the word boundary.
+ */
+ if(j0==19) i1 = 0x40000000; else
+ if(j0==18) i1 = 0x80000000; else
+ i0 = (i0&(~i))|((0x20000)>>j0);
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((u_int32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) return x; /* x is integral */
+ i>>=1;
+ if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20));
+ }
+ INSERT_WORDS(x,i0,i1);
+ STRICT_ASSIGN(double,w,TWO52[sx]+x);
+ return w-TWO52[sx];
+}
diff --git a/mingw-w64-crt/math/arm/s_rintf.c b/mingw-w64-crt/math/arm/s_rintf.c
new file mode 100644
index 0000000..0ec0170
--- /dev/null
+++ b/mingw-w64-crt/math/arm/s_rintf.c
@@ -0,0 +1,51 @@
+/* s_rintf.c -- float version of s_rint.c.
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/cdefs.h>
+
+#include <float.h>
+#include <stdint.h>
+
+#include "../bsd_private_base.h"
+
+static const float
+TWO23[2]={
+ 8.3886080000e+06, /* 0x4b000000 */
+ -8.3886080000e+06, /* 0xcb000000 */
+};
+
+float
+rintf(float x)
+{
+ int32_t i0,j0,sx;
+ float w,t;
+ GET_FLOAT_WORD(i0,x);
+ sx = (i0>>31)&1;
+ j0 = ((i0>>23)&0xff)-0x7f;
+ if(j0<23) {
+ if(j0<0) {
+ if((i0&0x7fffffff)==0) return x;
+ STRICT_ASSIGN(float,w,TWO23[sx]+x);
+ t = w-TWO23[sx];
+ GET_FLOAT_WORD(i0,t);
+ SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31));
+ return t;
+ }
+ STRICT_ASSIGN(float,w,TWO23[sx]+x);
+ return w-TWO23[sx];
+ }
+ if(j0==0x80) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+}
diff --git a/mingw-w64-crt/math/arm64/rint.c b/mingw-w64-crt/math/arm64/rint.c
new file mode 100644
index 0000000..03a7ffa
--- /dev/null
+++ b/mingw-w64-crt/math/arm64/rint.c
@@ -0,0 +1,12 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <math.h>
+
+double rint (double x) {
+ double retval = 0.0;
+ __asm__ __volatile__ ("frintx %d0, %d1\n\t" : "=w" (retval) : "w" (x));
+ return retval;
+}
diff --git a/mingw-w64-crt/math/arm64/rintf.c b/mingw-w64-crt/math/arm64/rintf.c
new file mode 100644
index 0000000..914769a
--- /dev/null
+++ b/mingw-w64-crt/math/arm64/rintf.c
@@ -0,0 +1,12 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <math.h>
+
+float rintf (float x) {
+ float retval = 0.0F;
+ __asm__ __volatile__ ("frintx %s0, %s1\n\t" : "=w" (retval) : "w" (x));
+ return retval;
+}
diff --git a/mingw-w64-crt/math/bsd_private_base.h b/mingw-w64-crt/math/bsd_private_base.h
index f31c75d..de5b935 100644
--- a/mingw-w64-crt/math/bsd_private_base.h
+++ b/mingw-w64-crt/math/bsd_private_base.h
@@ -10,6 +10,7 @@
*/
#include <inttypes.h>
+#include <float.h>
typedef unsigned int u_int32_t;
@@ -99,3 +100,24 @@
gf_u.word = (i); \
(d) = gf_u.value; \
} while(0)
+
+
+#ifdef FLT_EVAL_METHOD
+/*
+ * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
+ */
+#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
+#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
+#else
+#define STRICT_ASSIGN(type, lval, rval) do { \
+ volatile type __lval; \
+ \
+ if (sizeof(type) >= sizeof(long double)) \
+ (lval) = (rval); \
+ else { \
+ __lval = (rval); \
+ (lval) = __lval; \
+ } \
+} while (0)
+#endif
+#endif /* FLT_EVAL_METHOD */
diff --git a/mingw-w64-crt/math/rint.c b/mingw-w64-crt/math/rint.c
deleted file mode 100644
index d883314..0000000
--- a/mingw-w64-crt/math/rint.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is part of the mingw-w64 runtime package.
- * No warranty is given; refer to the file DISCLAIMER.PD within this package.
- */
-#include <math.h>
-
-double rint (double x) {
- double retval = 0.0;
-#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__)
- __asm__ __volatile__ ("frndint;" : "=t" (retval) : "0" (x));
-#elif defined(__arm__) || defined(_ARM_)
- if (isnan(x) || isinf(x))
- return x;
- float temp;
- __asm__ __volatile__ (
- "vcvtr.s32.f64 %[tmp], %[src]\n\t"
- "vcvt.f64.s32 %[dst], %[tmp]\n\t"
- : [dst] "=w" (retval), [tmp] "=t" (temp) : [src] "w" (x));
-#elif defined(__aarch64__) || defined(_ARM64_)
- __asm__ __volatile__ ("frintx %d0, %d1\n\t" : "=w" (retval) : "w" (x));
-#endif
- return retval;
-}
diff --git a/mingw-w64-crt/math/rintf.c b/mingw-w64-crt/math/rintf.c
deleted file mode 100644
index bfae515..0000000
--- a/mingw-w64-crt/math/rintf.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is part of the mingw-w64 runtime package.
- * No warranty is given; refer to the file DISCLAIMER.PD within this package.
- */
-#include <math.h>
-
-float rintf (float x) {
- float retval = 0.0F;
-#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__)
- __asm__ __volatile__ ("frndint;": "=t" (retval) : "0" (x));
-#elif defined(__arm__) || defined(_ARM_)
- if (isnan(x) || isinf(x))
- return x;
- __asm__ __volatile__ (
- "vcvtr.s32.f32 %[dst], %[src]\n\t"
- "vcvt.f32.s32 %[dst], %[dst]\n\t"
- : [dst] "=t" (retval) : [src] "w" (x));
-#elif defined(__aarch64__) || defined(_ARM64_)
- __asm__ __volatile__ ("frintx %s0, %s1\n\t" : "=w" (retval) : "w" (x));
-#endif
- return retval;
-}
diff --git a/mingw-w64-crt/math/x86/rint.c b/mingw-w64-crt/math/x86/rint.c
new file mode 100644
index 0000000..55a73d1
--- /dev/null
+++ b/mingw-w64-crt/math/x86/rint.c
@@ -0,0 +1,12 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <math.h>
+
+double rint (double x) {
+ double retval = 0.0;
+ __asm__ __volatile__ ("frndint;" : "=t" (retval) : "0" (x));
+ return retval;
+}
diff --git a/mingw-w64-crt/math/x86/rintf.c b/mingw-w64-crt/math/x86/rintf.c
new file mode 100644
index 0000000..f5a6bf2
--- /dev/null
+++ b/mingw-w64-crt/math/x86/rintf.c
@@ -0,0 +1,12 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <math.h>
+
+float rintf (float x) {
+ float retval = 0.0F;
+ __asm__ __volatile__ ("frndint;": "=t" (retval) : "0" (x));
+ return retval;
+}