########################################################################################## ## ANSWERS TO PART 1 ########################################################################################## ## Programming Partners: Ed Yakabosky & Kyle Nase ## CSE 331 Homework 8 ## The transmitter and receiver interrupts are each invoked 13 times. Each letter press ## provokes an interrupt from the keyboard (10) plus three more for the carriage returns. ########################################################################################## ## PART 2 ########################################################################################## # Test of SPIM memory mapped IO. # # Standard startup code. Invoke the routine "main" with arguments: # main(argc, argv, envp) # .text .globl __start __start: lw $a0 0($sp) # argc addiu $a1 $sp 4 # argv addiu $a2 $a1 4 # envp sll $v0 $a0 2 addu $a2 $a2 $v0 jal main nop li $v0 10 syscall # syscall 10 (exit) .globl __eoth __eoth: .data prompt: .asciiz "SPIM IO Test.\nOnly runs with -mapped_io flag.\nPlease type a line:\n" nl: .asciiz "\n" .align 2 buffer: .space 64 .text .globl main # Register usage: # s0 buffer address # s1 buffer pointer # s2 Line Ready (encounter New Line or Carriage Return) # s3 Line Size (Number of charecters in the line) # t0 address of recv_ctrl register (0xffff0000) # t4, t5 temporaries # t6 char input from keyboard (read from recv_data) # main: li $v0 4 la $a0 prompt syscall li $t0 0xffff0000 # recv ctrl li $t4 0x2 # Enable device(Input) interrupts sw $t4 0($t0) li $t4 0x0 sw $t4 8($t0) # Disable device(Output) interrupts la $s0 buffer li $s1 0 li $s2 0 li $s3 0 mfc0 $t4 $12 # Enable interrupts and mask in Status reg ori $t4 $t4 0xff01 mtc0 $t4 $12 addi $t4, $zero, 1 li $t5 0x7fffffff add $t5, $t5, $t4 # This instruction will cause an overflow loop: beq $s2 1 reverse # if a line is read in, reverse the chars b loop # Loop waiting for interrupts reverse: ############################################################### # reverse the chars within the readin line # !!! NEED YOUR WORK HERE !!! add $s1 $s0 $zero # Put s1 at the end of the line add $t4 $s0 $zero # Put t4 at the end of the line loop2: addi $s1 $s1 -4 # Move pointers s1 and s0 addi $s0 $s0 4 lw $t6 0($s1) # Load the word from s1 into t6 sw $t6 0($s0) # Store that word into s0 addi $s3 $s3 -1 bne $s3 0 loop2 # Loop until reach end of line addi $s0 $s0 4 li $t6 -1 sw $t6 0($s0) ############################################################### ############################################################### # Use polling to output the reversed line to console # !!! NEED YOUR WORK HERE !!! mtc0 $0 $12 # Disable interrupts li $t1 0xffff0008 print_backwards: lw $t2 0($t1) # Load the value in the transmitter into t2 and $t2 $t2 1 # Check if transmitter is ready beq $t2 $zero print_backwards lw $t6 0($t4) # Load the next letter in the line beq $t6 -1 done # If end of line, exit addi $t4 $t4 4 # Increment the address sw $t6 4($t1) # Store the letter in the transmitter j print_backwards ############################################################### done: li $v0 10 syscall ############################################################### # Interrupt Handler ############################################################### # Interrupt handler. Replaces the standard SPIM handler. .ktext 0x80000180 mfc0 $t4 $13 # Get ExcCode field from Cause reg srl $t5 $t4 2 and $t5 $t5 0x1f # ExcCode field bne $t5 0 exception # Receiver interrupt: lw $t5 0($t0) # Check receiver ready and $t5 $t5 1 beq $t5 0 no_recv_ready # Error if receiver is not ready lw $t6 4($t0) # Read character ############################################################### # Store the input char into the buffer and check End of line ############################################################### addi $s3 $s3 1 # Update Line Size sw $t6 0($s0) # Store new character addi $s0 $s0 4 # Update buffer pointer beq $t6 0xa prerev # Break on new line beq $t6 0xd prerev # Break on carriage return beq $zero 0 mid_rev # continue with interrupt handler prerev: addi $s2 $zero 1 # Set t2 to break condition value mid_rev: mfc0 $t4 $13 # Get Cause register and $t4 0xfffff7ff # Clear IP3 bit mtc0 $t4 $13 # Return from handler. ret_handler: mfc0 $t4 $12 # Enable interrupts and mask in Status reg ori $t4 $t4 0xff01 mtc0 $t4 $12 eret # return to interrupted instruction exception: ############################################################### # Handle the arithmetic overflow exception # !!! NEED YOUR WORK HERE !!! # If an overflow is detected, output arith_str li $v0 4 # Overflow Exception la $a0 arith_str # Print message and ignore syscall b ret_handler ############################################################### non_handled: li $v0 4 # Non-interrupt exception la $a0 other_str # Print message and ignore syscall b ret_handler no_recv_ready: li $v0 4 # Receiver was not ready after interrupt la $a0 no_recv_str # Print message and ignore syscall b ret_handler .data whereami : .asciiz "Receiver interrupt\n" trans : .asciiz "Transmitter step\n" arith_str: .asciiz "Overflow exception\n" other_str: .asciiz "Unhandled Non-interrupt exception\n" no_recv_str: .asciiz "Receiver not ready\n"