m68k-unknown-elf-gcc (GCC) 3.4.4 Bug: long long multiply is broken when returning the result from a subroutine. When using -O3 or higher, the lower half of the 64 bit result is set to zero. This example works correctly with -O2.
Do not compile ll.c and ll_test.c as one file. Test case 2 fails (2LL * 2LL), the variable 'res' is zero. m68k-unknown-elf-gcc -Wall -mcpu32 -c -O3 ll.c /* * ll.c */ long long mul_ll (long long a, long long b) { return a * b; } /* * ll_test.c */ long long mul_ll (long long a, long long b); typedef struct { long long a; long long b; long long result; } ll_test; int main (void) { ll_test cases[] = { { 1073741824LL, /* 2 ^ 30 */ 1000LL, 1073741824000LL }, { 536870912LL, /* 2 ^ 29 */ 2LL, 1073741824LL, }, { 2LL, 2LL, 4LL, } }; int i; long long res; for (i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) { res = mul_ll (cases[i].a, cases[i].b); if (res != cases[i].result) { printf ("case %d failed\n", i); } } return 0; } mul_ll: link.w %a6,#0 movm.l #0x3f00,-(%sp) clr.l %d0 clr.l %d1 move.l 8(%a6),%d4 move.l 12(%a6),%d5 move.l 16(%a6),%d2 move.l 20(%a6),%d3 move.l %d5,%d7 mulu.l %d3,%d0:%d7 *** %d7 should be %d1 *** move.l %d5,%d6 muls.l %d2,%d6 add.l %d0,%d6 move.l %d3,%d2 muls.l %d4,%d2 move.l %d6,%d0 add.l %d2,%d0 movm.l (%sp)+,#0xfc unlk %a6 rts -- Summary: Returning result of long long multiply from function clobbers lower 32 bits Product: gcc Version: 3.4.4 Status: UNCONFIRMED Severity: normal Priority: P2 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: j33433 at gmail dot com CC: gcc-bugs at gcc dot gnu dot org GCC build triplet: i686-pc-linux-gnu GCC host triplet: i686-pc-linux-gnu GCC target triplet: m68k-unknown-elf http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21671