* defaults.h (LARGEST_EXPONENT_IS_NORMAL, ROUND_TOWARDS_ZERO): New.
(MODE_HAS_NANS, MODE_HAS_INFINITIES): Evaluate to false if
LARGEST_EXPONENT_IS_NORMAL for the given mode.
(MODE_HAS_SIGN_DEPENDENT_ROUNDING): False when ROUND_TOWARDS_ZERO.
* real.c (eadd1): Make rounding dependent on !ROUND_TOWARDS_ZERO.
(ediv, emul, eldexp, esqrt): Likewise.
(etoe113, etoe64, etoe53, etoe24, etodec, etoibm, etoc4x): Likewise.
(e24toe): Only check NaNs & infinities if !LARGEST_EXPONENT_IS_NORMAL.
(saturate): New function.
(toe53, toe24): Saturate on overflow if LARGEST_EXPONENT_IS_NORMAL.
(make_nan): Use a saturation value instead of a NaN if
LARGEST_EXPONENT_IS_NORMAL. Warn when this happens.
* fp-bit.c (pack_d): Saturate on NaN, infinite or overflowing
inputs if LARGEST_EXPONENT_IS_NORMAL. Represent subnormals as
zero if NO_DENORMALS. Only round to nearest if !ROUND_TOWARDS_ZERO.
(unpack_d): No NaNs or infinities if LARGEST_EXPONENT_IS_NORMAL.
(_fpmul_parts, _fpdiv_parts): Only round to nearest if
!ROUND_TOWARDS_ZERO.
* doc/tm.texi (LARGEST_EXPONENT_IS_NORMAL): Document.
(ROUND_TOWARDS_ZERO): Document.
From-SVN: r50569
+2002-03-11 Richard Sandiford <rsandifo@redhat.com>
+
+ * defaults.h (LARGEST_EXPONENT_IS_NORMAL, ROUND_TOWARDS_ZERO): New.
+ (MODE_HAS_NANS, MODE_HAS_INFINITIES): Evaluate to false if
+ LARGEST_EXPONENT_IS_NORMAL for the given mode.
+ (MODE_HAS_SIGN_DEPENDENT_ROUNDING): False when ROUND_TOWARDS_ZERO.
+ * real.c (eadd1): Make rounding dependent on !ROUND_TOWARDS_ZERO.
+ (ediv, emul, eldexp, esqrt): Likewise.
+ (etoe113, etoe64, etoe53, etoe24, etodec, etoibm, etoc4x): Likewise.
+ (e24toe): Only check NaNs & infinities if !LARGEST_EXPONENT_IS_NORMAL.
+ (saturate): New function.
+ (toe53, toe24): Saturate on overflow if LARGEST_EXPONENT_IS_NORMAL.
+ (make_nan): Use a saturation value instead of a NaN if
+ LARGEST_EXPONENT_IS_NORMAL. Warn when this happens.
+ * fp-bit.c (pack_d): Saturate on NaN, infinite or overflowing
+ inputs if LARGEST_EXPONENT_IS_NORMAL. Represent subnormals as
+ zero if NO_DENORMALS. Only round to nearest if !ROUND_TOWARDS_ZERO.
+ (unpack_d): No NaNs or infinities if LARGEST_EXPONENT_IS_NORMAL.
+ (_fpmul_parts, _fpdiv_parts): Only round to nearest if
+ !ROUND_TOWARDS_ZERO.
+ * doc/tm.texi (LARGEST_EXPONENT_IS_NORMAL): Document.
+ (ROUND_TOWARDS_ZERO): Document.
+
2002-03-11 Andreas Jaeger <aj@suse.de>
* cfg.c (dump_flow_info): Remove unused variable.
/* This is a software floating point library which can be used
for targets without hardware floating point.
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002
Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
int sign = src->sign;
int exp = 0;
- if (isnan (src))
+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
+ {
+ /* We can't represent these values accurately. By using the
+ largest possible magnitude, we guarantee that the conversion
+ of infinity is at least as big as any finite number. */
+ exp = EXPMAX;
+ fraction = ((fractype) 1 << FRACBITS) - 1;
+ }
+ else if (isnan (src))
{
exp = EXPMAX;
if (src->class == CLASS_QNAN || 1)
{
if (src->normal_exp < NORMAL_EXPMIN)
{
+#ifdef NO_DENORMALS
+ /* Go straight to a zero representation if denormals are not
+ supported. The denormal handling would be harmless but
+ isn't unnecessary. */
+ exp = 0;
+ fraction = 0;
+#else /* NO_DENORMALS */
/* This number's exponent is too low to fit into the bits
available in the number, so we'll store 0 in the exponent and
shift the fraction to the right to make up for it. */
exp += 1;
}
fraction >>= NGARDS;
+#endif /* NO_DENORMALS */
}
- else if (src->normal_exp > EXPBIAS)
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
+ && src->normal_exp > EXPBIAS)
{
exp = EXPMAX;
fraction = 0;
else
{
exp = src->normal_exp + EXPBIAS;
- /* IF the gard bits are the all zero, but the first, then we're
- half way between two numbers, choose the one which makes the
- lsb of the answer 0. */
- if ((fraction & GARDMASK) == GARDMSB)
- {
- if (fraction & (1 << NGARDS))
- fraction += GARDROUND + 1;
- }
- else
+ if (!ROUND_TOWARDS_ZERO)
{
- /* Add a one to the guards to round up */
- fraction += GARDROUND;
+ /* IF the gard bits are the all zero, but the first, then we're
+ half way between two numbers, choose the one which makes the
+ lsb of the answer 0. */
+ if ((fraction & GARDMASK) == GARDMSB)
+ {
+ if (fraction & (1 << NGARDS))
+ fraction += GARDROUND + 1;
+ }
+ else
+ {
+ /* Add a one to the guards to round up */
+ fraction += GARDROUND;
+ }
+ if (fraction >= IMPLICIT_2)
+ {
+ fraction >>= 1;
+ exp += 1;
+ }
}
- if (fraction >= IMPLICIT_2)
+ fraction >>= NGARDS;
+
+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
{
- fraction >>= 1;
- exp += 1;
+ /* Saturate on overflow. */
+ exp = EXPMAX;
+ fraction = ((fractype) 1 << FRACBITS) - 1;
}
- fraction >>= NGARDS;
}
}
dst->fraction.ll = fraction;
}
}
- else if (exp == EXPMAX)
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
{
/* Huge exponent*/
if (fraction == 0)
}
}
#endif
- if ((high & GARDMASK) == GARDMSB)
+ if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
{
if (high & (1 << NGARDS))
{
numerator *= 2;
}
- if ((quotient & GARDMASK) == GARDMSB)
+ if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
{
if (quotient & (1 << NGARDS))
{
#define MODE_BASE_REG_CLASS(MODE) BASE_REG_CLASS
#endif
+#ifndef LARGEST_EXPONENT_IS_NORMAL
+#define LARGEST_EXPONENT_IS_NORMAL(SIZE) 0
+#endif
+
+#ifndef ROUND_TOWARDS_ZERO
+#define ROUND_TOWARDS_ZERO 0
+#endif
+
#ifndef MODE_HAS_NANS
-#define MODE_HAS_NANS(MODE) \
- (FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+#define MODE_HAS_NANS(MODE) \
+ (FLOAT_MODE_P (MODE) \
+ && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT \
+ && !LARGEST_EXPONENT_IS_NORMAL (GET_MODE_BITSIZE (MODE)))
#endif
#ifndef MODE_HAS_INFINITIES
-#define MODE_HAS_INFINITIES(MODE) \
- (FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+#define MODE_HAS_INFINITIES(MODE) \
+ (FLOAT_MODE_P (MODE) \
+ && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT \
+ && !LARGEST_EXPONENT_IS_NORMAL (GET_MODE_BITSIZE (MODE)))
#endif
#ifndef MODE_HAS_SIGNED_ZEROS
#endif
#ifndef MODE_HAS_SIGN_DEPENDENT_ROUNDING
-#define MODE_HAS_SIGN_DEPENDENT_ROUNDING(MODE) \
- (FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+#define MODE_HAS_SIGN_DEPENDENT_ROUNDING(MODE) \
+ (FLOAT_MODE_P (MODE) \
+ && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT \
+ && !ROUND_TOWARDS_ZERO)
#endif
#endif /* ! GCC_DEFAULTS_H */
The default definition of this macro is true if @var{mode} is
a floating-point mode and the target format is IEEE@.
+
+@findex ROUND_TOWARDS_ZERO
+@item ROUND_TOWARDS_ZERO
+If defined, this macro should be true if the prevailing rounding
+mode is towards zero. A true value has the following effects:
+
+@itemize @bullet
+@item
+@code{MODE_HAS_SIGN_DEPENDENT_ROUNDING} will be false for all modes.
+
+@item
+@file{libgcc.a}'s floating-point emulator will round towards zero
+rather than towards nearest.
+
+@item
+The compiler's floating-point emulator will round towards zero after
+doing arithmetic, and when converting from the internal float format to
+the target format.
+@end itemize
+
+The macro does not affect the parsing of string literals. When the
+primary rounding mode is towards zero, library functions like
+@code{strtod} might still round towards nearest, and the compiler's
+parser should behave like the target's @code{strtod} where possible.
+
+Not defining this macro is equivalent to returning zero.
+
+@findex LARGEST_EXPONENT_IS_NORMAL
+@item LARGEST_EXPONENT_IS_NORMAL (@var{size})
+This macro should only be defined when the target float format is
+described as IEEE@. It should return true if floats with @var{size}
+bits do not have a NaN or infinity representation, but use the largest
+exponent for normal numbers instead.
+
+Defining this macro to true for @var{size} causes @code{MODE_HAS_NANS}
+and @code{MODE_HAS_INFINITIES} to be false for @var{size}-bit modes.
+It also affects the way @file{libgcc.a} and @file{real.c} emulate
+floating-point arithmetic.
+
+The default definition of this macro returns false for all sizes.
@end table
@deftypefn {Target Hook} bool TARGET_MS_BITFIELD_LAYOUT_P (tree @var{record_type})
static int eiisneg PARAMS ((const UEMUSHORT *));
static void make_nan PARAMS ((UEMUSHORT *, int, enum machine_mode));
#endif
+static void saturate PARAMS ((UEMUSHORT *, int, int, int));
static void emovi PARAMS ((const UEMUSHORT *, UEMUSHORT *));
static void emovo PARAMS ((const UEMUSHORT *, UEMUSHORT *));
static void ecleaz PARAMS ((UEMUSHORT *));
esubm (ai, bi);
subflg = 1;
}
- emdnorm (bi, lost, subflg, ltb, 64);
+ emdnorm (bi, lost, subflg, ltb, !ROUND_TOWARDS_ZERO);
done:
emovo (bi, c);
i = edivm (ai, bi);
/* calculate exponent */
lt = ltb - lta + EXONE;
- emdnorm (bi, i, 0, lt, 64);
+ emdnorm (bi, i, 0, lt, !ROUND_TOWARDS_ZERO);
emovo (bi, c);
divsign:
j = emulm (ai, bi);
/* calculate exponent */
lt = lta + ltb - (EXONE - 1);
- emdnorm (bi, j, 0, lt, 64);
+ emdnorm (bi, j, 0, lt, !ROUND_TOWARDS_ZERO);
emovo (bi, c);
mulsign:
yy[M] = (r & 0x7f) | 0200;
r &= ~0x807f; /* strip sign and 7 significand bits */
#ifdef INFINITY
- if (r == 0x7f80)
+ if (!LARGEST_EXPONENT_IS_NORMAL (32) && r == 0x7f80)
{
#ifdef NANS
if (REAL_WORDS_BIG_ENDIAN)
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 113;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
#ifdef INFINITY
nonorm:
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 64;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
#ifdef INFINITY
nonorm:
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 53;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
#ifdef INFINITY
nonorm:
return;
}
#endif
+ if (LARGEST_EXPONENT_IS_NORMAL (64) && x[1] > 2047)
+ {
+ saturate (y, eiisneg (x), 64, 1);
+ return;
+ }
p = &x[0];
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 24;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
#ifdef INFINITY
nonorm:
return;
}
#endif
+ if (LARGEST_EXPONENT_IS_NORMAL (32) && x[1] > 255)
+ {
+ saturate (y, eiisneg (x), 32, 1);
+ return;
+ }
p = &x[0];
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
i = *p++;
/* Handle overflow cases. */
- if (i >= 255)
+ if (!LARGEST_EXPONENT_IS_NORMAL (32) && i >= 255)
{
#ifdef INFINITY
*y |= (UEMUSHORT) 0x7f80;
li = xi[1];
li += pwr2;
i = 0;
- emdnorm (xi, i, i, li, 64);
+ emdnorm (xi, i, i, li, !ROUND_TOWARDS_ZERO);
emovo (xi, y);
}
/* Round off to nearest or even. */
rndsav = rndprc;
rndprc = 56;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
todec (xi, d);
}
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 56;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
toibm (xi, d, mode);
}
/* Round off to nearest or even. */
rndsav = rndprc;
rndprc = mode == QFmode ? 24 : 32;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
toc4x (xi, d, mode);
}
{
int n;
const UEMUSHORT *p;
+ int size;
+ size = GET_MODE_BITSIZE (mode);
+ if (LARGEST_EXPONENT_IS_NORMAL (size))
+ {
+ warning ("%d-bit floats cannot hold NaNs", size);
+ saturate (nan, sign, size, 0);
+ return;
+ }
switch (mode)
{
/* Possibly the `reserved operand' patterns on a VAX can be
}
#endif /* NANS */
+
+/* Create a saturation value for a SIZE-bit float, assuming that
+ LARGEST_EXPONENT_IS_NORMAL (SIZE).
+
+ If SIGN is true, fill X with the most negative value, otherwise fill
+ it with the most positive value. WARN is true if the function should
+ warn about overflow. */
+
+static void
+saturate (x, sign, size, warn)
+ UEMUSHORT *x;
+ int sign, size, warn;
+{
+ int i;
+
+ if (warn && extra_warnings)
+ warning ("value exceeds the range of a %d-bit float", size);
+
+ /* Create the most negative value. */
+ for (i = 0; i < size / EMUSHORT_SIZE; i++)
+ x[i] = 0xffff;
+
+ /* Make it positive, if necessary. */
+ if (!sign)
+ x[REAL_WORDS_BIG_ENDIAN? 0 : i - 1] = 0x7fff;
+}
+
+
/* This is the inverse of the function `etarsingle' invoked by
REAL_VALUE_TO_TARGET_SINGLE. */
k |= (int) num[i];
/* Renormalize and round off. */
- emdnorm (sq, k, 0, exp, 64);
+ emdnorm (sq, k, 0, exp, !ROUND_TOWARDS_ZERO);
emovo (sq, y);
}
#endif