Summary of Philips PR8000 computer architecture These are notes describing the architecture (instruction set etc.) of the Philips PR8000, a 24 bit computer by Philips built in France and released in 1965. What follows is partly from memory, and partly from looking at a 1973 assembly language program listing, the first assembly language program I ever wrote. In what follows, all references to addresses and instruction encodings are in octal, which is the radix used by the assembler. This is a GPR machine, with 8 registers. It uses a single address instruction set, with the registers as destination for arithmetic operations. Register 0 is the program counter; other registers are general purpose. Unlike the PDP-11, instructions that reference registers can reference only registers 1-7; when the register field of an instruction contains zero, the result is a different instruction than for the same operation field but non-zero register number. (For example, see below AD1, 040nnnnn, vs. ACT, r40nnnnn.) Some instructions operate on 48 bit values; these use R1 for the high half, R2 for the low half, and do not contain an explicit register number in the instruction encoding. Memory references may include indirect reference, and for a number of instructions also allow indexing, using registers 5, 6, or 7. I/O is via dedicated I/O instructions that reference 6 (?) bit channel numbers. I/O is interrupt driven. There are a total of 8 levels, level 0 for normal execution and higher levels for interrupts. (In my program, I see level 5 used for the console terminal; I have no information on other devices. The machine I used had a Selectric console, high speed paper tape reader/punch, a modem, and a flat-bed plotter.) Each interrupt level has a dedicated set of registers, which are mapped to locations 0-77 of main memory: the low digit is the register number, the upper digit the priority level. Consequently there is no interrupt context save overhead, and the interrupt handler address (vector) is simply defined by the value of the PC (register 0) in the set for the interrupt level in question. Instructions that reference memory may use a value 0-7 to refer to the corresponding register instead. Note that the interrupt level is implied, not explicit, in this form. Conditional branches come in two forms: branch to address based on compare of GPR with zero, or skip one instruction based on compare of GPR with memory. There is a subroutine call instruction, which writes the return address at the instruction destination address, then continues execution at the destination address + 1. Instruction format, from top to bottom bit: 3 bits: GPR number. Note that 0 is the PC, and 0 in this field typically produces a different operation. 6 bits: opcode (no indexing), or 4 bits: opcode (instructions that support indexing) 2 bits: 0 (no index register) or 1-3 for indexing by R5-R7. 15 bits: literal argument (non-memory instruction), or 1 bit: indirect flag (memory instruction) 14 bits: memory address Opcodes. This is unlikely to be the full list; it shows only the opcodes used in the assembly listing mentioned above. It seems likely from the patterns that there is a larger set of conditional skips and branches, for example. The mnemonics shown are the ones used by the Philips assembler, which was apparently developed in Belgium (or France?) and consequently uses mnemonics inspired by French rather than English words. 00dnnnnn: BRR: Branch relative to current location + n if d = 0, to current location - n if d = 1. Also used for halt (00100000) and no operation (00000001). 00dnnnnn: BIA: Branch relative to current location + n if d = 4, to current location - n if d = 5, if sense switch A is off. 00dnnnnn: BIB: Branch relative to current location + n if d = 6, to current location - n if d = 7, if sense switch B is off. r00mmmmm: BPO: Branch to memory address m if GPR r is positive. r05mmmmm: BZE: Branch to memory address m if GPR r is zero. r07mmmmm: BDR: Decrement GPR r by 1, branch to m if r > 0. r10mmmmm: INF: Skip if GPR r < memory location m. r14mmmmm: DIF: Skip if GPR r != memory location m. 020nnnnn: CHP: Change priority. (Details unclear; I never did understand the interrupt machinery well at all.) r20mmmmm: MSP: Special store: stores GPR r into memory location m, where m may be a low memory register set address, e.g., m = 50 for the level 5 program counter. 024mmmmm: BRT: Subroutine call to address m. 030nnnnn: DNU: Disconnect I/O unit n. Skips 1 if successful. r32nnnnn: REC: Receive character from I/O unit n to GPR r. Skips 1 if successful. Character appears in the low 6 bits of r. 034nnnnn: CNU: Connect I/O unit n. Skips 1 if successful. r35nnnnn: SEM: Send data in GPR r to I/O unit n. Skips 1 if successful. The data is taken from the low bits of r. r36nnnnn: SEC: Send character in GPR r to I/O unit n. Skips 1 if successful. Character is sent from the upper 6 bits of r, and r is then shifted left by 6. 040mmmmm: AD1: Increment memory location m by 1. r40nnnnn: ACT: Add literal n to GPR r. 041mmmmm: ZER: Clear memory location m. r41nnnnn: SCT: Subtract literal n from GPR r. r42nnnnn: PCT: Load literal n into GPR r. r50mmmmm: PLA: Load memory location m into GPR r. Supports indexing. 054mmmmm: MDB: Store double: stores R1/R2 into m and m + 1. r54mmmmm: MEM: Store GPR r into memory location m. Supports indexing. 060mmmmm: ADB: Add double: adds contents of m and m + 1 to R1/R2. r60mmmmm: ADD: Add contents of memory location m to GPR r. Supports indexing (I think). r64mmmmm: STR: Subtract contents of memory location m from GPR r. Supports indexing (I think). 070mmmmm: MUL: Multiply R2 by the contents of memory location m. Result in R1/R2, R1 is the high half. 074mmmmm: DIV: Divide R1/R2 by the contents of memory location m. R1 is the high half. Remainder goes to R1, quotient to R2. I/O device unit numbers: 10: Selectric console output, black ribbon 11: Selectric console output, red ribbon 14: Selectric console keyboard input (unlocks keyboard)