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, “Linkage Conventions”, 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, “Linkage Conventions”, 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.