Instruction Set Architecture (ISA)

Sparsr Instruction Set Architecture (ISA)

The Sparsr Processor is a 5-stage pipelined core built on the 32-bit MIPS I instruction set, extended with custom 4096-bit Wide Instructions for parallel bitwise execution and Co-processor Memory (CMem) transfers.

This page lists every instruction that is either part of standard MIPS I or defined by Sparsr, and tracks — instruction by instruction — whether it is implemented in the Software Emulator backend (softemu) and/or in real Hardware (the Verilog Controller.v). The two don't always match: some instructions exist only for the software emulator, some hardware opcodes are reserved but not yet wired up, and most of classic MIPS I (branches, jumps, shifts, multiply/divide) isn't implemented by either.

Sources of truth used to build this table:

  • Hardware — the Verilog instruction decoder (Controller.v) and its case statement.
  • Software Emulator — the softemu backend of the Sparsr host runtime.
  • Assemblerspasm, which must be able to encode an instruction before it can run anywhere.

Register Layout

Register Type Registers Width Description
Scalar Registers $0$31 32-bit Standard MIPS general-purpose registers ($zero, $t0$t9, $s0$s7, $a0$a3, $v0$v1, $gp, $sp, $ra).
Wide Registers $wA$wB 4096-bit Ultra-wide registers used for 4096-bit bitwise operations and CMem payloads.
Data Memory (DMem) Standard RAM 32-bit Accessed via standard MIPS scalar loads/stores.
Compressed Memory (CMem) Block RAM (BRAM) 4096-bit High-speed storage accessed via wide instructions (WL, WS, WLR, WSR). Compression/decompression happens automatically inside these instructions — there is no separate compress/decompress opcode.

Instruction Formats

All instructions are encoded into 32-bit words. opcode is always the top 6 bits.

Format Layout Used by
R-Type opcode(6) · rs(5) · rt(5) · rd(5) · shamt(5) · funct(6) Register-register ALU ops
I-Type opcode(6) · rs(5) · rt(5) · immediate(16) Register-immediate ALU ops, LW/SW
J-Type opcode(6) · address(26) Jumps (reserved by MIPS I; unused by Sparsr)
WR-Type (Wide Register) opcode(6) · reserved(2) · wrs(8) · wrt(8) · wrd(8) WAND, WOR, WXOR, WADD, WSUB
WI-Type (Wide Immediate) opcode(6) · reserved(2) · wrd(8) · addr(16, BRAM offset) WL, WS, WLR, WSR
Halt All 1s (0xFFFFFFFF) Program terminator — both the assembler and softemu recognize this exact word as "stop execution".
 31      26 25      21 20      16 15      11 10       6 5        0
+----------+----------+----------+----------+----------+----------+
|  opcode  |    rs    |    rt    |    rd    |  shamt   |  funct   |  R-Type
+----------+----------+----------+----------+----------+----------+
|  opcode  |    rs    |    rt    |        immediate (16)          |  I-Type
+----------+----------+----------+----------+----------+----------+
|  opcode  |                    address (26)                      |  J-Type
+----------+----------+------------------------------------------------------+

 31      26 25      24 23              16 15               8 7              0
+----------+----------+------------------+------------------+------------------+
|  opcode  | reserved |     wrs (8)      |     wrt (8)      |     wrd (8)      |  WR-Type
+----------+----------+------------------+------------------+------------------+
|  opcode  | reserved |     wrd (8)      |        addr / BRAM offset (16)     |  WI-Type
+----------+----------+------------------+------------------+------------------+
|  1111111111111111111111111111111111111111111111111111111111111111111111  | Halt
+----------+----------+------------------+------------------+------------------+

The assembler automatically appends a NOP (0x00000000) followed by a Halt word (0xFFFFFFFF) to the end of every assembled program — you don't write these yourself.


Instruction Support Table

supported · ⚠️ opcode reserved/decoded but not fully wired · not implemented · not applicable

Sparsr Wide Instructions (4096-bit, CMem)

Mnemonic Name Format Opcode Softemu Hardware Notes
WAND Wide AND WR 18 Bitwise AND of $wrs/$wrt$wrd.
WOR Wide OR WR 19 Bitwise OR of $wrs/$wrt$wrd.
WXOR Wide XOR WR 20 Bitwise XOR of $wrs/$wrt$wrd.
WL Wide Load WI 21 Loads 4096 bits from CMem[addr] into $wrd, decompressing automatically.
WS Wide Store WI 22 Stores $wrd to CMem[addr], compressing automatically.
WADD Wide Add WR 23 ⚠️ Decoded but does not compute — see note below. Not encodable by the assembler, not executed by softemu.
WSUB Wide Subtract WR 24 ⚠️ Decoded but does not compute — see note below. Not encodable by the assembler, not executed by softemu.
WLR Wide Load, Register-indirect WI 23 Softemu-only extension (not in Controller.v); see note below. Not implemented in hardware yet.
WSR Wide Store, Register-indirect WI 24 Softemu-only extension (not in Controller.v); see note below. Not implemented in hardware yet.

