Commit f01519dd by Geoffrey Keating Committed by Geoffrey Keating

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
parent 975421be
...@@ -6,6 +6,15 @@ ...@@ -6,6 +6,15 @@
2004-01-09 Geoffrey Keating <geoffk@apple.com> 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. * config/rs6000/rs6000.md (fix_trunctfdi2): Delete.
2004-01-09 Richard Henderson <rth@redhat.com> 2004-01-09 Richard Henderson <rth@redhat.com>
......
...@@ -37,6 +37,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -37,6 +37,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
Floating-Point Computations", by Seppo Linnainmaa, ACM TOMS vol 7 Floating-Point Computations", by Seppo Linnainmaa, ACM TOMS vol 7
no 3, September 1961, pages 272-283. */ 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 fabs(x) __builtin_fabs(x)
#define unlikely(x) __builtin_expect ((x), 0) #define unlikely(x) __builtin_expect ((x), 0)
...@@ -68,11 +79,8 @@ _xlqadd (double a, double b, double c, double d) ...@@ -68,11 +79,8 @@ _xlqadd (double a, double b, double c, double d)
FPR_zero = 0.0; FPR_zero = 0.0;
FPR_PosInf = FPKINF; FPR_PosInf = FPKINF;
if (unlikely (a != a) || unlikely (c != c)) { if (unlikely (a != a) || unlikely (c != c))
z.dval[0] = a + c; /* NaN result. */ return a + c; /* NaN result. */
z.dval[1] = a + c; /* NaN result. */
return z.ldval;
}
/* Ordered operands are arranged in order of their magnitudes. */ /* Ordered operands are arranged in order of their magnitudes. */
...@@ -110,18 +118,14 @@ _xlqadd (double a, double b, double c, double d) ...@@ -110,18 +118,14 @@ _xlqadd (double a, double b, double c, double d)
t = (tau + b) + a; /* Sum values in ascending magnitude order. */ t = (tau + b) + a; /* Sum values in ascending magnitude order. */
/* Infinite or zero result. */ /* Infinite or zero result. */
if (unlikely (fabs (t) == FPR_PosInf) || unlikely (t == FPR_zero)) if (unlikely (t == FPR_zero) || unlikely (fabs (t) == FPR_PosInf))
{ return t;
z.dval[0] = t;
z.dval[1] = t >= 0.0 ? (fabs (t) >= 0.0 ? t : 0.0) : -0.0;
return z.ldval;
}
/* Usual case. */ /* Usual case. */
tau = (((a-t) + b) + c) + d; tau = (((a-t) + b) + c) + d;
u = t + tau; u = t + tau;
z.dval[0] = u; /* Final fixup for long double result. */ 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; return z.ldval;
} }
...@@ -142,22 +146,10 @@ _xlqmul (double a, double b, double c, double d) ...@@ -142,22 +146,10 @@ _xlqmul (double a, double b, double c, double d)
t = a * c; /* Highest order double term. */ t = a * c; /* Highest order double term. */
if (unlikely (t != t) || unlikely (t == FPR_zero)) if (unlikely (t != t) || unlikely (t == FPR_zero)
{ || unlikely (fabs (t) == FPR_PosInf))
/* NaN or zero result. */ return t;
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;
return z.ldval;
}
/* Finite nonzero result requires summing of terms of two highest /* Finite nonzero result requires summing of terms of two highest
orders. */ orders. */
...@@ -170,7 +162,7 @@ _xlqmul (double a, double b, double c, double d) ...@@ -170,7 +162,7 @@ _xlqmul (double a, double b, double c, double d)
/* Construct long double result. */ /* Construct long double result. */
z.dval[0] = u; z.dval[0] = u;
z.dval[1] = (u - t) + tau; z.dval[1] = (t - u) + tau;
return z.ldval; return z.ldval;
} }
...@@ -185,21 +177,9 @@ _xlqdiv (double a, double b, double c, double d) ...@@ -185,21 +177,9 @@ _xlqdiv (double a, double b, double c, double d)
t = a / c; /* highest order double term */ t = a / c; /* highest order double term */
if (unlikely (t != t) || unlikely (t == FPR_zero)) if (unlikely (t != t) || unlikely (t == FPR_zero)
{ || unlikely (fabs (t) == FPR_PosInf))
/* NaN or zero result. */ return t;
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;
}
/* Finite nonzero result requires corrections to the highest order term. */ /* Finite nonzero result requires corrections to the highest order term. */
......
...@@ -3235,53 +3235,23 @@ encode_ibm_extended (const struct real_format *fmt, long *buf, ...@@ -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; base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
switch (r->class) /* u = IEEE double precision portion of significand. */
{ u = *r;
case rvc_zero: round_for_format (base_fmt, &u);
/* Both doubles have sign bit set. */ encode_ieee_double (base_fmt, &buf[0], &u);
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: if (r->class == rvc_normal)
/* u = IEEE double precision portion of significand. */ {
u = *r; do_add (&v, r, &u, 1);
clear_significand_below (&u, SIGNIFICAND_BITS - 53); round_for_format (base_fmt, &v);
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);
encode_ieee_double (base_fmt, &buf[2], &v); encode_ieee_double (base_fmt, &buf[2], &v);
break; }
else
default: {
abort (); /* Inf, NaN, 0 are all representable as doubles, so the
least-significant part can be 0.0. */
buf[2] = 0;
buf[3] = 0;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment