NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: toolchain/45310: some mixed int/float computations are wrong on mips64



On Wed, Aug 31, 2011 at 01:30:06PM +0000, Manuel Bouyer wrote:
>  I __fixsfdi() uses __fixunssfdi() which uses double to uint casts, which is
>  the problem as shown by this new test:
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <sys/types.h>
>  
>  main()
>  {
>          double a;
>       uint b;
>  
>       a = 33.000000;
>       b = a;
>  
>       printf("a %f b %d\n",a, b);
>  }
>  
>  cuba:/home/bouyer> gcc -o test4 test4.c
>  cuba:/home/bouyer> ./test4
>  a 33.000000 b 0
>  
>  tracking this down, I ended up in fixunsgen_ieee754.c:__fixunsgen32.
>  It's called with
>  exp=5, sign=0, mant_dig=53, fracbits=20, frac={0, 0, 32768}
>  
>  as exp - mant_dig is larger than 32, __fixunsgen32 returns 0.

No, exp - mant_dig is -48 so it's not larger than 32.
The problem seems to be that in __fixunsgen32, both mant_dig and sizeof()
are unsigned so gcc does an unsigned comparison.
Casting to (long) makes it behaves as expected, and the
change in the assembly is:
-       lw      $3,32($fp)
        lw      $2,40($fp)
+       lw      $3,32($fp)
        subu    $2,$3,$2
-       sltu    $2,$2,32
+       slt     $2,$2,32
        bne     $2,$0,$L3
        nop

So unless gcc is doing the wrong thing here, I'd guess that the
attached patch is the right fix. With this, my test programs passes,
ftp(1) and progress(1) properly reports the download speed, and a pkgsrc
perl build which was failing is now making progress.

-- 
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
     NetBSD: 26 ans d'experience feront toujours la difference
--
Index: fixunsgen_ieee754.c
===================================================================
RCS file: /cvsroot/src/lib/libc/gen/fixunsgen_ieee754.c,v
retrieving revision 1.1
diff -u -p -u -r1.1 fixunsgen_ieee754.c
--- fixunsgen_ieee754.c 9 Jul 2011 02:30:27 -0000       1.1
+++ fixunsgen_ieee754.c 31 Aug 2011 19:51:02 -0000
@@ -66,7 +66,8 @@ FIXUNSNAME(__fixunsgen)(int exp, bool si
         * to zero.  If the exponent is so large that it is a multiple of
         * 2^N, then x module 2^N will be 0.
         */
-       if (__predict_false(exp < 0 || exp - mant_dig > sizeof(UINTXX_T)*8-1))
+       if (__predict_false(exp < 0 ||
+           exp - (long)mant_dig > (long)sizeof(UINTXX_T)*8-1))
                return 0;
 
        /*


Home | Main Index | Thread Index | Old Index