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>
next in thread | previous in thread | raw e-mail | index | archive | help
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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120116195113.GA87187>