From fbace81684f8cbb80a2048c01dc545af247f5cb7 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 20 Nov 2015 18:14:58 +0100 Subject: Import correctly working strtold from David M. Gay. * libc/stdlib/Makefile.am (GENERAL_SOURCES): Add strtodg.c and strtorx.c. * libc/stdlib/Makefile.in: Regenerate. * libc/stdlib/strtodg.c: New file implementing generic string to long double conversion. * libc/stdlib/strtorx.c: New file, implementing IEEE format string to long double conversion. * libc/stdlib/mprec.h (_strtodg_r): Declare. (_strtorx_r): Declare. * libc/stdlib/gdtoa.h (__UShort): Define. * libc/stdlib/strtold.c (__flt_rounds): Define for i386 and x86_64 target. (FLT_ROUNDS): Define, as 0 on platforms missing a __flt_rounds function. (_strtold_r): Converted from strtold. Call _strtorx_r on targets supporting distinct long doubles. (strtold): Just call _strtold_r. * libc/include/stdlib.h (_strtold_r): Declare. * libc/stdlib/ldtoa.c (_strtold): Comment out. Explain why. * libc/stdio/vfscanf.c (__SVFSCANF_R): Call _strtold_r instead of _strtold. * libc/machine/powerpc/vfscanf.c (__svfscanf_r): Ditto. * common.din (strtold): Drop redirection to _strtold. Signed-off-by: Corinna Vinschen --- newlib/libc/stdlib/strtold.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) (limited to 'newlib/libc/stdlib/strtold.c') 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 */ -- cgit v1.2.3