MIPS ISA

The Opcode enum organizes MIPS instructions into several functional categories, each serving a specific role in the instruction set:

#![allow(unused)]
fn main() {
pub enum Opcode {
    // ALU
    ADD = 0,         // ADDSUB
    SUB = 1,         // ADDSUB
    MULT = 2,        // MUL
    MULTU = 3,       // MUL
    MUL = 4,         // MUL
    DIV = 5,         // DIVREM
    DIVU = 6,        // DIVREM
    SLL = 7,         // SLL
    SRL = 8,         // SR
    SRA = 9,         // SR
    ROR = 10,        // SR
    SLT = 11,        // LT
    SLTU = 12,       // LT
    AND = 13,        // BITWISE
    OR = 14,         // BITWISE
    XOR = 15,        // BITWISE
    NOR = 16,        // BITWISE
    CLZ = 17,        // CLO_CLZ
    CLO = 18,        // CLO_CLZ
    // Control Flow
    BEQ = 19,        // BRANCH
    BGEZ = 20,       // BRANCH
    BGTZ = 21,       // BRANCH
    BLEZ = 22,       // BRANCH
    BLTZ = 23,       // BRANCH
    BNE = 24,        // BRANCH
    Jump = 25,       // JUMP
    Jumpi = 26,      // JUMP
    JumpDirect = 27, // JUMP
    // Memory Op
    LB = 28,         // LOAD
    LBU = 29,        // LOAD
    LH = 30,         // LOAD
    LHU = 31,        // LOAD
    LW = 32,         // LOAD
    LWL = 33,        // LOAD
    LWR = 34,        // LOAD
    LL = 35,         // LOAD
    SB = 36,         // STORE
    SH = 37,         // STORE
    SW = 38,         // STORE
    SWL = 39,        // STORE
    SWR = 40,        // STORE
    SC = 41,         // STORE
    // Syscall
    SYSCALL = 42,    // SYSCALL
    // Misc
    MEQ = 43,        // MOVCOND
    MNE = 44,        // MOVCOND
    TEQ = 45,        // MOVCOND
    SEXT = 46,       // SEXT
    WSBH = 47,       // MISC
    EXT = 48,        // EXT
    MADDU = 49,      // MADDSUB
    MSUBU = 50,      // MADDSUB
    INS = 51,        // INS
    UNIMPL = 0xff,
}
}

All MIPS instructions can be divided into the following taxonomies:

ALU Operators
This category includes the fundamental arithmetic logical operations and count operations. It covers addition (ADD) and subtraction (SUB), several multiplication and division variants (MULT, MULTU, MUL, DIV, DIVU), as well as bit shifting and rotation operations (SLL, SRL, SRA, ROR), comparison operations like set less than (SLT, SLTU) a range of bitwise logical operations (AND, OR, XOR, NOR) and count operations like CLZ counts the number of leading zeros, while CLO counts the number of leading ones. These operations are useful in bit-level data analysis.

Memory Operations
This category is dedicated to moving data between memory and registers. It contains a comprehensive set of load instructions—such as LH (load halfword), LWL (load word left), LW (load word), LB (load byte), LBU (load byte unsigned), LHU (load halfword unsigned), LWR (load word right), and LL (load linked)—as well as corresponding store instructions like SB (store byte), SH (store halfword), SWL (store word left), SW (store word), SWR (store word right), and SC (store conditional). These operations ensure that data is correctly and efficiently read from or written to memory.

Branching Instructions
Instructions BEQ (branch if equal), BGEZ (branch if greater than or equal to zero), BGTZ (branch if greater than zero), BLEZ (branch if less than or equal to zero), BLTZ (branch if less than zero), and BNE (branch if not equal) are used to change the flow of execution based on comparisons. These instructions are vital for implementing loops, conditionals, and other control structures.

Jump Instructions
Jump-related instructions, including Jump, Jumpi, and JumpDirect, are responsible for altering the execution flow by redirecting it to different parts of the program. They are used for implementing function calls, loops, and other control structures that require non-sequential execution, ensuring that the program can navigate its code dynamically.

Syscall Instructions
SYSCALL triggers a system call, allowing the program to request services from the zkvm operating system. The service can be a precompiles computation, such as do sha extend operation by SHA_EXTEND precompile. it also can be input/output operation such as SYSHINTREADYSHINTREAD and WRITE.

Misc Instructions
This category includes other instructions. TEQ is typically used to test equality conditions between registers. MADDU/MSUBU is used for multiply accumulation. SEB/SEH is for data sign extended. EXT/INS is for bits extraction and insertion.

Supported instructions

The support instructions are as follows:

