The Terak 8510a instruction set
The Terak 8510a (and its successors, the 8510b/8510c) used
an LSI-11 bit-sliced microprocessor. The instruction set of the LSI-11
was designed towards a clean, general, symmetric instruction set. It can
be used as a register-based, stack-based, or memory-based machine, depending
on the programmer's preferences. Interrupt responsiveness is also important,
supported with multiple interrupt levels for real-time computing as well
as allowing for a separate interrupt handler for each device that generates
interrupts.
Word length is 16 bits with the leftmost, most significant
bit (MSB) being bit 15. There are eight general registers of 16 bits each.
Register 7 is the program counter (PC) and, by convention, Register 6 is
the stack pointer (SP). There is also a Processor Status Register/Word
(PSW) which indicates the 4 condition code bits (N, Z, V, C), the Trace
Trap bit, processor interrupt priority, and 4 bits for current and previous
operating modes. Addressing on the LSI-11 is linear from memory address
0 through 177777. All I/O devices are addressed as if they were part of
memory. These live in the 4KW of reserved memory space at the top of the
addressing range. All word memory addresses are even. In byte operations,
an even address specifies the least-significant byte and an odd address
specifies the most-significant byte. Specifying an odd byte in a word operation
will return an odd address trap.
Addressing for the Single Operand, Double Operand and
Jump instructions is achieved via six bits:
_ _ _ _ _ _
|x|x|x|_|_|_|
|Mode |Reg |
where the modes are as follows: (Reg = Register, Def = Deferred)
Mode 0 Reg Direct addressing of the register
Mode 1 Reg Def Contents of Reg is the address
Mode 2 AutoIncr Contents of Reg is the address, then Reg incremented
Mode 3 AutoIncrDef Content of Reg is addr of addr, then Reg Incremented
Mode 4 AutoDecr Reg is decremented then contents is address
Mode 5 AutoDecrDef Reg is decremented then contents is addr of addr
Mode 6 Index Contents of Reg + Following word is address
Mode 7 IndexDef Contents of Reg + Following word is addr of addr
Note that the right-most bit of the mode is an indirection
bit.
Although not special cases, when dealing with R7 (aka
the PC), some of these operations are called different things:
_ _ _ _ _ _
|x|x|x|1|1|1|
|Mode | R7 |
Mode 2 Immediate Operand follows the instruction
Mode 3 Absolute Address of Operand follows the instruction
Mode 6 Relative Instr address+4+Next word is Address
Mode 7 RelativeDef Instr address+4+Next word is Address of address
Mainstream instructions are broken into Single operand and
Double operand instructions, which in turn can be word or byte instructions.
Double Operand Instructions
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|b|i|i|i|s|s|s|s|s|s|d|d|d|d|d|d|
| | | : | : |
| | Op | Source | Dest |
Bit 15, b, generally selects between word-sized (b=0) and
byte-sized (b=1) operands. In the table below, the mnemonics and names
are given in the order b=0/b=1.
The double operand instructions are:
-
b 000 ssssss dddddd
-
Non-double-operand instructions.
-
b 001 ssssss dddddd -- MOV/MOVB Move Word/Byte
-
Moves a value from source to destination.
-
b 010 ssssss dddddd -- CMP/CMPB Compare Word/Byte
-
Compares values by subtracting the destination from the source,
setting the condition codes, and then discarding the result of the subtraction.
-
b 011 ssssss dddddd -- BIT/BITB Bit Test Word/Byte
-
Performs a bit-wise AND of the source and the destination,
sets the condition codes, and then discards the result of the AND.
-
b 100 ssssss dddddd -- BIC/BICB Bit Clear Word/Byte
-
For each bit set in the source, that bit is cleared in the
destination. This is accomplished by taking the ones-complement of the
source and ANDing it with the destination. The result of the AND is stored
in the destination.
-
b 101 ssssss dddddd -- BIS/BISB Bit Set Word/Byte
-
For each bit set in the source, that bit is set in the destination.
This is accomplished by ORing the source and destination, and storing the
result in the destination.
-
b 110 ssssss dddddd -- ADD/SUB Add/Subtract Word
-
Adds the source and destination, storing the results in the
destination; or, Subtracts the source from the destination, storing the
results in the destination. Note that this is a special case for b=1, in
that it does not indicate that byte-wide operands are used.
-
b 111 xxxxxx xxxxxx
-
Extended Instruction Set operations. including multiplication
and division. The first operand must be a register. The
format is:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|b|1|1|1|i|i|i|s|s|s|d|d|d|d|d|d|
| | | |
| : |
| | | Op | Src | Dest
|
Single Operand Instructions
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|b|0|0|0|i|i|i|i|i|i|d|d|d|d|d|d|
| | | : | : |
| | |Instruction| Dest |
Bit 15, b, generally selects between word-sized (b=0) and
byte-sized (b=1) operands. In the table below, the mnemonics and names
are given in the order b=0/b=1. Unless otherwise stated, the operand is
read for the data to operate on, and the result is then written over that
data.
The single operand instructions are:
-
b 000 000 011 dddddd -- SWAB/BPL Swap Bytes/Branch Plus
-
Swap bytes exchanges the two bytes found in the destination,
writing the result back to it.
The branch (b=1) is described in the section on branches,
below.
Note that SWAB is actually a bit pattern from the range
reserved for branches. This particular pattern is otherwise unused, as
it would be a modification of BR, Branch Always, which has no obvious semantics.
-
b 000 101 000 dddddd -- CLR/CLRB Clear Word/Byte
-
Sets all the bits in destination to zero.
-
b 000 101 001 dddddd -- COM/COMB Complement Word/Byte
-
Calculates the ones-complement of the operand, and stores
it. The ones-complement is formed by inverting each bit (0->1, 1->0) independently.
-
b 000 010 010 dddddd -- INC/INCB Increment Word/Byte
-
Adds one to the destination.
-
b 000 101 011 dddddd -- DEC/DECB Decrement Word/Byte
-
Subtracts one from the destination.
-
b 000 101 100 dddddd -- NEG/NEGB Negate Word/Byte
-
Calculates the twos-complement of the operand, and stores
it. The twos-complement is formed by adding one to the ones-complement.
The effect is the same as subtracting the operand from zero.
-
b 000 101 101 dddddd -- ADC/ADCB Add Carry Word/Byte
-
Adds the current value of the carry flag to the destination.
This is useful for implementing arithmetic subroutines with more than word-sized
operands.
-
b 000 101 110 dddddd -- SBC/SBCB Subtract Carry Word/Byte
-
Subtracts the current value of the carry flag from the destination.
This is useful for implementing arithmetic subroutines with more than word-sized
operands.
-
b 000 101 111 dddddd -- TST/TSTB Test Word/Byte
-
Sets the N (negative) and Z (zero) condition codes based
on the value of the operand.
-
b 000 110 000 dddddd -- ROR/RORB Rotate Right Word/Byte
-
Rotates the bits of the operand one position to the right.
The right-most bit is placed in the carry flag, and the carry flag is copied
to the left-most bit (bit 15) of the operand.
-
b 000 110 001 dddddd -- ROL/ROLB Rotate Left Word/Byte
-
Rotates the bits of the operand one position to the left.
The left-most bit is placed in the carry flag, and the carry flag is copied
to the right-most bit (bit 0) of the operand.
-
b 000 110 010 dddddd -- ASR/ASRB Arithmetic Shift Right
Word/Byte
-
Shifts the bits of the operand one position to the right.
The left-most bit is duplicated. The effect is to perform a signed division
by 2.
-
b 000 110 011 dddddd -- ASL/ASLB Arithmetic Shift Left
Word/Byte
-
Shifts the bits of the operand one position to the left.
The right-most bit is set to zero. The effect is to perform a signed multiplication
by 2.
-
b 000 110 100 dddddd -- MARK/MTPS Mark/Move To Processor
Status
-
Mark is used as part of one of the subroutine call/ return
sequences. The operand is the number of parameters.
-
b 000 110 101 dddddd -- UNUSED opcode
-
b 000 110 110 dddddd -- UNUSED opcode
-
b 000 110 111 dddddd -- SXT/MFPS Sign Extend/Move From
Processor Status
-
SXT sets the destination to zero if the N (negative) flag
is clear, or to all ones if N is set. This is useful for implementing arithmetic
subroutines with more than word-sized operands. MFPS copies the processor
status byte to the indicated register.
Branches
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|b|0|0|0|b|b|b|b|d|d|d|d|d|d|d|d|
| Branch Code | Destination |
The destination of a branch is +127 to -128 words
from the word following the branch instruction itself. This seems slightly
odd, until you realize the sequence of events: the branch instruction is
read from memory and the PC incremented. If the branch is to be taken,
the offset is then added to the current value of the PC. Since the PC has
already been incremented, the offset is thus relative to the following
word. Note that all branch instructions are one word long.
The various branches test the values of specific condition
codes, and if the tests succeed, the branch is taken. The condition codes
are N (negative), Z (zero), C (carry), and V (overflow). In the table below,
the branch tests are shown as boolean expressions. `x' stands for exclusive-OR.
`v' stands for inclusive-OR.
-
0 000 000 1dd dddddd
-
BR: Branch Always
-
0 000 001 0dd dddddd
-
BNE: Branch if Not Equal (Z==0)
-
0 000 001 1dd dddddd
-
BEQ: Branch if EQual (Z==1)
-
0 000 010 0dd dddddd
-
BGE: Branch if Greater or Equal (NxV == 0)
-
0 000 010 1dd dddddd
-
BLT: Branch if Less Than (NxV == 1)
-
0 000 011 0dd dddddd
-
BGT: Branch if Greater Than (Zv(NxV) == 0)
-
0 000 011 1dd dddddd
-
BLE: Branch if Less or Equal (Zv(NxV) == 1)
-
1 000 000 0dd dddddd
-
BPL: Branch if PLus (N == 0)
-
1 000 000 1dd dddddd
-
BMI: Branch if MInus (N == 1)
-
1 000 001 0dd dddddd
-
BHI: Branch if HIgher (C==0 and Z==0)
-
1 000 001 1dd dddddd
-
BLOS: Branch if Lower Or Same (CvZ == 1)
-
1 000 010 0dd dddddd
-
BVC: Branch if oVerflow Clear (V == 0)
-
1 000 010 1dd dddddd
-
BVS: Branch if oVerflow set (V == 1)
-
1 000 011 0dd dddddd
-
BCC: Branch if Carry Clear (C == 0)
also known as
BHIS: Branch if Higher Or Same
-
1 000 011 1dd dddddd
-
BCS: Branch if Carry Set (C == 1)
also known as
BLO: Branch if Lower
Condition Code Operations
_ _ _ _ _ _ _ _ _ _:_ _ _:_ _ _
|0|0|0|0|0|0|0|0|1|0|1|s|N|Z|V|C|
| O p c o d e | | Mask |
General opcode 000240x. Set/Clear corresponding bits depending
on sense of bit 04 (set=1, clear=0). Codes 240 and 260 set/clear no bits
and are, thus, used as NOP. Although specific mnemonic are provided for
each flag and all flags, any combination may actually be set or cleared
at a time.
General mnemonics are:
-
CLx
-
Clear x, where x is N, Z, V, or C
-
SEx
-
Set x, where x is N, Z, V, or C
-
CCC
-
Clear all condition codes
-
SCC
-
Set all condition codes
-
0 000 000 010 1s0 000
-
NOP/NOP: No Operation
-
0 000 000 010 1s0 001
-
SEC/CLC: Set/Clear Carry
-
0 000 000 010 1s0 010
-
SEV/CLV: Set/Clear Overflow
-
0 000 000 010 1s0 100
-
SEZ/CLZ: Set/Clear Zero
-
0 000 000 010 1s1 000
-
SEN/CLN: Set/Clear Negative
-
0 000 000 010 1s1 111
-
SCC/CCC: Set/Clear All Condition Codes
Other, Miscellaneous
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|0|0|0|0|1|0|0|s|s|s|d|d|d|d|d|d|
| Opcode |Stack|Destination|
-
0 000 100 sss dddddd -- JSR Jump to Subroutine
-
The actual sequence of steps taken is:
MOV <source>,-(R6)
MOV PC,<source>
JMP <destination>
Thus, it loads the calling address into the specified source
register (after saving the original contents). It then jumps to the destination.
The fun part is (as usual with the LSI-11) that the PC is a general register,
and the description above is the result when the PC is used as the source.
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|0|0|0|0|0|0|0|0|1|0|0|0|0|s|s|s|
| Opcode |Stack|
-
0 000 000 010 000 sss -- RTS ReTurn from Subroutine
-
Undoes the effects of a JSR. For predictable results, it
is suggested that the same register should be used as was named in the
corresponding JSR instruction.
The actual operations involved are:
MOV <source>,PC
MOV (R6)+,<source>
This is the reverse of JSR. Obviously, the finesse
here too is that you can use the PC, to get what people normally consider
a CALL/RETURN function.
Why is it done like this then? Well, consider this example:
...
JSR R0,FOO
.WORD A
.WORD B
MOV R1,C
...
FOO: MOV @(R0)+,R1
ADD @(R0)+,R1
RTS R0
This type of parameter passing is used extensively
(in the PDP-8 and PDP-10, for example.) Also, the FORTRAN runtime system
on the PDP-11 did it this way. (It is fairly easy to write a compiler that
generates such a calling sequence, and then have a library of functions
which expect this calling convention.)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|0|0|0|0|0|0|0|0|0|1|d|d|d|d|d|d|
| Opcode |Destination|
-
0 000 000 001 ddd ddd -- JMP JuMP
-
Loads the destination address into the PC, thus effecting
an unconditional jump. Note that a trap will occur on some systems if an
odd address is specified. On others, the destination is silently rounded
down to the next-lower even address (i.e., the right-most bit is ignored).
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|0|0|0|0|0|0|0|0|0|0|0|0|0|i|i|i|
| | | | | | Op |
0 000 000 000 000 000 -- HALT Halts the machine
-
Ceases I/O, and gives control to the console. Operator intervention
is required to continue or restart the system.
0 000 000 000 000 001 -- WAIT WAIT for interrupt
0 000 000 000 000 010 -- RTI ReTurn from Interrupt
0 000 000 000 000 100 -- BPT BreakPoint Trap
0 000 000 000 000 101 -- RESET Initializes the system
The following opcode ranges are all unused (using three
bits per octal digit):
-
00 00 07 .. 00 00 77
-
00 02 10 .. 00 02 27
-
00 70 00 .. 00 77 77
-
07 50 40 .. 07 67 77
-
10 64 00 .. 10 64 77
-
10 67 00 .. 10 77 77