Thank you Paul,

On Wed, Nov 10, 2010 at 12:08 AM, Paul D. DeRocco
<pdero...@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:pdero...@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

Reply via email to