Question regarding libm

Jan-Benedict Glaw jbglaw at lug-owl.de
Fri Sep 30 06:21:41 UTC 2005


On Thu, 2005-09-29 22:02:06 +0200, Jan-Benedict Glaw <jbglaw at lug-owl.de> wrote:
> On Thu, 2005-09-29 13:39:21 -0600, Manuel Novoa III <mjn3 at codepoet.org> wrote:
> > Currently, _fpmaxtostr() assumes a base 2 representation.  But there's
> > a compile-time test for that using FLT_RADIX.  Otherwise, it makes no
> > assumptions about internal representation of float.  It _does_ assume
> > some IEEE float behavior though.  If you could isolate the problem down
> > to a particular area of the code, I'd be happy to take a look.
> 
> I'll try to do that, though it's not exactly simple. (Debugging by
> disassembling and matching disassembly output with source code. Yay:-)

Fortunately, it dies pretty early in _fpmaxtostr


   12acf:       56 8f 00 00     cvtfd $0x00000000 [f-float],r0
   12ad3:       00 00 50 
   12ad6:       71 56 50        cmpd r6,r0                              test if (x == 0)
   12ad9:       12 1c           bneq 12af7 <_fpmaxtostr+0x85>           if it's not, goto x_is_not_null
die_here:
~~~~~~~~~
   12adb:       67 8f 00 00     divd3 $0x0000000000000000 [d-float],$0x8 [d-float],r0
   12adf:       00 00 00 00 
   12ae3:       00 00 08 50 

   0x67 = divd3 x, y, z  (z = y/x,  with D_floating values)
   0x8f = immediate data following (a full D_floating value)
   0x00 00 00 00 00 00 00 00 = D_floating value (divident)
   0x08 = register deferred mode; a pointer to divisor (of type
          D_floating using 64bit representation) can be found in
          register R8
   0x50 = Register mode; put the result into R0 (and R1, because it's
          64 bits of data)

The immediate D_floating value 0x0000000000000000 is actually, you
already guess that, zero. So the compiler generates wrong code for

	if (x == 0) {
#if 1
		if (zeroisnegative(x)) {	<---- this
			*sign_str = '-';
		}
#endif
		exp = -1;
		goto GENERATE_DIGITS;
	}

zeroisnegative() is:
#define zeroisnegative(x)    ((1./(x)) < 0)

So the generated division is completely wrong, this is a compiler bug.
...and I fear it's arch specific, so it's my task...

Just to add a note: Some lines above that, my compiler (gcc-4.1 right
out of the CVS tree) eliminates this code part completely:

        if (isnan(x)) { /* First, check for nan. */
                pc_fwi[5] = NAN_OFFSET;
                goto INF_NAN;
        }

because isnan() is defined as

#define isnan(x)             ((x) != (x))

which I guess GCC think it could never ever happen... So this probably
needs to be casted to some volatile type, or you need some specific
function to detect NaNs.

   12ae7:       73 50           tstd r0                                 test if (x is -0)
   12ae9:       18 04           bgeq 12aef <_fpmaxtostr+0x7d>           if it's not -0, goto not_a_negative_zero
   12aeb:       90 2d ad f6     movb $0x2d,0xfffffff6(fp)               *sign_str = '-';
not_a_negative_zero:
   12aef:       d2 00 cd 6c     mcoml $0x0,0xffffff6c(fp)		exp = -1;
   12af3:       ff 
   12af4:       31 c3 00        brw 12bba <_fpmaxtostr+0x148>		goto GENERATE_DIGITS
x_is_not_null:
   12af7:       73 56           tstd r6
   .....:
GENERATE_DIGITS:
   12bba:


Thanks for the help! I'll now look at the generated assembly file to
see if it's GCC who emits wrong assembly, or gas assembling the wrong
stuff...

MfG, JBG

-- 
Jan-Benedict Glaw       jbglaw at lug-owl.de    . +49-172-7608481             _ O _
"Eine Freie Meinung in  einem Freien Kopf    | Gegen Zensur | Gegen Krieg  _ _ O
 für einen Freien Staat voll Freier Bürger"  | im Internet! |   im Irak!   O O O
ret = do_actions((curr | FREE_SPEECH) & ~(NEW_COPYRIGHT_LAW | DRM | TCPA));
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://lists.busybox.net/pipermail/uclibc/attachments/20050930/8a04e3d1/attachment-0002.pgp 


More information about the uClibc mailing list