Opcode 23/24 overlap: WADD/WSUB (hardware wide register-register add/subtract) and WLR/WSR (softemu register-indirect wide load/store) both use opcodes 23 and 24, but they're mutually exclusive extensions of the base ISA — hardware never implements WLR/WSR, and softemu never implements WADD/WSUB. Don't assume opcode 23/24 means the same thing on both backends.

WLR/WSR use the same $d,offset($t) shape as LW/SW, except $t holds a runtime CMem base address instead of the address coming from a fixed instruction immediate — mirroring the register-indirect addressing regular LW/SW already have. They exist purely to give torchhd-sparsr runtime-selectable CMem addressing.

WADD/WSUB are incomplete in hardware. Controller.v decodes both opcodes and enables wide write-back, but the corresponding cases in the wide ALU (Wide_ALU.v) are commented out, so execution falls through to the default branch and writes all zeros into the destination wide register — silently, with no trap. Treat them as unimplemented.

This is not simply a matter of uncommenting those lines. The wide unit is built as 128 independent 32-bit lanes with no signal crossing lane boundaries — which is exactly what makes the 4096-bit logical operations cheap — so the commented code would produce 128 separate 32-bit adds rather than one 4096-bit add. Wide arithmetic needs a carry chain the current design does not have.

MIPS I Standard Instructions

Mnemonic Name Format Opcode Funct Softemu Hardware Notes
ADD Add R 0 32
ADDU Add Unsigned R 0 33 Softemu/hardware treat identically to ADD (no trap on overflow).
SUB Subtract R 0 34
SUBU Subtract Unsigned R 0 35 Softemu/hardware treat identically to SUB.
AND Bitwise AND R 0 36
OR Bitwise OR R 0 37
XOR Bitwise XOR R 0 38
NOR Bitwise NOR R 0 39
SLT Set on Less Than R 0 42 Opcode/funct not referenced by Controller.v's decode case.
SLTU Set on Less Than Unsigned R 0 43 Same as above.
LW Load Word I 35
SW Store Word I 43
ADDI Add Immediate I 8 ⚠️ Decoded by Controller.v; assembler has no mnemonic for it, so it's unreachable in practice.
ADDIU Add Immediate Unsigned I 9 ⚠️ Same as ADDI.
SUBI Subtract Immediate I 16 ⚠️ Non-standard MIPS I opcode added locally; same gap as ADDI.
ANDI AND Immediate I 12 ⚠️ Same as ADDI.
ORI OR Immediate I 13 ⚠️ Same as ADDI.
XORI XOR Immediate I 14 ⚠️ Same as ADDI.
SLTI Set Less Than Immediate I 10 Opcode constant exists but is not referenced by Controller.v's decode case.
SLTIU Set Less Than Immediate Unsigned I 11 Same as above.
LUI Load Upper Immediate I 15 Same as above.
LB Load Byte I 32
LBU Load Byte Unsigned I 36
LH Load Halfword I 33
LHU Load Halfword Unsigned I 37
LWL Load Word Left I 34
LWR Load Word Right I 38
SB Store Byte I 40
SH Store Halfword I 41
SWL Store Word Left I 42
SWR Store Word Right I 46
SLL Shift Left Logical R 0 0
SRL Shift Right Logical R 0 2
SRA Shift Right Arithmetic R 0 3
SLLV Shift Left Logical Variable R 0 4
SRLV Shift Right Logical Variable R 0 6
SRAV Shift Right Arithmetic Variable R 0 7
MULT Multiply R 0 24
MULTU Multiply Unsigned R 0 25
DIV Divide R 0 26
DIVU Divide Unsigned R 0 27
MFHI Move From HI R 0 16
MTHI Move To HI R 0 17
MFLO Move From LO R 0 18
MTLO Move To LO R 0 19
J Jump J 2
JAL Jump and Link J 3
JR Jump Register R 0 8 ⚠️ Softemu special-cases the literal word for jr $ra only, as an end-of-program halt marker — not a general jump.
JALR Jump and Link Register R 0 9
BEQ Branch on Equal I 4
BNE Branch on Not Equal I 5
BLEZ Branch on ≤ Zero I 6
BGTZ Branch on > Zero I 7
BLTZ Branch on < Zero I (rt=0) 1
BGEZ Branch on ≥ Zero I (rt=1) 1
BLTZAL Branch on < Zero and Link I (rt=16) 1
BGEZAL Branch on ≥ Zero and Link I (rt=17) 1
SYSCALL System Call R 0 12
BREAK Breakpoint R 0 13
NOP No Operation All-zero instruction word; softemu treats it as a no-op rather than dispatching it as an opcode.

Coprocessor instructions (LWC*, SWC*, MFC*, MTC*, CFC*, CTC*) are part of MIPS I but aren't listed here — Sparsr's wide unit is a fixed-function extension, not a MIPS coprocessor interface, so these encodings don't apply to it.


Assembly Example

WL $t1,1
WL $t2,2
WAND $t3,$t1,$t2
WOR $t4,$t1,$t2
WXOR $t5,$t1,$t2
WS $t3,3
WS $t4,4
WS $t5,5