Build for every PDP-11 UNIX era, and run what you build.

Software Architecture, Design & Engineering by Nicholas J. Kisseberth.

Build PDP-11 programs on a modern host — preprocess, compile, optimize, assemble, link — into real 2BSD a.out binaries, and run them unmodified under a user-mode PDP-11 UNIX simulator, faithfully across every era from the First Edition and Sixth and Seventh Editions through 2.11BSD, from one set of tools.

One toolchain, every era

The same tools build for the First Edition through 2.11BSD. A universe — chosen with --universe or PDP11_UNIVERSE — selects that era's headers, C library and system-call personality; the objects and archives stay one a.out family, so everything links together and the simulator runs the result.

One source of truth for the ISA

The assembler's own operand tables define every instruction's operand count, access class and data type. The disassembler and the simulator read the same tables, so all three agree about the machine by construction rather than by care.

No host floating point

The PDP-11 FP11 (and the FIS instructions) are evaluated bit-exactly in software. Results do not depend on the host FPU, so the same program produces the same bits on every machine that can build the tools.

The tools

A full pipeline, plus the pieces around it.

Compiler chain

pdp11-cc

The compiler driver

Runs cpp → c0 → c1 [→ c2 with -O] → as → ld in order and propagates the chosen universe to each pass. Ritchie's own cc, made cross and universe-aware.

pdp11-cpp

The C preprocessor

The pristine 2.9BSD cpp (Reiser lineage) — the one the PDP-11 cc was built against, and where an era's #ifdefs are dated.

pdp11-c0

cc pass 1 — the parser

Ritchie cc's front end: reads preprocessed C and writes the intermediate form the code generator consumes.

pdp11-c1

cc pass 2 — code generator

Ritchie cc's PDP-11 code generator: turns c0's intermediate form into assembly.

pdp11-c2

The peephole optimizer

Ritchie cc's object-code improver, run over c1's assembly under -O.

pdp11-as

The assembler

A C reimplementation of the 2BSD as, with historical --isa and --aout axes. It owns the operand tables das and apsim read, so all three agree about the machine.

pdp11-ld

The link editor

The authentic 2.9BSD ld on an LP64 host: resolves, lays out and relocates into the era's native a.out — including the 0430/0431 auto-overlay formats.

pdp11-xstr

Extract string literals

Bill Joy's 1978 xstr: pulls a C program's string literals into one shared strings file and hashes them.

C library

pdp11-libc

One universal C library

A single libc.a and crt0 that serve every era: the universe is chosen at link (ld stamps __univ), crt0 records it, and the routines whose ABI moved branch on it at run time. Plus curses and termlib.

Object inspection

pdp11-das

The disassembler

The inverse of as, covering every era the assembler does; it splits a symboled a.out into per-object listings and goes linear on a stripped one.

Object editing

pdp11-objcopy

Copy / extract

Copies an a.out, or extracts its loadable image (-O binary) or a single text/data segment (-j) — the a.out-only analogue of objcopy.

Archives

Execution

pdp11-apsim

The PDP-11 UNIX simulator

Interprets PDP-11 instructions and translates the guest's sys traps into host ones, in one process. Runs unmodified binaries across the whole lineage — First Edition through 2.11BSD — with auto-overlays, job control, sockets, a bit-exact FP11 softfloat and a real adb debug channel.

Documentation

Start here.

Overview

What the toolchain is, the one-idea universe model, the tools by role, and how to build and run.

Open

Design

How the merged toolchain is put together: the universe mechanism, the shared a.out object model, the pipeline, and faithfulness as the correctness standard.

Open

User guide

Build the toolchain, pick a universe, compile and run PDP-11 programs, and drive the pipeline by hand.

Open

apsim: syscall parity

A category-by-category comparison of pdp11-apsim's system-call coverage against the reference vax11-apsim, and the calls both deliberately refuse.

Open