Skip to content

CPU Opcode Reference

This page lists the MIPS Allegrex instructions the interpreter implements, grouped by category. It is derived from the dispatch in src/cpu/executor.ts, the opcode constants in src/cpu/opcodes.ts, and the field decode in src/cpu/decoder.ts. Anything not listed here is treated as a NOP or throws "Unimplemented" at run time.

A few interpreter-wide notes:

  • Branch delay slots. Every branch and jump takes effect after the following instruction runs. The interpreter schedules this with inDelaySlot / delaySlotTarget and never stops between an instruction and its delay slot.
  • Branch-likely variants (the *L forms) skip the delay-slot instruction when the branch is not taken.
  • No overflow traps. ADD/ADDI/SUB do not raise the MIPS overflow exception; they behave like their unsigned counterparts.
  • SYSCALL sets cpu.pendingSyscall and cpu.step() dispatches it into the HLE kernel (see Syscall Flow).

Arithmetic and logic (register)

These are SPECIAL (op 0x00) R-type instructions.

MnemonicFunctDescription
ADD0x20rd = rs + rt (overflow ignored)
ADDU0x21rd = rs + rt
SUB0x22rd = rs - rt (overflow ignored)
SUBU0x23rd = rs - rt
AND0x24rd = rs & rt
OR0x25rd = rs | rt
XOR0x26rd = rs ^ rt
NOR0x27rd = ~(rs | rt)
SLT0x2ard = (rs < rt) ? 1 : 0, signed
SLTU0x2brd = (rs < rt) ? 1 : 0, unsigned
MAX0x2crd = max(rs, rt), signed (Allegrex)
MIN0x2drd = min(rs, rt), signed (Allegrex)
MOVZ0x0aif (rt == 0) rd = rs
MOVN0x0bif (rt != 0) rd = rs

Arithmetic and logic (immediate)

I-type instructions with their own primary opcode.

MnemonicOpDescription
ADDI0x08rt = rs + sign_ext(imm) (overflow ignored)
ADDIU0x09rt = rs + sign_ext(imm)
SLTI0x0art = (rs < sign_ext(imm)) ? 1 : 0, signed
SLTIU0x0brt = (rs < imm) ? 1 : 0, unsigned
ANDI0x0crt = rs & zero_ext(imm)
ORI0x0drt = rs | zero_ext(imm)
XORI0x0ert = rs ^ zero_ext(imm)
LUI0x0frt = imm << 16

Shifts

SPECIAL R-type. The Allegrex reuses the SRL/SRLV encodings for rotates, selected by a bit in the rs/shamt field.

MnemonicFunctDescription
SLL0x00rd = rt << shamt
SRL0x02rd = rt >>> shamt (logical)
ROTR0x02rotate right by shamt (when rs & 1)
SRA0x03rd = rt >> shamt (arithmetic)
SLLV0x04rd = rt << (rs & 31)
SRLV0x06rd = rt >>> (rs & 31)
ROTRV0x06rotate right by rs & 31 (when shamt & 1)
SRAV0x07rd = rt >> (rs & 31) (arithmetic)

Multiply, divide, and HI/LO

SPECIAL R-type. Results land in the hi/lo registers. The Allegrex keeps the multiply-accumulate forms here (not in SPECIAL2).

MnemonicFunctDescription
MULT0x18signed hi:lo = rs * rt
MULTU0x19unsigned hi:lo = rs * rt
DIV0x1asigned lo = rs / rt, hi = rs % rt
DIVU0x1bunsigned lo = rs / rt, hi = rs % rt
MADD0x1csigned hi:lo += rs * rt (Allegrex)
MADDU0x1dunsigned hi:lo += rs * rt (Allegrex)
MSUB0x2esigned hi:lo -= rs * rt (Allegrex)
MSUBU0x2funsigned hi:lo -= rs * rt (Allegrex)
MFHI0x10rd = hi
MTHI0x11hi = rs
MFLO0x12rd = lo
MTLO0x13lo = rs

Bit manipulation

