MIPS Exceptions
Objectives
-
Understand exception and interrupt handling in MIPS
-
Learn how to write exception handlers in MIPS.
Exercise 1: (Exception types)
Run the following sample code in MARS, then answer the questions below.
.text
.globl main
main:
li $t0, 2147483647 #
li $t1, 5000
add $a0, $t0, $t1 #
li $v0, 10 # exit
syscall
-
What is the value (in hexadecimal) of the status register of coprocessor 0?
-
What is the value (in hexadecimal) of the cause register of coprocessor 0?
-
What type of exception occurred?
-
At what address (in hexadecimal) did the exception occur?
Exercise 2 : (Interrupts)
Enabling interrupts on a MIPS processor is a two-step process:
-
Configure the device in question to send interrupt signals This usually requires setting an interrupt enable bit in a control register in the device.
-
Configure coprocessor 0 to accept interrupt signals This is done by setting bit 0 of the status register ($12) to enable interrupts globally, and then setting specific bits in the status register to enable specific interrupts. Bits 8 through 15 of the status register allow for 8 different levels of interrupts. For example, bits 3 and 4 of the mask (bits 11 and 12 of the status register) enable keyboard and display interrupts, respectively.
If we wanted to enable all interrupts in MIPS, complete the bitmask for the ori
instruction:
mfc0 $s1, $12 # read into $s1 the contents of the status register
ori $s1, _________ # <<<<< to compete
mtc0 $s1, $12 # update of the contents of the status register
If we wanted to enable only the keyboard and display interrupts, complete the bitmask for the ori
instruction:
mfc0 $s1, $12 # # read into $s1 the contents of the status register
ori $s1, _________ # <<<<< to compete
mtc0 $s1, $12 # update of the contents of the status register
Exercise 3: (Exception handler)
An exception handler must report the address of the instruction that caused the exception, the exception code, and must resume (or terminate) program execution after handling the exception.
-
For this exercise, we will use a custom exception handler instead of the one that is already built into MARS. To install our exception handler, follow these instructions:
-
Begin by downloading the starter file available at the top of this document. The file (
exceptions_handler.s
) is a custom MIPS exception handler. -
In MARS, click to unroll “Settings” from the menu
-
Check the box “Initialize Program Counter to global ‘main’ if defined”
-
unroll again the “Settings” menu and click on “Exception Handler”. A new dialog box will appear
-
Check the box “Include this exception handler file in all assemble operations”, then enter the path to the exception handler file you downloaded. Choose OK to finish.
-
MARS is now configured to use our new exception handler instead of the built-in handler.
-
-
In the MARS editor, write a program including instructions that cause: overflow, accesses to invalid memory addresses, trap instructions, and breakpoint instructions. Your program must start with this two lines of code:
.globl main:
-
Modify the exception handler to display the invalid vaddr when the exception is caused by a load, store, or instruction fetch (i.e. exception code 4 or 5). Test your exception handler by writing load and store instructions that generate invalid memory addresses.
-
Using memory-mapped I/O and polling (cf. « Exception mechanisms in MIPS »), write a function
print_string
that prints a string to the screen without using any system calls (i.e., do not usesyscall
instructions). The address of the string is passed in the register$a0
and the string must be terminated by the NUL (i.e. zero) character. Test this function by calling it from the main function. Make sure to enable the MMIO keyboard and display simulator from the menu (Tools | Keyboard and Display MMIO Simulator) and connect this simulator to MARS by clicking the « Connect to MIPS » button. -
Still using memory-mapped I/O and polling, write a program that reads characters directly from the keyboard (cf. « Exception mechanisms in MIPS »). To demonstrate how slow the keyboard is, print the character entered and the number of iterations after exiting the
wait_keyboard
loop. Repeat the execution of the program until you press the ↩ (Return) key on the keyboard. Make sure to run the MARS simulator at maximum speed. -
If the keyboard interrupt enable bit is set, the keyboard will interrupt the processor every time a key is pressed. Write a simple interrupt handler that returns the entered character to the
$v0
register. Rewrite the main function from question #4 using keyboard interrupts. -
Using memory-mapped I/O and polling, write a
read_string
function that reads a string directly from the keyboard. The function will retrieve the characters from the keyboard and store them in an array pointed to by the$a0
register. The function should continue untiln-1
characters are read or the newline character is received (i.e. ↩ (Return) key is pressed). Then
parameter should be passed in the$a1
register. The function should insert aNUL
byte at the end of the string and should return the actual number of characters read in$v0
register. Make sure to enable the MMIO Keyboard and Display Simulator and connect the simulator to Mars. Write a main function to testread_string
multiple times and to display the string after each call.