# PDP-8 Emulator

PDP-8 Emulator emulates a DEC PDP-8 minicomputer (1965-1975) on SymbOS. The emulation provides a working front panel, 8K words of core memory, a teletype, and a paper tape reader/punch.

While the emulation is technically functional and written in relatively efficient assembly, PDP-8 Emulator is neither very fast nor very compatible with later advanced features of the PDP-8 line. The primary goal is to run simple paper-tape software from the early days of the PDP-8 line ("Straight Eight"), not to actually emulate a full PDP-8/I system with (e.g.) the TSS/8 operating system and a hard drive connected to multiple time-sharing terminals. But, what were you planning on using this for anyway...?

The PDP-8 is a very different computer than what we are used to today. It uses a 12-bit architecture with only eight primary instructions, although many more operations are possible by combining these instructions either sequentially or simultaneously with bitwise microcoding, as well as by interacting with various physical or virtual I/O devices. Instructions and data are generally represented in octal, so that each digit (0-7) represents three bits. A full guide to using and programming a PDP-8 is beyond the scope of this documentation; please refer to DEC's original PDP-8 documentation. However, the following sections explain enough to get the virtual machine to boot.

## Emulation

### Front panel

The main window of PDP-8 Emulator simulates the physical front panel of a PDP-8/I, which is operated by flipping butterfly switches. To turn the machine on, click the Power key switch to turn it from vertical to horizontal. (Note that turning on the Lock switch will disable some of the front panel switches, as on a real PDP-8/I; if you intend to use the switches to interact with the machine, leave the Lock switch in its vertical "off" position.)

The PDP-8 has no ROM BIOS, so even the initial "bootstrap" code needed to load a program from paper tape must be inputted manually using the panel switches. On a real PDP-8/I, this code is called the "Rim Loader" and is physically printed on the front panel (in octal digits). Even then, the Rim Loader only loads tapes in the simple "Rim" format, so usually the next step is to use the Rim Loader to load the slightly larger Bin Loader from tape, and then use the Bin Loader to load the program you actually want to run.

This is tedious, so PDP-8 Emulator provides a shortcut: after attaching a paper tape image (see **Peripherals**), just click the "Loader" panel (where the Rim Loader would be printed on a real machine) and the emulator will automatically run the correct loading sequence. (See **Quickstart** for an example of how to use this in practice.) Note that PDP-8 Emulator assumes that files with the extension .BIN are in "Bin" format and should be loaded with the Bin Loader, while all other files are in "Rim" format and should be loaded with the Rim Loader.

### Peripherals

PDP-8 Emulator simulates a basic set of peripherals: a teletype for text input/output, a high-speed-type paper tape reader for program input, and a high-speed-type paper tape punch for program output.

**Teletype:** On startup, PDP-8 Emulator opens a second window called "Teletype" which emulates a standard Model 33 KSR teletype. You can see text output and type in this window to send keystrokes to the running program. Note that, as on a real ink-and-paper teletype, editing features are limited; this is an interface for sending and receiving keystrokes, not necessarily editing what you have sent!

**Tape reader:** The tape reader accepts paper tape image files in either Rim format (.PT, etc.) or Bin format (.BIN). To load a new tape, click on the tape reader panel (labeled "In" on the far right side of the main window) and select the relevant file. It is the running program's responsibility to actually read from this tape, although we can use the default bootstrap programs to read a whole tape into memory prior to execution (see **Quickstart**). Once the program has finished reading the entire tape, it will visibly eject from the reader and must be reattached in order to be read again. (The PDP-8 has no concept of "rewinding" a paper tape.)

**Tape punch:** The tape punch writes output to paper tape image files. To load a new blank output tape, click on the tape punch panel (labeled "Out" on the far right side of the main window) and specify the filename for the output file. **Warning: If you select an existing file, it will be overwritten!** Any punch output from the running program will be written to the file. There is no limit to how long this file can be (except for any limits imposed by the file system or available disk space); the punch is assumed to have infinite paper.

### Debug commands

In addition to the debugging features provided by the front panel (see **Panel reference**), PDP-8 Emulator allows several debug commands to be entered via the teletype window. To enter a command, first press the vertical pipe key to enter command mode, type the command letter followed by exactly four octal digits, and then press Enter. (The pipe key is used because it is not available on the Model 33 teletype, so it will not be displayed when typed.) Available commands are:

**A0000** - (A)ccumulator is set to the specified octal digits.

**B0000** - (B)reakpoint is set to the specified octal address; the processor will halt automatically when the program counter reaches this breakpoint. To continue after a breakpoint halt, toggle the Continue (C) switch. (There is only one breakpoint at a time. To clear the breakpoint, set it to an invalid value such as 9999.)

**D0000** - (D)eposit the value of the switch register into memory at the specified octal address. (Unlike the Dep switch, the program counter is not affected.)

**E0000** - (E)xamine the memory word at the specified octal address by showing it on the memory buffer lights. (Unlike the Exam switch, the program counter is not affected.)

**F0000** - (F)lags will be shown on the memory buffer lights, in the order: 0000TKPRTKPR, where T = teletype printer, K = teletype keyboard, P = tape punch, R = tape reader. The right set of four are pending interrupt requests, and the left set of four are the device flags. (The four address digits in the command will be ignored.)

**P0000** - (P)rogram counter is set to the specified octal address.

**S0000** - (S)witch register is set to the specified octal value.

## Tutorials

### Quickstart

Here are the steps to load a program (here, FOCAL69.BIN) from a paper tape image:

1. Click the tape reader panel (labeled "In" on the far right side of the main window) and select the sample tape file FOCAL69.BIN.

2. Click the "Loader" panel to boot the machine and read in the tape. After a minute or two the tape will stop moving and the processor will halt, indicating that the read has finished. (This is the behavior tapes in "Bin" format, which have a tail that is not read. For tapes in Rim format, the tape will visibly eject from the reader when finished and the Rim Loader will continue running in an infinite loop until halted by toggling the Stop switch.)

3. Set the register switches to the octal start address for the program (in this case, octal 0200, or in binary 000010000000). The register switches start with the third group of three from the left, meaning that the **middle** switch of the **fourth** group from the left should be flipped down, with the rest flipped up.

4. Toggle the Load Add switch (L) to load this address into the Program Counter. If done correctly, the top row of indicator lights should read 000000000010000000.

5. Toggle the Start switch (G) to begin execution of the loaded program.

If all goes well, after a moment, the teletype window will display a live session of the FOCAL-69 programming language. In the meantime, enjoy the blinkenlights!

### FORTRAN demo

This section briefly describes how to write, compile, and run a program with 4K FORTRAN. (It assumes more familiarity with operating the emulator than the Quickstart guide.) The code and steps are largely adapted from "Running 4K FORTRAN on a DEC PDP-8" and "A Quickstart Guide to Editing Paper Tape With the Symbolic Tape Editor on the DEC PDP-8" by Lawrence Woodman (CC-BY 4.0).

If you want to skip the step of entering the source code, you can use the included file FACTOR.PT (which is a pre-punched tape with the source code shown in Step 5) and skip to Step 8.

**Punching source tapes**

1. Load EDITOR.BIN with the Bin Loader. This is the Symbolic Tape Editor; for details on use, see DEC-08-NGCC-D. Broadly, the editor has a command mode (activated by Ctrl+L while in edit mode) and an edit mode (activated by A while in command mode). While in command mode, you can type short commands to edit or list specific lines, punch the current buffer to tape, etc. While in edit mode, you can type text to store in the buffer.

2. Load the starting address 0200 (octal) into the program counter (with the register and Load switches) and then set the switch register to 0003 to tell the editor to use high-speed tape punch mode.

3. Toggle the Start (G) switch to start the editor.

4. On the teletype, type 'A' and press Enter to switch to Append mode. Then type your source code, typing Enter after each line. An example program that calculates factorials is as follows:

|C;   | THIS PROGRAM CALCULATES FACTORIALS |
|5;   | TYPE 200 |
|10;  | ACCEPT 300,X |
|     | FACT=Y=1. |
|     | IF (X) 5,32,30 |
|30;  | IF (X-Y) 41,32,33 |
|32;  | TYPE 400,X,FACT |
|     | GO TO 10 |
|33;  | FACT=FACT*(Y=Y+1.) |
|     | GO TO 30 |
|41;  | PAUSE |
|     | GO TO 5 |
|200; | FORMAT (/, "PLEASE TYPE A POSITIVE NUMBER", /) |
|300; | FORMAT (E) |
|400; | FORMAT (/,E, "FACTORIAL IS",E) |
|     | END |

5. Press Ctrl+L to return to command mode.

6. Type 'P' and press Enter. The processor will halt so you can prepare the punch.

7. Attach a blank tape file to the tape punch. When you are ready to continue, toggle the Cont (C) switch to resume the program. The editor will punch the buffer to tape.

**Compiling source tapes**

8. Load FORTRANC.BIN (the compiler) with the Bin Loader.

9. Load the starting address 0200 (octal) into the program counter (with the register and Load switches) and then set the switch register to 3000 to tell the compiler to use high-speed tape reader mode.

10. Attach the source-code tape to the tape reader (e.g., FACTOR.PT or the tape you just punched).

11. Attach a blank tape to the tape punch. (This is where the compiled object-code will be punched.)

12. Toggle the Start (G) switch to start the compiler. Wait for the processor to halt, indicating that compilation has finished.

**Running compiled tapes**

The compiled code must be run via the "FORTRAN Operating System" runtime.

13. Load FORTRANO.BIN (the runtime) with the Bin Loader.

14. Load the starting address 0200 (octal) into the program counter (with the register and Load switches) and then set the switch register to 3000 to tell the runtime to use high-speed tape reader mode.

15. Attach the compiled object-code tape to the tape reader.

16. Toggle the Start (G) switch to start the runtime. After a moment, execution will halt automatically.

17. Set the switch register to 0000 to tell the runtime to use the teletype for user I/O.

18. Toggle the Continue (C) switch to execute the object code. You can interact with the program via the teletype.

## Panel reference

Note: The following information is quoted more or less directly from Chapter 3 of "Maintenance Manual PDP-8/I Volume I" (1969, DEC-8I-HR1A-D), with minor commentary.

The PDP-8/I controls (except the power and panel lock switches) are of two types: butterfly switches, and momentary-contact switches. The butterfly switches are considered to be in their zero or off-state when the top half of the butterfly is fully depressed, and are considered to be in their one or on state when the bottom half of the butterfly is depressed. The momentary-contact switches include the Start, Exam, Load Add, Cont, Dep and Stop switches. These switches (except Dep) are actuated when the bottom half is fully depressed. The Dep switch is the reverse of the above. Indicators are considered to be in their on or one state when they are lit, and in their off or zero state when not lit.

### Switches

**Panel Lock key switch:** When turned clockwise, this key-operated switch disables all controls except the Switch Register switches on the operator console. In this condition, inadvertent key operation cannot disturb the program. The program can, however, monitor the content of SR by execution of the OSR instruction.

**Power key switch:** This key-operated switch controls application of primary power to the computer. When this switch is turned clockwise, primary power is applied.

**Data Field indicators and switches:** (the leftmost 3 switches, and the corresponding indicators in the top row) The indicators denote the content of the data field and switches register (DF), and the switches serve as an extension of SR to load DF by means of the Load Add key. DF determines the core memory field of data storage and retrieval.

**Inst Field indicators and switches:** (the next leftmost 3 switches, and the corresponding indicators in the top row) The indicators denote the content of the instruction and switches field register (IF), and the switches serve as an extension of SR to load the IF by means of the Load Add key. IF determines the core memory field from which instructions are to be taken.

**Switch Register:** (the next leftmost 12 switches) Provide a means of manually setting a 12-bit word into switches the machine. Load the content of this register into PC by pressing the Load Add key or load the content into the MB and core memory by the Dep key. Under program control, the OSR and LAS instructions can set the content of SR into AC.

**Start key (G for Go)**: Starts the program by turning off the program interrupt circuits clearing the AC and L, setting the Fetch state, and starts the central processor. (Note that, when the emulation is running, the panel display will only be updated at most 8x per second unless single-stepping.)

**Load Add key (L)**: This key transfers the content of SR into PC, the content of INST FIELD switches into IF, the content of the DATA FIELD switches into DF, and clears the major state flip-flops.

**Dep key (D)**: This key transfers the content of SR into MB and core memory at the address specified by the current content of PC. The major state flip-flops are cleared. The contents of PC is then incremented by one to allow storing of information in sequential core memory addresses by repeated operation of the Dep key.

