This is the mail archive of the
ecos-discuss@sourceware.org
mailing list for the eCos project.
Re: issue with floor()
Thank you Paul,
On Wed, Nov 10, 2010 at 12:08 AM, Paul D. DeRocco
<pderocco@ix.netcom.com> wrote:
>> From: David Brennan
>>
>> I am using a relatively recent CVS of eCos on an x86 VME
>> target. I am trying to get an existing application working,
>> and I stumbled across an unusual result.
>>
>> The code called floor() with a value of 0.048000000000000001.
>> the correct return value should have been 0.0.
>>
>> Single stepping through the "bit twiddling" looked like it
>> was pursuing the correct code path, but at this point,
>> somthing went wrong.
>>
>> 97 ? ? ? ? ? ? ? ? ? ?if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
>> (gdb) s
>> 98 ? ? ? ? ? ? ? ? ? ? ? ?if(i0>=0) {i0=i1=0;}
>> (gdb) p i0
>> $4 = 8
>> (gdb) s
>> 131 ? }
>> (gdb) info locals
>> i0 = 8
>> j0 = -5
>> i = 1067989024
>> x = 0.048000000000000001
>> (gdb) li
>> 126 ? ? ? ? ? ? ? }
>> 127 ? ? ? ? ? }
>> 128 ? ? ? ? ? CYG_LIBM_HI(x) = i0;
>> 129 ? ? ? ? ? CYG_LIBM_LO(x) = i1;
>> 130 ? ? ? ? ? return x;
>> 131 ? }
>> 132
>> 133 ? #endif // ifdef CYGPKG_LIBM
>> 134
>> 135 ? // EOF s_floor.c
>>
>> It appears that the code did not run line 98 correctly.
>
> <snip>
>
>> I am using a compiler that I built (so that is most likely
>> the problem). I am using OS X for my host, and there are not
>> pre-built binaries for that.
>
> I would think examining the assembly language would clear up the mystery,
> especially if you find the problem persists with optimization turned off.
> For instance, it could be that the arithmetic doesn't work because
> something's busted in the FP support, but the sign test works correctly
> because it doesn't use an FP instruction to test the sign.
>
> --
>
> Ciao, ? ? ? ? ? ? ? Paul D. DeRocco
> Paul ? ? ? ? ? ? ? ?mailto:pderocco@ix.netcom.com
>
Here is the disassemlby of floor.o
clifford:eCosHighRam david$ i386-elf-objdump -d -S
language/c/libm/current/src/double/portable-api/language_c_libm_s_floor.o
language/c/libm/current/src/double/portable-api/language_c_libm_s_floor.o:
file format elf32-i386
Disassembly of section .text.floor:
00000000 <floor>:
double floor(double x)
{
int i0,i1,j0;
unsigned i,j;
i0 = CYG_LIBM_HI(x);
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 57 push %edi
4: 56 push %esi
5: 53 push %ebx
6: 83 ec 0c sub $0xc,%esp
9: 8b 75 08 mov 0x8(%ebp),%esi
c: 89 75 e8 mov %esi,-0x18(%ebp)
f: 8b 55 0c mov 0xc(%ebp),%edx
12: 89 55 ec mov %edx,-0x14(%ebp)
i1 = CYG_LIBM_LO(x);
j0 = ((i0>>20)&0x7ff)-0x3ff;
15: 89 d1 mov %edx,%ecx
17: c1 f9 14 sar $0x14,%ecx
1a: 81 e1 ff 07 00 00 and $0x7ff,%ecx
20: 8d 99 01 fc ff ff lea -0x3ff(%ecx),%ebx
if(j0<20) {
26: 83 fb 13 cmp $0x13,%ebx
29: 7f 1d jg 48 <floor+0x48>
if(j0<0) { /* raise inexact if x != 0 */
2b: 85 db test %ebx,%ebx
2d: 78 61 js 90 <floor+0x90>
if(i0>=0) {i0=i1=0;}
else if(((i0&0x7fffffff)|i1)!=0)
{ i0=0xbff00000;i1=0;}
}
} else {
i = (0x000fffff)>>j0;
2f: b8 ff ff 0f 00 mov $0xfffff,%eax
34: 88 d9 mov %bl,%cl
36: d3 f8 sar %cl,%eax
if(((i0&i)|i1)==0) return x; /* x is integral */
38: 85 d0 test %edx,%eax
3a: 74 78 je b4 <floor+0xb4>
if(huge+x>0.0) { /* raise inexact flag */
3c: dd 45 e8 fldl -0x18(%ebp)
}
}
CYG_LIBM_HI(x) = i0;
CYG_LIBM_LO(x) = i1;
return x;
}
3f: 83 c4 0c add $0xc,%esp
42: 5b pop %ebx
43: 5e pop %esi
44: 5f pop %edi
45: c9 leave
46: c3 ret
47: 90 nop
if(huge+x>0.0) { /* raise inexact flag */
if(i0<0) i0 += (0x00100000)>>j0;
i0 &= (~i); i1=0;
}
}
} else if (j0>51) {
48: 83 fb 33 cmp $0x33,%ebx
4b: 7e 13 jle 60 <floor+0x60>
if(j0==0x400) return x+x; /* inf or NaN */
4d: 81 fb 00 04 00 00 cmp $0x400,%ebx
53: 74 57 je ac <floor+0xac>
else return x; /* x is integral */
} else {
i = ((unsigned)(0xffffffff))>>(j0-20);
if((i1&i)==0) return x; /* x is integral */
55: dd 45 e8 fldl -0x18(%ebp)
}
}
CYG_LIBM_HI(x) = i0;
CYG_LIBM_LO(x) = i1;
return x;
}
58: 83 c4 0c add $0xc,%esp
5b: 5b pop %ebx
5c: 5e pop %esi
5d: 5f pop %edi
5e: c9 leave
5f: c3 ret
}
} else if (j0>51) {
if(j0==0x400) return x+x; /* inf or NaN */
else return x; /* x is integral */
} else {
i = ((unsigned)(0xffffffff))>>(j0-20);
60: 81 e9 13 04 00 00 sub $0x413,%ecx
66: b8 ff ff ff ff mov $0xffffffff,%eax
6b: d3 e8 shr %cl,%eax
if((i1&i)==0) return x; /* x is integral */
6d: 85 f0 test %esi,%eax
6f: 74 e4 je 55 <floor+0x55>
if(huge+x>0.0) { /* raise inexact flag */
71: dd 45 e8 fldl -0x18(%ebp)
74: dd 05 00 00 00 00 fldl 0x0
7a: d8 c1 fadd %st(1),%st
7c: d9 ee fldz
7e: d9 c9 fxch %st(1)
80: da e9 fucompp
82: df e0 fnstsw %ax
84: f6 c4 45 test $0x45,%ah
87: 75 b6 jne 3f <floor+0x3f>
if(i0<0) {
89: 85 d2 test %edx,%edx
8b: eb b2 jmp 3f <floor+0x3f>
8d: 8d 76 00 lea 0x0(%esi),%esi
i0 = CYG_LIBM_HI(x);
i1 = CYG_LIBM_LO(x);
j0 = ((i0>>20)&0x7ff)-0x3ff;
if(j0<20) {
if(j0<0) { /* raise inexact if x != 0 */
if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */
90: dd 45 e8 fldl -0x18(%ebp)
93: dd 05 00 00 00 00 fldl 0x0
99: d8 c1 fadd %st(1),%st
9b: d9 ee fldz
9d: d9 c9 fxch %st(1)
9f: da e9 fucompp
a1: df e0 fnstsw %ax
a3: f6 c4 45 test $0x45,%ah
a6: 75 97 jne 3f <floor+0x3f>
if(i0>=0) {i0=i1=0;}
a8: 85 d2 test %edx,%edx
aa: eb 93 jmp 3f <floor+0x3f>
if(i0<0) i0 += (0x00100000)>>j0;
i0 &= (~i); i1=0;
}
}
} else if (j0>51) {
if(j0==0x400) return x+x; /* inf or NaN */
ac: dd 45 e8 fldl -0x18(%ebp)
af: d8 c0 fadd %st(0),%st
b1: eb 8c jmp 3f <floor+0x3f>
b3: 90 nop
else if(((i0&0x7fffffff)|i1)!=0)
{ i0=0xbff00000;i1=0;}
}
} else {
i = (0x000fffff)>>j0;
if(((i0&i)|i1)==0) return x; /* x is integral */
b4: 85 f6 test %esi,%esi
b6: 75 84 jne 3c <floor+0x3c>
b8: eb 9b jmp 55 <floor+0x55>
Unfornately in its optimized state, (and my very meager x86 assembly
skills), I can't really follow if it is correct.
But it does seem that this instruction is wrong:
aa: eb 93 jmp 3f <floor+0x3f>
Because at this point it does not look like i0 and i1 have been set to
0, which is exactly the problem that I saw single stepping in C.
I will re-run the floor test later today without optimization. But if
that solves the problem, then what? Is this a gcc bug? Or a gcc
configuration error?
Thanks again for your help
David Brennan
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss