.data
doi:
        .ascii "We hold these truths to be self-evident that all men "
        .ascii "are created equal, that they are endowed by their "
        .ascii "Creator with certain unalienable Rights, that among "
        .ascii "these are Life, Liberty, and the pursuit of "
        .ascii "Happiness. That to secure these rights, Governments "
        .ascii "are instituted among Men, deriving their just powers "
        .ascii "from the consent of the governed.  That whenever any "
        .ascii "Form of Government becomes destructive of these ends, "
        .ascii "it is the Right of the People to alter or to abolish "
        .ascii "it, and to institute new Government, laying its "
        .ascii "foundation on such principles and organizing its "
        .ascii "powers in such form, as to them shall seem most likely "
        .asciiz "to effect their Safety and Happiness "

msg:
        .asciiz "Letter %/t3/c  count: %/t1/3d (%/f4/6.2f%%) %/t5/s\n";

        .align 4
histogram_data:
        .space 104
stars:
        .space 40

        .text
        .globl __start
__start:
        la $a0, doi
        la $a1, histogram_data
        addi $t1, $a1, 0
        addi $t2, $t1, 100
L3:
        sw $0, 0($t1)
        bne $t1, $t2, L3
        addi $t1, $t1, 4

        la $t1, stars
        addi $t2, $t1, 40
        addi $t3, $0, 42  # '*'
L4:
        sb $t3, 0($t1)
        bne $t1, $t2, L4
        addi $t1, $t1, 1
        sb $0, 0($t1)

        jal strlen
        nop
        mtc1 $v0, $f2
        cvt.d.w $f2, $f2
        addi $v0, $0, 100
        mtc1 $v0, $f4
        cvt.d.w $f4, $f4
        div.d $f2, $f4, $f2

        jal histo
        nop
        add $t0, $0, $0
        addi $t3, $0, 64
        addi $t4, $t3, 26
        la $s1, histogram_data
        addi $v0, $0, 11
        la $s2, stars
        addi $s2, $s2, 41
L2:
        lw $t1, 0($s1)
        addi $s1, $s1, 4
        beq $t1, $0, TEST
        addi $t3, $t3, 1
        srl $t6, $t1, 1
        sub $t5, $s2, $t6
        mtc1 $t1, $f0
        cvt.d.w $f0, $f0
        mul.d $f4, $f0, $f2
        syscall
TEST:
        bne $t3, $t4, L2
        nop

        addi $v0, $0, 10
        syscall


################################################################################
## histo: Compute Character Usage Histogram

histo:
        ## Register Usage
        #
        # Call: $a0  String to analyze.
        #       $a1  Address of table.  Each element is an integer.

        addi $s0, $ra, 0    # Make a copy of the return address.
        jal upper           # Convert to upper case.
        addi $t0, $a0, 0    # Make a copy of string start address.
        addi $ra, $s0, 0    # Restore return address.

LOOP:
        lbu $t1, 0($t0)     # Load a character.
        addi $t0, $t0, 1    # Increment address.
        beq $t1, $0, DONE   # Check for null termination.
        addi $t1, $t1, -65  # Set $t1 to table index. ( A->0, B->1, etc.)
        sltiu $t2, $t1, 26  # If $t1 is >= 26 then it's not a letter.
        beq $t2, $0, LOOP   # Note that comparison above is unsigned.
        sll $t1, $t1, 2     # Scale index.
        add $t3, $a1, $t1   # Add index on to address of first element
        lw $t4, 0($t3)      # Load histogram entry.
        addi $t4, $t4, 1
        j LOOP
        sw $t4, 0($t3)      # Store the incremented value.

DONE:
        jr $ra
        nop


################################################################################
## upper: Convert to Upper Case

upper:
        ## Register Usage
        #
        # $a0: (Call) Address of string to convert.
        #
        # $a0: Address of character being examined.
        # $t1: Character being examined.
        # $t2: Comparison result.
ULOOP:
        lbu $t1, 0($a0)
        addi $a0, $a0, 1
        beq $t1, $0, UDONE
        slti $t2, $t1, 97 # < 'a'
        bne $t2, $0 ULOOP
        slti $t2, $t1, 123 # 'z' + 1
        beq $t2, $0, ULOOP
        addi $t1, $t1, -32
        j ULOOP
        sb $t1,-1($a0)

UDONE:
        jr $ra
        nop


################################################################################
## strlen: String Length

strlen:
        ## Register Usage
        #
        # $a0: Address of first character of string.
        # $v0: Return value, the length of the string.
        #
        # $t0: Character being examined.
        # $t1: Address of current character being examined.
        #
        addi $t1, $a0, 0
SLOOP:
        lbu $t0, 0($t1)
        bne $t0, $0, SLOOP
        addi $t1, $t1, 1

        addi $t1, $t1, -1
        jr $ra
        sub $v0, $t1, $a0