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);
libc-mulsf.diff
Description: Binary data
test.c
Description: Binary data