**Exam key (E)**: This key transfers the content of core memory at the address specified by the content of PC, into the MB. The content of the PC is then incremented by one to allow examination of the contents of sequential core memory addresses by repeated operation of the Exam key. The major state flip-flop register cleared. The MA indicates the address of the data in the MB.

**Cont key (C)**: This key sets the RUN flip-flop to continue the program in the state and instruction designated by the lighted console indicators, at the address currently specified by the PC if key SS is not on.

**Stop key (S)**: Causes the RUN flip-flop to be cleared at the end of the instruction in progress at the time the key is pressed.

**Sing Step key (s)**: This key causes the RUN flip-flop to be cleared to disable the timing circuits at the end of one cycle of operation. Thereafter, repeated operation of the Cont key steps the program one cycle at a time so that the operator can observe the contents of registers in each major state. (Note: this emulator does not emulate instructions at the step level, so this does nothing.)

**Sing Inst key (i)**: This key allows execution of one instruction. When the computer is started by pressing the Start or Cont key, the Sing Inst key causes the RUN flip-flop to be cleared at the end of the last cycle of the current instruction. Thereafter, repeated operation of the Cont key steps the program one instruction at a time.

### Indicators

**REGISTER INDICATORS**

**Program Counter:** The PC contains the location of the next instruction to indicators be performed.

**Memory Address:** Indicate the content of MA. Usually, the contents of MA indicators denote the core memory address of the word currently or previously read or written. After operation either the Dep or Exam key, the contents of MA indicate the core memory address just examined or deposited into.

**Memory Buffer:** Indicates the content of MB. Usually, the contents of MB indicators designate the word just written at the core memory address in MA.

**Accumulator:** Indicates the content of AC.

**Link (Ln):** Indicates the content of L.

**Multiplier Quotient:** Indicates the content of the multiplier quotient (MQ). MQ holds the multiplier at the beginning of a multiplication and holds the least-significant half of the product at the conclusion. It holds the least-significant half of the dividend at the start of division and holds the quotient at the conclusion.

**INSTRUCTION INDICATORS**

**And:** Indicates that the processor is currently performing or has performed an And instruction.

**Tad:** Indicates that the processor is currently performing or has performed a Tad instruction.

**Isz:** Indicates that the processor is currently performing or has performed an Isz Instruction.

**Dca:** Indicates that the processor is currently performing or has performed a Dca Instruction.

**Jms:** Indicates that the processor is currently performing or has performed a Jms instruction.

**Jmp:** Indicates that the processor is currently performing or has performed a Jmp instruction.

**Iot:** Indicates that the processor is currently performing or has performed an Iot instruction.

**Opr:** Indicates that the processor is currently performing or has performed an Opr instruction.

**MAJOR STATE INDICATORS**

(Note: These indicators are not necessarily accurate in the emulation because instructions are not emulated on a cycle basis.)

**Fetch:** Indicates that the processor is currently performing or has performed a Fetch cycle.

**Execute:** Indicates that the processor is currently performing or has performed an Execute cycle.

**Defer:** Indicates that the processor is currently performing or has performed a Defer cycle.

**Word Count:** Indicates that the processor is currently performing or has performed a Word Count cycle.

**Current Address:** Indicates that the processor is currently performing or has performed a Current Address cycle.

**Break:** Indicates that the processor is currently performing or has performed a Break cycle.
 
**MISCELLANEOUS INDICATORS**

**Ion:** Indicates the 1 status of the INT.ENABLE flip-flop. When lit, the interrupt control is enabled for information exchange with an I/O device.

**Pause:** Indicates the 1 status of the PAUSE flip-flop when lit. The PAUSE flip-flop is set for 2.75 microseconds by any IOT instruction that requires generation of IOP pulses or by any EAE instruction that require shifting of information.

**Run:** Indicates the 1 status of the RUN flip-flop. When lit, the internal timing circuits are enabled and the machine performs instructions.

### Tape interface

On the far right of the main window, the tape reader interface is schematically represented.

**Question mark:** Click to open this help file.

**In:** Click to attach an an input tape to the paper tape reader.

**Out:** Click to attach an output tape to the paper tape punch.

### Rim Loader

