################################################################################
##
## LSU EE 4720 Fall 2005 Homework 3
##
##
 ## Due Wednesday, 12 October 2005

 # Note: This version does not have comments in the pack routine.
 # A version with comments will be posted Thursday evening or Friday
 # morning, either version can be used for your solution.

.data
name:
        .asciiz ""  # Put your name between the quotes.

 ## Instructions:
  #
  # (0) Read and follow account setup instructions at
  #     http://www.ece.lsu.edu/ee4720/proc.html
  #
  # (1) Copy this assignment, local path name
  #     /home/classes/ee4720/com/s/hw3.s, to a directory ~/hw in your
  #     class account. (~ is your home directory.)  Use this file for your
  #     solution.  The TA-bot will look first for a file named ~/hw/hw3.s.
  #     If you have multiple versions make sure the one you want graded
  #     is in ~/hw/hw3.s.
  #
  # (2) Find the problem in this file and solve it.
  #
  #     A procedure shell has been provided for the each problem.  Place
  #     your solution there.
  #
  #     Assembler code following the problems runs your solutions.
  #     That code can be modified.
  #
  #     Your entire solution should be in this file.
  #
  #     Do not rename the line labels in this file and be sure to use the
  #     directory and filename given above.  (Line labels may be added.)
  #
  # (3) Your solution will automatically be copied from your account by
  #     the TA-bot.  Late submissions can be E-mailed.
  #

 ## Additional Resources
  #
  # MIPS Architecture Manual Volume 2 (Contains a list of instructions.)
  #      http://www.ece.lsu.edu/ee4720/mips32v2.pdf
  #      Note: SPIM implements MIPS-I instructions.
  #
  # SPIM Documentation:
  #      Appendix A of Patterson and Hennessey.
  #      http://www.ece.lsu.edu/3755/spim.pdf
  #
  # Account Setup and Emacs (Text Editor) Instructions
  #      http://www.ece.lsu.edu/ee4720/proc.html
  #      To learn Emacs look for and follow instructions for the Emacs tutorial.
  #
  # Unix Help
  #      http://www.ece.lsu.edu/v/4ltrwrd/


 ## Note on SPIM
#
# Clicking the close button (usually the upper-right-hand button on
# the window frame) of any window will immediately exit SPIM.
#

 ## Troubleshooting
#
# Make sure that the "run" dialog box shows 0x0400000 for the starting
# address.  If not, __start was not properly defined, possibly due to
# an error before __start.
#
# Check the messages (bottommost) pane for syntax and other errors.  It
# may be necessary to shorten other panes to make the messages pane visible.
# Common syntax errors include using "addi" instead of "add", or vice versa.
# Another common error is mistyping a label in a branch or jump target.
#
# Check the "Text Segments" pane to make sure all of your program is there.
# If not, there may have been an error reading the program.
#
# If your program fails a test or otherwise does not produce the
# expected output modify the test code so that the particular test it
# fails comes first (if it's not already).  Then, single-step the code
# (using the "step") button until you find the problem.
#
# If you've hit a wall ask the TA or instructor help.  It's better to
# err on the side of too many questions than too few.


################################################################################
## Problem 0

# Do the setup described in the instructions above.
#
# Before making any changes to this file (other than comments) run
# the assembler/simulator SPIM using the following steps:
#
#  Load this file into an Emacs buffer using the class-account Emacs.
#
#  If setup was done correctly comments should be red, "Problem 0" above
#  should be in a black, bold, sans-serif font and the assembler below
#  should look something like fruit salad, with pale blue mnemonics,
#  italicized pseudo instructions, purple assembler directives, green
#  line labels, etc.
#
#  Start the SPIM assembler/simulator by pressing [F9].
#    -> A window entitled "xspim" should pop up.  The top pane should show
#       register values, the next pane should have buttons, the third
#       should show the program in binary and assembler forms, the fourth
#       pane shows the data area, and the bottom pane (which might extend
#       past the bottom of the screen) shows messages.
#
#  Run the program by clicking the "run" button then clicking "ok" on the
#  dialog box that pops up.
#    -> A window entitled "SPIM Console" should pop up, the window
#       should be asking you to include your name in this file.  After
#       a name is entered and Spim is re-run it should show four wrong
#       conversions (for Problem 1).  For Problem 0 that's success!!!
#
#  Put your name at the top of the file then run the code in this
#  file. 
#    -> The output window of the simulator (which might be hidden
#       behind the main window) should show that the output of the unpack
#       routine is "Not yet implemented." and is not the correct output.


################################################################################
## Problem 1 -- Unpack Routine

# The unpack routine below unpacks every string into "Not yet
# implemented", which of course can't be right. Modify the routine so
# that it unpacks correctly. Follow the guidelines below next to the
# check boxes ([ ]).


        ## Register Usage
        #
        # $a0: Procedure call argument. Address of packed string.
        # $a1: Procedure call argument. Address of memory for unpacked string.
        # There are no return values.

        # [ ] Make sure that the code at least runs to completion.
        #     Substantial credit will be deducted for syntax
        #     and run-time errors.
        # [ ] Make sure the code passes the test in the demo routine
        #     and works for other strings too. The unpack routine may be
        #     graded using different strings.
        #
        # [ ] Registers $t0-$t9 and $a0-$a3 can be used.
        # [ ] Fill as many delay slots as possible.
        # [ ] The only pseudo instructions that can be used are "nop" and "la".
        # [ ] The code should be reasonable efficient,
        #     don't use two instructions where one would do.

        .data
NYI:
        .asciiz "Not yet implemented."

        .text

unpack:
        la $t0, NYI

