The opcodes for our instructions come in a few different formats
|2||opcode, R2, R1, R0||MOVE, ALU, LOAD, LOADL, STOR, STORL, JAL|
|2||opcode, R2, R1, n||MOVER|
|2||opcode, R2, byte||LOADI|
|2||opcode, R2, X||POP, PUSH, MARK|
|2||F, F, F, F||HALT|
|4||opcode,cond,R1,X||Offset hi, Offset lo||SETBRA|
|6||opcode,R2,R1,R0||byte 3, byte 2||byte 2, byte 0||LOADIL|
All fields are 4 bits wide and X means 'dont care'. n is a 4 bit signed number, i.e can range from -8 to +7
The two offset bytes for the SETBRA instruction are a signed 16 but, big endian number.
Not all registers are general purpose, in fact because register 0 always contains 0 and register 1 always contains 1 we can do some clever tricks. Combined with the implied addition of the registers indicated in fields R1 and R1 (in format 1) we can for example increment any register.
MOVE r5,r5,r1 would add 1 to the value in register 5 and store the result in r5 again.
Also, because register 15 is the program counter (PC) we could jump to an address with
The full list of registers is shown below
|0||zero||value always 0|
|1||one||value always 1|
|2||r2/arg1||general purpose||arg 1|
|3||r3/arg2||general purpose||arg 2|
|4||r4/index||general purpose||index in frame|
|5 - 6||r5 - r10||general purpose|
|11||r11/link||general purpose||return address|
|12||r12/frame||general purpose||frame pointer|
|13||flags||flags (bits[31:29]) and alu op (bits[7:0])|
|14||sp||stack pointer (SP)|
|15||pc||program counter (PC)|
Register 0 and 1 have a fixed value and the register 13 (flags) always has bit 31 fixed to 1. Bits 30 and 29 are the negative and zero flags respectively. The lower 8 bits hold the operation used by the ALU instruction.
Register 14 (SP) is used by the POP and PUSH instructions and register 15 (PC) is the program counter. The program counter can be assigned to directly but is normally manipulated by the JAL and SETBRA instructions.
In the C-compiler some of the registers have additional designations, those are indicated in the ABI columns.