Motorola 68k Application Binary Interface (ABI)
m680x0.github.io
m680x0.github.io
In many respects the 68000 is the oldest most "retro" architecture for which you can still run a modern compiler suite. Processor introduced in 1979 for which you could compile a Rust binary today. That's pretty amazing.
As for abi/syscalls. I noticed that strace reports hundreds of calls to get_thread_area() under Linux/m68k. I presume under x86, arm etc. some CPU register is used to store pointer to the TLS, but under m68k "they" decided to invoke syscall every single time. I don't think it'd be very efficient, and also it pollutes strace output, unfortunately, given how frequently TLS is accessed these days.
$ uname -a
Linux ds-m68k 5.16.0-rc1-g02e0dceb9e3b #7 Fri Jan 14 01:27:22 CET 2022 m68k GNU/Linux
$ strace -c /bin/ls
% time seconds usecs/call calls errors syscall
---- ----------- ----------- --------- --------- ----------------
0.00 0.000000 0 6 read
0.00 0.000000 0 1 write
0.00 0.000000 0 10 close
0.00 0.000000 0 1 execve
0.00 0.000000 0 2 2 access
0.00 0.000000 0 3 brk
0.00 0.000000 0 3 ioctl
0.00 0.000000 0 1 munmap
0.00 0.000000 0 2 2 statfs
0.00 0.000000 0 1 uname
0.00 0.000000 0 10 mprotect
0.00 0.000000 0 14 mmap2
0.00 0.000000 0 2 getdents64
0.00 0.000000 0 8 openat
0.00 0.000000 0 285 get_thread_area
0.00 0.000000 0 1 set_thread_area
0.00 0.000000 0 9 statx
---- ----------- ----------- --------- --------- ----------------
100.00 0.000000 0 359 4 total There are no spare registers available to designate as the thread
register. Therefore, kernel magic is needed to obtain the thread
pointer from userspace.
I guess there was unused 'fs' in intel. There was nothing left in m68k.Maybe it was thought more like a thread-level thing, and not runtime thing. E.g. if we had some competing runtimes in one process space (e.g. go, jvm, libc), then they can all obtain TLS pointer via some unified method (via register or syscall). Otherwise there would be need for some chosen runtime, which would keep the pointer and distribute it around - which would create another set of problems.
Putting it on the top of initial process stack would work I guess, though.
You can store it in a GPR instead (that's what some modern architectures do) but then it needs to be part of the ABI. Otherwise at the beginning of a function you can't assume any register contains the correct value.
Could you get some kind of stack trace at the time of the get_thread_area call?
I'd like to be able to pinpoint the call(s) somewhere in
https://codesearch.debian.net/search?q=get_thread_area&perpk...
Allocate the segment for TLS and the thread stack together so that both start (stack grows down, TLS up) at a 2*n - aligned address, with n large enough so that the stack size never exceeds 2*n. Then, you could always get TLS-1 from SP by setting the lower bits to 1.
To avoid an odd size for the segment, you could put the TLS block at negative offset from the end of the segment.
I had intended mine for machines with 64-bit pointers, but data structures tend to be smaller on 32-bit machines, so they can cope with smaller stacks. On the M68K Amiga the stack size was fixed and often relatively small: recommended minimum was 16000 bytes, and for large programs recommended size was 80000. Modern operating systems for CPUs with MMUs grow the stack dynamically but still have to set aside a part of the address space for the maximum it could grow into.
That said, most library routines would then store the register contents on the stack and restore on return so not sure it's more efficient for memory access etc.
The m68k is the most CISC of ISAs I've seen, you have plentiful addressing modes and register orthogonality. It had adressing modes to do auto postincrements/predecrements, indirect indexed accesses and all sorts of fun.
edit: also relevant is the the PiStorm, a software emulated 680x0 running on a RaspberryPi that plugs into a 680x0 socket.
edit2: the MiST/MiSTer are also well known 680x0 open source FPGA implementations.
much more blue cover - I think I kept it until about 10 years ago, when I did a purge of physical books that didn't have a fairly deep sentimental attachment. of course, that still ended up with hundreds of pounds of paper.
Maybe something closer to a 64-bit version of the NS32k ISA.
I think the lesson from x86 is that it's entirely possible to make a legacy CISC ISA perform really well with enough engineering. But the question is: why do that for an extinct arch? Only 32-bits, but ColdFire attempted to revive the ISA and that didn't work out, either.