Chapter 1. Registers
Prev |  | Next

## Chapter 1. Registers

This chapter describes the organization of data in memory, and the naming and usage conventions that the assembler applies to the CPU and FPU registers. See Chapter 7, “Writing Assembly Language Code”, for information regarding register use and linkage.

## Register Format

The CPU uses four data formats: a 64-bit doubleword, a 32-bit word, a 16-bit halfword and an 8-bit byte. Byte ordering within each of the larger data formats - doubleword, word or halfword - the CPU's byte ordering scheme (or endian issues), affects memory organization and defines the relationship between address and byte position of data in memory.

For R4000 and earlier systems, byte ordering is configurable into either big-endian or little-endian byte ordering (configuration occurs during hardware reset). When configured as a big-endian system, byte 0 is always the most-significant (leftmost) byte. When configured as a little-endian system, byte 0 is always the least-significant (rightmost byte).

The R8000 CPU, at present, supports big-endian only.

## General Registers

For the MIPS1 and MIPS2 architectures, the CPU has thirty-two 32-bit registers. In the MIPS3 architecture and above, the size of each of the thirty-two integer registers is 64-bit.

Table 1-1, and Table 1-2, summarize the assembler's usage, conventions and restrictions for these registers. The assembler reserves all register names; you must use lowercase for the names. All register names start with a dollar sign (`$`).

The general registers have the names `$0..$31`. By including the file `regdef.h` (use `#include` <`regdef.h`>) in your program, you can use software names for some general registers.

The operating system and the assembler use the general registers `$1`, `$26`, `$27`, `$28`, and `$29` for specific purposes. Attempts to use these general registers in other ways can produce unexpected results.

Table 1-1. General (Integer) Registers (`-32`)

Register Name | Software Name (from `regdef.h`) | Use and Linkage
--- | --- | ---
$0 |  | Always has the value 0.
$1 or $at |  | Reserved for the assembler.
$2..$3 | v0-v1 | Used for expression evaluations and to hold the integer type function results. Also used to pass the static link when calling nested procedures.
$4..$7 | a0-a3 | Pass the first 4 words of actual integer type arguments; their values are not preserved across procedure calls.
$8..$11 $11..$15 | t0-t7 t4-t7 or ta0-ta3 | Temporary registers used for expression evaluations; their values aren't preserved across procedure calls.
$16..$23 | s0-s7 | Saved registers. Their values must be preserved across procedure calls.
$25 | t9 or jp | PIC jump register.
$26..27 or $kt0..$kt1 | k0-k1 | Reserved for the operating system kernel.
$28 or $gp | gp | Contains the global pointer.
$29 or $sp | sp | Contains the stack pointer.
$30 or $fp | fp or s8 | Contains the frame pointer (if needed); otherwise a saved register (like s0-s7).
$31 | ra | Contains the return address and is used for expression evaluation.

| Note: General register `$0` always contains the value 0. All other general registers are equivalent, except that general register `$31` also serves as the implicit link register for jump and link instructions. See Chapter 7, “Writing Assembly Language Code”, for a description of register assignments.

Table 1-2. General (Integer) Registers (64-Bit)

Register Name | Software Name (from `regdef.h`) | Use and Linkage
--- | --- | ---
$0 |  | Always has the value 0.
$1 or $at |  | Reserved for the assembler.
$2..$3 | v0-v1 | Used for expression evaluations and to hold the integer type function results. Also used to pass the static link when calling nested procedures.
$4..$7 $8..$11 | a0-a3 a4-a7 or ta0-ta3 | Pass up to 8 words of actual integer type arguments; their values are not preserved across procedure calls.
$12..$15 | t0-t3 | Temporary registers used for expression evaluations; their values aren't preserved across procedure calls.
$16..$23 | s0-s7 | Saved registers. Their values must be preserved across procedure calls.
$24..$25 | t8-t9 | Temporary registers used for expression evaluations; their values aren't preserved across procedure calls.
$26..27 or $kt0..$kt1 | k0-k1 | Reserved for the operating system kernel.
$28 or $gp | gp | Contains the global pointer.
$29 or $sp | sp | Contains the stack pointer.
$30 or $fp | fp or s8 | Contains the frame pointer (if needed); otherwise a saved register (such as s0-s7).
$31 | ra | Contains the return address and is used for expression evaluation.

