FastFPE's implementation of the lfm opcode ('load floating-point
multiple') marks all floating-point numbers that it loads as normalized.
Unfortunately, zero and infinity are denormalized numbers, and FastFPE's
lfm will therefore corrupt any stored zero or infinity values reloaded
from memory.

The enclosed patch fixes this bug by testing for the two magic exponents
in FastFPE that indicate zero or infinity, and ensuring that the
'normalized' bit is cleared.

Minimal test cases that illustrate the problem are at
<http://www.booyaka.com/~paul/arm/fpa11_lfm_tests.tar.gz>.  After patching
with the patch below, the result of the test cases is identical between
NWFPE and FastFPE.  (The test cases are derived from code posted earlier
by Nicholas Clark <[EMAIL PROTECTED]> - thanks!)

Particular thanks go to Tony Lindgren <[EMAIL PROTECTED]> for providing the
opportunity to catch the bug, and for rebuilding Linux kernels for his
Psion as required to test solutions.

The following bug reports in other software are known to be caused by this 
bug:

. 'Re: [ID 20020504.002] 1 == 1 but 0 != 0'
  <http://lists.debian.org/debian-arm/2002/debian-arm-200205/msg00004.html>

. 'Perl IPC::Open3 bug, affects apt-get, compiler issue?' 
  <http://lists.debian.org/debian-arm/2002/debian-arm-200206/msg00001.html>


- Paul

--- linux-2.4.19-rmk2/arch/arm/fastfpe/CPDT.S   Thu Sep 26 12:09:16 2002
+++ linux-2.4.19-rmk2-pjw/arch/arm/fastfpe/CPDT.S       Thu Sep 26 14:39:32 2002
@@ -402,16 +402,25 @@
        .globl  CPDT_lfm
 CPDT_lfm:
        add     r2,r10,r0,lsr#8
-       ldr     r3,[r6],#4
-       and     r4,r3,#0x80000000
-       orr     r3,r3,#0x80000000
-       str     r4,[r2,#0]
-       str     r3,[r2,#4]
+       ldr     r4,[r6],#4
+       and     r3,r4,#0x80000000
+       str     r3,[r2,#0]              
        ldr     r3,[r6],#4
        str     r3,[r2,#8]
        ldr     r3,[r6],#4
        str     r3,[r2,#12]
 
+       cmp     r3,#0x80000000          @ does the exp indicate zero?
+       biceq   r4,r4,#0x80000000       @ if so, indicate 'denormalized'
+       beq     CPDT_lfm_storer4
+       cmp     r3,#0x7fffffff          @ does the exp indicate inf or NaN?
+       biceq   r4,r4,#0x80000000       @ if so, indicate 'denormalized'
+       beq     CPDT_lfm_storer4
+       orrne   r4,r4,#0x80000000       @ otherwise, set normalized bit
+
+CPDT_lfm_storer4:      
+       str     r4,[r2,#4]
+                       
        add     r0,r0,#1<<12
        and     r0,r0,#7<<12
        subs    r1,r1,#1




Reply via email to