Mark Smotherman. Last updated October 2003.
The PDP-8 was the first mass-produced minicomputer. It was a 12-bit, word-addressed, accumulator-based design, first shipped in 1965. It was influenced by the CDC 160, the MIT Lincoln Labs LINC, and the DEC PDP-5.
Instructions are one 12-bit word each.
+-----+-+-+-------------+
| opc |i|p| offset |
+-----+-+-+-------------+
0 1 2 3 4 5 6 7 8 9 a b
opc 3-bit opcode
i 1-bit direct/indirect addressing mode
p 1-bit global/current page for high address bits
offset 7-bit offset
effective address = p ? ( top 5 bits of last pc # offset )
: ( 00000 # offset );
A notable feature of the PDP-8 was the lack of a load instruction.
Instead, you would first clear the accumulator (cla) and then add the
contents of a memory loaction to the accumulator (tad). The function
of a store was done by the deposit and clear accumulator (dca)
instruction. The PDP-8 did provide a fast loop-closing instruction,
increment and skip if zero (isz), that did not use the accumulator.
The isz instruction was also used as a general way to increment memory
locations apart from its function in loops.
A single interrupt enable bit controlled whether or not interrupts would be accepted. Upon an interrupt,
Since the PC was saved to a fixed memory location, nested interrupts are not allowed until the interrupt handler saves the interrupted-PC, accumulator, and link bit into a memory stack. A instruction exists to reenable interrupts.
Since there is only one entry point, the interrupt handler has to poll the I/O devices and clock to determine which one caused the interrupt. This was done by using a set of device-specific skips and jumps to the corresponding device handlers. The overall structure of skips and jumps was called a skip chain. Device-specific skips were provided for the ADC, clock, disk, keyboard, and teletype. Device priority is thus equivalent to the position of the corresponding device-specific skip in the skip chain.
After handling the interrupt, the device-specific handler would need to restore the saved accumulator and link bit and re-enable interrupts before returning to the interrupted program. This was typically accomplished by jumping to a common epilog. The effect of the instruction to re-enable interrupts was delayed by one instruction so that it could be placed as the next-to-last instruction in the exit epilog and thus allow the return jump to execute before another interrupt was allowed.
/
/ skeleton of interrupt driven program with clock and keyboard interrupts
/
*0
0 / reserve word to save program counter on interrupt
jmp i pints / jump to interrupt handler
pints, inthnd / address of interrupt handler
accsav, 0 / reserve word to save accumulator
lnksav, 0 / reserve word to save link
ticks, 0 / count of clock ticks
/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/
/ main routine
/
*200
start, cla cll / clear acc and link
dca ticks / clear clock tick counter
clkt / start the clock
ion / enable interrupts
/ ... main program ...
iof / disable interrupts
hlt / stop execution
/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/
/ initial interrupt handler
/
*400
inthnd, dca accsav / save acc and link
rar
dca lnksav
/
/ skip chain to determine source of interrupt
/
clksf / skip next inst if clock flag set
skp / unconditional skip
jmp clksrv
ksf / skip next inst if keyboard flag set
skp / unconditional skip
jmp kbdsrv
/ ... rest of chain ...
hlt / unknown interrupt
/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/
/ common epilog to return from interrupt
/
xit, cla cll
tad lnksav / restore registers
ral
tad accsav
ion / re-enable interrupts
jmp i 0 / return
/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/
/ clock service routine
/
clksrv, clkcf / clear clock flag
isz ticks / increment tick counter
nop
jmp xit
/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/
/ keyboard service routine
/
kbdsrv, krb / read keyboard (clears keyboard flag)
dca char / store character in circular buffer
tad inbuf / base address
tad inptr / + index
dca temp / = required address
tad char
dca i temp / character stored in "inbuf[inptr]"
tad inptr / NOTE: no buffer overflow logic in
iac / this version
and m177 / force inptr to stay in range 0-177 octal
dca inptr
jmp xit
char, 0
inptr, 0
temp, 0
m177, 0177
*1000
inbuf, 0
[History of interrupts page] [Mark's homepage] [CPSC homepage] [Clemson Univ. homepage]
mark@cs.clemson.edu