Subject: Re: [PATCH] Fix rounding bug in emulation for double floatoperating

From: Zang Roy-r61911 <[email-masked]>
Date: 11 Dec 2007 11:19:03 +0800

On Mon, 2007-12-10 at 23:00, Kumar Gala wrote:
> On Dec 9, 2007, at 11:25 PM, Liu Yu wrote:
> >
> >> -----Original Message-----
> >> From: David Gibson [mailto:[email-masked]]
> >> Sent: Monday, December 10, 2007 12:56 PM
> >> To: Liu Yu
> >> Cc: [email-masked]
> >> Subject: Re: [PATCH] Fix rounding bug in emulation for double
> >> floatoperating
> >>
> >>
> >> On Mon, Dec 10, 2007 at 01:00:52PM +0800, Liu Yu wrote:
> >>>
> >>> This patch fixes rounding bug in emulation for double float
> >> operating on PowerPC platform.
> >>>
> >>> When pack double float operand, it need to truncate the
> >> tail due to the limited precision.
> >>> If the truncated part is not zero, the last bit of work bit
> >> (totally 3 bits) need to '|' 1.
> >>>
> >>> This patch is completed in _FP_FRAC_SRS_2(X,N,sz)
> >> (arch/powerpc/math-emu/op-2.h).
> >>> Originally the code leftwards rotates the operand to just keep the
> >>> truncated part, then check whether it is zero. However, the
> >> number it
> >>> rotates is not correct when N is not smaller than
> >> _FP_W_TYPE_SIZE, and it will cause the work bit '|' 1 in the
> >> improper case.
> >>>
> >>> This patch fixes this issue.
> >>>
> >>> Signed-off-by: Liu Yu <[email-masked]>
> >>
> >> Wow someone deciphered the hideous macro hell of the math
> >> emulation code enough to fix a bug.  I don't suppose you'd
> >> care to fix the millions of warnings that the math-emu code
> >> generates...?
> >
> > Oh, I don't like macro define either. But it's really a bug...
> 
> 
> how did you find this?
> 
It supposed to run the following test case on a powerpc platform.
Yu's patch fixes the issue.
Could you help to merge this patch in your tree?
---
#include <stdio.h>
#include <math.h>
#include <bits/nan.h>
#ifdef __SPE__
#include <spe.h>
int
getSPEFSCR()
{
    return __builtin_spe_mfspefscr();
}

void
setSPEFSCR(int i)
{
    __builtin_spe_mtspefscr(i);
}
#else
int
getSPEFSCR()
{
    return 0;
}

void
setSPEFSCR(int i)
{
}
#endif

void
dmul(double d, double d1, double expected)
{
    double d2;
    int before, after;

    before = getSPEFSCR();
    d2 = d * d1;
    after = getSPEFSCR();

    printf("dmul %llx * %llx = %llx expected %llx %s [0x%x 0x%x]\n", d, d1, d2, expected,
           (d2 == expected) ? "(PASS)" : "(FAIL)", before, after);
}

void
ddiv(double d, double d1, double expected)
{
    register double d2;
    int before, after;

    before = getSPEFSCR();
    d2 = d / d1;
    after = getSPEFSCR();

    printf("ddiv %llx / %llx = %llx expected %llx %s [0x%x 0x%x]\n", d, d1, d2, expected,
           (d2 == expected) ? "(PASS)" : "(FAIL)", before, after);
}

main()
{
    const double min_double = 4.9406564584124654e-324L;

    printf("\n");
    dmul(0.5L, min_double, 0.0L);
    dmul(-0.5L, min_double, 0.0L);
    dmul(-min_double, -0.5L, 0.0L);
    printf("\n");
    ddiv(min_double, 2.0L, 0.0L);
}