This is the mail archive of the egcs@egcs.cygnus.com mailing list for the EGCS project. See the EGCS home page for more information.
Gary Thomas <gdt@linuxppc.org> writes:
|> There is an error in all versions of GAS which use IEEE floating point.
|> The version I was testing is: GNU assembler version 2.9.1
|>
|> This constant is improperly assembled:
|> 9 0020 00000000 .float 0d1.40129846432481707092e-45
|> The correct value (Big Endian) would be
|> 9 0020 00000001 .float 0d1.40129846432481707092e-45
|> The correct value (Little Endian) would be
|> 9 0020 01000000 .float 0d1.40129846432481707092e-45
|>
|> Note: this is the smallest possible IEEE unnormalized "float" value.
|>
|> A simple patch for this (seems to work at least) is:
|>
|> --- binutils-2.9.1/gas/config/atof-ieee.c~ Fri May 1 16:44:33 1998
|> +++ binutils-2.9.1/gas/config/atof-ieee.c Sat Mar 6 06:57:08 1999
|> @@ -444,6 +444,8 @@
|> unget_bits (1);
|> num_bits = -exponent_4;
|> prec_bits = LITTLENUM_NUMBER_OF_BITS * precision - (exponent_bits + 1 + num_bits);
|> + // There is 1 more bit of precision here (hidden)
|> + prec_bits += 1;
|> #ifdef TC_I386
|> if (precision == X_PRECISION && exponent_bits == 15)
|> {
This is wrong. The hidden zero has already been accounted for, since the
exponent bias is one less in a denormal. The bug is actually in the
rounding code. It should never ignore a set round bit, even if the
prec_bits bitfield already has all bits set, especially if prec_bits == 0.
There is also another bug here: the assembler rejects the smallest
extended precision number, which is 0d1.822599765941237301264e-4951 on the
m68k. If prec_bits is zero then the round bit is always set and the
mantissa will be rounded up.
1999-03-11 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
* config/atof-ieee.c (gen_to_words): Correctly round a
denormalized number. Fix off-by-one in range checking for
exponent in a denormal.
--- binutils-2.9.4/gas/config/atof-ieee.c.~1~ Thu Apr 23 23:55:07 1998
+++ binutils-2.9.4/gas/config/atof-ieee.c Thu Mar 11 02:06:35 1999
@@ -460,7 +460,7 @@
/* Bigger than one littlenum */
num_bits -= (LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits;
*lp++ = word1;
- if (num_bits + exponent_bits + 1 >= precision * LITTLENUM_NUMBER_OF_BITS)
+ if (num_bits + exponent_bits + 1 > precision * LITTLENUM_NUMBER_OF_BITS)
{
/* Exponent overflow */
make_invalid_floating_point_number (words);
@@ -501,7 +501,7 @@
if (next_bits (1))
{
--lp;
- if (prec_bits > LITTLENUM_NUMBER_OF_BITS)
+ if (prec_bits >= LITTLENUM_NUMBER_OF_BITS)
{
int n = 0;
int tmp_bits;
@@ -515,7 +515,19 @@
--n;
tmp_bits -= LITTLENUM_NUMBER_OF_BITS;
}
- if (tmp_bits > LITTLENUM_NUMBER_OF_BITS || (lp[n] & mask[tmp_bits]) != mask[tmp_bits])
+ if (tmp_bits > LITTLENUM_NUMBER_OF_BITS
+ || (lp[n] & mask[tmp_bits]) != mask[tmp_bits]
+ || (prec_bits != (precision * LITTLENUM_NUMBER_OF_BITS
+ - exponent_bits - 1)
+#ifdef TC_I386
+ /* An extended precision float with only the integer
+ bit set would be invalid. That must be converted
+ to the smallest normalized number. */
+ && !(precision == X_PRECISION
+ && prec_bits == (precision * LITTLENUM_NUMBER_OF_BITS
+ - exponent_bits - 2))
+#endif
+ ))
{
unsigned long carry;
@@ -539,11 +551,18 @@
<< ((LITTLENUM_NUMBER_OF_BITS - 1)
- exponent_bits));
*lp++ = word1;
+#ifdef TC_I386
+ /* Set the integer bit in the extended precision format.
+ This cannot happen on the m68k where the mantissa
+ just overflows into the integer bit above. */
+ if (precision == X_PRECISION)
+ *lp++ = 1 << (LITTLE_NUMBER_OF_BITS - 1);
+#endif
while (lp < words_end)
*lp++ = 0;
}
}
- else if ((*lp & mask[prec_bits]) != mask[prec_bits])
+ else
*lp += 1;
}