################################## # Must enable memory-mapped I/O! # ################################## ################ # Handler Data # ################ .kdata ktemp: .space 16 hex: .ascii "0123456789abcdef" # table for quick hex conversion exc: .ascii "\texception:" spc: .asciiz " " timer: .asciiz "\ttimer expired... and reset\n" key: .ascii "\tkey: " char: .ascii " " nl: .asciiz "\n" ########################## # Handler Implementation # ########################## # Overwrites previous handler defined in exceptions.s .ktext 0x80000180 .set noat move $k0, $at .set at la $k1, ktemp sw $a0, 0($k1) sw $a1, 4($k1) sw $v0, 8($k1) sw $ra, 12($k1) mfc0 $a0, $14 # EPC jal print_hex la $a0, spc jal print_string mfc0 $a0, $12 # Status jal print_hex la $a0, spc jal print_string mfc0 $a0, $13 # Cause jal print_hex la $a0, spc jal print_string mfc0 $a0, $9 # Count jal print_hex la $a0, nl jal print_string mfc0 $a0, $13 # Cause andi $v0, $a0, 0x7C # Cause bits [6:2] beq $v0, $zero, e_int # Program exception la $a0, exc jal print_string mfc0 $a0, $13 # Cause srl $a0, $a0, 2 andi $a0, $a0, 0x1f jal print_hex la $a0, nl jal print_string # skip offending instruction mfc0 $v0, $14 # EPC addiu $v0, $v0, 4 mtc0 $v0, $14 # EPC j e_int_end e_int: # hardware interrupt mfc0 $a0, $13 # Cause andi $v0, $a0, 0x8000 beq $v0, $zero, e_int_timer_end # timer interrupt xor $a0, $a0, $v0 mtc0 $a0, $13 # Cause # reset timer mtc0 $zero, $9 la $a0, timer jal print_string e_int_timer_end: mfc0 $a0, $13 # Cause andi $v0, $a0, 0x0800 beq $v0, $zero, e_int_keyrecv_end # keyboard receive interrupt xor $a0, $a0, $v0 mtc0 $a0, $13 # Cause li $a0, 0xffff0000 lw $v0, 4($a0) la $a0, char sb $v0, ($a0) la $a0, key jal print_string e_int_keyrecv_end: e_int_end: la $k1, ktemp lw $a0, 0($k1) lw $a1, 4($k1) lw $v0, 8($k1) lw $ra, 12($k1) .set noat move $at, $k0 .set at mfc0 $k0, $12 # Status ori $k0, 0x01 # re-enable interrupts mtc0 $k0, $12 # Status eret ############################### # print_string Implementation # ############################### print_string: # $a0: string j ps_cond ps_loop: lw $v0, 0xffff0008 andi $v0, $v0, 0x01 beq $v0, $zero, ps_loop sw $a1, 0xffff000c ps_cond: lbu $a1, ($a0) addi $a0, $a0, 1 bne $a1, $zero, ps_loop j $ra ############################ # print_hex Implementation # ############################ print_hex: # $a0: int la $a1, hex li $v0, 28 ph_loop: lw $k1, 0xffff0008 andi $k1, $k1, 0x01 beq $k1, $zero, ph_loop srlv $k1, $a0, $v0 andi $k1, $k1, 0x0f add $k1, $a1, $k1 lbu $k1, ($k1) sw $k1, 0xffff000c addi $v0, $v0, -4 bge $v0, $zero, ph_loop j $ra ####################### # Program Entry Point # ####################### .text .globl main main: li $a0, 0xffff0000 lw $t0, 0($a0) ori $t0, 0x02 # use keyboard interrupts sw $t0, 0($a0) mfc0 $t0, $12 # Status ori $t0, 0x01 # interrupts enable mtc0 $t0, $12 # Status li $t0, 200 mtc0 $t0, $11 # Compare = 200 mtc0 $zero, $9 # Count = 0 # divide by zero div $t0, $t0, $zero li $t1, 0x7fffffff addi $t1, $t1, 1 # illegal memory address sw $t2, 123($zero) #.word 0xdeadbeef # illegal instruction (crashes SPIM!) loop: nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop j loop