# 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 ```sh 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) ```sh 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 implicit `int` happened to be pointer-sized; on x86-64 it truncates. * **K&R printf wrappers** (`amprintf`, `ameprintf`, `amfprintf`, `eprintf`) declared `p1…p6` as `int`, truncating `%s` arguments. Rewritten as real variadic functions with `va_list`. * **`imalloc`** likewise made variadic, and declared in `proto.h` (included with `-include` for the assembler's translation units). * **flex 2.6**: `yyGetReady()` used to set `yy_init = 1`; with the modern skeleton that leaves `yy_c_buf_p` NULL and segfaults. It is now a no-op — `YY_INPUT`/`am_input` still supplies the line buffer. * `abort(1)` → `abort()`; `hash()` uses unsigned arithmetic; two `exit(eprintf(...))` calls split. ## Upstream quirks worth knowing * **`-e` takes 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 `_start` as an object file. * **The container format depends on the host `long` size.** `link.h` stores addresses and sizes as `long`; this build writes 8-byte fields, so the header is 156 bytes rather than the historical 80. `as34`, `ld34` and `extract.py` all agree, but these files are not interchangeable with 32-bit-host `g.out` files. Making the format stable would mean changing `long` to `int32_t` in `link.h`. * **`ld34` runs `as34` from `PATH`** when generating C++ ctor/dtor tables. `test.sh` passes `-c` to skip that. * `as34` is **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.