# o.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 .data .globl buffer .globl nextIn .globl nextOut # 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. 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). .text # 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. .globl print .globl chkfull 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 call print over and over with a # test string. .globl __start __start: addi $29,$29,-4 sw $31,0($29) addiu $8,$0,0x1801 # Set IntMask[0] and IEc. mtc0 $8,$12 loop: la $4,string # Load string address in arg register. jal print # Print it. j loop # That was FUN! Let's do it again. # Since we're dealing with a "raw" terminal here, must output both # a carriage-return character (\015) and a newline character (\n) # to finish off a line. .data string: .asciiz "This project is really cool!\X0D\n" # DO NOT MODIFY ANYTHING ABOVE THIS LINE!! .ktext 0x80000080 # Forces interrupt routine below to # be located at address 0x80. intrp: addiu $29,$29,-16 # Save registers. .set noat sw $1,12($29) .set at sw $10,8($29) sw $9,4($29) sw $8,0($29) # HERE YOU HAVE TO PROVIDE YOUR CODE!!!! 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 intDone 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 intDone: lw $8,0($29) lw $9,4($29) lw $10,8($29) .set noat lw $1,12($29) .set at addiu $29,$29,16 mfc0 $26,$14 # Read the exception program counter. rfe # Restore status bits on the way out. jr $26 # Jump to it.