dciabrin / ngdevkit

Open source development for Neo-Geo
GNU Lesser General Public License v3.0
273 stars 26 forks source link

The GCC toolchain included with ngdevkit has some problems with multiplication #38

Closed ghost closed 4 years ago

ghost commented 4 years ago

I've tried to compile a c file to assembly using this command m68k-neogeo-elf-gcc -S -O2 fixmath.c.

I've noticed a problem both with division and multiplication, instead then using the 68k instruction for multiplication and division, this happens

; [...]
    .globl  __mulsi3
    .align  2
    .globl  fix_mul
    .type   fix_mul, @function
fix_mul:
    link.w %fp,#0
    move.l 12(%fp),-(%sp)
    move.l 8(%fp),-(%sp)
    jsr __mulsi3                            ; <======== This should use 68k's multiplication instructions
    addq.l #8,%sp
    swap %d0
    ext.l %d0
    unlk %fp
    rts
    .size   fix_mul, .-fix_mul
    .globl  __divsi3
    .align  2
    .globl  fix_div
    .type   fix_div, @function
fix_div:
    link.w %fp,#0
    move.l 8(%fp),%d0
    swap %d0
    clr.w %d0
    move.l 12(%fp),-(%sp)
    move.l %d0,-(%sp)
    jsr __divsi3                                ; <======== This should use 68k's division instructions
    addq.l #8,%sp
    unlk %fp
    rts
    .size   fix_div, .-fix_div
    .align  2
; [...]

This was confirmed when I tried to use a different toolchain with the same command, compiling the same file. This was the result:

; [...]
    .globl  fix_mul
    .type   fix_mul, @function
fix_mul:
    move.l 4(%sp),%d0
    muls.l 8(%sp),%d0               ; <======== Uses the 68k's multiplication instruction
    swap %d0
    ext.l %d0
    rts
    .size   fix_mul, .-fix_mul
    .align  2
    .globl  fix_div
    .type   fix_div, @function
fix_div:
    move.l 4(%sp),%d0
    swap %d0
    clr.w %d0
    divs.l 8(%sp),%d0  ; <======== Uses the 68k's division instruction
    rts
    .size   fix_div, .-fix_div
    .align  2
; [...]

fixmath.c neogeo_fixmath.s toolchain68k_fixmath.s

dciabrin commented 4 years ago

Thanks for the report, I'll have a look shortly as to why this happens.

Would you be able to paste the output of gcc --verbose with your other toolchain?

I wonder if this is due to some default optimization flags used in ngdevkit, the linkscript, or something else entirely.

ghost commented 4 years ago

Thanks for the report, I'll have a look shortly as to why this happens.

Would you be able to paste the output of gcc --verbose with your other toolchain?

I wonder if this is due to some default optimization flags used in ngdevkit, the linkscript, or something else entirely.

$ m68k-elf-gcc fixmath.c --verbose
Using built-in specs.
COLLECT_GCC=m68k-elf-gcc
COLLECT_LTO_WRAPPER=/opt/crosschain/libexec/gcc/m68k-elf/9.2.0/lto-wrapper
Target: m68k-elf
Configured with: ../configure --target=m68k-elf --prefix=/opt/crosschain/ --enable-languages=c,c++ --disable-bootstrap --with-newlib --disable-libmudflap --disable-libssp --disable-libgomp --disable-libstdcxx-pch --disable-threads --with-gnu-as --with-gnu-ld --disable-nls --with-headers=yes --disable-checking --without-headers
Thread model: single
gcc version 9.2.0 (GCC) 
COLLECT_GCC_OPTIONS='-v' '-mcpu=68020'
 /opt/crosschain/libexec/gcc/m68k-elf/9.2.0/cc1 -quiet -v fixmath.c -quiet -dumpbase fixmath.c -mcpu=68020 -auxbase fixmath -version -o /tmp/ccN9PGBl.s
GNU C17 (GCC) version 9.2.0 (m68k-elf)
        compiled by GNU C version 10.1.0, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version isl-0.18-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/opt/crosschain/lib/gcc/m68k-elf/9.2.0/../../../../m68k-elf/sys-include"
#include "..." search starts here:
#include <...> search starts here:
 /opt/crosschain/lib/gcc/m68k-elf/9.2.0/include
 /opt/crosschain/lib/gcc/m68k-elf/9.2.0/include-fixed
 /opt/crosschain/lib/gcc/m68k-elf/9.2.0/../../../../m68k-elf/include
End of search list.
GNU C17 (GCC) version 9.2.0 (m68k-elf)
        compiled by GNU C version 10.1.0, GMP version 6.1.0, MPFR version 3.1.4, MPC version 1.0.3, isl version isl-0.18-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: aef50da67371b936af677ce3e104e538
COLLECT_GCC_OPTIONS='-v' '-mcpu=68020'
 /opt/crosschain/lib/gcc/m68k-elf/9.2.0/../../../../m68k-elf/bin/as -v -mcpu=68020 -o /tmp/ccRmNlmo.o /tmp/ccN9PGBl.s
GNU assembler version 2.33.1 (m68k-elf) using BFD version (GNU Binutils) 2.33.1
COMPILER_PATH=/opt/crosschain/libexec/gcc/m68k-elf/9.2.0/:/opt/crosschain/libexec/gcc/m68k-elf/9.2.0/:/opt/crosschain/libexec/gcc/m68k-elf/:/opt/crosschain/lib/gcc/m68k-elf/9.2.0/:/opt/crosschain/lib/gcc/m68k-elf/:/opt/crosschain/lib/gcc/m68k-elf/9.2.0/../../../../m68k-elf/bin/
LIBRARY_PATH=/opt/crosschain/lib/gcc/m68k-elf/9.2.0/:/opt/crosschain/lib/gcc/m68k-elf/9.2.0/../../../../m68k-elf/lib/
COLLECT_GCC_OPTIONS='-v' '-mcpu=68020'
 /opt/crosschain/libexec/gcc/m68k-elf/9.2.0/collect2 -plugin /opt/crosschain/libexec/gcc/m68k-elf/9.2.0/liblto_plugin.so -plugin-opt=/opt/crosschain/libexec/gcc/m68k-elf/9.2.0/lto-wrapper -plugin-opt=-fresolution=/tmp/cc1Xohrn.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc /opt/crosschain/lib/gcc/m68k-elf/9.2.0/crtbegin.o -L/opt/crosschain/lib/gcc/m68k-elf/9.2.0 -L/opt/crosschain/lib/gcc/m68k-elf/9.2.0/../../../../m68k-elf/lib /tmp/ccRmNlmo.o -lgcc -lc -lgcc /opt/crosschain/lib/gcc/m68k-elf/9.2.0/crtend.o
/opt/crosschain/lib/gcc/m68k-elf/9.2.0/../../../../m68k-elf/bin/ld: attenzione: impossibile trovare il simbolo d'ingresso _start; ripristinato il predefinito 0000000080000080
COLLECT_GCC_OPTIONS='-v' '-mcpu=68020'
ghost commented 4 years ago

I've actually found out that the 68000 doesn't support 32bit multiplication, that's why it uses a subroutine instead.