darwin-ldouble.c: Add big comment explaining exactly what is expected as a 'long double'.

* config/rs6000/darwin-ldouble.c: Add big comment explaining
	exactly what is expected as a 'long double'.
	(_xlqadd): When a value to be returned is representable as a
	'double', just return it directly, do not construct it using a union.
	Also, correct final fixup.
	(_xlqmul): Likewise.
	(_xlqdiv): Likewise.
	* real.c (encode_ibm_extended): Make consistent with darwin-ldouble.c.

From-SVN: r75629
This commit is contained in:
Geoffrey Keating 2004-01-10 05:47:14 +00:00 committed by Geoffrey Keating
parent 975421be9e
commit f01519dd00
3 changed files with 47 additions and 88 deletions

View file

@ -6,6 +6,15 @@
2004-01-09 Geoffrey Keating <geoffk@apple.com>
* config/rs6000/darwin-ldouble.c: Add big comment explaining
exactly what is expected as a 'long double'.
(_xlqadd): When a value to be returned is representable as a
'double', just return it directly, do not construct it using a union.
Also, correct final fixup.
(_xlqmul): Likewise.
(_xlqdiv): Likewise.
* real.c (encode_ibm_extended): Make consistent with darwin-ldouble.c.
* config/rs6000/rs6000.md (fix_trunctfdi2): Delete.
2004-01-09 Richard Henderson <rth@redhat.com>

View file

@ -37,6 +37,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
Floating-Point Computations", by Seppo Linnainmaa, ACM TOMS vol 7
no 3, September 1961, pages 272-283. */
/* Each long double is made up of two IEEE doubles. The value of the
long double is the sum of the values of the two parts. The most
significant part is required to be the value of the long double
rounded to the nearest double, as specified by IEEE. For Inf
values, the least significant part is required to be one of +0.0 or
-0.0. No other requirements are made; so, for example, 1.0 may be
represented as (1.0, +0.0) or (1.0, -0.0), and the low part of a
NaN is don't-care.
This code currently assumes big-endian. */
#define fabs(x) __builtin_fabs(x)
#define unlikely(x) __builtin_expect ((x), 0)
@ -68,11 +79,8 @@ _xlqadd (double a, double b, double c, double d)
FPR_zero = 0.0;
FPR_PosInf = FPKINF;
if (unlikely (a != a) || unlikely (c != c)) {
z.dval[0] = a + c; /* NaN result. */
z.dval[1] = a + c; /* NaN result. */
return z.ldval;
}
if (unlikely (a != a) || unlikely (c != c))
return a + c; /* NaN result. */
/* Ordered operands are arranged in order of their magnitudes. */
@ -110,18 +118,14 @@ _xlqadd (double a, double b, double c, double d)
t = (tau + b) + a; /* Sum values in ascending magnitude order. */
/* Infinite or zero result. */
if (unlikely (fabs (t) == FPR_PosInf) || unlikely (t == FPR_zero))
{
z.dval[0] = t;
z.dval[1] = t >= 0.0 ? (fabs (t) >= 0.0 ? t : 0.0) : -0.0;
return z.ldval;
}
if (unlikely (t == FPR_zero) || unlikely (fabs (t) == FPR_PosInf))
return t;
/* Usual case. */
tau = (((a-t) + b) + c) + d;
u = t + tau;
z.dval[0] = u; /* Final fixup for long double result. */
z.dval[1] = (u - t) + tau;
z.dval[1] = (t - u) + tau;
return z.ldval;
}
@ -142,22 +146,10 @@ _xlqmul (double a, double b, double c, double d)
t = a * c; /* Highest order double term. */
if (unlikely (t != t) || unlikely (t == FPR_zero))
{
/* NaN or zero result. */
z.dval[0] = t;
z.dval[1] = t;
return z.ldval;
}
if (unlikely (t != t) || unlikely (t == FPR_zero)
|| unlikely (fabs (t) == FPR_PosInf))
return t;
if (unlikely (fabs(t) == FPR_PosInf))
{
/* Infinite result. */
z.dval[0] = t;
z.dval[1] = t >= 0 ? 0.0 : -0.0;
return z.ldval;
}
/* Finite nonzero result requires summing of terms of two highest
orders. */
@ -170,7 +162,7 @@ _xlqmul (double a, double b, double c, double d)
/* Construct long double result. */
z.dval[0] = u;
z.dval[1] = (u - t) + tau;
z.dval[1] = (t - u) + tau;
return z.ldval;
}
@ -185,21 +177,9 @@ _xlqdiv (double a, double b, double c, double d)
t = a / c; /* highest order double term */
if (unlikely (t != t) || unlikely (t == FPR_zero))
{
/* NaN or zero result. */
z.dval[0] = t;
z.dval[1] = t;
return z.ldval;
}
if (unlikely (fabs (t) == FPR_PosInf))
{
/* Infinite result. */
z.dval[0] = t;
z.dval[1] = t >= 0.0 ? 0.0 : -0.0;
return z.ldval;
}
if (unlikely (t != t) || unlikely (t == FPR_zero)
|| unlikely (fabs (t) == FPR_PosInf))
return t;
/* Finite nonzero result requires corrections to the highest order term. */

View file

@ -3235,53 +3235,23 @@ encode_ibm_extended (const struct real_format *fmt, long *buf,
base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
switch (r->class)
/* u = IEEE double precision portion of significand. */
u = *r;
round_for_format (base_fmt, &u);
encode_ieee_double (base_fmt, &buf[0], &u);
if (r->class == rvc_normal)
{
case rvc_zero:
/* Both doubles have sign bit set. */
buf[0] = FLOAT_WORDS_BIG_ENDIAN ? r->sign << 31 : 0;
buf[1] = FLOAT_WORDS_BIG_ENDIAN ? 0 : r->sign << 31;
buf[2] = buf[0];
buf[3] = buf[1];
break;
case rvc_inf:
case rvc_nan:
/* Both doubles set to Inf / NaN. */
encode_ieee_double (base_fmt, &buf[0], r);
buf[2] = buf[0];
buf[3] = buf[1];
return;
case rvc_normal:
/* u = IEEE double precision portion of significand. */
u = *r;
clear_significand_below (&u, SIGNIFICAND_BITS - 53);
normalize (&u);
/* If the upper double is zero, we have a denormal double, so
move it to the first double and leave the second as zero. */
if (u.class == rvc_zero)
{
v = u;
u = *r;
normalize (&u);
}
else
{
/* v = remainder containing additional 53 bits of significand. */
do_add (&v, r, &u, 1);
round_for_format (base_fmt, &v);
}
round_for_format (base_fmt, &u);
encode_ieee_double (base_fmt, &buf[0], &u);
do_add (&v, r, &u, 1);
round_for_format (base_fmt, &v);
encode_ieee_double (base_fmt, &buf[2], &v);
break;
default:
abort ();
}
else
{
/* Inf, NaN, 0 are all representable as doubles, so the
least-significant part can be 0.0. */
buf[2] = 0;
buf[3] = 0;
}
}