## Special Registers

The CPU defines three special registers: PC (program counter), HI and LO, as shown in Table 1-3. The HI and LO special registers hold the results of the multiplication (`mult` and `multu`) and division (`div` and `divu`) instructions.

You usually do not need to refer explicitly to these special registers; instructions that use the special registers refer to them automatically.

Table 1-3. Special Registers

Name | Description
--- | ---
PC | Program Counter
HI | Multiply/Divide special register holds the most-significant 32 bits of multiply, remainder of divide
LO | Multiply/Divide special register holds the least-significant 32 bits of multiply, quotient of divide

| Note: In MIPS3 architecture and later, the HI and Lo registers hold 64-bits.

## Floating-Point Registers

The FPU has sixteen floating-point registers. Each register can hold either a single-precision (32-bit) or double-precision (64-bit) value. In case of a double-precision value, `$f0` holds the least-significant half, and `$f1` holds the most-significant half. For 32-bit systems, all references to these registers use an even register number (for example, `$f4`). 64-bit systems can reference all 32 registers directly. The following tables summarize the assembler's usage conventions and restrictions for these registers.

Table 1-4. Floating-Point Registers (`-32`)

Register Name | Software Name (from `fgregdef.h`) | Use and Linkage
--- | --- | ---
$f0..$f2 | fv0-fv1 | Hold results of floating-point type function ($f0) and complex type function ($f0 has the real part, $f2 has the imaginary part.
$f4..$f10 | ft0-ft3 | Temporary registers, used for expression evaluation whose values are not preserved across procedure calls.
$f12..$f14 | fa0-fa1 | Pass the first two single- or double-precision actual arguments; their values are not preserved across procedure calls.
$f16..$f18 | ft4-ft5 | Temporary registers, used for expression evaluation, whose values are not preserved across procedure calls.
$f20..$f30 | fs0-fs5 | Saved registers, whose values must be preserved across procedure calls.

Table 1-5. Floating-Point Registers (`-64`)

Register Name | Software Name(from `fgregdef.h`) | Use and Linkage
--- | --- | ---
$f0, $f2 | fv0,fv1 | Hold results of floating-point type function ($f0) and complex type function ($f0 has the real part, $f2 has the imaginary part.
$f1, $f3, $f4..$f11 | ft12, ft13, ft0-ft7 | Temporary registers, used for expression evaluation; their values are not preserved across procedure calls.
$f12..$f19 | fa0-fa7 | Pass single- or double-precision actual arguments, whose values are not preserved across procedure calls.
$f20..$f23 | ft8-ft11 | Temporary registers, used for expression evaluation; their values are not preserved across proceadure calls.
$f24..$f31 | fs0-fs7 | Saved registers, whose values must be preserved across procedure calls.

Table 1-6. Floating-Point Registers (`-n32`)

Register Name | Software Name(from `fgregdef.h`) | Use and Linkage
--- | --- | ---
$f0, $f2 | fv0,fv1 | Hold results of floating-point type function ($f0) and complex type function ($f0 has the real part, $f2 has the imaginary part.)
$f1, $f3 $f4..$f11 | ft14, ft15, ft0-ft7 | Temporary registers, used for expression evaluation; their values are not preserved across procedure calls.
$f12..$f19 | fa0-fa7 | Pass single- or double-precision actual arguments, whose values are not preserved across procedure calls.
$f21, $f23, $f25, $f27, $f29, $f31 | ft8-ft13 | Temporary registers, used for expression evaluation; their values are not preserved across procedure calls.
$f20, $f22, $f24, $f26, $f28, $f30 | fs0-fs5 | Saved registers, whose values must be preserved across procedure calls.

## Floating-Point Condition Codes

The floating-point condition code registers hold the result of a floating-point comparison, and then decide whether or not to branch. For `-32` compilers, there is only register: $fcc0. For `-n32` and `-64` compilers, there are eight registers available: `$fcc0` through `$fcc7`.

Prev | Table of Contents | Next
About This Guide |  | Chapter 2. Addressing