# io.s: # This file contains a skeleton of a program to performed buffered # interrupt-driven output. Your job is to fill in the body of the # interrrupt routine .ktext 0x80000080 # Forces interrupt routine below to # be located at address 0x80. intrp: addiu $29,$29,-20 # Save registers. .set noat sw $1,16($29) .set at sw $11,12($29) sw $10,8($29) sw $9,4($29) sw $8,0($29) #You have to provide your code here! li $8 0xffff0008 lw $9 nextIn lw $10 nextOut #case 1, if no more data to write bne $9 $10 case2 #see if there is data sw $0 0($8) #turn off interrupt j intputcase case2: lw $8 0($8) #load the transmitter control bit andi $8 $8 0x1 #leave the ready bit alone beq $8 $0 intDone #if not ready, return la $9 buffer addu $9 $9 $10 lbu $9 0($9) li $8, 0xffff000c #set $8 to 0xffff000c sw $9 0($8) #write to transmitter data register addi $10 $10 1 #increase $10 by 1 byte andi $10 $10 31 sw $10, nextOut #write back intputcase: li $8 0xffff0000 lw $9 rcvInput lw $10 rcvOutput #if $9 == $10, no new data beq $9 $10 intDone lw $11 0($8) andi $11 1 beq $11 $0 intDone #no more data, jump #check if it's full addi $9 $9 1 andi $9 $9 7 bne $9 $10 case3 #case3 is rcvbuff not full li $8 0xffff0004 lw $0 0($8) #discard the new char j intDone case3: lw $9 rcvInput lw $11 rcvBuf add $10 $9 $11 #$10 points to next space li $8 0xffff0004 lbu $11 0($8) #$11 get the new char sb $11 0($10) #store the new char in rcvBuf addi $9 $9 1 andi $9 $9 7 sw $9 rcvInput #store back intDone: lw $8,0($29) lw $9,4($29) lw $10,8($29) lw $11,12($29) .set noat lw $1,16($29) .set at addiu $29,$29,20 mfc0 $26,$14 # Read the exception program counter. rfe # Restore status bits on the way out. jr $26 # Jump to it. # Variables for the output buffer. If nextIn and nextOut are equal # then the buffer is empty. If nextIn points to the character just # before nextOut then the buffer is full. .data buffer: .space 32 # 32 characters of storage space for # characters waiting to be output. nextIn: .word 0 # Index of next place to insert # character into buffer (rotates # circularly through the buffer). nextOut: .word 0 # Index of next character to remove # from buffer at interrupt time # (rotates circularly through the # buffer). # Variables for input buffer: similar in function to those for output # buffer, except interrupt routine adds characters, getchar removes # them. rcvBuf: .space 8 # Storage space. rcvInput: .word 0 # Index at which to insert. rcvOutput: .word 0 # Index at which to remove. .text # int getchar() # # This procedure returns the next input character, waiting if necessary # for a character to become available. getchar: lw $8,rcvInput # See if buffer empty. lw $9,rcvOutput beq $8,$9,getchar la $10,rcvBuf add $10,$9,$10 lb $2,0($10) # Fetch next character. addiu $9,$9,1 # Update buffer index. andi $9,$9,7 sw $9,rcvOutput jr $31 # void print(char *string) # # This procedure adds a string of characters to the output buffer. # If the buffer fills up then it waits until space is available in # the buffer before adding more characters. print: lb $11,0($4) # Fetch next character to store addiu $4,$4,1 # in buffer, check for end of string. beq $11,$0,alldone lw $8,nextIn # Fetch current input index, and # compute new input index after we addiu $9,$8,1 # store the next character. andi $9,$9,31 # Wrap around from 32 back to 0. chkfull: lw $10,nextOut # Is buffer full? (i.e. is nextIn # just before nextOut?) beq $10,$9,chkfull # If so, just check again until # things get better. la $12,buffer add $12,$12,$8 sb $11,0($12) # Space in buffer: store character. sw $9,nextIn # Update "nextIn" index. lui $11,0xffff # Make sure interrupts are enabled addiu $10,$0,2 # in the transmitter. sw $10,8($11) j print # Go back for more characters. alldone: jr $31 # Return to caller. # Main program: # Set up stack, enable interrupts in the status register (but not in # any specific I/O devices), then enter a loop reading characters and # printing them with an identifying string. .globl __start __start: addi $29,$29,-4 sw $31,0($29) addiu $8,$0,0x1801 # Set IntMask[0] and IEc. mtc0 $8,$12 lui $8,0xffff # Enable receiver interrupts. addi $9,$0,2 sw $9,0($8) loop: jal getchar # See if there is an input character # in the buffer. la $4,string sb $2,20($4) # Store character into string to print. jal print # Print the string. j loop # In the string below, the "x" will be overwritten with the # most recent character read in. .data string: .asciiz "Received character 'x'\X0D\n"