Closed vinriviere closed 1 year ago
Key point to understand my initial m68k-atari-mintelf settings was that I wanted it to be similar to m68k-elf, to enable all fancy ELF features. But now I understand that using m68k-elf as reference wasn't a good choice, because it also brings in SVR4 ABI oddities which we don't want.
Main configuration issue is there: https://github.com/freemint/m68k-atari-mint-gcc/blob/0e0cacb8c8f25f6a7fc35063b72a2403f21137c4/gcc/config.gcc#L2361
I shouldn't have used m68k/m68kelf.h
there. I plan to finally remove it, but before that I want to discuss all the relevant parameters.
Testcase: struct.c
struct s
{
long a, b, c;
};
struct s f(void)
{
struct s ret = {0};
return ret;
}
$ m68k-linux-gcc -Os -fomit-frame-pointer -S struct.c -o -
#NO_APP
.file "struct.c"
.text
.align 2
.globl f
.type f, @function
f:
move.l %a1,%a0
clr.l (%a1)
clr.l 4(%a1)
clr.l 8(%a1)
rts
.size f, .-f
.ident "GCC: (GCC MiNT ELF 20230819) 13.2.0"
.section .note.GNU-stack,"",@progbits
$ m68k-elf-gcc -Os -fomit-frame-pointer -S struct.c -o -
#NO_APP
.file "struct.c"
.text
.align 2
.globl f
.type f, @function
f:
clr.l (%a0)
clr.l 4(%a0)
clr.l 8(%a0)
move.l %a0,%d0
rts
.size f, .-f
.ident "GCC: (GCC MiNT ELF 20230819) 13.2.0"
$ m68k-atari-mint-gcc -Os -fomit-frame-pointer -S struct.c -o -
#NO_APP
.text
.even
.globl _f
_f:
move.l %d2,-(%sp)
move.l %a1,%d2
pea 12.w
clr.l -(%sp)
move.l %a1,-(%sp)
jsr _memset
lea (12,%sp),%sp
move.l %d2,%d0
move.l (%sp)+,%d2
rts
I leave apart code generation oddities. But we can see that, as expected
So the obvious choice is to configure the new m68k-atari-mintelf-gcc to use a1, just like the default (Linux) behaviour and old atari gcc. I will change that, as I already agreed in https://github.com/freemint/m68k-atari-mint-gcc/issues/26#issuecomment-1714248886.
What's the right setting for a new and modern Atari toolchain?
Definitely it should stay as before (a1). There is absolutely no reason to change that. And as mentioned before, the shared libs that i deliver depend on that.
@th-otto also mentioned the parameter STATIC_CHAIN_REGNUM
which is related. Official documentation is here, pretty obscure:
https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gccint/Frame-Registers.html#index-STATIC_005fCHAIN_005fREGNUM
Actually, this is related to nested functions (a GCC extension). Nested functions can access the parent function's local variables transparently. This is achieved by passing a hidden pointer to the parent's local variables to the nested function. The "static chain register" is the register used to pass that pointer from the parent to the nested function.
Default (m68k-linux) setting is to use a0 as STATIC_CHAIN_REGNUM
:
https://github.com/freemint/m68k-atari-mint-gcc/blob/0e0cacb8c8f25f6a7fc35063b72a2403f21137c4/gcc/config/m68k/m68k.h#L412-L413
But m68k-elf, having an SVR4 ABI, uses a1 instead: https://github.com/freemint/m68k-atari-mint-gcc/blob/0e0cacb8c8f25f6a7fc35063b72a2403f21137c4/gcc/config/m68k/m68kelf.h#L91-L94
It's "funny" to see that m68k-linux (default) and m68k-elf (SVR4) use the same pair of registers a0/a1 as M68K_STRUCT_VALUE_REGNUM
and STATIC_CHAIN_REGNUM
, but with inverted meaning. Of course if one is changed, the other needs to changed, too.
I write this for documentation and memory. As we agreed that I must revert M68K_STRUCT_VALUE_REGNUM
to a1, I will also revert STATIC_CHAIN_REGNUM
to a0. I will do.
Done: https://github.com/freemint/m68k-atari-mint-gcc/commit/cb42ec3d119f6b2f02f5abb282397977dbae07f0 I've rebuilt all my Ubuntu binaries.
For the sake of simplicity, I've just added an override in mint.h. After everything is done, I plan to completely remove the usage of m68k/m68kelf.h. But for now, I prefer to go forward step by step. Slowly but surely.
The testcase works as expected:
$ m68k-atari-mintelf-gcc -Os -fomit-frame-pointer -S struct.c -o -
#NO_APP
.file "struct.c"
.text
.align 2
.globl f
.type f, @function
f:
clr.l (%a1)
clr.l 4(%a1)
clr.l 8(%a1)
move.l %a1,%d0
rts
.size f, .-f
.ident "GCC: (GCC MiNT ELF 20231027) 13.2.0"
As a summary, right settings for m68k-atari-mint* targets are:
#define STATIC_CHAIN_REGNUM A0_REG
#define M68K_STATIC_CHAIN_REG_NAME REGISTER_PREFIX "a0"
#define M68K_STRUCT_VALUE_REGNUM A1_REG
I open this issue to find a definitive answer to the
STRUCT_VALUE_REGNUM
question. It has been discussed at several places, including: https://github.com/freemint/m68k-atari-mint-gcc/issues/18#issue-1858676224 https://github.com/freemint/m68k-atari-mint-gcc/issues/26#issuecomment-1713941782Concretely:
So basically:
Moreover,
m68k-atari-mint-gcc 4.6.4
uses a1, just like default m68k.It turns out that my initial m68k-atari-mintelf-gcc build used a0, by chance. What's the right setting for a new and modern Atari toolchain?