-
Notifications
You must be signed in to change notification settings - Fork 0
ISA Reference
For every instruction:
- CPU fetches the instruction word from
ProgramEAM:PC. - Instruction is decoded.
- Encoded immediate words are fetched, in order:
- Immediate X
- Immediate Y
- The instruction executes.
- PC advances according to the instruction's architectural semantics.
Immediate fetch occurs before any architectural EAM modification caused by the instruction.
Instruction width is determined by the encoded LX/LY fields. Additional words are fetched even when their values are architecturally irrelevant.
All instruction encodings are architecturally defined. There are no illegal opcode encodings or invalid operand combinations.
Fields explicitly designated as don't-care have no architectural meaning.
If a branch is not taken, normal sequential PC advancement occurs.
Opcode:
0x0000
Semantics:
EAM = Rx
EAM is currently 11 bits. Values supplied to EAM.SET are masked to the implemented EAM width.
Bits outside the implemented width do not cause an exception.
Opcode:
0x0800
Semantics:
IVR = Rx
The bank portion of IVR is limited to the implemented bank width.
Opcode:
0x1000
Semantics:
Rd = Rx + Ry
if the operation overflows, the carry flag is set, the carry latch is set (1), otherwise it is cleared (0).
NOTE: Carry has no bearing at all on branching.
If M is set:
Rd = Rx + Ry + Carry
The result wraps modulo 65536.
Carry is updated according to the arithmetic result.
Opcode:
0x2000
Semantics:
Rd = Rx - Ry
if the operation underflowed, carry is set (1), otherwise it is cleared (0). NOTE: Carry has no direct bearing on branching
If M is set:
Rd = Rx - Ry - Carry
The result wraps modulo 65536.
Carry is updated according to the arithmetic result.
Opcode:
0x3000
M=0: Rd = Rx & Ry
M=1: Rd = Rx & ~Ry
Carry is unchanged.
Opcode:
0x4000
M=0: Rd = Rx | Ry
M=1: Rd = Rx | ~Ry
Carry is unchanged.
Opcode:
0x5000
M=0: Rd = ~Rx
M=1: Rd = two's-complement negation of Rx
Carry is unchanged.
Opcode:
0x6000
M=0: Rd = Rx ^ Ry
M=1: Rd = Rx ^ ~Ry
Carry is unchanged.
Opcode:
0x7000
Shift amount:
Y[3:0]
M=0:
Rd = Rx << amount
M=1:
Rd = rotate-left(Rx, amount)
For SHL, a shift operation updates Carry with the last bit shifted out.
A zero-count shift leaves the operand unchanged but clears Carry.
Rotates do not modify Carry.
Opcode:
0x8000
Shift amount:
Y[3:0]
M=0:
Rd = Rx >> amount
The shift is logical.
M=1:
Rd = rotate-right(Rx, amount)
For SHR, a shift operation updates Carry with the last bit shifted out.
A zero-count shift leaves the operand unchanged but clears Carry.
Rotates do not modify Carry.
Opcode:
0x9000
Format:
LDM Rd, Address
Effective address:
EA = DataEAM : Address
If Address is a register, its value is sampled before the instruction modifies architectural state.
Read:
Rd = Memory[EA]
If M is set and Address is a register:
Address = Address + 1
The increment occurs after the memory read.
The increment is performed on the 16-bit address register only. Overflow wraps from FFFF to 0000 and does not increment DataEAM.
Peripheral reads may have device-defined side effects.
Opcode:
0xA000
Format:
STM Address, Rx
The effective address and source value are obtained from the pre-instruction state.
Write:
Memory[DataEAM : Address] = Rx
If M is set and Address is a register:
Address = Address + 1
The increment occurs after the memory write.
The increment is performed on the 16-bit address register only. Overflow wraps from FFFF to 0000 and does not increment DataEAM.
Writes to ROM are ignored.
Peripheral writes may have device-defined side effects.
Opcode:
0xB000
Semantics:
JR = Rx
Only JR is modified.
STJ does not modify PC.
JR is persistent until overwritten.
Jump instructions consume the value of JR but do not modify it.
Branches compare their operands directly.
Signed comparisons interpret operands as signed 16-bit two's-complement values.
Unsigned comparisons interpret operands as uint16_t.
Equality and inequality produce the same result in signed and unsigned forms.
JLT JEQ JLE JGT JNE JGE
A taken conditional branch loads PC/PB from JR.
A not-taken branch proceeds normally.
JR is not modified.
JLT.U JEQ.U JLE.U JGT.U JNE.U JGE.U
These perform the corresponding unsigned comparison.
Opcode:
0xC700
Semantics:
PC/PB = JR
JR is unchanged.
Opcode:
0xD000
CAL pushes a return address onto the hardware return-address buffer.
The saved return address is:
saved PC = PC + LX + LY + 1
saved PB = current ProgramEAM
The saved PC is therefore the address of the next instruction.
The target PC is loaded from X.
If M is clear:
ProgramEAM = DataEAM
If M is set:
ProgramEAM is unchanged
JR is unchanged.
The hardware return-address buffer is independent of interrupt state.
The architecture guarantees a minimum of 256 entries.
Behavior beyond the guaranteed implementation capacity is outside the architectural guarantee.
Opcode: 1110
The M bit selects between normal subroutine return and interrupt return.
- Pop the top entry from the CAL/RET return-address stack.
- Restore ProgramEAM and PC from that entry.
- Pop the top entry from the CAL/RET return-address stack.
- Discard the popped value.
- Restore ProgramEAM and PC from the interrupt-saved state.
- Clear the interrupt mask.
- Clear the active-interrupt state.
Interrupt entry itself does not push an entry onto the CAL/RET return-address stack. RETI nevertheless consumes one existing stack entry as part of its defined operation.
RETI therefore requires a valid CAL/RET stack entry as well as an active interrupt state.
Opcode:
0xF000
CPU enters the halted state.
Wake/resume behavior is implementation-defined.
Opcode:
0xC000
NIL performs no architectural operation other than normal instruction completion and PC advancement.
NIL may contain encoded immediate words according to LX/LY, and those words are still fetched.