MIPS Instruction Set

From Leo's Notes
Last edited on 24 September 2022, at 22:16.

The MIPS instruction set is relatively easy to read since all instructions are 32 bits.

There are 4 types of instructions (though R and FR are basically the same):

  1. R instructions - where all the data values used by the instruction are located in registers.
  2. FR instructions - Like the R instructions but used for floating point numbers.
  3. I instructions - where the instruction must operate on an immediate value and a register value. Immediate values may be a maximum of 16 bits long.
  4. J instructions - where jumps are needed. The immediate jump offset can be up to 26 bits

See: https://en.wikibooks.org/wiki/MIPS_Assembly/Instruction_Formats

MIPS overview[edit | edit source]

Instruction Name Action Fields
R instruction Used when all the data values used by the instruction are located in registers. Opcode

6 bits

Reg Source

(rs, 5 bits)

Reg Source

(rt, 5 bits)

Reg Dest

(rd, 5 bits)

Shift

(shamt) 5 bits

Function

6 bits

I instruction Used when the instruction must operate on an immediate value and a register value.

Immediate values may be a maximum of 16 bits long.

Opcode

6 bits

Reg Source

(rs, 5 bits)

Reg Source

(rt, 5 bits)

Immediate value

16 bits

J instruction Used when jumps are needed.

The immediate jump offset can be up to 26 bits

Opcode

6 bits