The octal data for the Rim Loader (as originally printed on the panel marked "Loader" in this emulator) is as follows. For a fully authentic experience, you may key it in manually using the panel switches rather than using the built-in loader. The starting address for the program counter is 7756.

| Address | Value | Opcode     |
| ------- | ----- | ---------- |
| 7756    | 6014  | RFC        |
| 7757    | 6011  | RSF        |
| 7760    | 5357  | JMP 7757   |
| 7761    | 6016  | RRB RFC    |
| 7762    | 7106  | CLL RTL    |
| 7763    | 7006  | RTL        |
| 7764    | 7510  | SPA        |
| 7765    | 5357  | JMP 7757   |
| 7766    | 7006  | RTL        |
| 7767    | 6011  | RSF        |
| 7770    | 5367  | JMP 7767   |
| 7771    | 6016  | RFC RRB    |
| 7772    | 7420  | SNL        |
| 7773    | 3776  | DCA I 7776 |
| 7774    | 3376  | DCA 7776   |
| 7775    | 5357  | JMP 7757   |
| 7776    | 0000  |            |
| 7777    | 0000  |            |

## Information

### Warning

**ACHTUNG!**

ALLES TURISTEN UND NONTEKNISCHEN LOOKENSPEEPERS! DAS KOMPUTERMASCHINE IST NICHT FUR DER GEFINGERPOKEN UND MITTENGRABEN! ODERWISE IST EASY TO SCHNAPPEN DER SPRINGENWERK, BLOWENFUSEN UND POPPENCORKEN MIT SPITZENSPARKEN. IST NICHT FUR GEWERKEN BEI DUMMKOPFEN. DER RUBBERNECKEN SIGHTSEEREN KEEPEN DAS COTTONPICKEN HANDER IN DAS POCKETS MUSS. ZO RELAXEN UND WATSCHEN DER BLINKENLICHTEN.

-- Popular pseudo-German warning sign from PDP labs of the 1970s (with apologies to the actual German language).

### Included software

Included software:

**FOCAL69.BIN:** The FOCAL programming language, which runs as an interpreter in a live teletype session. Courtesy of Digital Equipment Corporation. Starting address 0200.

**CHEKMO.BIN:** The chess game CHEKMO-II. Starting address 0200. See the included CHEKMO.TXT for playing instructions. Due to the slow speed of emulation, playing in blitz mode is recommended - even then, expect to wait awhile!

**4K FORTRAN:** DEC's simplest FORTRAN compiler. FORTRANC.BIN is the compiler, FORTRANO.BIN is the runtime ("operating system"), and FORTRANP.BIN is the symbol printer. See DEC-08-AFCO-D and the **FORTRAN demo** section for usage information.

**FACTOR.PT:** Sample source code for 4K FORTRAN (see **FORTRAN demo**).

**EDITOR.BIN:** The Symbolic Tape Editor, used to punch source-code tapes for 4K FORTRAN and others. See DEC-08-ESAB-D for usage information.

**BINLOAD.PT:** The Bin Loader as a paper tape, for those who would like the full experience of a manual boot-up. Courtesy of Digital Equipment Corporation. Starting address 7777; however, after loading 7777 into the program counter but before pressing Start (G), you should flip the first address switch down, setting the switch register to 3777. This tells the Bin Loader that it should read binary data from the tape reader rather than the teletype.

Additional software can be found on the Internet, e.g., https://pop.aconit.org/Programs/ or https://so-much-stuff.com/pdp8/software/decus.php. Note however that PDP-8 software is distributed in a variety of formats and targets a variety of PDP-8 hardware configurations, so any given program is not guaranteed to work with this emulator. The starting address 0200 is most common, but this varies, so you will need to check the documentation for any given piece of software.

Software by DECUS was intended for wide distribution and is generally considered to be in the public domain (or something close to it). The licensing for original software by the Digital Equipment Corporation (DEC) is not always clear, although OS/8 software has been made explicitly free and other core software (notably including FOCAL69) have been circulated and modified as effectively public domain since the early days of the PDP-8. The included 4K FORTRAN is distributed under the assumption that it belongs to this category as well; while it was less frequently distributed and modified than FOCAL69, by the late 1970s DEC's catalogs listed both in the same "non-supported" category, distributed at-cost.

### License

Copyright 2025 Daniel E. Gaskell

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
