Computer Science/Computer Architecture
[MIPS] MIPS Registers & Instructions
piccolo
2024. 4. 11. 15:24
Registers
Name | Number | Description |
$zero, $0 | 0 | contains the value 0 |
$at | 1 | reserved for assembler |
$v0 - $v1 | 2-3 | values returned by functions |
$a0 - $a3 | 4-7 | arguments to functions |
$t0 - $t7 | 8-15 | temporary variables |
$s0 - $s7 | 16-23 | saved values |
$t8 - $t9 | 24-25 | more temporary registers |
$sp | 29 | stack pointer to the top of stack |
$ra | 31 | return address |
Temporary vs. Saved Registers
MIPS convention specifies how the registers are supposed to be used:
- Use $t for values that may be overwritten by another procedure. If you wish to preserve $t values, save them before calling another procedure.
- Use $s for values that must be preserved when calling another procedure. The called procedure saves the $s values and restores them before returning. This guarantees that $s values remain the same before and after a call.
Do NOT expect $s registers to automatically preserve your values. $t and $s registers are no different from each other unless you implement the appropriate codes for them to be used the intended way.
In MIPS, $s registers are also called callee-saved registers, while $t registers are called caller-saved registers because of where their values are expected to be saved/restored in. Following the MIPS calling convention gives you the following code:
li $a0, 7
li $t0, 7
#funct_caller(n)
#$a0 = argument n
funct_caller:
#save $t0 while in the caller
addi $sp, $sp, -4
sw $t0, 0($sp)
#value of n MUST be saved, so put n in $s
move $s0, $a0
#make call to funct_callee(n-1)
addi $a0, $a0, -1
jal funct_callee
#restore $t0
lw $t0, 0($sp)
addi $sp, $sp, 4
#both $t0 and $s0 are preserved
#funct_callee(m)
#$a0 = argument m
funct_callee:
#save $s0 while in callee
addi $sp, $sp, -4
sw $s0, 0($sp)
#do some things
#restore $s0
lw $s0, 0($sp)
addi $sp, $sp, 4
#return to caller
jr $ra
Instructions
Arithmetic and Logical Instructions
Instruction | Type | Example | Meaning |
add | R | add $t2, $t0, $t1 | $t2 = $t0 + $t1 |
add immediate | I | addi $t1, $t0, n | $t1 = $t0 + n |
move | move $t1, $t0 | $t1 = $t0 | |
subtract | R | sub $t2, $t0, $t1 | $t2 = $t0 - $t1 |
multiply (without overflow) | R | mul $t2, $t0, $t1 | $t2 = $t0 * $t1 *only 32 bits |
multiply | R | mult $t2, $t3 mfhi $t1 mflo $t0 |
$t1 = upper 32 bits $t0 = lower 32 bits |
divide | R | div $t2, $t3 mflo $t0 mfhi $t1 |
$t0 = $t2 / $t3 $t1= $t2 % $t3 |
shift left logical | R | sll $t1, $t0, n | shift left by n bits $t1 = $t0 << n = $t0 * (2^n) |
- The instruction add $t1, $t0, $zero is equilvalent to addi $t1, $t0, 0 and move $t1, $t0
Data Transfer Instructions
Instruction | Type | Example | Meaning |
load word | I | lw $t1, n($t0) | $t1 = Memory[$t0 + n] |
load address | la $t0, label | $t0 = address of label | |
load immediate | li $t0, n | $t0 = n | |
store word | I | sw $t0, n($t1) | Memory[$t1 + n] = $t0 |
Branch and Comparison Instructions
Instruction | Type | Example | Meaning |
branch on equal | I | beq $t0, $t1, label | if ($t0 == $t1) go to label |
branch on not equal | I | bne $t0, $t1, label | if ($t0 != $t1) go to label |
branch on greater than | bgt $t0, $t1, label | if ($t0 > $t1) go to label | |
branch on greater than or equal to | bge $t0, $t1, label | if ($t0 >= $t1) go to label | |
branch on less than | bgt $t0, $t1, label | if ($t0 < $t1) go to label | |
branch on less than or equal to | bge $t0, $t1, label | if ($t0 <= $t1) go to label | |
set on less than | R | slt $t2, $t0, $t1 | if ($t0 < $t1) $t2 = 1 else $t2 = 0 |
set on less than immediate | I | slti $t2, $t0, n | if ($t0 < n) $t2 = 1 else $t2 = 0 |
Jump Instructions
Instruction | Type | Example | Meaning |
jump | J | j label | go to label |
jump register | R | jr $t0 | go to address stored in $t0 |
jump and link | J | jal label | set $ra = PC + 4 (return address) and go to label |
The instructions that are written in orange are pseudoinstructions. Note that some MIPS registers/instructions were ommitted from the list.