I noticed that the multiply function in libfp had a bug where you could not
get negative numbers as results (e.g. 46.0 * -21.0 = 966).  Upon examining
mulsf.c it was discovered that the inline asm was not generating the
expected asm (or at least the intended asm).  The erroneous asm is below.
As you can see at lines 117-119 r12 is erroneously being used as both %0 and
%B3.  I'm not too good with inline assembly so I don't know if this is
incorrect code or a compiler mistake.  I also noticed lines 83-87 are
inefficient and can be redone with a mov, xor, then and.  This change alone
didn't change fact that code was being generated contrary to intent.  

I found that changing a1 and a2 from type "r" to type "m" fixed this
problem.  I noticed that in the assembly code generated a1 and a2 ended up
on the stack and needed to be moved to registers when inline was done so
changing a1 and a2 to type "m" made since.

Attached is the diff file (old - new +) with my fixes.  Also attached is a
.c file that illustrates this problem.  Below I've pasted the diff.

-Chris Takahashi

ASM LIST:
81:mulsf.old.c   ****     /* sign = SIGN (fl1.l) ^ SIGN (fl2.l); */
  82:mulsf.old.c   ****     __asm__ __volatile__ (
 111                .LM9:
 112 005a 2D41              mov @r1, r13
 113 005c 1E41 0200         mov 2(r1), r14
 114 0060 1B41 0400         mov 4(r1), r11
 115 0064 1C41 0600         mov 4+2(r1), r12
 116                /* #APP */
 117 0068 0C4E              mov r14, r12
 118 006a 3CF0 0080         and #0x8000, r12
 119 006e 0F4C              mov r12, r15
 120 0070 3FF0 0080         and #0x8000, r15
 121 0074 0CEF              xor r15, r12
 122                /* #NOAPP */
 123 0076 814C 0800         mov r12, 8(r1)
  83:mulsf.old.c   ****     "mov    %B2, %0         \n\t"
  84:mulsf.old.c   ****     "and    #0x8000, %0     \n\t"
  85:mulsf.old.c   ****     "mov    %B3, %1         \n\t"
  86:mulsf.old.c   ****     "and    #0x8000, %1     \n\t"
  87:mulsf.old.c   ****     "xor    %1, %0"
  88:mulsf.old.c   ****         : "=r" (sign)
  89:mulsf.old.c   ****         : "r" (tmp),
  90:mulsf.old.c   ****         "r" (a1),
  91:mulsf.old.c   ****         "r" (a2)
  92:mulsf.old.c   ****     );


FIX: (diff -u old new)
--- msp430-libc/src/libm/mulsf.old.c    2003-08-01 08:55:47.000000000 -0700
+++ msp430-libc/src/libm/mulsf.c        2003-08-01 10:18:02.000000000 -0700
@@ -80,15 +80,12 @@

        /* sign = SIGN (fl1.l) ^ SIGN (fl2.l); */
        __asm__ __volatile__ (
-       "mov    %B2, %0         \n\t"
+       "mov    %B1, %0         \n\t"
+       "xor    %B2, %0         \n\t"
        "and    #0x8000, %0     \n\t"
-       "mov    %B3, %1         \n\t"
-       "and    #0x8000, %1     \n\t"
-       "xor    %1, %0"
                : "=r" (sign)
-               : "r" (tmp),
-               "r" (a1),
-               "r" (a2)
+               : "m" (a1),
+               "m" (a2)
        );

        a1 = MANT (a1);

Attachment: libc-mulsf.diff
Description: Binary data

Attachment: test.c
Description: Binary data

Reply via email to