My code wouldn't work after attempting this. Can somebody show me how it's done?
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"
I am working on a very similar assignment and new to MIPS. Looking over the program I think the directive in the kernel code at the bottom of pgm (line 123) should be .kdata and not .data. Also .data directive above main: is missing in the post.
User contributions licensed under CC BY-SA 3.0