ULOOP:
        lb $t1, 0($t0)
        addi $t0, $t0, 1
        sb $t1, 0($a1)
        bne $t1, $0, ULOOP
        addi $a1, $a1, 1

        jr $ra
        nop



################################################################################
## Demonstration Routine

# This routine calls the pack and unpack routines on a sample
# string below (DEMO_STRING), displays the original and unpacked strings
# side by side, and verifies whether the unpacked string is correct.

# It's okay to change DEMO_STRING if that will help you debug your code,
# but your code should work on the original DEMO_STRING and any other
# string.


        .data         # Indicate to the assembler that the stuff below is data.

#
# String to demonstrate pack and unpack routines.
#
DEMO_STRING: # Address of stuff immediately following.
        # Place string in memory here, end string with NULL (0).
        .asciiz ".,!Time flies like an arrow, fruit flies like a banana. azAZ09"
        .byte 0, 0, 0 # Put three zeros in memory here.

#
# Memory space for packed and unpacked strings.
#
        .align 4      # Make sure the address below is a multiple of 4.
BUFFER_PACK:
        .space 256    # Allocate 256 characters for use by the pack routine.
        .align 4
BUFFER_UNPACK:
        .space 256    # Allocate 256 characters for use by the unpack routine.

#
# Message printed by the demonstration routine.
#
MSG:
        .asciiz "Original:\n\"%/a2/s\"\nUnpacked: \n\"%/a1/s\"\n"
MSGSPACES:
        .asciiz "                                                                                                                                                                                                                                                                "
MSGERROR:
        .asciiz "%/s4/s |<---- First error here."
MSGCORRECT:
        .asciiz "Unpack appears correct."

#
# Message displayed if name omitted.
#
who_are_you:
        .asciiz "Please put your name at the top of the file where indicated."


        .text         # Indicate to the assembler that the stuff below is code.
        .globl __start
__start:

        la $s0, name
        lb $s0, ($s0)
        bne $s0, $0,  DOTESTS
        la $a0, who_are_you
        addi $v0, $0, 11
        syscall
        addi $v0, $0, 10
        syscall


DOTESTS:
        # Load address of string and address of memory for packed
        # string and call the pack routine.
        #
        la $a0, DEMO_STRING
        la $a1, BUFFER_PACK
        jal pack
        nop

        # Load address of packed string and address of memory for unpacked
        # string and call the unpack routine.
        #
        la $a0, BUFFER_PACK
        la $a1, BUFFER_UNPACK
        jal unpack
        nop

        # Call a system (simulator) routine to display results.
        #
        la $a0, MSG
        la $a1, BUFFER_UNPACK
        la $a2, DEMO_STRING
        addi $v0, $0, 11
        syscall

        la $s0, DEMO_STRING
        la $s1, LUT
        la $s2, BUFFER_UNPACK

DVLOOP:
        lb $t0, 0($s0)
        beq $t0, $0 DVDONEOKAY
        add $t1, $s1, $t0
        lb $t1, 0($t1)
        lb $t2, 0($s2)
        bne $t1, $0 DCHAR
        addi $s0, $s0, 1
        addi $t0, $0, 46 # '.'
DCHAR:
        beq $t0, $t2, DVLOOP
        addi $s2, $s2, 1
        la $s3, DEMO_STRING
        sub $s3, $s0, $s3
        la $s4, MSGERROR
        sub $s4, $s4, $s3
        la $a0, MSGERROR
        j DVDONE
        nop
DVDONEOKAY:
        la $a0, MSGCORRECT
DVDONE:
        addi $v0, $0, 11
        syscall


        addi $v0, $0, 10
        syscall
        nop



################################################################################
## Pack Routine

        ## Register Usage
        #
        # $a0: Procedure call argument. Address of string to pack.
        # $a1: Procedure call argument. Address of memory for packed string.
        # There are no return values.

        .data
        .align 4
LUT:
        .space 256
KEEP:
        .asciiz ".,!?;abcdefghijklmnopqrstuvwxyz "
        .byte 0   # HINT, needed for solution to last part.   <---- HINT!!

        .text
pack:

        #
        ## Section
        #

        la $t0, LUT
        addi $t2, $t0, 252
PLOOP1:
        sw $0, 0($t0)
        bne $t0, $t2, PLOOP1
        addi $t0, $t0, 4

        #
        ## Section
        #

        la $t0, LUT
        la $t1, KEEP
        addi $t3, $0, 0
PLOOP2:
        lbu $t2, 0($t1)
        add $t4, $t0, $t2
        sb $t3, 0($t4)
        addi $t1, $t1, 1
        bne $t2, $0  PLOOP2
        addi $t3, $t3, 1

        addi $t3, $0, -1
        sb $t3, 0($t0)

        #
        ## Section
        #

PLOOP:
        lbu $t4, 0($a0)
        add $t1, $t0, $t4

        lb $t2, 0($t1)
        add $t5, $t2, $0

        lbu $t4, 1($a0)
        add $t1, $t0, $t4

        lb $t3, 0($t1)
        or $t5, $t5, $t3

        sll $t3, $t3, 5
        or $t2, $t2, $t3

        lbu $t4, 2($a0)
        add $t1, $t0, $t4

        lb $t3, 0($t1)
        or $t5, $t5, $t3
        sll $t3, $t3, 10
        or $t2, $t2, $t3

        sh $t2, 0($a1)
        addi $a1, $a1, 2

        bgez $t5  PLOOP
        addi $a0, $a0, 3

        #
        ## Section
        #

        ori $t2, $t2, 0x8000

        jr $ra
        sh $t2, -2($a1)