--- _ldtoa.c.orig 2008-09-07 11:38:10.000000000 -0700 +++ _ldtoa.c 2008-09-07 12:55:35.000000000 -0700 @@ -46,7 +46,7 @@ char * __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, char **rve) { - static FPI fpi = { + static FPI fpi0 = { LDBL_MANT_DIG, /* nbits */ LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ @@ -61,28 +61,57 @@ __ldtoa(long double *ld, int mode, int n char *ret; union IEEEl2bits u; uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; + FPI *fpi = &fpi0, fpi1; +#ifdef Honor_FLT_ROUNDS + int rounding = Flt_Rounds; +#endif + int type; u.e = *ld; +#if defined(__ppc__) || defined(__ppc64__) + /* + * Subnormal head-tail doubles don't seem to be converted correctly + * by gdtoa. So we multiply by 10^32 to make them normal then + * subtract 32 from the exponent later. + */ + if ((type = __fpclassify(u.e)) == FP_NORMAL && __fpclassifyd(u.d[1]) == FP_SUBNORMAL) + type = FP_SUBNORMAL; + if (type == FP_SUBNORMAL) + u.e *= 1.0e32L; +#else /* !defined(__ppc__) && !defined(__ppc64__) */ + type = fpclassify(u.e); +#endif /* defined(__ppc__) || defined(__ppc64__) */ *sign = u.bits.sign; be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1); +#if defined(__ppc__) || defined(__ppc64__) + be -= LDBL_TO_ARRAY32(u, bits); +#else /* !defined(__ppc__) && !defined(__ppc64__) */ LDBL_TO_ARRAY32(u, bits); +#endif /* defined(__ppc__) || defined(__ppc64__) */ - switch (fpclassify(u.e)) { + switch (type) { +#if defined(__ppc__) || defined(__ppc64__) + case FP_SUBNORMAL: +#endif /* defined(__ppc__) || defined(__ppc64__) */ case FP_NORMAL: + case FP_SUPERNORMAL: kind = STRTOG_Normal; +/* For ppc/ppc64 and head-tail long double, the implicit bit is already there */ +#if !defined(__ppc__) && !defined(__ppc64__) #ifdef LDBL_IMPLICIT_NBIT bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); #endif /* LDBL_IMPLICIT_NBIT */ +#endif /* !defined(__ppc__) && !defined(__ppc64__) */ break; case FP_ZERO: kind = STRTOG_Zero; break; +#if !defined(__ppc__) && !defined(__ppc64__) case FP_SUBNORMAL: kind = STRTOG_Denormal; -#ifdef LDBL_IMPLICIT_NBIT be++; -#endif break; +#endif /* !defined(__ppc__) && !defined(__ppc64__) */ case FP_INFINITE: kind = STRTOG_Infinite; break; @@ -90,11 +119,22 @@ __ldtoa(long double *ld, int mode, int n kind = STRTOG_NaN; break; default: - abort(); + LIBC_ABORT("fpclassify returned %d", type); } - ret = gdtoa(&fpi, be, (ULong *)bits, &kind, mode, ndigits, decpt, rve); +#ifdef Honor_FLT_ROUNDS + if (rounding != fpi0.rounding) { + fpi1 = fpi0; /* for thread safety */ + fpi1.rounding = rounding; + fpi = &fpi1; + } +#endif /* Honor_FLT_ROUNDS */ + ret = gdtoa(fpi, be, (ULong *)bits, &kind, mode, ndigits, decpt, rve); if (*decpt == -32768) *decpt = INT_MAX; +#if defined(__ppc__) || defined(__ppc64__) + else if (type == FP_SUBNORMAL) + *decpt -= 32; +#endif /* defined(__ppc__) || defined(__ppc64__) */ return ret; }