From CloudModding OoT Wiki
(Redirected from Registers)

Registers are the variables used by their respective processor/co-processor. MIPS has more registers, and less addressing modes in comparison to a lot of other instruction sets. A plus to this is that it operates more efficiently with a slower memory bus.

Every register holds a value of 32-bits (aligned) (XX XX YY YY) which can be sign extended (to hold larger values). Luckily, having a static length gives it a simplified memory model for editing purposes. The following is an arithmetic instruction; the opcode (ADD)'s usage as an example:

| ADD       | ADD word                                          |
|-----------|---------------------------------------------------|
|  000000   |   rs    |   rt    |   rd    |  00000  |100000 (32)|
------6----------5---------5---------5---------5----------6------
Format:  ADD rd, rs, rt
Purpose: To add 32-bit integers. If overflow occurs, then trap.
Comment: ADD rd, r0, rs is equal to a MOVE rd, rs
Descrip: rd = rs + rt

A link to more examples like such. For understanding the instruction fields and addressing modes found above: http://wiki.osdev.org/MIPS_Overview

Brief rundown of register instruction format for CPU, COP0 and COP1

Taken directly from: https://github.com/mikeryan/n64dev/blob/master/docs/n64ops/n64ops%23a.txt

Type Size Purpose
rs 5-bit source register specifier
rt 5-bit target (source/destination) register or branch condition
rd 5-bit 5-bit destination register specifier
sa 5-bit shift amount
fs 5-bit floating point source register specifier
ft 5-bit floating point target (source/destination)
fd 5-bit floating point destination register specifier
base 5-bit value
imm 16-bit immediate value
offset 16-bit branch displacement or address displacement
target 26-bit jump target address


As seen below, each processor has 31 registers (CPU has 32). COP0 (MMU) converts virtual addresses into physical addresses, selects an operating mode and control exceptions, while COP1 (FPU) is for floating point operations, and COP2 (RCP), or the "Reality Co-Processor" which is composed of the RSP (signal) and RDP (drawing) and together acts as a polygon cruncher.

CPU General Purpose Registers

Number Name Usage
0 zero, r0 Is a hardwired zero value and cannot be changed
1 at Assembler Temporary: Reserved by assemblers (Pseudo instructions)
2-3 $v0 - $v1 Value: Subroutine return value
4-7 $a0 - $a3 Arguments: First four parameters for a subroutine
8-15 $t0 - $t7 Temporary registers (Accessible to a subroutine without saving)
16-23 $s0 - $s7 Saved registers*: preserved across function calls (Must be saved and restored by the subroutine)
24-25 $t8 - $t9 Temporary registers (Subroutines can use without saving, but is not kept across procedure calls)
26-27 $k0 - $k1 Kernel: reserved for kernel operations, most importantly thread context switching. Do NOT use $K0 or $K1 outside kernel code
28 $gp Global Pointer*
29 $sp Stack Pointer* (points to the last location on the stack)
30 $fp/s8 Frame Pointer* or Saved value*
31 $ra Return Address for a subroutine
32 Hi/Lo Special registers that aren't directly accessible (used to store result of multiplication and division)

Note: However, you can access the contents of Hi and Lo with special instruction MFHI ("move from Hi") and MFLO ("move from Lo"). Another Note: The stack is a place in memory where the game backs up registers temporarily while doing other things. Larger addresses being stored at the bottom of the stack, smaller at the top of the stack (otherwise known as "stack limit") The stack pointer is usually a register that contains the top of the stack.

Unless you're writing kernel code, the $K0 and $K1 registers should never be used in custom mods. The reason for this is that when an interrupt occurs (and hardware interrupts can occur at any time), execution jumps immediately into the interrupt vector table and the kernel takes over. The only registers available for free use is $k0 and $k1, so the state of these registers will be obliterated by the kernel code. You can disable hardware interrupts, but you're most likely better off finding a free general purpose register

Co-processor 0 (COP0) Registers

Number Name Usage
0 Index Index into the TLB array (entry index register)
1 Random Randomly generated index into the TLB array (randomized access register)
2 EntryLo0 Low-order portion of the current TLB entry for even-number virtual pages
3 EntryLo1 Low-order portion of the TLB entry for odd-number virtual pages
4 Context Pointer to page-table entry in memory/lookup address
5 PageMask Control for variable page size in TLB entries
6 Wired Controls the number of fixed TLB entries
7 Reserved
8 BadVAddr Stores virtual address for the most recent address related exception
9 Count Increments every time an opcode is processed
10 EntryHi High-order portion of the TLB entry
11 Compare Timer interrupt control
12 Status Process status register/Used for exception handling
13 Cause Exception cause register/Stores the type of exception that last occurred
14 EPC
(ExceptionPC)
Contains address of instruction that caused the exception
15 PRId Processor identification and revision.
16 Config Configuration Register
17 LLAddr Load linked address
18 WatchLo Watchpoint address
19 WatchHi Watchpoint control
20 XContext Context register for R4300i addressing/PTE array related
21-26 Reserved
27 CacheErr Cache parity error control and status
28 TagLo Low-order portion of cache tag interface
29 TagHi High-order portion of cache tag interface (reserved)
30 ErrorEPC Error exception Program Counter
31 Reserved

Translation Lookaside Buffer (TLB): Address aliasing/Virtual addresses are mapped to physical addresses through the TLB.

Co-processor 1 (COP1) Registers

Number Name Usage
$f0-$f2 Floating point function return values
$f4-$f10 Temporary registers
$f12 - $f14 Floating point function parameters
$f16 - $f18 Temporary floating point registers
$f20 - $f30 Saved floating point registers*

*The value of saved registers are preserved across function calls. Any routine that uses a saved register must first store their value on the stack before use, and restore the value before exiting the routine.


Bitwise Operators (Shifting)

Bitwise operations are operations that, as the name suggests, take place on the smallest scale (bits) with the use of an operation. Outside of it's practical usage here, there are other reasons why programmers need to be familiar with operating on the bit level: sockets, bitfield flags, graphics, encryption, in tight loops you can avoid conditional statements with them, and so forth. Needless to say, bitwise operations are everywhere! Anyways, Left shift is denoted by << and Right is >>.

Left Shift (<<)

Left shift works like multiplication. Shifting left makes all right-most bits shift over to the left, then fills zeros into blank spaces!

SLL: 0011 1100 << 1
= 0111 1000

Right Shift (>>)

Right shift works like division. While shifting to the right, bits that cross the most right slot do not appear on the other side, but instead the newly shifted bits from the far most left side are zero's.

SRL: 0011 1100 >> 2
= 0000 1111

With MIPS, though, we have the option of arithmetic (SRA) or logical shifts (SRL/SLL). SRA is an acronym for Shift Right Arithmetic and SRL stands for Shift Right Logical: SRL shifts will always result in 0's on the far left side, while SRA will treat the leftmost, or Most Significant Bit (MSB) as a sign bit, copying it's value into the "blank" spaces. This is for dividing negative numbers.

SRA: 1010 0111 >> 3
= 1111 0100

References

R4300 datasheet

Rundown of CPU and RSP opcodes, matrixs, ROM header information, memory map and misc.