The 3op Processor
3op is a general purpose 16 bit processor with 16 registers and a 3 operand
instruction set. 3 operands of 4 bits each leaves only 4 bits to specify
an operation, making it quite challenging to define a useful set of
instructions.
Memory is 64K of 16 bits words, and is word addressed. The only data type
supported is the 16 bit word.
The 3op Instruction Set
Registers
3op has 16 registers. 3 of them have fixed (hardware-defined) uses, and
another 3 have conventional (software-defined) uses.
R0(hardware)(0)Constant 0
R1(software)(-1)Constant -1
R2-R11General Purpose Registers
R12(software)(L)Subroutine Link Register
R13(software)(SP)Stack Pointer
R14(hardware)(IV)Interrupt Vector
R15(hardware)(PC)Program Counter
| | | | | | | | | | | | | | | | | | | | | | | | | | | |
The software-defined registers may be used for other purposes if a
particular program doesn't need them. Operating Systems may impose their
own register conventions.
PC is incremented before the instruction is executed, so it will always be
pointing to the next program word.
Instructions
The instruction set is divided into four groups: load/store, arithmetic,
logical, and flow control. The instruction encoding depends on the
instruction in question, but in all cases the top two bits determine the
group, and the next two the operation (with one exception).
Load/Store Instructions
0000 aaaa bbbb ccccMOVE Ra,(Rb:c)
0001 aaaa bbbb ccccMOVE Ra,-(Rb:c)
0010 aaaa bbbb ccccMOVE (Rb:c),Ra
0011 aaaa bbbb ccccMOVE (Rb:c)+,Ra
| | | | | | | |
The first two instructions are stores, while the second two are loads.
The address is the sum of a 4 bit constant and the contents of a register.
-() will decrement the register before address calculation occurs; ()+ will
increment it after.
Immediate loads can be implemented with MOVE
(PC:0)+,Ra. Using the (Rb:c) mode on PC is useless, and the predecrement
mode is fatal, so these combinations should be considered illegal.
The first 16 parameters passed on the stack may be accessed with MOVE
Ra,(SP:offset) and MOVE (SP:offset),Ra. Local and global variables may be
accessed in a similar way if registers are loaded with the appropriate
pointers.
Arithmetic Instructions
0100 aaaa bbbb ccccADD Rb,Rc,Ra
0100 aaaa bbbb ccccSUB Rb,Rc,Ra
0100 aaaa bbbb ccccSHZ Rb,Rc,Ra
0100 aaaa bbbb ccccSHF Rb,Rc,Ra
| | | | | | | |
ADD stores the result of Rb+Rc in Ra. SUB stores the result of Rb-Rc in
Ra.
SHZ and SHF are the shift instructions. They both load Ra with the result
of shifting Rb by Rc places, shifting to the left if Rc is positive, and to
the left if Rc is negative. SHZ fills with 0. SHF fills with the contents
of bit 15 of Rb at each step of the shift.
If SHF is shifting to the right, the result will be an arithmetic shift.
If the shift is to the left, the result will be a 16 bit roll.
Logical Instructions
1000 aaaa bbbb ccccAND Rb,Rc,Ra
1001 aaaa bbbb ccccOR Rb,Rc,Ra
1010 aaaa bbbb ccccBIC Rb,Rc,Ra
1011 aaaa bbbb ccccXOR Rb,Rc,Ra
| | | | | | | |
AND stores the result of Rb AND Rc in Ra. The rest
should be obvious.
Flow Control Instructions
This is where it gets messy
1100 aaaa bbbb ccccSKP Rb CONDa Rc
1101 aaaa xxxx xxxxLDI Ra,xxxxxxxx
111x xxxx xxxx xxxxBRA xxxxxxxxxxxxx
| | | | | |
SKP compares the registers Rb and Rc using the condition specified by aaaa,
and skips the next instruction if the comparison succeeds. It is still not
clear what the conditions should be.
LDI simply loads Ra with an 8 bit constant (sign extending it to 16 bits
first).
BRA is an unconditional branch with a 13 bit offset. Subroutine calls may
be implemented by loading a return address into the Subroutine Link
Register immediately before the branch.
Interrupts
Interrupts are level sensitive, and interrupting devices should keep /IRQ
low until the interrupt is acknowledged. This is the way interrupts are
handled on the 6502. It requires polling to determine the interrupt
source, but allows a very simple hardware implementation. Applications
that require a faster response can speed things up with more sophisticated
hardware.
On recieving an interrupt, the processor must first complete the current
instruction. It then sets the Interrupt Disable Flag and swaps the
contents of IV and PC. The
interrupt handler must determine the source of the interrupt, acknowledge
it, and carry out any processing required.
To return from an interrupt, the handler must ensure that interrupts get
enabled, IV is loaded with the address of an interrupt handler, and PC is
loaded with the return address. A little register juggling will be
required, since the return address is in IV.
Unresolved Issues
The Interrupt Disable Flag
The location of the Interrupt Disable Flag has not been determined. One
proposal is that it is write-only, and can be modified by writing to R0
(which is always read as 0). Another possibility is that it is stored in
a memory-mapped I/O register. Or the BRA offset could be reduced to 12
bits, and another instruction added to access a control register.
The SKP Instruction
A possible modification of the SKP instruction is to split it into two
instructions, determined by the top bit of the condition field. One of
these would be a normal skip on one of 8 conditions. The other would be a
skip on the same 8 conditions, but it would decrement Rb first. This makes
loops somewhat easier.
In this case, the 8 conditions would be:
000Rb<Rc unsigned100Rb>=Rc unsigned
001Rb<Rc signed101Rb>=Rc signed
010Rb=Rc110Rb!=Rc
011Rb+Rc gives carry111Rb+Rc does not give carry
| | | | | | | | | | | | | | | |
Indirect Memory Referencing
3op has only 64K of memory, and can't afford to waste any. But
consider a machine like 3op with 32 registers, and a 19 bit word.
With this machine, it would be possible to use the top bit of an address as
an indirect bit. If the indirect bit is clear, then the address points
directly to the data required. If it is set, then the location that it
points to is not the data, but another pointer. If this pointer's indirect
bit is clear, then it points to the data. Otherwise it
points to yet another pointer...
The top bit of PC is ignored, and always read as 1. The top bit of IV is
the interrupt disable flag. When PC is copied to IV, the
interrupt disable flag will be set.
Back