_ldtoa.c.patch   [plain text]


--- _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;
 }