instructionOp [31:26]rs [25:21]rt [20:16]rd [15:11]shamt [10:6]func [5:0]function
ADD000000rsrtrd00000100000rd = rs + rt
ADDI001000rsrtimmimmimmrt = rs + sext(imm)
ADDIU001001rsrtimmimmimmrt = rs + sext(imm)
ADDU000000rsrtrd00000100001rd = rs + rt
AND000000rsrtrd00000100100rd = rs & rt
ANDI001100rsrtimmimmimmrt = rs & zext(imm)
BEQ000100rsrtoffsetoffsetoffsetPC = PC + sext(offset<<2), if rs == rt
BGEZ000001rs00001offsetoffsetoffsetPC = PC + sext(offset<<2), if rs >= 0
BGTZ000111rs00000offsetoffsetoffsetPC = PC + sext(offset<<2), if rs > 0
BLEZ000110rs00000offsetoffsetoffsetPC = PC + sext(offset<<2), if rs <= 0
BLTZ000001rs00000offsetoffsetoffsetPC = PC + sext(offset<<2), if rs < 0
BNE000101rsrtoffsetoffsetoffsetPC = PC + sext(offset<<2), if rs != rt
CLO011100rsrtrd00000100001rd = count_leading_ones(rs)
CLZ011100rsrtrd00000100000rd = count_leading_zeros(rs)
DIV000000rsrt0000000000011010(hi, lo) = (rs%rt, rs/ rt), signed
DIVU000000rsrt0000000000011011(hi, lo) = (rs%rt, rs/rt), unsigned
J000010instr_indexinstr_indexinstr_indexinstr_indexinstr_indexPC = PC[GPRLEN-1..28] || instr_index || 00
JAL000011instr_indexinstr_indexinstr_indexinstr_indexinstr_indexr31 = PC + 8, PC = PC[GPRLEN-1..28] || instr_index || 00
JALR000000rs00000rdhint001001rd = PC + 8, PC = rs
JR000000rs0000000000hint001000PC = rs
LB100000basertoffsetoffsetoffsetrt = sext(mem_byte(base + offset))
LBU100100basertoffsetoffsetoffsetrt = zext(mem_byte(base + offset))
LH100001basertoffsetoffsetoffsetrt = sext(mem_halfword(base + offset))
LHU100101basertoffsetoffsetoffsetrt = zext(mem_halfword(base + offset))
LL110000basertoffsetoffsetoffsetrt = mem_word(base + offset)
LUI00111100000rtimmimmimmrt = imm<<16
LW100011basertoffsetoffsetoffsetrt = mem_word(base + offset)
LWL100010basertoffsetoffsetoffsetrt = rt merge most significant part of mem(base+offset)
LWR100110basertoffsetoffsetoffsetrt = rt merge least significant part of mem(base+offset)
MFHI0000000000000000rd00000010000rd = hi
MFLO0000000000000000rd00000010010rd = lo
MOVN000000rsrtrd00000001011rd = rs, if rt != 0
MOVZ000000rsrtrd00000001010rd = rs, if rt == 0
MTHI000000rs000000000000000010001hi = rs
MTLO000000rs000000000000000010011lo = rs
MUL011100rsrtrd00000000010rd = rs * rt
MULT000000rsrt0000000000011000(hi, lo) = rs * rt
MULTU000000rsrt0000000000011001(hi, lo) = rs * rt
NOR000000rsrtrd00000100111rd = !rs | rt
OR000000rsrtrd00000100101rd = rs | rt
ORI001101rsrtimmimmimmrd = rs | zext(imm)
SB101000basertoffsetoffsetoffsetmem_byte(base + offset) = rt
SC111000basertoffsetoffsetoffsetmem_word(base + offset) = rt, rt = 1, if atomic update, else rt = 0
SH101001basertoffsetoffsetoffsetmem_halfword(base + offset) = rt
SLL00000000000rtrdsa000000rd = rt<<sa
SLLV000000rsrtrd00000000100rd = rt << rs[4:0]
SLT000000rsrtrd00000101010rd = rs < rt
SLTI001010rsrtimmimmimmrt = rs < sext(imm)
SLTIU001011rsrtimmimmimmrt = rs < sext(imm)
SLTU000000rsrtrd00000101011rd = rs < rt
SRA00000000000rtrdsa000011rd = rt >> sa
SRAV000000rsrtrd00000000111rd = rt >> rs[4:0]
SYNC000000000000000000000stype001111sync (nop)
SRL00000000000rtrdsa000010rd = rt >> sa
SRLV000000rsrtrd00000000110rd = rt >> rs[4:0]
SUB000000rsrtrd00000100010rd = rs - rt
SUBU000000rsrtrd00000100011rd = rs - rt
SW101011basertoffsetoffsetoffsetmem_word(base + offset) = rt
SWL101010basertoffsetoffsetoffsetstore most significant part of rt
SWR101110basertoffsetoffsetoffsetstore least significant part of rt
SYSCALL000000codecodecodecode001100syscall
XOR000000rsrtrd00000100110rd = rs ^ rt
XORI001110rsrtimmimmimmrd = rs ^ zext(imm)
BAL0000010000010001offsetoffsetoffsetRA = PC + 8, PC = PC + sign_extend(offset || 00)
SYNCI000001base11111offsetoffsetoffsetsync (nop)
PREF110011basehintoffsetoffsetoffsetprefetch(nop)
TEQ000000rsrtcodecode110100trap,if rs == rt
ROTR00000000001rtrdsa000010rd = rotate_right(rt, sa)
ROTRV000000rsrtrd00001000110rd = rotate_right(rt, rs[4:0])
WSBH01111100000rtrd00010100000rd = swaphalf(rt)
EXT011111rsrtmsbdlsb000000rt = rs[msbd+lsb..lsb]
SEH01111100000rtrd11000100000rd = signExtend(rt[15..0])
SEB01111100000rtrd10000100000rd = signExtend(rt[7..0])
INS011111rsrtmsblsb000100rt = rt[32:msb+1] || rs[msb+1-lsb : 0] || rt[lsb-1:0]
MADDU011100rsrt0000000000000001(hi, lo) = rs * rt + (hi,lo)
MSUBU011100rsrt0000000000000101(hi, lo) = (hi,lo) - rs * rt

