PDP-10
A from-scratch DEC PDP-10 authored for emulators.org and running in the browser. The PDP-10 is the classic 36-bit mainframe of 1966 — the machine of MIT's ITS, DEC's TOPS-10, MacLisp and the early hacker era. This build models a KA10-class processor with the signature effective-address loop (indirection and indexing), the MOVE / logic / arithmetic / halfword / test-skip-jump / stack / byte-pointer families and a console teletype, so it boots and prints HELLO, WORLD! then echoes whatever you type. It plugs into the shared debugger, where you can single-step the CPU, watch the PC and the sixteen 36-bit accumulators (shown as octal half pairs) change, set breakpoints on the program counter, and read core memory as octal disassembly.
Runs on: Web browser
PDP-10 Online Emulator
Play PDP-10 using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| HELLO, WORLD! console demo | PDP-10 | DEC PDP-10 | open | Open ⛶ |
Notes
Embedding
The emulator is two small, self-contained pieces: a pure DEC PDP-10 processor (pdp-10.js) and a console-teletype canvas (pdp-10-screen.js). Vendor both and drive the machine from your own loop. The core never touches the DOM, so the debugger can pause, step and breakpoint it. A 36-bit word does not fit a JavaScript 32-bit integer, so every word is a BigInt:
var cpu = new PDP10({ onOutput: function (ch) { screen.putChar(ch); } });
cpu.load(image, 0o100); // image = { addr: BigInt }, start PC = 0100
while (!cpu.halted) cpu.step(); // step() = one PDP-10 instruction
The machine is plain objects. Everything the debugger needs is a live field or method on the core:
| Member | Kind | What it does |
|---|---|---|
cpu.step() | method | Execute exactly one PDP-10 instruction — including the effective-address loop (indexing then indirection), and byte-pointer auto-increment. |
cpu.pc / cpu.flags | field | The 18-bit program counter and the PC flags (overflow / carries). |
cpu.rd(a) / cpu.wr(a,v) | method | Side-effect-free read / write of one 36-bit BigInt word. The sixteen accumulators are simply memory words 0–17 octal, so cpu.rd(1) is AC1. |
cpu.ea(word) | method | Resolve a full effective address (index + indirect), the signature PDP-10 addressing loop. |
cpu.keyFlag / cpu.keyBuf | field | The console keyboard flag and character buffer; the host raises the flag when a key is ready. |
Because the CPU and core store are ordinary JavaScript, breakpoints and watchpoints are host-side checks around cpu.step() and cpu.wr(), with no changes to the core.
Debugger integration
The boot shim publishes window.EMU_BOOT with a full transport: pause / resume / isPaused, stepInsn(n) (one instruction) and step(n) (a burst), reset, plus breakpoints (program-counter values the loop checks before each step) and watchpoints (core addresses, checked inside the write path). A dedicated CPU decoder, /debugger/src/cpus/pdp10.js, disassembles each 36-bit word into native octal mnemonics: the MOVE family, the sixteen Boolean ops (SETZ AND XOR IOR EQV SETO …), ADD SUB IMUL IDIV, the shifts (ASH LSH ROT), the whole halfword set (HLL HRR HRLZ HRRZ …), the test/skip/jump conditions (CAI CAM JUMP SKIP AOJ SOS …), the stack (PUSH POP PUSHJ POPJ), the byte instructions (LDB DPB ILDB IDPB) and the I/O instructions (DATAI DATAO CONSO).
The core store is 32K thirty-six-bit words. Because a 36-bit word does not fit a JS 32-bit integer, the plug-in exposes the store as a 5-bytes-per-word chip (byte 5n+j = bits 8j..8j+7 of word n), so every instruction is length five and the disassembler assembles words with arithmetic rather than shifts. The sixteen accumulators are shown as register pairs 0:L / 0:R … 17:L / 17:R, each an 18-bit octal half, because the shared register view edits 32 bits at a time and a full AC is 36. The register plug-in returns a byte-scaled pc() so the disassembly gutter, the program-counter highlight and breakpoints all line up on word boundaries.
Architecture
The DEC PDP-10, introduced in 1966, is the classic 36-bit mainframe of the early hacker era — the machine of MIT's ITS, DEC's TOPS-10, MacLisp and the first big time-sharing communities. This build is a from-scratch KA10-class processor.
- 36-bit words, 18-bit addresses. Two's-complement arithmetic; 256K words of address space. The sixteen accumulators are also the first sixteen memory locations, so an index register and a scratch word are the same thing.
- The effective-address loop. Every memory-reference word carries a 4-bit index field X, a 1-bit indirect flag I and an 18-bit address Y. The CPU adds the right half of index register X to Y, and while the indirect bit is set it fetches the pointed word and repeats with that word's own I / X / Y — a small interpreter run before every operand access.
- Byte pointers.
LDB/DPBaddress a variable-width byte anywhere in a word via a pointer holding a position and a size;ILDB/IDPBauto-advance it across word boundaries. The bundled program usesILDBto unpack five 7-bit characters per word.
The bundled program is authored PDP-10 machine code assembled inline. It loads a byte pointer, walks a packed ASCII string with ILDB, prints each character with DATAO to the console teletype (device 120), and when it reaches the null byte drops into a CONSO / DATAI / DATAO keyboard-echo loop — a genuine console session in miniature.