CLZ/CLO live in SPECIAL on the Allegrex; the rest are SPECIAL3 (op 0x1f), where SEB/SEH/WSBH/WSBW/BITREV are selected by the shamt field.

MnemonicDescription
CLZcount leading zeros of rs into rd
CLOcount leading ones of rs into rd
EXTextract a bit field from rs into rt
INSinsert a bit field from rs into rt
SEBsign-extend the low byte
SEHsign-extend the low halfword
WSBHswap bytes within each halfword
WSBWreverse all four bytes of the word
BITREVreverse the 32 bits
RDHWRread hardware register (only ULR/reg 29 is meaningful)

Loads and stores

MnemonicOpDescription
LB0x20load byte, sign-extended
LH0x21load halfword, sign-extended
LW0x23load word
LBU0x24load byte, zero-extended
LHU0x25load halfword, zero-extended
SB0x28store byte
SH0x29store halfword
SW0x2bstore word
LWL0x22load word left (unaligned)
LWR0x26load word right (unaligned)
SWL0x2astore word left (unaligned)
SWR0x2estore word right (unaligned)
LL0x30load linked (behaves like LW here)
SC0x38store conditional (always succeeds, sets rt = 1)
CACHE0x2fcache control, NOP

Branches and jumps

MnemonicEncodingCondition
Jop 0x02unconditional jump
JALop 0x03jump and link (ra = pc + 8)
JRSPECIAL 0x08jump to rs
JALRSPECIAL 0x09jump to rs, link into rd
BEQop 0x04rs == rt
BNEop 0x05rs != rt
BLEZop 0x06rs <= 0
BGTZop 0x07rs > 0
BEQLop 0x14rs == rt (likely)
BNELop 0x15rs != rt (likely)
BLEZLop 0x16rs <= 0 (likely)
BGTZLop 0x17rs > 0 (likely)

REGIMM (op 0x01)

The branch condition is selected by the rt field. The AL forms link into ra.

MnemonicrtCondition
BLTZ0x00rs < 0
BGEZ0x01rs >= 0
BLTZL0x02rs < 0 (likely)
BGEZL0x03rs >= 0 (likely)
BLTZAL0x10rs < 0, link
BGEZAL0x11rs >= 0, link
BLTZALL0x12rs < 0, link (likely)
BGEZALL0x13rs >= 0, link (likely)

FPU (COP1)

Single-precision only. Moves and the branch use the rs field as the sub-opcode; the computational ops use the S (single) format with the funct field, and W (word) format for integer conversion.

MnemonicDescription
MFC1move FPR bits to GPR
MTC1move GPR bits to FPR
CFC1move from FPU control register (FCR31)
CTC1move to FPU control register (FCR31)
BC1branch on the FPU condition bit (true/false, with likely forms)
ADD.Sfd = fs + ft
SUB.Sfd = fs - ft
MUL.Sfd = fs * ft
DIV.Sfd = fs / ft
SQRT.Sfd = sqrt(fs)
ABS.Sfd = abs(fs)
MOV.Sfd = fs
NEG.Sfd = -fs
ROUND.W.Sconvert to int, round to nearest even
TRUNC.W.Sconvert to int, truncate
CEIL.W.Sconvert to int, toward +inf
FLOOR.W.Sconvert to int, toward -inf
CVT.W.Sconvert float to int using the FCR31 rounding mode
CVT.S.Wconvert int to float
C.cond.Scompare fs and ft, set the FPU condition bit (funct 0x30 to 0x3f)
LWC1load word into FPR
SWC1store word from FPR

The arithmetic ops apply the FCR31 rounding mode and flush-to-zero bit.

System control (COP0)

Only the registers the HLE kernel needs are modeled (Status = 12, Cause = 13, EPC = 14).

MnemonicDescription
MFC0move from a CP0 register (unhandled registers read 0)
MTC0move to a CP0 register
ERETreturn from exception (pc = EPC)

System and special

