summaryrefslogtreecommitdiffstats
path: root/newlib/libc/stdlib/strtold.c
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/stdlib/strtold.c')
-rw-r--r--newlib/libc/stdlib/strtold.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/newlib/libc/stdlib/strtold.c b/newlib/libc/stdlib/strtold.c
index a620251ee..96254eb49 100644
--- a/newlib/libc/stdlib/strtold.c
+++ b/newlib/libc/stdlib/strtold.c
@@ -32,17 +32,49 @@ POSSIBILITY OF SUCH DAMAGE.
#include "local.h"
#ifdef _HAVE_LONG_DOUBLE
-extern long double _strtold (const char *, char **);
-/* On platforms where long double is as wide as double. */
+#if defined (__x86_64__) || defined (__i386__)
+static const int map[] = {
+ 1, /* round to nearest */
+ 3, /* round to zero */
+ 2, /* round to negative infinity */
+ 0 /* round to positive infinity */
+};
+
+int
+__flt_rounds(void)
+{
+ int x;
+
+ /* Assume that the x87 and the SSE unit agree on the rounding mode. */
+ __asm("fnstcw %0" : "=m" (x));
+ return (map[(x >> 10) & 0x03]);
+}
+#define FLT_ROUNDS __flt_rounds()
+#else
+#define FLT_ROUNDS 0
+#endif
+
long double
-strtold (const char *__restrict s00, char **__restrict se)
+_strtold_r (struct _reent *ptr, const char *__restrict s00,
+ char **__restrict se)
{
#ifdef _LDBL_EQ_DBL
- return strtod(s00, se);
+ /* On platforms where long double is as wide as double. */
+ return _strtod_r (ptr, s00, se);
#else
- return _strtold (s00, se);
+ long double result;
+
+ _strtorx_r (ptr, s00, se, FLT_ROUNDS, &result);
+ return result;
#endif
}
+
+long double
+strtold (const char *__restrict s00, char **__restrict se)
+{
+ return _strtold_r (_REENT, s00, se);
+}
+
#endif /* _HAVE_LONG_DOUBLE */