Introduction
An operand is named by six bits: three of mode (bits 5–3) and three of register (bits 2–0). A double-operand instruction has two such fields, source in bits 11–6 and destination in bits 5–0; a single-operand instruction has one, in bits 5–0. The registers are R0 to R5, SP (R6) and PC (R7). The mode says how the register is used to find the operand.
Modes 6 and 7, and modes 2 and 3 with the PC as the register, are followed by one operand word. A double-operand instruction can therefore have 0, 1 or 2 operand words: the source’s comes first.
The eight modes
Shown for R3. MACRO-11 is DEC’s assembler and the explorer’s default; the UNIX column is the UNIX assembler’s syntax (* where DEC has @).
| Mode | Name | MACRO-11 | UNIX as | The operand is |
|---|---|---|---|---|
| 0 | Register | r3 | r3 | the register itself |
| 1 | Register deferred | (r3) | (r3) | the word or byte at the address in R3 |
| 2 | Autoincrement | (r3)+ | (r3)+ | at the address in R3; then R3 is increased by 1 (byte instruction) or 2 (word) |
| 3 | Autoincrement deferred | @(r3)+ | *(r3)+ | at the address held in the word R3 points to; then R3 is increased by 2 |
| 4 | Autodecrement | -(r3) | -(r3) | R3 is first decreased by 1 (byte) or 2 (word); then the operand is at R3 |
| 5 | Autodecrement deferred | @-(r3) | *-(r3) | R3 is first decreased by 2; the word there is the address of the operand |
| 6 | Index | 10(r3) | 10(r3) | at R3 plus the operand word (a signed 16-bit offset); R3 is unchanged |
| 7 | Index deferred | @10(r3) | *10(r3) | the word at R3 plus the offset is the address of the operand |
A byte instruction changes an autoincrement or autodecrement register by 1, but by 2 for SP and PC, and always by 2 in the deferred modes (the register holds a pointer to a word). Mode 0 with a byte instruction uses the low byte of the register; a MOVB into a register copies the byte sign-extended into the whole register.
The program counter as the register
With R7, the modes give the forms that make the PDP-11 code short and position-independent:
| Field | Name | MACRO-11 | UNIX as | The operand is |
|---|---|---|---|---|
27 | Immediate | #n | $n | the word after the instruction word itself |
37 | Absolute | @#addr | *$addr | the word at the address that follows |
67 | Relative | addr | addr | the word at PC plus the offset that follows: the offset is stored relative to the address after the offset word, so the code runs wherever it is loaded |
77 | Relative deferred | @addr | *addr | the word at the relative address holds the operand’s address |
The disassembler writes a relative operand as the address it names, not as the offset, and with a symbol where one is known. The address is the position after the operand word plus the signed offset. For a double-operand instruction both operand words count: the source’s offset is measured from the end of the source word, and the destination’s from the end of the destination word, which is the end of the instruction.
Example. At address 2000, the words 016700 176774 are mov 1000,r0: the offset word is at 2002, the address after it is 2004, and 2004 + 176774 (that is, 2004 − 1004) is 1000.
The words 012700 000005 are mov #5,r0, 013701 177564 are mov @#177564,r1, and 016501 000004 are mov 4(r5),r1.
The same register in the other modes: (pc), -(pc) and @-(pc) address the instruction stream itself and are rarely written (the explorer decodes them as they stand); 10(pc) is the same as the relative form with a written offset; @(pc)+ is the absolute form.
The stack idioms
With SP, modes 2 and 4 are the stack: mov r0,-(sp) pushes and mov (sp)+,r0 pops. tst (sp)+ drops a word and mov (sp),r0 reads the top. jsr pc,addr and rts pc use the same stack.
C compilers for UNIX use R5 as the frame pointer and call helper routines named csv and cret; jsr r5,addr is how they are reached: the link register is R5, and the words after the call (arguments or data) are read through it.
Not described
Known, not yet covered
- The floating-point operand modes (the autoincrement step is 4 or 8 bytes there; see floating point) and the models’ differences in the timing of each mode.
Unknown
- What the models do when an instruction uses the same register twice in an autoincrement (for example
mov (r0)+,(r0)+): the order is described in the handbooks; it was not tested here.
Links
Reference
- UNIX Assembler Reference Manual – the UNIX address syntax:
$,*,*$ - PDP-11 architecture – Wikipedia