From en64 wiki
Jump to navigation Jump to search

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.

Usually, ever register holds a value of 32-bits (aligned) (XX XX YY YY) which can be sign extended (to hold larger values).However, depending on the kernel addressing mode, they can also hold 64-bits. Normally, to maximize performance, they are 32-bits wide. Luckily, having a static length be is 32, or 64-bits it creates a simplified memory model which makes it easier for editing purposes rather than needing to remember rules or certain opcodes that have more or less than the general "usual" amount. The following is an arithmetic instruction; the opcode (ADD)'s usage as an example:
Binary Opcode Format

| ADD       | ADD word                                          |
|  000000   |   rs    |   rt    |   rd    |  00000  |100000 (32)|
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:

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

Taken directly from:

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

*The value of saved registers (Otherwise known as non-volatile 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.Essentially, if there is no asterisk they can be changed without consequences which makes them volatile registers.

As seen below, each processor has 31 registers(and two hidden ones), while the CPU has 32 (and three hidden ones). COP0 (MMU) converts virtual addresses into physical addresses, selects an operating mode and control exceptions and the COP1 (FPU) is for floating point operations. The Reality Co-Processor, which is composed of the RSP (signal) and RDP (drawing), together acts as a polygon cruncher. The RSP's COP0 handles communication between the CPU and the RCP through DMA, the COP2 is the RSP's Vector Unit (VU), and the RSP uses it's own microcode (uCodes). As seen below, I implemented a naming convention to make it easier to recall their usages.

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 - (May not want to use if hooked to JR $RA (unless you know what that function returns))
4-7 $a0 - $a3 Arguments: First four parameters for a subroutine - (Avoid using if you've hooked a JAL/JALR (unless what arg the function expects is known))
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: Do not use $K0, exception handler uses this, $K1 is an open register that's value is almost always 0xAAA (read note below)
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
spec Hi/Lo These special registers that aren't directly accessible. They're used to store result of multiplication and division
spec PC The Program Counter stores the address of the instruction that's currently being executed
spec LLB dedicated for load-link and store-conditional instructions which can be used to perform SYNC operations

spec = Special registers

  • The $K0 and $K1 registers should not be used because almost all mods will only modify code that is executed while the CPU is in "User" state. In user state, a hardware interrupt can occur at any point during execution, thus invalidating the $K0 and $K1 registers.
  • 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.

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
Processor cycle count
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
Contains address of instruction that caused the exception
Address at which to resume execution after an 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.
For further information.

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 two hidden/special registers for the COP1 are FCR0 and FCR31: they're the floating point Implementation and Control registers.
For more information.

Reality Signal Coprocessor (RSPCOP0) Registers

Detailed list

Number Name
Mode Description
RW I/DMEM address for DMA
RW DRAM address for DMA
RW DMA READ length (DRAM -> i/DMEM)
RW RSP Status
R DMA full
R DMA busy
RW CPU-RSP Semaphore
RW RDP command buffer START
RW RDP command buffer END
R RDP command buffer CURRENT
RW RDP Status
RW RDP clock counter
R RDP command buffer BUSY

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


R4300 datasheet

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