Skip to content

ISA Reference

Alex edited this page Aug 22, 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 M is set:

Rd = Rx + Ry + 1

The result wraps modulo 65536.

Carry is updated according to the arithmetic result.


SUB

Opcode:

0x2000

Semantics:

Rd = Rx - Ry

If M is set:

Rd = Rx - Ry - 1

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.


Return

RET

Opcode:

0xE000

RET pops the next entry from the hardware return-address buffer.

The saved ProgramEAM and PC are restored.

RET does not modify JR.

RET does not modify interrupt state.

The return-address buffer is strictly LIFO.


Interrupt Return

IRET

IRET restores the PC/PB state saved by interrupt entry.

IRET does not access the CAL/RET return-address buffer.

IRET does not restore GPRs or Carry.

IRET unmasks interrupts.


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.

Clone this wiki locally