fenv.h fixes for softfloat
David Schultz
das at freebsd.org
Mon Jan 16 19:51:16 UTC 2012
On Mon, Jan 16, 2012, Ian Lepore wrote:
> So, on theory that there's probably nothing wrong with rint() but maybe
> something wrong with casting, I tried a test that does what the guts of
> llrint() does, but breaking the casting into a separate step and looking
> at the flags after each operation. I also tried casting to (long)
> versus (long long) and the results are different. Here's the broken
> down test code:
>
> fenv_t env;
> volatile long long llr;
> volatile double dr;
> volatile double _d = 1.0;
>
> feclearexcept(FE_ALL_EXCEPT);
> feholdexcept(&env);
> printf("except 1: %#x\n", fetestexcept(FE_ALL_EXCEPT));
>
> dr = rint(_d);
> printf("except 2: %#x\n", fetestexcept(FE_ALL_EXCEPT));
>
> if (fetestexcept(FE_INVALID))
> feclearexcept(FE_INEXACT);
> printf("except 3: %#x\n", fetestexcept(FE_ALL_EXCEPT));
>
> llr = (long)dr;
> printf("except 4: %#x\n", fetestexcept(FE_ALL_EXCEPT));
>
> llr = (long long)dr;
> printf("except 5: %#x\n", fetestexcept(FE_ALL_EXCEPT));
>
> feupdateenv(&env);
> printf("except 6: %#x _d=%f dr=%f llr=%lld\n", fetestexcept(FE_ALL_EXCEPT), _d, dr, llr);
>
> And here's the output from running it:
>
> except 1: 0
> except 2: 0
> except 3: 0
> except 4: 0
> except 5: 0x10
> except 6: 0x10 _d=1.000000 dr=1.000000 llr=1
>
> It's interesting that a cast to 32 bits is fine but a cast directly to
> 64 bits raises FE_INEXACT for the same value.
The problem is that double->long conversions use the __fixdfsi
function in softfloat, but there's no equivalent double->longlong.
Instead, a semi-bogus __fixdfdi function is provided in libc/quad.
It'll take a little while to come up with a good fix.
More information about the freebsd-arm
mailing list