Skip to content

ISA Reference

Alex edited this page Aug 25, 2026 · 9 revisions

ISA Reference

Common execution model

For every instruction:

  1. CPU fetches the instruction word from ProgramEAM:PC.
  2. Instruction is decoded.
  3. Encoded immediate words are fetched, in order:
    • Immediate X
    • Immediate Y
  4. The instruction executes.
  5. 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.


EAM.SET

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.


IVR.SET

Opcode:

0x0800

Semantics:

IVR = Rx

The bank portion of IVR is limited to the implemented bank width.


Arithmetic Instructions

ADD

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.


SUB

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.


Logical Instructions

AND

Opcode:

0x3000

M=0: Rd = Rx & Ry
M=1: Rd = Rx & ~Ry

Carry is unchanged.


OR

Opcode:

0x4000

M=0: Rd = Rx | Ry
M=1: Rd = Rx | ~Ry

Carry is unchanged.


NOT

Opcode:

0x5000

M=0: Rd = ~Rx
M=1: Rd = two's-complement negation of Rx

Carry is unchanged.


XOR

Opcode:

0x6000

M=0: Rd = Rx ^ Ry
M=1: Rd = Rx ^ ~Ry

Carry is unchanged.


Shift Instructions

SHL

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.


SHR

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.


Memory Instructions

LDM

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.


STM

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.


Jump Register

STJ

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.

Branch Instructions

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.

Signed

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.

Unsigned

JLT.U JEQ.U JLE.U JGT.U JNE.U JGE.U

These perform the corresponding unsigned comparison.

JMP

Opcode:

0xC700

Semantics:

PC/PB = JR

JR is unchanged.

Call

CAL

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.


RET / RETI

Opcode: 1110

The M bit selects between normal subroutine return and interrupt return.

M = 0 — RET

  1. Pop the top entry from the CAL/RET return-address stack.
  2. Restore ProgramEAM and PC from that entry.

M = 1 — RETI

  1. Pop the top entry from the CAL/RET return-address stack.
  2. Discard the popped value.
  3. Restore ProgramEAM and PC from the interrupt-saved state.
  4. Clear the interrupt mask.
  5. 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.

Halt

HLT

Opcode:

0xF000

CPU enters the halted state.

Wake/resume behavior is implementation-defined.


NIL

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.