eggert@twinsun.com (Paul Eggert) (12/08/89)
GCC 1.36 sometimes mishandles the conversion of unsigned values greater than
INT_MAX to floating point. For example, the program
#include <stdio.h>
main()
{
unsigned long L;
double D;
D = L = ~0;
printf("L=%lu, D=%g\n", L, D);
return 0;
}
should print something like "L=4294967295, D=4.29497e+09". Instead, D has
either the value 0 (Sun-3 -m68881, or Sun-4) or -1 (Sun-3 -msoft-float).
Looking at the generated code, there seem to be two different bugs depending
on whether -msoft-float is set. The 0 arises when GCC converts unsigned long
as if it were long, notices that the original number was negative, and
corrects by adding 1; it should correct by adding 4294967296. The -1 arises
because GCC uses __floatsidf to convert the unsigned long to double;
__floatsidf expects a signed long argument.
In the following transcripts, 'dry' is a Sun-3/60 running SunOS 4.0.3; 'rise'
is a SPARCstation 1 running SunOS 4.0.3c.
1-dry% gcc -v -m68881 t.c
gcc version 1.36
/local/lib/gcc-cpp -v -undef -D__GNUC__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D
__sun__ -D__unix__ -D__HAVE_68881__ -Dmc68020 t.c /usr/tmp/cca20148.cpp
GNU CPP version 1.36
/local/lib/gcc-cc1 /usr/tmp/cca20148.cpp -quiet -dumpbase t.c -m68881 -version
-o /usr/tmp/cca20148.s
GNU C version 1.36 (68k, MIT syntax) compiled by GNU C version 1.36.
default target switches: -m68020 -mc68020 -mbitfield
as -mc68020 -o t.o /usr/tmp/cca20148.s
/local/lib/gcc-ld -e start -dc -dp /lib/crt0.o /lib/Mcrt1.o t.o /local/lib/gcc-
gnulib -lc
2-dry% ./a.out
L=4294967295, D=0
3-dry% gcc -v -msoft-float t.c
gcc version 1.36
/local/lib/gcc-cpp -v -undef -D__GNUC__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D
__sun__ -D__unix__ -Dmc68020 t.c /usr/tmp/cca20154.cpp
GNU CPP version 1.36
/local/lib/gcc-cc1 /usr/tmp/cca20154.cpp -quiet -dumpbase t.c -msoft-float -ver
sion -o /usr/tmp/cca20154.s
GNU C version 1.36 (68k, MIT syntax) compiled by GNU C version 1.36.
default target switches: -m68020 -mc68020 -mbitfield
as -mc68020 -o t.o /usr/tmp/cca20154.s
/local/lib/gcc-ld -e start -dc -dp /lib/crt0.o /lib/Fcrt1.o t.o /local/lib/gcc-
gnulib -lc
4-dry% ./a.out
L=4294967295, D=-1
1-rise% gcc -v t.c
gcc version 1.36
/local/lib/gcc-cpp -v -undef -D__GNUC__ -Dsparc -Dsun -Dunix -D__sparc__ -D__su
n__ -D__unix__ t.c /usr/tmp/cca01280.cpp
GNU CPP version 1.36
/local/lib/gcc-cc1 /usr/tmp/cca01280.cpp -quiet -dumpbase t.c -version -o /usr/
tmp/cca01280.s
GNU C version 1.36 (sparc) compiled by GNU C version 1.36.
default target switches: -mfpu -mepilogue
as -o t.o /usr/tmp/cca01280.s
/local/lib/gcc-ld -e start -dc -dp /lib/crt0.o t.o /local/lib/gcc-gnulib -lc
2-rise% ./a.out
L=4294967295, D=0