Andrew Morton's Unix-hosted assembler/linker for the TMS34010, fetched from the gsptools archive and patched to build on x86-64. The K&R sources silently truncate pointers there: implicit int parameter declarations and fixed-argument printf wrappers. The patch fixes those and the flex 2.6 yy_init mismatch. hello.as34.g is harness/hello-world/hello.asm in as34 syntax. as34/ld34 reproduce the GSPA-built payload byte-for-byte (82 bytes, md5 db91788991ebba476b55a11127a36475), and the MAME hello.lua run reports the same markers, the same 1024-word VRAM block and a byte-identical frame. build.sh downloads the upstream tarball at build time (sha256 pinned); the tree is not vendored.
as34 / ld34 — Morton's Unix-hosted TMS34010 binutils
as34 (assembler) and ld34 (linker) are Andrew Morton's 1990s TMS34010
tools, shipped with his GCC 2.5.x port. They are not TI tools and not
related to GSPA/GSPLNK; they run natively on Linux, with no DOSBox.
build.sh fetches the original gsp.tar.gz from the Wayback Machine,
applies as34-port.patch, and builds three programs:
| tool | what it does |
|---|---|
as34 |
assembles .g source to a .go object (LINKMAGIC 0x3abf782e) |
ld34 |
links .go objects to g.out (same linkhdr container), with a map |
dis34 |
disassembles g.out (kept for inspection; the repo's tools/smart34010/dis34 is a better independent decoder) |
The compiled .text is extracted from g.out by extract.py. g.out is
not COFF — ld34/coff.c is dead code that is neither compiled nor called.
The live writer is ld34/header.c, which emits the same packed linkhdr
format that as34 produces.
Build
tools/as34/build.sh
Everything is fetched and built under tools/as34/build/ (git-ignored;
override with AS34_BUILD_DIR). The tools end up at:
tools/as34/build/src/gsp/binutils/as34/as34
tools/as34/build/src/gsp/binutils/ld34/ld34
tools/as34/build/src/gsp/binutils/ld34/dis34
The tarball is 2.1 MB and is an uncompressed tar with a .tar.gz name —
that is how the archive is stored. Its SHA-256 is pinned in build.sh.
Test (byte comparison, then MAME)
tools/as34/test.sh
REPO=$PWD MAME=/home/arti/code/k-space/mame0289/vt1200 tools/as34/test.sh
hello.as34.g is harness/hello-world/hello.asm ported to as34 syntax.
The result is byte-identical to the GSPA-built
harness/hello-world/payload.bin (82 bytes, md5
db91788991ebba476b55a11127a36475), and the MAME run reports the same
markers, the same 1024-word VRAM block and the same frame as the original
payload.
Syntax differences from GSPA
| GSPA | as34 | |
|---|---|---|
| hex | 0DEADh |
>DEAD (also 0xdead) |
| immediate width | movi x, a0, L |
no L/W suffix; movi is always the 32-bit form |
| 16-bit immediate add | addi |
addiw — as34's addi is the 32-bit immediate form |
| immediate order | same (op src, dst) |
same |
Everything else — labels, @absolute, *a2+, dsjs, bit addresses, field
specifiers — is unchanged. dsjs displacement encoding matches GSPA (checked
against tools/smart34010/dis34).
What the port patch changes
The code is K&R C written for 32-bit SunOS. On x86-64 the original build produces truncated pointers, so the patch is not cosmetic:
- Pointer parameters declared implicitly as
int(Xwrite,openfiles,emitslcode/emitnslcode/emitswcode/emitnswcode). On a 32-bit host the implicitinthappened to be pointer-sized; on x86-64 it truncates. - K&R printf wrappers (
amprintf,ameprintf,amfprintf,eprintf) declaredp1…p6asint, truncating%sarguments. Rewritten as real variadic functions withva_list. imalloclikewise made variadic, and declared inproto.h(included with-includefor the assembler's translation units).- flex 2.6:
yyGetReady()used to setyy_init = 1; with the modern skeleton that leavesyy_c_buf_pNULL and segfaults. It is now a no-op —YY_INPUT/am_inputstill supplies the line buffer. abort(1)→abort();hash()uses unsigned arithmetic; twoexit(eprintf(...))calls split.
Upstream quirks worth knowing
-etakes its argument attached:-e_start. The space form (-e _start) is broken in the original parser: it sets the entry name to the empty string and treats_startas an object file.- The container format depends on the host
longsize.link.hstores addresses and sizes aslong; this build writes 8-byte fields, so the header is 156 bytes rather than the historical 80.as34,ld34andextract.pyall agree, but these files are not interchangeable with 32-bit-hostg.outfiles. Making the format stable would mean changinglongtoint32_tinlink.h. ld34runsas34fromPATHwhen generating C++ ctor/dtor tables.test.shpasses-cto skip that.as34is not GSPA-compatible at the token level (see the table above).
Licence
The upstream tarball contains GPLv2-era GNU binutils code plus Morton's own sources. It is downloaded at build time, not vendored here; the patch is the only derived file committed.