My code wouldn't work after attempting this. Can somebody show me how it's done?
Instructions -
Turn off branch and load delays for this program, if you wish. It will make it considerably simpler. Be sure to turn on memory-mapped I/O. Make sure you fully understand what the memory mapped I/O example program from my Web site does before you start designing or programming this. You will not be polling, but you need a clear understanding of memory-mapped I/O.
You may not use syscall for input or output, because the program would then block on the input. Instead, use an interrupt-driven I/O routine to handle all input and output. You must do ALL input and output through the interrupt-driven memory-mapped input/output services, NOT through syscall. You may NOT poll for I/O. The only syscall you may use for this program is a syscall with code 10 to end the program.
Write a program that starts with two arrays of characters (to hold .asciiz strings), of equal length (at least 60 characters in length), labeled 'source' and 'display'. Initially, make the source array contain a character string with a '\n' before the terminating NUL. Include upper- and lower-case letters and other characters (punctuation, digits, and spaces) in the string. Start your program by copying the source array into the display array. Use a subroutine to do this passing in the addresses of the two arrays on the stack. Use the "real-world" subroutine calling convention.
After copying the string, enable interrupts, and then loop, examining a variable (which may be changed by code inside the interrupt handler) until the user tells the program to quit. Whenever an output ready (transmitter) interrupt occurs, the interrupt handler will print the next single character from the display array, wrapping back to the beginning after it prints the '\n'. Whenever the input interrupt (receiver) interrupt occurs, you will extract the user's input (one character) and do one of the following tasks depending on the user's input:
's': sort the display array using any easy sort routine (bubble or ripple is fine). Do not sort the '\n'.
't': toggle the case of every alphabetic character (for example, 'T' becomes 't', 't' becomes 'T' and all non-alphabetic characters stay unchanged).
'a': replace the display array elements with the source elements once again.
'r': reverse the elements in the display array (again, excluding the '\n').
'q': quit -- terminate program execution.
Ignore any other character in input. Handle the commands from the user inside the interrupt handler, not inside the main program.
The 'q' command should just set the variable being queried (repeatedly) by the main program, which will cause the main program to then exit with a syscall with code 10. You MAY NOT use registers to send information between the program and the interrupt handler.
Note: an interrupt could happen in the middle of displaying the array, so the characters being displayed could change mid-line. This program is obviously designed to build on previous assignments, so you should reuse code wherever possible. The primary new feature is the interrupt-driven input and output. Instead of reading entire strings in one syscall, you will read and process each character as it arrives. Again, you MAY NOT use syscall for any I/O. This is about three or four pages of code in total.
This is my code but I can't get it to work -
prompt: .asciiz "SPIM IO Test.\nOnly runs with -mapped_io flag.\nPlease type 6 input lines:\n"
nl: .asciiz "\n"
.text
.globl main
main:
li $v0 4
la $a0 prompt
syscall
# Register usage:
# s0 loop counter
# t0 address of recv_ctrl
# t1 address of recv_buffer
# t2 address of trans_ctrl
# t3 address of trans_buffer
# t4, t5 temporaries
# t6 char read from input
# t7 1 => char in t6
li $s0, 3 # loop counter
li $t0, 0xffff0000 # recv ctrl
li $t1, 0xffff0004 # recv buf
li $t2, 0xffff0008 # trans ctrl
li $t3, 0xffff000c # trans buf
# First, read and echo 3 lines of input by polling the IO registers, not through
# interrupts:
mtc0 $0, $12 # Clear IE bit in Status reg to disable interrupts
l1:
lw $t4, 0($t0) # Wait for receiver ready
and $t4, $t4, 1
beq $t4, 0, l1
lw $t6, 0($t1) # Read character
l2:
lw $t4, 0($t2) # Wait for transmitter ready
and $t4, $t4, 1
beq $t4, 0, l2
sw $t6, 0($t3) # Write character
beq $t6, 0xa, decr # New line (nl)
bne $t6, 0xd, l1 # Carriage return (cr)
decr:
add $s0, $s0, -1 # Decrement line counter
bne $s0, 0, l1 # If not zero, get another line
# Second, read and echo 3 lines of input by through interrupts:
mfc0 $t4, $13
and $t4, 0xffff00ff # Clear IP bits in Cause register
mtc0 $t4, $13
li $s0, 3 # loop counter
li $t4, 0x2 # Enable device interrupts
sw $t4, 0($t0)
sw $t4, 0($t2)
mfc0 $t4, $12 # Enable interrupts and mask in Status reg
ori $t4, $t4, 0xff01
mtc0 $t4, $12
l3: b l3 # Loop waiting for interrupts
# Trap 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
# An interrupt:
and $t5, $t4, 0x800 # Check for IP3 (HW 1)
beq $t5, 0, check_trans
# 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, 0($t1) # Read character
li $t7, 1
beq $t6, 0xa, decr2 # New line (nl)
bne $t6, 0xd, next # Carriage return (cr)
decr2:
add $s0, $s0, -1 # Decrement line counter
next:
mfc0 $t4, $13 # Get Cause register
and $t4, 0xfffff7ff # Clear IP3 bit
mtc0 $t4, $13
check_trans:
beq $t7, 0, ret_handler # No char to write yet
and $t5, $t4, 0x400 # Check for IP2 (HW 0)
beq $t5, 0, check_loop
# Transmitter interrupt:
lw $t5, 0($t2) # Check transmitter ready
and $t5, $t5, 1
beq $t5, 0, no_trans_ready
sw $t6, 0($t3) # Write character
li $t7, 0
mfc0 $t4, $13 # Get Cause register
and $t4, 0xfffffbff # Clear IP2 bit
mtc0 $t4, $13
check_loop:
bne $s0, 0, ret_handler # If line counter not zero, get another line
# Done echoing, so terminate program.
li $v0, 10
syscall # syscall 10 (exit)
# 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:
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
bad_int:
li $v0, 4 # Interrupt was not from recv or trans
la $a0, bad_int_str # Print message and ignore
syscall
b ret_handler
no_trans_ready:
li $v0, 4 # Transmitter was not ready after interrupt
la $a0, no_trans_str # Print message and ignore
syscall
b ret_handler
.data
other_str:
.asciiz "Non-interrupt exception\n"
no_recv_str:
.asciiz "Receiver not ready\n"
no_trans_str:
.asciiz "Transmitter not ready\n"
bad_int_str:
.asciiz "Unknown interrupt\n"