PDP-11
The PDP-11 is Digital Equipment Corporation's 16-bit minicomputer, launched in 1970 and one of the most influential computers ever made, the machine on which early Unix and the C language grew up. This entry runs Paul Nankervis's pure-JavaScript PDP-11/70, a faithful emulation of the top-of-the-range model, entirely in the browser.
By default it boots DEC RT-11 v4.0 to its . keyboard monitor over a VT52 serial console; a second configuration boots Bell Labs Unix V5. Because the whole machine - the CPU registers, the memory and the fetch-decode-execute loop - is ordinary JavaScript, it plugs into the site's in-page debugger: you can pause it, single-step real PDP-11 instructions, set breakpoints and watchpoints, and read and write the R0-R7 registers, the PSW and memory live.
Runs on: any modern web browser
PDP-11 Online Emulator
Play PDP-11 using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| RT-11 v4.0 console | PDP-11 | grey | Open ⛶ | ||
| Unix V5 console | PDP-11 | grey | Open ⛶ |
Notes
Embedding
The emulator is Paul Nankervis's pure-JavaScript PDP-11/70. Vendor the engine (pdp11.js CPU core, fpp.js floating point, iopage.js device I/O page, vt52.js terminal, bootcode.js boot ROM) and load them in order. There is no wasm heap; the machine is plain objects on the global CPU.
Own the loop. The stock engine drives itself with a chain of setTimeout(pdp11Processor, 4) calls, which cannot be paused or stepped from outside. We disable that self-scheduling and call pdp11Processor() ourselves: a batch when running, or one instruction at a time for the debugger:
boot(); // load boot ROM at 0120000, RUN
(function frame(){
if (running) {
if (breakpoints.size === 0) {
pdp11Processor(); // run a ~12ms batch of instructions
} else {
CPU.runState = 4; // STATE_STEP: exactly one instruction
pdp11Processor();
}
}
setTimeout(frame, 4);
})();
The machine is plain objects. Everything the debugger needs is a field or function on the global CPU:
| Member | Kind | What it does |
|---|---|---|
CPU.runState = 4; pdp11Processor() | call | Run in STATE_STEP: execute exactly one PDP-11 instruction, then halt. The single-step primitive. |
CPU.registerVal | field | The live Uint16Array register file R0-R7 (R6 = SP, R7 = PC) - read and write directly. |
readPSW() / writePSW(v) | fn | Assemble / load the 16-bit Processor Status Word (mode, priority and the N Z V C flags). |
CPU.memory | field | Physical memory as 16-bit words (byte address >> 1); read side-effect-free for the memory view. |
writeWordByPhysical(a,v) | fn | The physical memory write path, wrapped host-side to implement watchpoints. |
vt52Initialize(unit, recv, ...) | fn | The DL11 registers its console receive routine here; we capture it to inject console keystrokes. |
Because the CPU and memory are ordinary JavaScript, the debugger single-steps with a STATE_STEP call, reads and writes CPU.registerVal straight off the core, and implements breakpoints and watchpoints as host-side checks around the loop, no changes to the CPU decode.
Debugger integration
The plug-in (pdp11-debug.js) describes the machine to the shared debugger and nothing more:
- Registers are read live from
CPU.registerValeach refresh: R0-R5, SP (R6), PC (R7) and the full PSW, plus the N Z V C condition flags decoded fromreadPSW()- and written back through the same array andwritePSW. - Disassembly uses the shared
pdp11decoder: a 16-bit word machine over byte-addressable, little-endian memory. At the RT-11 monitor the MMU maps virtual to physical one-to-one in low memory, so the disassembly at PC lines up with the code. - Memory is the low 64 KB of physical store, read straight from
CPU.memory(side-effect-free, no bus cycle, so device I/O is never triggered). - Single step is one STATE_STEP call - a genuine single PDP-11 instruction; breakpoints (checked against PC) and watchpoints (wrapping
writeWordByPhysical/writeByteByPhysical) are host-side checks around the loop.
Architecture
The PDP-11 is Digital Equipment Corporation's hugely influential 16-bit minicomputer (1970). This is a faithful PDP-11/70, the top of the line, with memory management and 22-bit physical addressing, implemented entirely in JavaScript:
- CPU (
pdp11.js) - the 11/70 instruction set with eight general registers (R6 = SP, R7 = PC), kernel/supervisor/user modes and the KT11 MMU.pdp11Processor()is the fetch-decode-execute loop. - FPP (
fpp.js) - the FP11 floating-point processor. - I/O page (
iopage.js) - the device registers at0760000+: the DL11 serial consoles, the KW11 line clock, and the RK11 / RL11 / RP11 disk and TM11 tape controllers. Disk images are fetched by block (with a compressed.zstfallback via fzstd) and cached. - Console (
vt52.js) - a VT52/VT100 hybrid glass terminal, rendered into a<textarea>, wired to the DL11 console line (unit 0). - Boot ROM (
bootcode.js) - a small bootstrap loaded at0120000that printsBoot>and loads a guest OS from a disk unit.
The bundled RK05 pack (grey historic DEC software) carries RT-11 v4.0 on RK1 and Unix V5 on RK0. We auto-type boot rk1 so the machine comes up at the RT-11 "." monitor, a live, single-steppable minicomputer.