R3000 instruction set
- 1 Intro
- 2 Registers
- 3 Instructions
- 3.1 nop
- 3.2 Arithmetic
- 3.3 Memory
- 3.4 Comparison
- 3.5 Binary
- 3.6 Control
Registers are 32-bit boxes that hold values during computation.
Registers that can be used as arguments to instructions.
- r0: Always 0. Writing to this register does nothing.
- r1: Reserved for the assembler. For ASM hacking, you're basically the assembler, so it might be safe to use, until someone figures out it isn't.
- r2-r3: Used as scrap paper for work.
- r4-r7: Used as arguments.
- r8-r15: Temporaries.
- r16-r23: Non-temporaries.
- r24-r25: Temporaries.
- r26-r27: Reserved. Do not modify.
- r28: Global pointer. Do not modify.
- r29: Stack pointer. Points to the first free address on the stack. Change this to make more room on the stack. As more things are put on the stack, this pointer decreases.
- r30: Frame pointer. Do not modify.
- r31: Typically the return address. The
jalinstruction implicitly writes to this register. Do not modify except to restore an earlier value.
The following registers are expected to be preserved across calls. If used, their original values must be restored before returning.
- r16 - r23
- r26 - r27 (maybe)
- r28 - r31 (probably)
The following registers are expected NOT to be preserved across calls. A subroutine is free to change the value of these registers. After a call, these registers should be assumed to have garbage values (except r2).
- r2-r3: If the function has a return value, that value is stored here.
- r4-r7: The first four arguments of a call. (Additional arguments are passed on the stack.)
- r8-r15, r24-r25: Nothing special.
For calculations, use r2 and r3, then r4-r15 and r24-r25. Use r16-r23 for values that need to be preserved while calling a function, but make sure to store their original values on the stack, and to restore them before the return.
There are other registers, but they are special and require special instructions to use.
Note: This section is meant to be linked to, and used to generate tooltips (title text) for code pages.
The first paragraph of an instruction's description should be a short one-liner. It will be used as the tooltip. Think "reminder", rather than "explanation".
These are stolen from Wikipedia. Whoops.
Used to cause delays between instructions, because some instructions step on each other's toes.
These instructions act on registers as 32-bit two's-complement integers.
This operation is used to add both signed and unsigned integers (and is in fact the default used by C compilers). The "unsigned" part is misleading: it means that, if the sign changes, don't set the "overflow" error flag, which can cause an exception handler to trigger.
Add immediate unsigned
Multiply $s and $t.
Unlike most instructions, this instruction doesn't say where to store the result. The product of two 32-bit integers is at most 64 bits long, so the top and bottom parts of the result are stored separately. To access them, use the #mflo (move from low) and #mfhi (move from high) instructions.
This instruction is slow, so the compiler might instead use a combination of shifts and additions for multiplications by constants.
This instruction is sometimes used to multiply by positive decimals less than 1. For example, to multiply by 0.14, the compiler can multiply by an integer close to 0.14 * 2^32, and then only take the high part of the result.
mult r2,r3 Multiply mflo r4 r4 = the lower part of the product mfhi r5 r5 = the upper part of the product (r5 * 2^32) + r4 == r2 * r3 (mathematically)
Multiply unsigned. Multiply as if the arguments are 32-bit unsigned integers.
The quotient $s/$t is stored in the LO register, while the remainder $s%$t is stored in the HI register. See #mult.
div $s, $t
divu $s, $t
Getting data from/to the RAM.
Load halfword unsigned
Load byte unsigned
Load upper immediate
Move from high
Move from low
Set $d to 1 if true, 0 if false.
Set on less than
Set on less than immediate
These instructions act on registers as sequences of 0's and 1's.
Shift left logical immediate
Shift right logical immediate
Shift right arithmetic immediate
Shift left logical
Shift right logical
Shift right arithmetic
These instructions may or will cause a jump to a different part of the program.
The instruction right after one of these will always be executed, even if there's a jump.
Branch on equal
Branch on not equal
Jump. Jump to the given constant address.
Jump register. Like #j, but jumps to the address stored in the given register.
Jump and link. Used for calling subroutines.
Stores PC+8 (current instruction address plus 8) into r31, and then jump to the given constant. The idea is, when the subroutine is done, it will jump back to the instruction two steps after this one (thus, linking to PC+8).
Jump and link register. Like jal, but jumps to the address in the source register instead of to a constant.
The two-argument form also states which register to store the link (PC+8) into. The one-argument form assumes r31 is the destination register.
Warning: psxfin's disassembly has the arguments for the 2-arg form in the wrong order. This wiki and FFH's tools use the wrong order, for consistency with psxfin.
jalr $s jalr $s,$d
Format (MIPS specification, page 117):
jalr $s jalr $d,$s