From owner-freebsd-arm@FreeBSD.ORG Mon Jan 16 16:15:56 2012 Return-Path: Delivered-To: freebsd-arm@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 16F361065670 for ; Mon, 16 Jan 2012 16:15:56 +0000 (UTC) (envelope-from freebsd@damnhippie.dyndns.org) Received: from qmta07.emeryville.ca.mail.comcast.net (qmta07.emeryville.ca.mail.comcast.net [76.96.30.64]) by mx1.freebsd.org (Postfix) with ESMTP id E97CB8FC14 for ; Mon, 16 Jan 2012 16:15:55 +0000 (UTC) Received: from omta14.emeryville.ca.mail.comcast.net ([76.96.30.60]) by qmta07.emeryville.ca.mail.comcast.net with comcast id NGCe1i0051HpZEsA7GFvDr; Mon, 16 Jan 2012 16:15:55 +0000 Received: from damnhippie.dyndns.org ([24.8.232.202]) by omta14.emeryville.ca.mail.comcast.net with comcast id NGFu1i00D4NgCEG8aGFu2j; Mon, 16 Jan 2012 16:15:55 +0000 Received: from [172.22.42.240] (revolution.hippie.lan [172.22.42.240]) by damnhippie.dyndns.org (8.14.3/8.14.3) with ESMTP id q0GGFrrC003930; Mon, 16 Jan 2012 09:15:53 -0700 (MST) (envelope-from freebsd@damnhippie.dyndns.org) From: Ian Lepore To: David Schultz In-Reply-To: <20120116022647.GA36657@zim.MIT.EDU> References: <20120111101833.GA88428@ci0.org> <1326291254.2419.55.camel@revolution.hippie.lan> <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> Content-Type: text/plain Date: Mon, 16 Jan 2012 09:15:52 -0700 Message-Id: <1326730552.1669.29.camel@revolution.hippie.lan> Mime-Version: 1.0 X-Mailer: Evolution 2.26.0 FreeBSD GNOME Team Port Content-Transfer-Encoding: 7bit Cc: freebsd-arm Subject: Re: fenv.h fixes for softfloat X-BeenThere: freebsd-arm@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Porting FreeBSD to the StrongARM Processor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 Jan 2012 16:15:56 -0000 On Sun, 2012-01-15 at 21:26 -0500, David Schultz wrote: > On Sat, Jan 14, 2012, Ian Lepore wrote: > I believe 0x10 is FE_INEXACT on arm, not FE_INVALID. FE_INEXACT > is correct here, because w+TWO52[sx] is inexact. That still > doesn't explain the lrint() failures, but it makes them less > mysterious. For instance, the implementation of the cast from > double to int could raise a bogus inexact exception when the > number is an integer to begin with. In practice, I think the > emulated casts don't raise the proper exceptions even when they > should. It might depend on whether it's linking against libgcc's > __fixdfsi() or libc's. Doh! I could've sworn at one point I was seeing FE_INVALID set after the cast, but now the only thing I'm really sure of is that in jumping from one theory and way of testing it to another I seem to have thoroughly confused myself (and probably you too, sorry about that). 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. I did spot-check a few values other than 1.0, and they behaved the same (IE, 1.0 is not special, it happens with anything.0), and of course with non-integer starting values FE_INEXACT is set coming out of rint() as you'd expect. BTW, I never reposted the results of running all the tests after fixing the long double printf glitch, but basically it looked like they were identical to the prior results except that the values were printedly correctly. That is, it appears that everything that was failing still failed, but I'm going to confirm that more rigorously soon (like making sure I don't have any forgotten hacks/tweaks in any lib or test code). -- Ian