Mips coprocessor 0

A MIPS processor consists of an integer processing unit (the CPU) and a collection of coprocessors that perform ancillary tasks or operate on other types of data such as floating-point numbers.

Integer arithmetic and logical operations are executed directly by the CPU. Floating point operations are executed by Coprocessor 1. Coprocessor 0 is used do manage exceptions and interrupts.

Normal user level code doesn’t have access Coprocessor 0, but interrupt and exception aware code has to use it. Coprocessor 0 has several registers which controls exceptions and interrupts.

Status (register 12)

The coprocess 0 status register is a read-write register used to enable or disable various types of interrupts.

Interrupt enable

If the interrupt enable bit is 1, interrupts are allowed. If it is 0, they are disabled.

Exception level

The exception level bit is normally 0, but is set to 1 after an exception occurs. When this bit is 1, interrupts are disabled and the EPC is not updated if another exception occurs. This bit prevents an exception handler from being disturbed by an interrupt or exception, but it should be reset when the handler finishes.

User mode

The user mode bit is 0 if the processor is running in kernel mode and 1 if it is running in user mode.

User mode fixed to 1 in Mars and Spim

Neither Mars nor Spim implements kernel mode and fixes the user mode bit to 1.

Interrupt mask

The 8 bit interrupt mask 8 field contains one bit for each of the 6 hardware level interrupts and the 2 software level interrupts. A mask bit set to 1 allows interrupts at that level to interrupt the processor. A mask bit set to 0 disables interrupts at that level.

Hardware interrupt levelUsed forMarsSpim
Bit nr.Bit maskBit nr.Bit mask
0Transmitter (terminal output)90x00000200100x00000400
1Receiver (keyboard interrupt)80x00000100110x00000800
5TimerNot supported150x00008000

Startup value

On startup the status register has the following value.

RegisterMARSSPIM
Status0x0000ff110x3000ff10

To see which bits are set in the status register on startup we must translate the hexadecimal startup value to binary.

From hexadecimal to binary

When translating from hexadecimal to binary we do this by translating each hexadecimal digit to a four bit binary value.

  • 0x0 = [binary] = 0000
  • 0x1 = [binary] = 0001
  • 0xf = [binary] = 1111

Next, we replace each hexadecimal digit with the corresponding four bit binary number.

Mars initializes the status register in coprocessor 0 to 0x0000ff11 = [binary] = 0000 0000 0000 0000 1111 1111 0001 0001.

On startup:

  • Interrupts are enabled.
  • User mode is set to 1.
  • All interrupt mask bits are set to 1.

Cause (register 13)

The Cause register, is a mostly read-only register whose value is set by the system when an interrupt or exception occurs. It specifies what kind of interrupt or exception just happened.

When an exception or interrupt occur, a code is stored in the cause register as a 5 bit value (bits 2-6). This field is commonly referred to as the exception code although it is used for both exceptions and interrupts.

Exception codeNameCause of exception
0IntInterrupt (hardware)
4AdELAddress Error exception (Load or instruction fetch)
5AdESAddress Error exception (Store)
6IBEInstruction fetch Buss Error
7DBEData load or store Buss Error
8SysSyscall exception
9BpBreakpoint exception
10RIReversed Instruction exception
11CpUCoprocessor Unimplemented
12OvArithmetic Overflow exception
13TrTrap
14FPEFloating Point Exception

EPC (register 14)

Exception Program Counter (EPC) register. When an interrupt or exception occurs, the address of the currently executing instruction is copied from the Program Counter (PC) to EPC. This is the address that your handler jumps back to when it finishes.

Timer (register 9 and 11)

In SPIM, a timer is simulated with two more coprocessor registers: Count (register 9), whose value is continuously incremented by the hardware, and Compare (register 11), whose value can be set. When Count and Compare are equal, an interrupt is raised, at Cause register bit 15.

To schedule a timer interrupt, a fixed amount called the time slice (quantum) is stored in the Compare register. The smaller the time slice, the greater the frequency of timer interrupts.

No timer in Mars

Timer interrupts are yet not implemented in MARS.

Accessing registers in Coprocessor 0

To access a register in Coprocessor the register value must be transferred from Coprocessor 0 to one of the regular CPU registers. To update one of the registers in Coprocessor 0 a value in one of the of the regular CPU register in the CPU must be transferred to to one of the Coprocessor 0 registers.

If you want to modify a value in a Coprocessor 0 register, you need to move the register’s value to a general- purpose register with mfc0, modify the value there, and move the changed value back with mtc0.

mfc0

The mfc0 (Move From Coprocessor 0) instruction moves a value from a Coprocessor 0 register to a general-purpose register.

Example:

mfc0 $t5, $13  # Copy $13 (cause) from coprocessor 0 to $t5.

mtc0

The mtc0 (Move To Coprocessor 0) instruction moves a value from a general-purpose register to a Coprocessor 0 register.

Example:

mtc0 $v0, $12  # Copy $v0 to $12 (status) in coprocessor 0.

References

Assemblers, Linkers, and the SPIM Simulator