[PATCH 2.6.9-rc3] mnfd (move negated) emulation is busted on…

Top Page
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Lennert Buytenhek
To: linux-arm-kernel
Subject: [PATCH 2.6.9-rc3] mnfd (move negated) emulation is busted on big-endian
When you issue the mnfd opcode to negate a double, nwfpe is supposed to
flip the most significant bit of your double, which is the sign bit.
However, on big endian systems, it ended up flipping the most significant
bit of the least significant sub-u32, which is one of the mantissa bits.

On my system this was manifesting itself as sed regression tests failing,
and ntpd/ntpdate consistently adjusting the system clock into the wrong

In pretty much all of NWFPE, doubles are stored in u64s and manipulations
on those doubles are done by using u64 bitops. But for negation and fabs()
it was poking into one of the sub-u32s directly instead of XORing the u64
with 0x8000000000000000 resp. ANDing with 0x7fffffffffffffff.

Since on big-endian, 'native u64 order' means that the most significant
byte (containing bits 63-56) is kept at the lowest byte address, the sign
bit is the MSB of the first sub-u32, instead of the MSB of the second one
as is the case on little endian.

Signed-off-by: Lennert Buytenhek <>

diff -urN linux-2.6.9-rc3-ds1.commit/arch/arm/nwfpe/double_cpdo.c linux-2.6.9-rc3-ds1.snap/arch/arm/nwfpe/double_cpdo.c
--- linux-2.6.9-rc3-ds1.commit/arch/arm/nwfpe/double_cpdo.c    2004-08-14 07:36:11.000000000 +0200
+++ linux-2.6.9-rc3-ds1.snap/arch/arm/nwfpe/double_cpdo.c    2004-10-10 20:29:15.514512796 +0200
@@ -75,7 +75,11 @@
     union float64_components u;

     u.f64 = rFm;
+#ifdef __ARMEB__
+    u.i[0] ^= 0x80000000;
     u.i[1] ^= 0x80000000;

     return u.f64;
@@ -85,7 +89,11 @@
     union float64_components u;

     u.f64 = rFm;
+#ifdef __ARMEB__
+    u.i[0] &= 0x7fffffff;
     u.i[1] &= 0x7fffffff;

     return u.f64;