# This is an interrupt handler that ignores exceptions. # It uses a one-character input buffer and a one-character output buffer. .ktext 0x80000180 # interrupt handler entry address handler: # Start by saving registers. addiu $sp,$sp,-24 sw $at,20($sp) sw $t4,16($sp) sw $t3,12($sp) sw $t2,8($sp) sw $t1,4($sp) sw $t0,0($sp) # Register use in interrupt handler: # $t0 contains 0xFFFF0000 (base address for i/o status and data words). # $t1 contains a status word. # $t2 contains a character being read or to be written. # $t3 contains information about the buffer (full or not). # $t4 contains the address of "done". lui $t0,0xFFFF # Load base address. la $t4,done # First see if interrupt has resulted from a character appearing in receiver (keyboard) data. lw $t1,0($t0) # Get receiver status word. andi $t1,$t1,1 # Is receiver ready? I.e., is a character waiting? beq $t1,$0,checkOutput # No if branch, so go check transmitter. # A character awaits processing. Read it from the receiver data word # and put it into the buffer. lw $t2,4($t0) # Get the character. sb $t2,inputBuffer # Put it into the buffer. addi $t3,$0,1 # Signal that buffer is full. sb $t3,inputBufferIsFull # Next see if interrupt has resulted from the transmitter (display) becoming ready. checkOutput: lw $t1,8($t0) # Get transmitter status word. andi $t1,$t1,1 # Is transmitter ready? beq $t1,$0,done # No if branch, so return. # The transmitter has just become ready. If there is a character in the buffer, # send it to the transmitter. Otherwise disable transmitter interrupts until # another character comes along to be printed. lb $t3,outputBufferIsFull bne $t3,$0,sendChar # If branch, a character is waiting. # The buffer is empty. Disable transmitter interrupts. # lw $t1,8($t0) # andi $t1,0xFFFFFFFD # Turn off the "interrupt enable" bit. # sw $t1,8($t0) jr $t4 # A character is waiting in the buffer. Copy it to the transmitter data word. sendChar: lb $t2,outputBuffer # Get the character. sb $0,outputBufferIsFull # Signal buffer empty. sw $t2,12($t0) # Print the character. # We're done. Restore registers and return. done: mfc0 $t0,$13 # Get Cause register, then clear it. (Do I need this?) mtc0 $0, $13 lw $t0,0($sp) # Restore registers. lw $t1,4($sp) lw $t2,8($sp) lw $t3,12($sp) lw $t4,16($sp) lw $at,20($sp) addi $sp,$sp,24 eret .kdata .globl inputBuffer .globl inputBufferIsFull .globl outputBuffer .globl outputBufferIsFull inputBuffer: .space 1 inputBufferIsFull: .byte 0 outputBuffer: .space 1 outputBufferIsFull: .byte 0