Supported syscalls

syscall numberfunction
SYSHINTLEN = 0x00_00_00_F0,Return length of current input data.
SYSHINTREAD = 0x00_00_00_F1,Read current input data.
SYSVERIFY = 0x00_00_00_F2,Verify pre-compile program.
HALT = 0x00_00_00_00,Halts the program.
WRITE = 0x00_00_00_02,Write to the output buffer.
ENTER_UNCONSTRAINED = 0x00_00_00_03,Enter unconstrained block.
EXIT_UNCONSTRAINED = 0x00_00_00_04,Exit unconstrained block.
SHA_EXTEND = 0x00_30_01_05,Executes the SHA_EXTEND precompile.
SHA_COMPRESS = 0x00_01_01_06,Executes the SHA_COMPRESS precompile.
ED_ADD = 0x00_01_01_07,Executes the ED_ADD precompile.
ED_DECOMPRESS = 0x00_00_01_08,Executes the ED_DECOMPRESS precompile.
KECCAK_SPONGE = 0x00_01_01_09,Executes the KECCAK_SPONGE precompile.
SECP256K1_ADD = 0x00_01_01_0A,Executes the SECP256K1_ADD precompile.
SECP256K1_DOUBLE = 0x00_00_01_0B,Executes the SECP256K1_DOUBLE precompile.
SECP256K1_DECOMPRESS = 0x00_00_01_0C,Executes the SECP256K1_DECOMPRESS precompile.
BN254_ADD = 0x00_01_01_0E,Executes the BN254_ADD precompile.
BN254_DOUBLE = 0x00_00_01_0F,Executes the BN254_DOUBLE precompile.
COMMIT = 0x00_00_00_10,Executes the COMMIT precompile.
COMMIT_DEFERRED_PROOFS = 0x00_00_00_1A,Executes the COMMIT_DEFERRED_PROOFS precompile.
VERIFY_ZKM_PROOF = 0x00_00_00_1B,Executes the VERIFY_ZKM_PROOF precompile.
BLS12381_DECOMPRESS = 0x00_00_01_1C,Executes the BLS12381_DECOMPRESS precompile.
UINT256_MUL = 0x00_01_01_1D,Executes the UINT256_MUL precompile.
U256XU2048_MUL = 0x00_01_01_2F,Executes the U256XU2048_MUL precompile.
BLS12381_ADD = 0x00_01_01_1E,Executes the BLS12381_ADD precompile.
BLS12381_DOUBLE = 0x00_00_01_1F,Executes the BLS12381_DOUBLE precompile.
BLS12381_FP_ADD = 0x00_01_01_20,Executes the BLS12381_FP_ADD precompile.
BLS12381_FP_SUB = 0x00_01_01_21,Executes the BLS12381_FP_SUB precompile.
BLS12381_FP_MUL = 0x00_01_01_22,Executes the BLS12381_FP_MUL precompile.
BLS12381_FP2_ADD = 0x00_01_01_23,Executes the BLS12381_FP2_ADD precompile.
BLS12381_FP2_SUB = 0x00_01_01_24,Executes the BLS12381_FP2_SUB precompile.
BLS12381_FP2_MUL = 0x00_01_01_25,Executes the BLS12381_FP2_MUL precompile.
BN254_FP_ADD = 0x00_01_01_26,Executes the BN254_FP_ADD precompile.
BN254_FP_SUB = 0x00_01_01_27,Executes the BN254_FP_SUB precompile.
BN254_FP_MUL = 0x00_01_01_28,Executes the BN254_FP_MUL precompile.
BN254_FP2_ADD = 0x00_01_01_29,Executes the BN254_FP2_ADD precompile.
BN254_FP2_SUB = 0x00_01_01_2A,Executes the BN254_FP2_SUB precompile.
BN254_FP2_MUL = 0x00_01_01_2B,Executes the BN254_FP2_MUL precompile.
SECP256R1_ADD = 0x00_01_01_2C,Executes the SECP256R1_ADD precompile.
SECP256R1_DOUBLE = 0x00_00_01_2D,Executes the SECP256R1_DOUBLE precompile.
SECP256R1_DECOMPRESS = 0x00_00_01_2E,Executes the SECP256R1_DECOMPRESS precompile.