MnemonicEncodingDescription
SYSCALLSPECIAL 0x0cdispatch to the HLE kernel via the pending-syscall flag
BREAKSPECIAL 0x0dsoft exception; an onBreak handler can claim it (used by the GE callback trampoline)
SYNCSPECIAL 0x0fmemory barrier, NOP
HALT / MFIC / MTICSPECIAL2 (op 0x1c)interrupt-controller ops, all NOP under HLE

VFPU

The VFPU is a 128-register vector unit. Operands are single (S), pair (P), triple (T), or quad (Q), encoded in the instruction. Most ALU ops honor the operand prefixes (vpfxs/vpfxt/vpfxd), which swizzle, negate, take absolute value, substitute constants, and saturate or mask the result. The prefixes are consumed by the next VFPU op.

Load, store, and move

MnemonicDescription
LV.S / SV.Sload/store one VFPU scalar
LV.Q / SV.Qload/store an aligned quad
LVL.Q / LVR.Qunaligned quad load (left/right)
SVL.Q / SVR.Qunaligned quad store (left/right)
MFV / MTVmove a VFPU register to/from a GPR (COP2)
MFVC / MTVCmove a VFPU control register to/from a GPR

Arithmetic

MnemonicDescription
vadd / vsubelement-wise add / subtract
vdivelement-wise divide
vmulelement-wise multiply
vsclscale a vector by a scalar
vdotdot product into a scalar
vhdphomogeneous dot product (last source lane forced to 1)
vcrscross product (triple)
vdet2D determinant
vsbnscale by setting the exponent from an integer
vfad / vavghorizontal sum / average

Compare and select

MnemonicDescription
vcmpcompare lanes against a condition, set the VFPU condition code
vmin / vmaxelement-wise min / max
vscmpsign of s - t per lane
vsges >= t ? 1 : 0 per lane
vslts < t ? 1 : 0 per lane
vcmovconditional move on the condition code

Single-argument and transcendental

MnemonicDescription
vmov / vabs / vnegcopy / absolute value / negate
vidtidentity-row generator
vzero / vonefill with 0 / 1
vsat0 / vsat1saturate to [0, 1] / [-1, 1]
vrcp / vnrcpreciprocal / negated reciprocal
vrsqreciprocal square root
vsqrtsquare root
vsin / vcos / vnsinsine / cosine / negated sine (argument in quarter-turns)
vasinarcsine
vexp2 / vlog2 / vrexp2base-2 exponential / logarithm / reciprocal exponential
vcstload a named VFPU constant
vsgnsign of each lane
vocp / vsocpone's complement (1 - x) / saturated one's complement pairs

Conversions

MnemonicDescription
vf2in / vf2iz / vf2iu / vf2idfloat to int (round / toward zero / ceil / floor), with a scale
vi2fint to float, with a scale
vf2h / vh2ffloat to half / half to float
vuc2i / vc2i / vus2i / vs2iunpack unsigned/signed char and short to int
vi2uc / vi2c / vi2us / vi2spack int down to unsigned/signed char and short
vt4444 / vt5551 / vt5650pack to 16-bit color formats

Utility

MnemonicDescription
vsrt1 / vsrt2 / vsrt3 / vsrt4sorting-network min/max passes
vbfy1 / vbfy2butterfly add/subtract

Matrix

MnemonicDescription
vmmulmatrix multiply
vtfm / vhtfmmatrix-vector transform (homogeneous form forces the last coordinate to 1)
vmsclscale a matrix by a scalar
vmmovcopy a matrix
vmidtidentity matrix
vmzero / vmonematrix of 0 / 1
vcrsp3D cross product
vqmulquaternion multiply
vrotrotation-row generator from an angle

Prefixes and immediates

MnemonicDescription
vpfxs / vpfxt / vpfxdset the source/source/destination prefix for the next op
viim.sload a 16-bit signed integer immediate into a scalar
vfim.sload a half-float immediate into a scalar

VFPU branches

bvf / bvt / bvfl / bvtl branch on a selected bit of the VFPU condition code (false/true, with likely forms).

See CPU (Allegrex) for the fetch, decode, execute loop and the register file.