Address (26 bits)
Arithmetic Logic Unit
ADD rd, rs, rt Add rd = rs + rt 000000 rs rt rd 00000 100000
ADDI rt, rs, imm Add Immediate rt = rs + imm 001000 rs rt imm
ADDIU rt, rs, imm Add Immediate Unsigned (no 2's complement) rt = rs + imm 001001 rs rt imm
ADDU rd, rs, rt Add Unsigned rd = rs + rt 000000 rs rt rd 00000 100001
SUB rd, rs, rt Subtract rd = rs - rt 000000 rs rt rd 00000 100010
SUBU rd, rs, rt Subtract Unsigned rd = rs - rt 000000 rs rt rd 00000 100011
AND rd, rs, rt And rd = rs & rt 000000 rs rt rd 00000 100100
ANDI rt, rs, imm And Immediate rt = rs & imm 001100 rs rt imm
NOR rd, rs, rt NOR rd = ~(rs|rt) 000000 rs rt rd 00000 100111
OR rd, rs, rt OR rd = rs|rt 000000 rs rt rd 00000 100101
ORI rt, rs, imm OR Immediate rt = rs|imm 001101 rs rt imm
SLT rd, rs, rt Set On Less Than rd = (rs < rt) ? 1 : 0 000000 rs rt rd 00000 101010
SLTI rt, rs, imm Set On Less Than Immediate rt = (rs < imm) ? 1 : 0 001010 rs rt imm
SLTIU rt, rs, imm Set On < Immediate Unsigned rt = (rs < imm) ? 1 : 0 001011 rs rt imm
SLTU rd, rs, rt Set On Less Than Unsigned rd = (rs < rt) ? 1 : 0 000000 rs rt rd 00000 101011
XOR rd, rs, rt Exclusive OR rd = rs ^ rt 000000 rs rt rd 00000 100110
XORI rt, rs, imm Exclusive OR Immediate rt = rs ^ imm 001110 rs rt imm
Logical Shifts
SLL rd, rt, sa Shift Left Logical rd = rt << sa 000000 rs rt rd sa 000000
SLLV rd, rt, rs Shift Left Logical Variable rd = rt << rs 000000 rs rt rd 00000 000100
SRA rd, rt, sa Shift Right Arithmetic rd = rt >> sa 000000 rs=00000 rt rd sa 000011
SRAV rd, rt, rs Shift Right Arithmetic Variable rd = rt >> rs 000000 rs rt rd 00000 000111
SRL rd, rt, sa Shift Right Logical rd = rt >> sa 000000 rs rt rd sa 000010
SRLV rd, rt, rs Shift Right Logical Variable rd = rt >> rs 000000 rs rt rd 00000 000110
Multiply
DIV rs, rt Divide HI= rs % rt; LO = rs/rt 000000 rs rt 0000000000 011010
DIVU rs, rt Divide Unsigned HI= rs % rt; LO = rs/rt 000000 rs rt 0000000000 011011
MFHI rd Move From HI rd = HI 000000 0000000000 rd 00000 010000
MFLO rd Move From LO rd = LO 000000 0000000000 rd 00000 010010
MTHI rs Move To HI register HI= rs 000000 rs 000000000000000 010001
MTLO rs Move To LO register LO = rs 000000 rs 000000000000000 010011
MULT rs, rt Multiply HI, LO = rs*rt 000000 rs rt 0000000000 011000
MULTU rs, rt Multiply Unsigned HI, LO = rs*rt 000000 rs rt 0000000000 011001
Branch
BEQ rs, rt, offset Branch On Equal if (rs == rt) pc = pc + 4 + offset 000100 rs rt offset
BGEZ rs, offset Branch On >= 0 if (rs >= 0) pc = pc + 4 + offset 000001 rs rt=00001 offset
BGEZAL rs, offset Branch On >= 0 and link. Saves return address in $ra $ra = pc; if (rs>= 0) pc = pc + 4 + offset 000001 rs rt=10001 offset
BGTZ rs, offset Branch On > 0 if (rs>0) pc = pc + 4 + offset 000111 rs rt=00000 offset
BLEZ rs, offset Branch On if (rs<= 0) pc = pc + 4 + offset 000110 rs rt=00000 offset
BLTZ rs, offset Branch On < 0 if (rs<0) pc = pc + 4 + offset 000001 rs rt=00000 offset
BLTZAL rs, offset Branch On < 0 and link. Saves return address in $ra $ra = pc; if (rs<0) pc = pc + 4 + offset 000001 rs rt=10000 offset
BNE rs, rt, offset Branch On Not Equal if (rs != rt) pc = pc + 4 + offset 000101 rs rt offset
bgt $1,$2,100 branch on greater than if ($1 > $2) pc = pc + 4 + 100 Pseudo instruction
bge $1,$2,100 branch on greater than or equal if ($1 >= $2) pc = pc + 4 + 100 Pseudo instruction
blt $1,$2,100 branch on less than if ($1 < $2) pc = pc + 4 + 100 Pseudo instruction
ble $1,$2,100 branch on less than or equal if ($1 <= $2) pc = pc + 4 + 100 Pseudo instruction
BREAK Breakpoint epc = pc; pc = 0x3c 000000 code 001101
J target Jump pc = pc_upper|(target<<2) 000010 target
JAL target Jump and link.

Saves return address in $ra

$ra = pc + 4; pc = target<<2 000011 target
JR rs Jump register pc = rs 000000 rs rt=00000 rd=00000 00000 001000
JALR rs Jump and link register.

Like JR, but return address saved in specified register.

$ra = pc + 4; pc = rs 000000 rs rt=00000 rd 00000 001001
MFC0 rt, rd Move From Coprocessor rt = CPR[0, rd] 010000 00000 rt rd 00000000000
MTC0 rt, rd Move To Coprocessor CPR[0, rd]= rt 010000 00100 rt rd 00000000000
SYSCALL System Call epc = pc; pc = 0x3c 000000 00000000000000000000 001100
Memory Access
LB rt, imm(rs) Load Byte rt = (char) Mem[rs + imm] 100000 rs rt imm
LBU rt, imm(rs) Load Byte Unsigned rt = (uchar) Mem[rs + imm] 100100 rs rt imm
LH rt, imm(rs) Load Halfword, 2 bytes rt = (short) Mem[rs + imm] 100001 rs rt imm
LHU rt, imm(rs) Load Halfword Unsigned rt = (ushort) Mem[rs + imm] 100101 rs rt imm
LW rt, imm(rs) Load Word, 4 bytes. rt = Mem[rs + imm] 100011 rs rt imm
LUI rt, imm Load Upper Immediate rt = imm << 16 001111 rs=00000 rt imm
SB rt, imm(rs) Store (least significant) byte Mem[rs + imm] = (byte) rt 101000 rs rt imm
SH rt, imm(rs) Store (least significant) halfword content of rt Mem[rs + imm] = (short) rt 101001 rs rt imm
SW rt, imm(rs) Store content of rt in memory Mem[rs + imm] = rt 101011 rs rt imm

Pseudo instructions[edit | edit source]

There are pseudo instructions that are provided by your assembler and are converted to multiple instructions. Think of these as assembler macros.

See: https://en.wikibooks.org/wiki/MIPS_Assembly/Pseudoinstructions

move $1, $2 Move data from one register to another $1 = $2
li $1,100 Loads immediate value into register $1 = 100
la $1,label Loads computed address of label (not its contents) into register $1 = Address of label
bgt $1,$2,100 branch on greater than if ($1 > $2) pc = pc + 4 + 100
bge $1,$2,100 branch on greater than or equal if ($1 >= $2) pc = pc + 4 + 100
blt $1,$2,100 branch on less than if ($1 < $2) pc = pc + 4 + 100
ble $1,$2,100 branch on less than or equal if ($1 <= $2) pc = pc + 4 + 100
abs $1, $2 Puts the absolute value from one register ao another $1 = abs($2)
neg
negu
not
sge
sgt
NOP No operation. This can be done by running SLL $0 $0 $0 or 32bits of 0's.

Registers[edit | edit source]

All the register fields are 5 bits in size giving us 32 registers in total to work with.

All 32 registers are listed in the following table.

Register Decimal Binary Comments
$zero $0 00000 Always zero
$at $1 00001 used for temporary values within pseudo commands
$v0 $2 00010 used for returning values from functions

first and second, respectively.

$v1 $3 00011
$a0 $4 00100 used for the first 4 function arguments.
$a1 $5 00101
$a2 $6 00110
$a3 $7 00111
$t0 $8 01000 temporary registers. 8 in total
$t1 $9 01001
$t2 $10 01010
$t3 $11 01011
$t4 $12 01100
$t5 $13 01101
$t6 $14 01110
$t7 $15 01111
$s0 $16 10000 Saved values representing final computed results
$s1 $17 10001
$s2 $18 10010
$s3 $19 10011
$s4 $20 10100
$s5 $21 10101
$s6 $22 10110
$s7 $23 10111
$t8 $24 11000 Two additional temporary registers
$t9 $25 11001
$k0 $26 11010 Registers reserved for the kernel / operating system
$k1 $27 11011
$gp $28 11100 Global pointer
$sp $29 11101 Stack pointer
$fp $30 11110 Frame pointer
$ra $31 11111 Return address