Exceptions, Traps, and Interrupts
Table of Contents
This page is largely based on the original MARS documentation.
Introduction
Exceptions, traps, and interrupts are all distinct from each other, though they use the same underlying mechanism. Exceptions are caused by exceptional conditions that occur at runtime such as invalid memory address references. Traps are caused explicitly by certain instructions, most of which have a mnemonic starting with “t
”. Interrupts are caused by external devices in memory-mapped I/O (MMIO).
MARS simulates basic elements of the MIPS32 exception mechanism, but many features are not supported.
When an exception, trap, or interrupt occurs, the following steps are taken by the simulator:
- Bit 1 of Coprocessor 0 Status (
$12
) is set. - Bits 2-6 of Coprocessor 0 Cause (
$13
) are set to the exception type (see below for the list of supported exception types). - Coprocessor 0 EPC (
$14
) is set to the address of the instruction that triggered the exception or trap, or in the case of an interrupt, the address of the instruction being executed when the interrupt occurred. - If the exception was caused by an invalid memory address, Coprocessor 0 BadVAddr (
$8
) is set to the invalid address. - Program execution flow jumps to the MIPS instruction at memory location
0x80000180
. Or, if there is no instruction at location0x80000180
, MARS will terminate the MIPS program with an appropriate error message by default. This address in the kernel text segment is the standard MIPS32 exception handler location. The only way to change it in MARS is to change the MIPS memory configuration through the Settings→Memory Configuration dialog.
The following exception causes are used by MARS:
ADDRESS_FETCH (4) | Attempted to read memory at an invalid or misaligned address. |
ADDRESS_STORE (5) | Attempted to write memory at an invalid or misaligned address. |
SYSCALL (8) | An exception occurred while executing a syscall instruction. |
BREAKPOINT (9) | Encountered a break instruction. |
RESERVED_INSTRUCTION (10) | Encountered an instruction whose opcode is not recognized by the instruction set. |
ARITHMETIC_OVERFLOW (12) | Arithmetic overflow occurred during addition or subtraction. Division by zero does not cause an exception! |
TRAP (13) | Trapped due to a trap instruction. |
Bits 8-15 of Coprocessor 0 Cause ($13
) are used to indicate pending interrupts. This is used by the Keyboard and Display Simulator tool, for example, where bit 8 represents a keyboard interrupt and bit 9 represents a display interrupt. For more details, see the help menu for that tool.
Exception Handlers
An exception handler, also known as a trap handler or interrupt handler, can easily be incorporated into a MIPS program. This guide is not intended to be comprehensive but provides the essential information for writing and using exception handlers.
There are multiple ways to include an exception handler in a MIPS program:
- Write the exception handler in the same file as the rest of the program. An example of this is presented below.
- Write the exception handler in a separate file, store that file in the same directory as the other program files, and assemble using the Run→Assemble Folder action.
- Write the exception handler in a separate file, store that file in any directory, then open the Settings→Exception Handler dialog, check the checkbox and browse to that file. Note that using this method keeps the exception handler active until the checkbox is unchecked again.
The exception handler itself should start at kernel text address 0x80000180
in the standard memory configuration (open the Settings→Memory Configuration dialog to find the address if you are using a different layout). Use the directive .ktext 0x80000180
to achieve this.
If you use any general-purpose registers in your exception handler besides $k0
and $k1
(which are reserved for this exact purpose), you should save their original values and restore them after use to prevent the “clobbered” register values from interfering with the regular program. Note that this includes $at
, which is used by many extended instructions! You can save the values either by move
ing them into $k0
/ $k1
, or by using the stack.
The exception handler can return control to the program using the eret
instruction. This will set the Program Counter to the value of Coprocessor 0 EPC ($14
), so be sure to increment $14
by 4 before returning if you want to skip over the instruction that caused the exception.
Use the mfc0
and mtc0
instructions to read from and write to Coprocessor 0 registers.
Exception Handler Example
The sample MIPS program below generates a trap exception, triggering the exception handler. After printing a message, the exception handler returns control to the instruction following the one that triggered the exception, then the program terminates normally.
# Regular program code
.text
main:
# Generate a trap exception
teqi $zero, 0 # Trap unconditionally
# Exit the program now that the exception handler has returned
li $v0, 10 # "Exit" system call
syscall # Exit the program
# Relevant data for the exception handler
.kdata
msg:
.asciiz "Trap generated"
# Exception handler code
.ktext 0x80000180
# Save the value of $at (typically good practice) using the stack
addi $sp, $sp, -4 # Grow the stack by one word
sw $at, ($sp) # Push the value of $at to the stack
# Save the values of $v0 and $a0 using $k0 and $k1, respectively
move $k0, $v0
move $k1, $a0
# Print a message to console
li $v0, 4 # "Print String" system call
la $a0, msg # Address of the string to print
syscall # Print the string to console
# Restore the original values of $v0 and $a0
move $v0, $k0
move $a0, $k1
# Restore the original value of $at
lw $at, ($sp) # Pop the value of $at from the stack
addi $sp, $sp, 4 # Shrink the stack by one word
# Increment EPC (Exception Program Counter) in order to skip the trap instruction
mfc0 $k0, $14 # Coprocessor 0 register $14 has address of trapping instruction
addi $k0, $k0, 4 # Add 4 to point to next instruction
mtc0 $k0, $14 # Store new address back into $14
# Return to the regular program code
eret # Exception return; jump to EPC