Documentation
User guide
Build the toolchain, pick a universe, compile and run PDP-11 programs, and drive the pipeline by hand.
pdp11-xdev — user guide
Build the toolchain, pick a universe, compile and run PDP-11 programs. For how it is put together, see design.md.
1. Build
make # every host tool -> ./bin/pdp11-*
make libc # matched headers -> ./include/, one universal libc.a
# + crt0 -> ./lib/ (both FLAT: the universe is
# chosen at link, see design.md)
make check # full gate: per-tool suites + end-to-end pipeline +
# the cross-universe matrix
make check-san # apsim under ASan+UBSan: the suite + the loader fuzz
Prerequisites: a host C compiler, make, yacc (byacc/bison), python3.
Everything is vendored; no network, no external trees.
2. Quick start
echo 'int main(){ printf("hello, pdp-11!\n"); return 0; }' > hi.c
bin/pdp11-cc hi.c -o hi # default universe: bsd29
bin/pdp11-apsim ./hi
Choose the era per invocation or per shell:
bin/pdp11-cc --universe=bsd28 hi.c -o hi # flag form (also: -u bsd28)
PDP11_UNIVERSE=bsd28 bin/pdp11-cc hi.c -o hi # environment form
export PDP11_UNIVERSE=bsd28 # ...or for the whole session
An unknown universe is rejected with the list of valid ones. There is one
universal libc.a and one header set (both flat); the universe is applied
at link — ld stamps __univ into the executable — so the same command
line targets any era. The compile targets run from First Edition through
2.11BSD plus System III, SVR2, and Ultrix-11 1.0–3.1; bin/pdp11-cc --universe=bogus x.c prints the full list.
3. The pipeline by hand
B=$PWD/bin
$B/pdp11-cc -S prog.c # stop after codegen -> prog.s
$B/pdp11-cc -c prog.c # compile -> prog.o
$B/pdp11-cc -O prog.c -o prog # with the c2 peephole optimizer
$B/pdp11-as -o prog.o prog.s # assemble 2BSD syntax
PDP11_UNIVERSE=bsd29 $B/pdp11-ld -X lib/crt0.o prog.o -lc -o prog
# ld reads $PDP11_UNIVERSE, stamps __univ
$B/pdp11-nm prog # symbols
$B/pdp11-size prog # text/data/bss
$B/pdp11-das prog # disassemble (any era, V1..2.11BSD)
$B/pdp11-apsim prog # run it
cc accepts K&R / pre-1977 C — the dialect the 2BSD system itself is
written in (old-style definitions, implicit int). Compiler passes honor
$TMPDIR for scratch files.
4. Overlays
For programs past 64 KB of text, the MENLO auto-overlay scheme works end to end:
bin/pdp11-cc -V -c big1.c big2.c ... # ovas-mode objects
bin/pdp11-ld -X crt0.o -Z ov1.o ... -Z ov2.o ... -L base.o ... -lovc -o prog
produces a 0430 executable that apsim loads and switches automatically
(-lovc is built for bsd29). size/das understand the overlay header;
the oracle suite links the 2.9 GENERIC kernel this way byte-identically.
5. The assembler's historical axes
Independent of the universe, as can speak every era's dialect:
--isa=v1|v4|bsd211|extended instruction set (1972 .. full DEC line)
--sys=none|v1|v6 syscall keyword tables
--aout=v1|v2|v2+ object format: 12-byte V1 header with
bit-stream relocation / 16-byte 0407 /
2.11 string-table symbols
--std=v1,...,v7,bsd,newbsd,extended composable presets
See ../src/pdp11-as/docs/std.md. -j
enables the late-hardware mnemonics (MFPT/CIS/FIS...) that the apsim test
probe uses.
6. Running vintage binaries
apsim runs originals, not just our output: 0407/0410/0411/0430/0431 2BSD
a.outs, and First Edition (0405) images with the 1971 trap conventions.
Pick the right personality for the binary's era, and it runs — native
V5/V6/V7, 2.10/2.11 (including the csh with job control), System III, and
all four Ultrix-11 releases all execute their real /bin under apsim:
-u NAME the kernel personality (or --universe=NAME, or
(or $PDP11_UNIVERSE) $PDP11_UNIVERSE) -- default bsd29
APSIM_ROOT=path guest filesystem root for absolute paths
APSIM_PTRACE=1 enable the cooperative ptrace channel (runs adb)
-s / -t syscall / instruction trace
-p N, APSIM_PID pin getpid (rogue seeds), APSIM_TIME pins time(2)
-2 force the 4BSD stack-arg convention (normally the
personality sets it; an override for odd binaries)
For example, APSIM_ROOT=~/unix/v6 bin/pdp11-apsim -u v6 ~/unix/v6/bin/ls /.
src/pdp11-apsim/root/ is a minimal guest root skeleton; mkroot.sh
populates /tmp and can install rogue.
7. Verifying against the originals
The opt-in oracle suites compare the toolchain to the native 1981/1983 binaries executed under apsim — see ../oracle/README.md for fixture setup and the full battery (compiler corpus, tree-wide as sweeps, ar/ranlib byte-matching, ld/kernel links, das round-trips, self-hosting).