GCC cross-compiler for the Sharp X68000 / Human68k.
Forward-ports Lyderic Maillet's original Human68k cross-compiler (GCC 4.6.2, 2012) onto Stefan "Bebbo" Franke's amiga-gcc fork, which provides GCC 6.5.0 with significant m68k-specific optimizations.
Builds a complete m68k-human68k toolchain: GCC 6.5.0, binutils 2.39,
newlib 3.0, plus:
- elf2x68k -- ELF-to-X-file converter
- run68 -- Human68k CLI emulator for testing
- vasm -- m68k assembler with Motorola syntax
- hudson-bridge -- GDB RSP to DB.X protocol bridge for on-hardware debugging
See COMPILING.md for platform-specific prerequisites and build instructions (Linux, macOS, Docker, Tart VM).
source.c --> m68k-human68k-gcc --> ELF (.elf) --> elf2x68k --> X-file (.x)
The toolchain compiles and links to standard ELF, then elf2x68k converts
to the Human68k X-file executable format with delta-encoded relocations and
optional symbol tables.
For hand-written assembly, vasm can produce ELF (for linking with GCC) or X-files directly:
source.S --> vasmm68k_mot -Felf --> .o --> gcc link --> elf2x68k --> .x
source.S --> vasmm68k_mot -Fxfile --> .x
System calls are provided as library functions via hand-written assembly stubs in newlib (219 IOCS + 187 DOS):
- IOCS (I/O Controller Supervisor):
trap #15with function number in d0. Called as_iocs_xxx()from C, declared in<sys/iocs.h>. Frequently-used IOCS calls are also available as inline functions (no library call overhead), enabled by default and suppressible with-D_NO_INLINE. - DOS (Disk Operating System): Inline
.short 0xFFxxopcodes with args on stack. Called as_dos_xxx()from C, declared in<sys/dos.h>.
For assembly programming, make vasm installs dos.inc and iocs.inc with
EQU constants, generic dispatcher macros, and convenience macros for common calls.
hudson-bridge bridges GDB's Remote Serial Protocol to the DB.X 3.00 text-based debugger running on real X68000 hardware (or MAME). Connect GDB to the bridge, which translates commands to/from DB.X over a serial link.
Supports: registers, memory read/write, software breakpoints, single-step, continue, and binary load (X protocol).
m68k-human68k-gdb program.elf --> hudson-bridge --> serial --> DB.X on X68000
Several cross-compiler projects exist for the X68000. All target the MC68000 and produce Human68k X-file executables, but they differ significantly in approach.
| lydux (2012) | human68k-gcc (this) | xdev68k | elf2x68k | |
|---|---|---|---|---|
| Status | Inactive since 2014 | Active | Active | Active |
| GCC | 4.6.2 | 6.5.0 | 13.4.0 | 13.4.0 |
| Binutils | 2.22 | 2.39 | 2.44 | 2.44 |
| Newlib | 1.19.0 | 3.0 | -- | 4.5.0 |
| GDB | 7.4 (ROM monitor) | 13.0 (DB.X bridge) | -- | 16.3 (gdbserver) |
| Target triple | human68k |
m68k-human68k |
m68k-elf |
m68k-xelf |
| Languages | C | C, C++ | C, C++ | C, C++ |
| C library | Newlib only | Newlib only | Native XC/LIBC | Newlib or native XC |
| Assembler | GAS (patched) | GAS + vasm | GAS -> HAS060.X | GAS (unmodified) |
| Emulator | -- | run68 | run68 | run68 |
| lydux | human68k-gcc | xdev68k | yunkya2/elf2x68k | |
|---|---|---|---|---|
| Assembler | GAS (patched) | GAS (patched) + vasm | GAS -> HAS060.X | GAS (unmodified) |
| Linker | LD (patched) | LD (patched) | hlk301.x (native) | LD (unmodified) |
| Object format | ELF (internal) | ELF (internal) | Native X68k | ELF (internal) |
| X-file conversion | objcopy -O xfile |
elf2x68k |
Native linker output | m68k-xelf-elf2x68k |
| GCC/binutils patches | Yes (deep) | Yes (deep) | No (unmodified) | No (specs file only) |
lydux -- Patched GCC, binutils, and newlib with native
Human68k target support. Added an X-file BFD backend to objcopy for
format conversion. Included a GDB port with HudsonBug ROM monitor backend
for on-hardware debugging over serial. Also implemented an iocscall GCC
attribute for declaring IOCS trap calls directly in C, though it was never
used in practice (all projects use assembly stubs instead). Development
stopped in 2014.
human68k-gcc (this project) -- Forward-ports lydux's Human68k target onto
amiga-gcc, gaining GCC 6.5.0 with bebbo's m68k optimizations
(see below), C++ support, binutils 2.39, and newlib 3.0. Replaces the BFD
X-file backend with a standalone elf2x68k converter. Replaces lydux's GDB
ROM monitor stub with hudson-bridge, a GDB RSP to DB.X 3.00 protocol bridge.
The newlib Human68k syscall layer, IOCS/DOS stubs, crt0, and linker scripts
carry forward from lydux with fixes.
xdev68k -- Uses an unmodified m68k-elf GCC toolchain and converts GAS
assembly output to Motorola syntax via a Perl script (x68k_gas2has.pl),
then assembles and links with the original Sharp tools (HAS060.X, hlk301.x)
running under the run68 emulator.
This means it can use native X68k libraries directly (XC, LIBC) without any
newlib port, but depends on the GAS-to-HAS conversion handling all edge cases.
Uses -fcall-used-d2 -fcall-used-a2 for XC ABI compatibility.
yunkya2/elf2x68k -- Uses an unmodified m68k-elf toolchain with a custom
specs file that transparently invokes an ELF-to-X-file converter at link time.
Closest to our approach but avoids patching GCC/binutils entirely.
Can use either newlib (based on lydux's port) or native XC libraries via an
x68k2elf object converter. Provides remote debugging via gdbserver-x68k.
Uses -fcall-used-d2 -fcall-used-a2 for XC ABI compatibility.
| lydux | human68k-gcc | xdev68k | yunkya2/elf2x68k | |
|---|---|---|---|---|
| IOCS calls | Assembly stubs (219) | Assembly stubs (219) | Native XC headers | Assembly stubs (219) |
| DOS calls | Assembly stubs (187) | Assembly stubs (187) | Native XC headers | Assembly stubs (187) |
| Inline IOCS | No | Yes (default on) | N/A (native XC) | No |
| iocscall attribute | Implemented, unused | Removed | No | No |
| Headers | <iocs.h> <dos.h> |
<sys/iocs.h> <sys/dos.h> |
XC <iocslib.h> |
<x68k/iocs.h> <x68k/dos.h> |
| vasm includes | -- | dos.inc iocs.inc |
-- | -- |
Patched vs unmodified toolchain: lydux and human68k-gcc patch GCC/binutils
to add m68k-human68k as a proper target. xdev68k and yunkya2 use standard
m68k-elf and work around it externally. Patching gives a cleaner target
definition and native linker script support, but requires maintaining patches
across GCC upgrades. The unmodified approach makes version upgrades trivial.
Optimizations: human68k-gcc inherits amiga-gcc's m68k-specific optimization
pass (bbb-opts.c, ~7000 lines) not available in stock GCC at any version:
register renaming, move propagation out of loops, stack frame shrinking,
add merging, shift reduction, auto-increment addressing mode conversion, and
__attribute__((regparm)) for passing parameters in registers. Also includes
68000-specific instruction cost tables (from the MC68000 User's Manual) for
scheduling and register allocation, replacing stock GCC's generic m68k costs.
Native XC library support: xdev68k and yunkya2 can link against original Sharp XC/LIBC libraries. lydux and human68k-gcc use newlib exclusively. For new code this rarely matters, but it enables reusing existing X68k library code without recompilation.
ABI compatibility: xdev68k and yunkya2 use -fcall-used-d2 -fcall-used-a2
to match the XC calling convention where d0-d2/a0-a2 are caller-saved.
Standard GCC m68k ABI only caller-saves d0-d1/a0-a1. human68k-gcc does not
need this flag because its newlib IOCS wrappers save/restore d2 and a2
internally before calling trap #15. The flag is only required when linking
against original XC libraries that assume the Sharp calling convention.