     .text
main:
     la    $a0, toSort
     li    $a1, 3
     jal   mergesort
     li    $v0, 10
     syscall
    
     .data
toSort:
     .word   3, 1, 2

     .text

# mergesort(p, n)
#    use mergesort technique to sort an array of integers
#    n integers stored at location p.
#    p will be passed in $a0, n in $a1
#    precondition: n>=0
#    Result: p[0..n) is sorted

# mergesort(p, n) {
#    if (n==1) return;
#    mergesort(p, n/2);
#    mergesort(p+(n/2), n-(n/2));
#    #!! remember that this is pointer addition!
#    merge(p, n/2, n-(n/2));
# }
 
mergesort:
# prolog
     addiu $sp, $sp, -20
     sw    $ra, 0($sp)
     li    $t0, 1
     ble   $a1, $t0, sortEpilog
     sw    $a0, 4($sp)   # store p
     sw    $a1, 8($sp)   # store n
# set up first recursive call
     sra   $a1, $a1, 1   # n/2
     sw    $a1, 12($sp)  # save n/2 for later
     jal   mergesort
# set up second recursive call     
     lw    $a0, 4($sp)   # p 
     lw    $a1, 8($sp)   # n

#     move  $t0, $a1      # n
#     sll   $t0, 1       # (n/2)*4 - incorrect!
     lw    $a1, 12($sp)
     sll   $a1, $a1, 2   # (n/2)*4  - correct!

#    add   $a0, $a0, $a1         # address of p+(n/2) in $a0
     add   $a0, $a0, $t0         # address of p+(n/2) in $a0 (bug)
     lw    $a1, 8($sp)   # n
     lw    $t0, 12($sp)  # n/2
     sub   $a1, $a1, $t0 # n - (n/2)
     sw    $a1, 16($sp)  # save n - (n/2) for later
     jal   mergesort
# set up call to merge
     lw    $a0, 4($sp)   # p
     lw    $a1, 12($sp)  # n/2
     lw    $a2, 16($sp)  # n - (n/2)
     jal   merge

sortEpilog:
     lw    $ra, 0($sp)
     addiu $sp, $sp, 20
     jr    $ra



# merge(p, n1, n2)
#   auxiliary procedure 
#   p - pointer to an array
#   n1 - number of elements in first segment
#   n2 - number of elements in second segment
#   precondition p[0..n1) is sorted and
#                p[n1+1..n1+n2) is sorted
#   postcondition: p[n1..n1+n2) is sorted
#   
# merge(p, n1, n2) {
#
#    # first make a copy
#    int tmp[n1+n2];
#    int *p1 = p;
#    int *p2 = tmp;
#    int *limit = &(tmp[p1+p2])
#    for (p1=p, p2=tmp; p2 < limit; p1++, p2++) {
#        *p2 = *p1;
#    }
#    p1 = tmp;
#    p2 = &tmp[n1];
#    int *p1limit = p2
#    int *p2limit = limit;
#    int *p3 = p;
#    
#    while (1) {
#       if ((p1 < p1limit) && (p2 < p2limit)) {
#          if (*p1 <= *p2) {w = *p1; p1++}
           else { w = *p2; p2++}
#       }
#       else if (p1 < p1limit) {w = *p1; p1++}
#       else if (p2 < p2limit) {w = *p2; p2++}
#       else break
#       *p3 = w; p3++
# }

merge:
#prolog


mergeepilog:
    jr    $ra
