13 KiB
DEC PDP-8/L Emulation Core Instruction Set Architecture
This document provides a detailed reference of the PDP-8/L instruction set implemented in the ILDEC emulation core.
1. Architectural Overview & State
The emulator models a simplified 12-bit DEC PDP-8/L processor. CPU registers and state are defined as follows:
memory: An array of 4,096 12-bit words (a single 4K memory field).pc(Program Counter): 12-bit register holding the address offset of the next instruction.ac(Accumulator): 12-bit register used for arithmetic, logic, and I/O.link(Link Register): 1-bit register functioning as a carry/overflow indicator, logically positioned to the left of the Accumulator for shifts.- sr` (Switch Register): 12-bit register representing front panel switches, queried via operate instructions.
- Program Interrupt Registers:
ie(Interrupt Enable Flag): 1-bit register controlling the interrupt system.ion_delay(Interrupt On Delay): Counter managing the 1-instruction latency for enabling interrupts.
- Peripheral Buffers & Flags:
kbb(Keyboard Buffer) &kbf(Keyboard Flag)chb(Character Buffer) &chf(Character Flag)
2. Memory Addressing System
Memory is organized into 32 pages of 128 words each (4,096 words total).
Memory Reference Instructions (MRIs) contain a 9-bit address specification block. The bits are mapped as follows:
3 4 5 6 7 8 9 10 11
+---+---+---+---+---+---+---+---+---+
| I | Z | 7-bit Page Offset |
+---+---+---+---+---+---+---+---+---+
- Bit 3 (
I- Indirect Address Bit):0: Direct addressing.1: Indirect addressing.
- Bit 4 (
Z- Sector/Page Select Bit):0: Page 0 (addresses0o0000to0o0177).1: Current Page (the page containing the instruction being executed).
- Bits 5–11 (Page Offset): 7-bit relative address (
0to127).
Target Address Resolution Flow
- Base Address Offset Calculation:
- If
Z = 1: The 5 high-bits of the currentPCare combined with the 7-bit offset:\text{Base Target} = (\text{PC} \ \& \ \text{0xF80}) \ | \ \text{Offset} - If
Z = 0: The base target is within Page 0:\text{Base Target} = \text{Offset}
- If
- Effective Address Calculation:
- Direct Addressing (
I = 0):\text{Effective Address} = \text{Base Target} - Indirect Addressing (
I = 1):- The pointer address is the base target:
\text{Pointer Address} = \text{Base Target} - Auto-Indexing: If the base target is in the range
8to15(0o0010to0o0017in octal), the pointer word is incremented by 1 (modulo 4096) and written back to memory:\text{Memory}[\text{Pointer Address}] = (\text{Memory}[\text{Pointer Address}] + 1) \ \& \ \text{0xFFF} - The 12-bit target pointer offset is read from the pointer address:
\text{Effective Address} = \text{Memory}[\text{Pointer Address}]
- The pointer address is the base target:
- Direct Addressing (
3. Instruction Set Details
Every instruction is 12 bits wide. The top 3 bits (bits 0–2) specify the opcode.
0 1 2 3 4 5 6 7 8 9 10 11
+---+---+---+---+---+---+---+---+---+---+---+---+
| Opcode | Rest of Instruction |
+---+---+---+---+---+---+---+---+---+---+---+---+
3.1. Memory Reference Instructions (Opcodes 0–5)
These instructions perform operations involving memory locations.
| Opcode | Octal | Mnemonic | Description | Py-8-S Emulation Core Logic |
|---|---|---|---|---|
0 |
0o0 |
AND | Logical AND | self.ac &= self.memory[target_addr] |
1 |
0o1 |
TAD | Two's Complement Add | val = self.ac + self.memory[target_addr]self.ac = val & 0xFFFself.link ^= (val >> 12) (Carry toggles Link) |
2 |
0o2 |
ISZ | Increment and Skip if Zero | self.memory[target_addr] = (self.memory[target_addr] + 1) & 0xFFFif self.memory[target_addr] == 0: PC = (PC + 1) & 0xFFF |
3 |
0o3 |
DCA | Deposit and Clear AC | self.memory[target_addr] = self.acself.ac = 0 |
4 |
0o4 |
JMS | Jump to Subroutine | self.memory[target_addr] = self.pcself.pc = (target_addr + 1) & 0xFFF |
5 |
0o5 |
JMP | Jump | self.pc = target_addr & 0xFFF |
3.2. Input/Output Transfer (IOT) Instructions (Opcode 6)
IOT instructions control and transfer data to/from peripheral devices. The instruction format is:
- Device Code (
dev): Bits 3–8 (6 bits, range 0–63). - Sub-operation (
op): Bits 9–11 (3 bits, range 0–7).
Device 0: Interrupt Control (Program Interrupt System)
Manages the CPU's Program Interrupt (PI) system.
6001(ION - Interrupt Turn On): Enables the program interrupt system. The interrupt system is enabled after the execution of the instruction following ION.6002(IOF - Interrupt Turn Off): Disables the program interrupt system immediately.6003(SRQ - Skip on Interrupt Request): Skips the next instruction if a device interrupt request is pending:if self.kbf or self.chf: PC = PC + 16004(GTF - Get Flags): Loads various processor flags into the Accumulator:- AC Bit 0: Link Register (
self.link) - AC Bit 2: Interrupt Request (
self.kbf or self.chf) - AC Bit 4: Interrupt Enable Flip-Flop (
self.ie) - All other bits are cleared to
0.
- AC Bit 0: Link Register (
6005(RTF - Restore Flags): Restores flags from the Accumulator:- Link is restored from AC Bit 0:
self.link = (self.ac >> 11) & 1 - Enables interrupts with a one-instruction delay (equivalent to
ION).
- Link is restored from AC Bit 0:
6007(CAF - Clear All Flags): Resets the processor and I/O status:- Clears Accumulator and Link:
self.ac = self.link = 0 - Clears I/O device buffers/flags:
self.kbf = self.kbb = self.chf = self.chb = 0 - Disables the program interrupt system:
self.ie = self.ion_delay = 0
- Clears Accumulator and Link:
Device 3: Keyboard / Reader
Interfaces with the standard keyboard/character input.
-
Micro-programmed Keyboard Operations (bits 9, 10, 11):
- Bit 11 (
op & 1): Skip on Keyboard Flag. - Bit 10 (
(op >> 1) & 1): Clear Accumulator and Keyboard Flag. - Bit 9 (
op >> 2): OR Keyboard Buffer into the Accumulator.
Combined, these bits form the standard Keyboard instructions:
6031(KSF - Keyboard Skip on Flag):if self.kbf: PC = PC + 16032(KCC - Keyboard Clear Flag):self.ac = self.kbf = 06034(KRS - Keyboard Read Static):self.ac |= self.kbb6036(KRB - Keyboard Read Buffer):self.ac = self.kbf = 0followed byself.ac |= self.kbb
- Bit 11 (
Device 4: Teleprinter / Punch
Interfaces with the standard teleprinter/character output.
-
6040(Custom IOT: Force Teleprinter Flag): Forces the teleprinter flag to high (chf = 1). -
Micro-programmed Teleprinter Operations (bits 9, 10, 11):
- Bit 11 (
op & 1): Skip on Teleprinter Flag. - Bit 10 (
(op >> 1) & 1): Clear Teleprinter Flag. - Bit 9 (
op >> 2): Load Accumulator into Character Buffer, trigger write callback, and set Teleprinter Flag.
Combined, these bits form the standard Teleprinter instructions:
6041(TSF - Teleprinter Skip on Flag):if self.chf: PC = PC + 16042(TCF - Teleprinter Clear Flag):self.chf = 06044(TPC - Teleprinter Print Character):self.chb = self.ac; self.chf = 1; self.outc(self.ac)6046(TLS - Teleprinter Load Sequence):self.chf = 0; self.chb = self.ac; self.chf = 1; self.outc(self.ac)
- Bit 11 (
3.3. Operate Instructions (Opcode 7)
Operate (OPR) instructions are register manipulation commands. They do not reference memory addresses. The lower 9 bits function as micro-programmed instruction controls.
Note
If the lower 9 bits are
0(7000) or0o401(7401), the instruction is treated as aNOP(No Operation) and returns immediately.
Sub-group Determination
- Bit 3 (MSB of the instruction's lower 9 bits):
- If
0: Group 1 (Register manipulation, complements, and shifts). - If
1: Group 2 (Status testing, skips, and halt). - Note: Group 3 (EAE/MQ register operations) is not supported.
- If
Group 1 Operate Instructions (Bit 3 = 0)
Used for bitwise operations, clearing registers, incrementing, and rotations.
3 4 5 6 7 8 9 10 11
+---+---+---+---+---+---+---+---+---+
| 0 |CLA|CLL|CMA|CML|RAR|RAL|BSW|IAC|
+---+---+---+---+---+---+---+---+---+
Bit Mapping & Function
- Bit 4 (
CLA): Clear Accumulator. - Bit 5 (
CLL/b5): Clear Link. - Bit 6 (
CMA/b6): Complement Accumulator. - Bit 7 (
CML/b7): Complement Link. - Bit 8 (
RAR/b8): Rotate Accumulator and Link Right. - Bit 9 (
RAL/b9): Rotate Accumulator and Link Left. - Bit 10 (
BSW/b10): Byte Swap / Rotate Command Modifier.- If
RARorRALis active: Specifies double rotation (rotate 2 positions). - If neither
RARnorRALis active: Swaps the high and low 6-bit halves ofAC:self.ac = ((self.ac << 6) | (self.ac >> 6)) & 0xFFF
- If
- Bit 11 (
IAC/b11): Increment Accumulator.
Execution Order
Group 1 micro-operations are executed sequentially in the following order:
- Clear:
- If
CLAis1:self.ac = 0 - If
CLLis1:self.link = 0
- If
- Complement:
- If
CMAis1:self.ac ^= 0xFFF - If
CMLis1:self.link ^= 1
- If
- Increment:
- If
IACis1:self.ac, self.link = (self.ac + 1) & 0xFFF, self.link ^ ((self.ac + 1) >> 12)(Carry toggles Link)
- If
- Rotation / Swap:
- If
RARis1: Circular right rotateb10 + 1times of the 13-bit combined register[Link, AC]. - If
RALis1: Circular left rotateb10 + 1times of the 13-bit combined register[Link, AC]. - If
BSWis1and neitherRARnorRALis active: Swaps the high and low 6-bit halves ofAC:self.ac = ((self.ac << 6) | (self.ac >> 6)) & 0xFFF
- If
Group 2 Operate Instructions (Bit 3 = 1, Bit 11 = 0)
Used for conditional skips, input register integration, and program termination.
3 4 5 6 7 8 9 10 11
+---+---+---+---+---+---+---+---+---+
| 1 |CLA|SMA|SZA|SNL|REV|OSR|HLT| 0 |
+---+---+---+---+---+---+---+---+---+
Bit Mapping & Function
- Bit 4 (
CLA): Clear Accumulator. - Bit 5 (
SMA/b5): Skip on Minus Accumulator (AC & 0x800is set /AC > 0x7FF). - Bit 6 (
SZA/b6): Skip on Zero Accumulator (AC == 0). - Bit 7 (
SNL/b7): Skip on Non-Zero Link (Link == 1). - Bit 8 (
REV/b8): Reverse skip condition sense (OR group if0, AND group if1). - Bit 9 (
OSR/b9): OR AC with Switch Register. - Bit 10 (
HLT/b10): Halt processor execution.
Condition Evaluation & Skip Logic
- Or Group (
REV = 0): Skips the next instruction if any of the enabled conditions are true:\text{Skip} \iff (\text{SMA} \land \text{AC} < 0) \lor (\text{SZA} \land \text{AC} == 0) \lor (\text{SNL} \land \text{Link} \ne 0) - And Group (
REV = 1): Skips the next instruction if none of the enabled conditions are true. This evaluates to:\text{Skip} \iff (\neg\text{SMA} \lor \text{AC} \ge 0) \land (\neg\text{SZA} \lor \text{AC} \ne 0) \land (\neg\text{SNL} \lor \text{Link} == 0)
Execution Order
Group 2 micro-operations execute sequentially in the following order:
- Skip Condition: Evaluate conditions and increment
PCif met:if any_cond != b8: self.pc = (self.pc + 1) & 0xFFF - Clear:
- If
CLAis1:self.ac = 0
- If
- OR Switch Register:
- If
OSRis1:self.ac |= self.sr
- If
- Halt:
- If
HLTis1:self.halted = True
- If
4. Emulation & Support Control Mechanisms
4.1. Loader format
Octal tape images are loaded with the load_oct function. The loader parses files containing lines of addr: value configurations, storing values directly in standard memory locations. In this simplified core, all loaded addresses are masked with 0xFFF to restrict them to the 4K word field limit.
4.2. Program Interrupt Mechanism
When the program interrupt system is enabled (self.ie == 1) and a device interrupt request is active (either self.kbf == 1 or self.chf == 1), the CPU executes the interrupt sequence at the start of an instruction step:
- Interrupts are disabled:
self.ie = 0 - The current Program Counter (
self.pc) is saved to memory location0. - The Program Counter is set to
1(self.pc = 1), branching control to the interrupt handler.