diff --git a/TMS34010.md b/TMS34010.md index 8f9e92d..6c0b41b 100644 --- a/TMS34010.md +++ b/TMS34010.md @@ -9,14 +9,16 @@ Those tools (`gspa`, `gsplnk`, `gsprom`, `gspcg`, `gspopt`, `gspcl`, …) are 16-bit OS/2 1.x `NE` executables that import **only `DOSCALLS`** — exactly the shape 2ine's 16-bit bridge targets. -## Status (verified 2026-10-31) +## Status (verified 2026-11-01) | tool | result | |---|---| -| `gspa` (TMS340 COFF assembler) | **works** — assembles a 2,400-line source, "No Errors, No Warnings", valid COFF | -| `gsplnk` (linker) | **works** — links `.obj` + `rts.lib` into an absolute image | -| `gsprom` (COFF → Tek-hex) | **works** — "Translation complete" | -| `gspcl` → `gspac` (C compiler) | **blocked** — the compiler child starts, then 2ine asserts in `lxConvert1616to32` | +| `gspa` (TMS340 COFF assembler) | **works** — assembles an 11,852-line disassembly of the VT1200 firmware region, "No Errors, No Warnings", valid COFF | +| `gsplnk` (linker) | **works** — links `.obj` + `rts.lib`/`flib.lib` into an absolute image | +| `gsprom` (COFF → Tek-hex) | **works** — both `-i` EPROM pair and plain Tek-hex | +| `gspar` (archiver) | **works** — lists `rts.lib` members | +| `gspac` / `gspopt` / `gspcg` (C front end, optimizer, codegen) | **work** — the null-selector fix below unblocks the C compiler | +| `gspcl` (driver) | **partial** — runs `gspac`, then stops; `gspac`/`gspcg` exit `139` at teardown. Drive the pipeline manually. | Example session (from the repo root): @@ -27,6 +29,21 @@ cd build # lx_loader dlopen()s ./lib.so, so cwd ma ./lx_loader /path/to/gsprom.exe test.out test.hex ``` +The C pipeline (front end → optimizer → codegen → assembler → linker): + +```sh +./lx_loader /path/to/gspac.exe -k file.c file.if +./lx_loader /path/to/gspopt.exe -k -O2 file.if file.opt +./lx_loader /path/to/gspcg.exe -m file.opt file.asm file.tmp +./lx_loader /path/to/gspa.exe file.asm +./lx_loader /path/to/gsplnk.exe file.obj rts.lib flib.lib -o file.out +./lx_loader /path/to/gsprom.exe file.out file.hex +``` + +Pass **relative** filenames and keep the sources, objects and libraries in the +loader's cwd: the OS/2 tools cannot open Unix absolute paths, and the tools +consume their intermediate `.if`/`.opt` files, so regenerate them per run. + ``` TMS340 COFF Assembler Version 5.01 (c) Copyright 1985, 1990 Texas Instruments Incorporated @@ -47,10 +64,24 @@ sudo apt install build-essential cmake libncurses-dev libncurses-dev:i386 \ libc6-dev-i386 gcc-multilib ``` +Arch names (verified 2026-11-01): + +```sh +sudo pacman -S --needed base-devel cmake lib32-glibc lib32-gcc-libs \ + lib32-ncurses sdl2-compat +``` + 2ine builds **32-bit** (`-m32`) and links the 32-bit `libSDL2-2.0.so.0` that is -checked into the repo root. `cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug && -cmake --build build -j2` produces `build/lx_loader` (32-bit), `build/lx_dump` -and the `lib*.so` modules. +checked into the repo root. On CMake 4.x, pass the policy floor explicitly: + +```sh +cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 +cmake --build build -j2 +``` + +That produces `build/lx_loader` (32-bit), `build/lx_dump` and the `lib*.so` +modules. ## Patches @@ -76,16 +107,29 @@ and the `lib*.so` modules. 16 bits. On modern kernels (`pid_max` = 4194304) it does not, so the process aborted before the tool ran. The 16-bit API already truncates; the asserts are disabled. +5. **`lx_loader.c`** — `lxConvert1616to32` treated only `0` as null. The C + tools pass `0003:0000` (selector index 0 with RPL 3), which is the OS/2 null + far pointer; it hit `ldt[0]` and aborted. Segment index 0 now returns `NULL`. + This unblocks `gspac`, `gspopt` and `gspcg`. +6. **`CMakeLists.txt`** — `HAVE_CURSES_H` fallback for CMake 4.x when + `FindCurses` leaves `CURSES_HAVE_*` unset, and a `/usr/lib32` fallback for + the ncurses library when the Debian `/usr/lib/i386-linux-gnu` path is absent. ## Known issues / next steps -* `gspcl` (C compiler driver) spawns `gspac` successfully, but the child dies on - `lx_loader.c:546: lxConvert1616to32: Assertion 'GLoaderState.ldt[selector] != 0'` - — a 16:16 far pointer whose selector is not one of 2ine's mapped segments - (likely selector arithmetic around `Dos16CreateCSAlias`/`Dos16AllocSeg`). - The assembler/linker/converter path is unaffected. +* `gspcl` (the driver) runs `gspac`, then stops: `gspac` and `gspcg` exit `139` + at teardown even though they write correct output, and `gspcl` gives up on the + child status. Drive `gspac → gspopt → gspcg → gspa` manually; that pipeline + produces a correct image. +* `gspa` 5.01 rejects the B-file name `b15` (`INVALID REGISTER VALUE`). The + bare `sp` encodes the A15 namespace, while the 1987 assembler accepted + `b15` and encoded the B15 namespace. SP is the same physical register as A15 + or B15, so the result is semantically identical but a firmware round-trip + differs in one byte. See the VT1200 `tools/tms34010-sdk/2INE-501.md`. * Huge-segment selector arithmetic is stubbed; nothing in the assembler path needs more than 64 KB of data. +* The tools commonly return a non-zero exit status (segfault or `1`) after + successful work. Check the output files rather than the exit code. ## Provenance