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