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.
The coprocess 0 status register is a read-write register used to enable or disable various types of interrupts.
If the interrupt enable bit is 1, interrupts are allowed. If it is 0, they are disabled.
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.
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.
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 level | Used for | Mars | Spim | ||
---|---|---|---|---|---|
Bit nr. | Bit mask | Bit nr. | Bit mask | ||
0 | Transmitter (terminal output) | 9 | 0x00000200 | 10 | 0x00000400 |
1 | Receiver (keyboard interrupt) | 8 | 0x00000100 | 11 | 0x00000800 |
5 | Timer | Not supported | 15 | 0x00008000 |
On startup the status register has the following value.
Register | MARS | SPIM |
---|---|---|
Status | 0x0000ff11 |
0x3000ff10 |
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:
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 code | Name | Cause of exception |
---|---|---|
0 | Int | Interrupt (hardware) |
4 | AdEL | Address Error exception (Load or instruction fetch) |
5 | AdES | Address Error exception (Store) |
6 | IBE | Instruction fetch Buss Error |
7 | DBE | Data load or store Buss Error |
8 | Sys | Syscall exception |
9 | Bp | Breakpoint exception |
10 | RI | Reversed Instruction exception |
11 | CpU | Coprocessor Unimplemented |
12 | Ov | Arithmetic Overflow exception |
13 | Tr | Trap |
14 | FPE | Floating Point Exception |
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.
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.
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
.
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.
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.