Date: Mon, 16 Jan 2012 14:51:13 -0500 From: David Schultz <das@freebsd.org> To: Ian Lepore <freebsd@damnhippie.dyndns.org> Cc: freebsd-arm <freebsd-arm@freebsd.org> Subject: Re: fenv.h fixes for softfloat Message-ID: <20120116195113.GA87187@zim.MIT.EDU> In-Reply-To: <1326730552.1669.29.camel@revolution.hippie.lan> References: <20120111175516.GA99475@zim.MIT.EDU> <1326509894.48691.100.camel@revolution.hippie.lan> <20120114081214.GA14925@zim.MIT.EDU> <1326563626.1678.34.camel@revolution.hippie.lan> <20120114182933.GA17739@zim.MIT.EDU> <1326568038.1678.43.camel@revolution.hippie.lan> <20120114211039.GA18310@zim.MIT.EDU> <1326591214.1678.85.camel@revolution.hippie.lan> <20120116022647.GA36657@zim.MIT.EDU> <1326730552.1669.29.camel@revolution.hippie.lan>
index | next in thread | previous in thread | raw e-mail
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.
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120116195113.GA87187>
