The MMIX Instruction Set#
Instructions in the MMIX architecture are always 32 bits wide. These bits are divided into four groups of 8 bits.
The opcode bits uniquely identify each instruction, while the other three groups specify the operands with which the instruction is to be executed.
When a general-purpose register `n is used as an operand, the corresponding bits are just the n in unsigned integer representation.
When a special register, it is represented in binary according to the following table:
| Special Register | Binary Representation |
|---|---|
rB | 0x00 |
rD | 0x01 |
rE | 0x02 |
rH | 0x03 |
rJ | 0x04 |
rM | 0x05 |
rR | 0x06 |
rBB | 0x07 |
rC | 0x08 |
rN | 0x09 |
r0 | 0x0A |
rS | 0x0B |
rI | 0x0C |
rT | 0x0D |
rTT | 0x0E |
rK | 0x0F |
rQ | 0x10 |
rU | 0x11 |
rV | 0x12 |
rG | 0x13 |
rL | 0x14 |
rA | 0x15 |
rF | 0x16 |
rP | 0x17 |
rW | 0x18 |
rX | 0x19 |
rY | 0x1A |
rZ | 0x1B |
rWW | 0x1C |
rXX | 0x1D |
rYY | 0x1E |
rZZ | 0x1F |
These representations overlap with those of general-purpose register. This ambiguity is resolved by allowing only certain registers, either general-purpose or special, to be used with a given instruction.
The instructions themselves and their representations can be found in the following table:
| 0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 | 0x7 | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x0 | TRAP | FCMP | FUN | FEQL | FADD | FIX | FSUB | FIXU | 0x0 |
| FLOT[I] | FLOTU[I] | SFLOT[I] | SFLOTU[I] | ||||||
| 0x1 | FMUL | FCMPE | FUNE | FEQLE | FDIV | FSQRT | FREM | FINT | 0x1 |
| MUL[I] | MULU[I] | DIV[I] | DIVU[I] | ||||||
| 0x2 | ADD[I] | ADDU[I] | SUB[I] | SUBU[I] | 0x2 | ||||
| 2ADDU[I] | 4ADDU[I] | 8ADDU[I] | 16ADDU[I] | ||||||
| 0x3 | CMP[I] | CMPU[I] | NEG[I] | NEGU[I] | 0x3 | ||||
| SL[I] | SLU[I] | SR[I] | SRU[I] | ||||||
| 0x4 | BN[B] | BZ[B] | BP[B] | BOD[B] | 0x4 | ||||
| BNN[B] | BNZ[B] | BNP[B] | BEV[B] | ||||||
| 0x5 | PBN[B] | PBZ[B] | PBP[B] | PBOD[B] | 0x5 | ||||
| PBNN[B] | PBNZ[B] | PBNP[B] | PBEV[B] | ||||||
| 0x6 | CSN[I] | CSZ[I] | CSP[I] | CSOD[I] | 0x6 | ||||
| CSNN[I] | CSNZ[I] | CSNP[I] | CSEV[I] | ||||||
| 0x7 | ZSN[I] | ZSZ[I] | ZSP[I] | ZSOD[I] | 0x7 | ||||
| ZSNN[I] | ZSNZ[I] | ZSNP[I] | ZSEV[I] | ||||||
| 0x8 | LDB[I] | LDBU[I] | LDW[I] | LDWU[I] | 0x8 | ||||
| LDT[I] | LDTU[I] | LDO[I] | LDOU[I] | ||||||
| 0x9 | LDSF[I] | LDHT[I] | CSWAP[I] | LDUNC[I] | 0x9 | ||||
| LDVTS[I] | PRELD[I] | PREGO[I] | GO[I] | ||||||
| 0xA | STB[I] | STBU[I] | STW[I] | STWU[I] | 0xA | ||||
| STT[I] | STTU[I] | STO[I] | STOU[I] | ||||||
| 0xB | STSF[I] | STHT[I] | STCO[I] | STUNC[I] | 0xB | ||||
| SYNCD[I] | PREST[I] | SYNCID[I] | PUSHGO[I] | ||||||
| 0xC | OR[I] | ORN[I] | NOR[I] | XOR[I] | 0xC | ||||
| AND[I] | ANDN[I] | NAND[I] | NXOR[I] | ||||||
| 0xD | BDIF[I] | WDIF[I] | TDIF[I] | ODIF[I] | 0xD | ||||
| MUX[I] | SADD[I] | MOR[I] | MXOR[I] | ||||||
| 0xE | SETH | SETMH | SETML | SETL | INCH | INCMH | INCML | INCL | 0xE |
| ORH | ORMH | ORML | ORL | ANDNH | ANDNMH | ANDNML | ANDNL | ||
| 0xF | JMP[B] | PUSHJ[B] | GETA[B] | PUT[I] | 0xF | ||||
| POP | RESUME | SAVE | UNSAVE | SYNC | SWYM | GET | TRIP | ||
| 0x8 | 0x9 | 0xA | 0xB | 0xC | 0xD | 0xE | 0xF | ||
Each row corresponds to the hexadecimal value of the most-significant nibble of the cells in it:
- If a cell is in the top sub-row of its row, then the top row of the table is used for finding its least-significant nibble.
- If a cell is in the bottom sub-row of its row, then the bottom row of the table is used for finding its least-significant nibble.
Each column corresponds to the least-significant nibble of the cells under it. When a cell spans two columns:
- Use the left column for the normal variant.
- Use the right column for the
[I]/[B]variant.
The row of a cell corresponds to the hexadecimal value of its most-significant nibble.