################################################################################
##
## LSU EE 4720 Spring 2021 Homework 1 -- SOLUTION
##
##

################################################################################
## Problem 1
#
#  Instructions: https://www.ece.lsu.edu/ee4720/2021/hw01.pdf
#  Solution narrative: https://www.ece.lsu.edu/ee4720/2021/hw01_sol.pdf

.text

getbit:
        ## Register Usage
        #
        # CALL VALUES
        #  $a0: Address of start of array.
        #  $a1: Bit number to retrieve.
        #
        # RETURN
        #  $v0: This bit. (Zero or one.)
        #
        # Note:
        #  Can modify $t0-$t9, $a0-$a3
        #
        # [✔] Test code should show 0 errors.
        # [✔] Code should be correct.
        # [✔] Code should be reasonably efficient.
        # [✔] Do not use pseudoinstructions except for nop and la.

        ## SOLUTION -- Problem 1a.
        #
        srl $t0, $a1, 3     # Compute byte offset from $a0.
        add $t0, $a0, $t0   # Compute address of byte holding bit.
        lbu $t1, 0($t0)     # Load that byte.
        andi $t2, $a1, 0x7  # Compute bit number within loaded byte.
        addi $t2, $t2, 24   # Find left shift amt that puts needed bit in MSB.
        sllv $t1, $t1, $t2  # Shift so that needed bit is most-significant.
        jr $ra
        srl $v0, $t1, 31    # Shift so that needed bit is least significant.

        


################################################################################
## Testbench Routine
#
# 


        .data
        .align 4
bit_vector_start:  # Note: MIPS is big-endian.
        .byte 0xc5, 0x1f
        .half 0x05af
        .word 0xedcba987
        .ascii "1234"
bit_vector_end:
testdata:
        ## SOLUTION -- Problem 1b.
        #
        #  The "1234" above follows two bytes, one half, and one word.
        #  The total size of these is 2*1 + 2 + 4 = 8 bytes. So the
        #  "1" in "1234" starts at bit 8 * 8 = 64, which is the
        #  most-significant bit of the "1". The ASCII for "1" is 0x31
        #  and "2" is 0x32, these differ in the least-significant bit,
        #  so we need to check bit 64 + 7 = 71. It will be 1 for "1".
        .half 71, 1   # Solution to 1b.


        .half 0, 1
        .half 4, 0
        .half 10, 0
        .half 16, 0,  20,0,  21,1,         # The part specified using ".half"
        .half 32,1    35,0,  39,1,  63,1,  # The part specified using ".word"
        .half 5, 1
        .half 6, 0
        .half 1, 1
        .half 2, 0
        .half 11, 1
        .half 12, 1
        .half 13, 1
        .half 3, 0
        .half 7, 1
        .half 8, 0
        .half 9, 0
        .half 14, 1
        .half 15, 1
        .half -1, -1

msg_good:
        .asciiz "Bit number: %/a1/3d  Val: %/s4/1d, correct\n"
msg_bad:
        .asciiz "Bit number: %/a1/3d  Val: %/s4/1d, wrong. Correct val: %/s5/1d\n"

msg_done:
        .asciiz "Done with tests, %/s6/d errors.\n";

        .text

        .globl __start
__start:
        la $s0, bit_vector_start
        la $s1, testdata
        addi $s6, $0, 0

TB_LOOP:
        addi $a0, $s0, 0
        lh $a1, 0($s1)
        bltz $a1, TB_DONE
        nop
        jal getbit
        nop
        addi $s4, $v0, 0
        lhu $s5, 2($s1)
        la $a0, msg_good
        beq $v0, $s5, TB_CORRECT
        lh $a1, 0($s1)
        la $a0, msg_bad
        addi $s6, $s6, 11
TB_CORRECT:
        addi $v0, $0, 11
        syscall
        nop
        j TB_LOOP
        addi $s1, $s1, 4

TB_DONE:
        la $a0, msg_done
        addi $v0, $0, 11
        syscall
        nop

        addi $v0, $0, 10
        syscall
        nop