Hello! First of all - I am only a C-newbie. Please keep your answers easy.
Ich found a bug in the compiler MSP430-GCC: The software multiplication (16bits * 16 bits = 32 bits) produces wrong results. The point, where the error occurs is located and a hint for the solution will be presented. The used operating system is Solaris 5.7, the version of msp430-gcc is 3.2.2. The target is any MSP430 without hardware multiplier - e.g. MSP430x311-series. A minimal example: //////////////////////////////////////// #include <msp430x31x.h> int main(void) { long int multi(int a, int b); int a = 0x1234; int b = 0xabcd; long int res; /*hide the multiplication in a function otherwise the compiler optimizes it away*/ res = multi(a,b); /*dummy-operations - otherwise the result would have been never used and would be optimized away*/ *((unsigned int*)0x200) = res; *((unsigned int*)0x202) = res >> 16; return 0; } long int multi(int a, int b) { return (long int)a * b; } //////////////////////////////////////// The used Makefile: //////////////////////////////////////// NAME=mspgcc_mulbug CPU = msp430x311 #no hardware multiplier ASMOPT = -mmcu=${CPU} COPT = -mmcu=${CPU} -O2 -Wall -g CC = msp430-gcc ${NAME}.elf: ${NAME}.o $(CC) -mmcu=${CPU} -g -o $@ $^ msp430-objcopy -O ihex $@ ${NAME}.a43 msp430-objdump -DS ${NAME}.elf >${NAME}.lst ${NAME}.o: ${NAME}.c msp430-gcc ${COPT} -c $< clean: rm -f ${NAME}.elf ${NAME}.a43 ${NAME}.lst ${NAME}.ini *.o //////////////////////////////////////// The point, where the bug occurs is marked in the source code. During "make" a list file is created. An extract of the buggy code follows: //////////////////////////////////////// return (long int)a * b; f862: 0a 4f mov r15, r10 ; f864: 0c 4e mov r14, r12 ; f866: 0b 43 clr r11 ; f868: 0a 93 cmp #0, r10 ;subst r3 with As==00 f86a: 01 34 jge $+4 ;abs dst addr 0xf86e f86c: 3b 43 mov #-1, r11 ;subst r3 with As==11 f86e: 0c 43 clr r12 ; f870: 0c 93 cmp #0, r12 ;subst r3 with As==00 f872: 01 34 jge $+4 ;abs dst addr 0xf876 f874: 3d 43 mov #-1, r13 ;subst r3 with As==11 f876: b0 12 84 f8 call #-1916 ;#0xf884 //////////////////////////////////////// The final "call" on address 0xF876 is the jump to the software multiplication routine. The listed code shows both conversions of "a" (register R10) and "b" (register R12) from type "int" to "long int". ("b" is converted automatically.)