.text
	j	main
.data
	
# #define MAXSIZE 20
# 
# // The values to be sorted
# int values[MAXSIZE];
values:	.space 	80
# 
# // How many values are in the values array
# int valc;
valc:	.word  	0





.text
#int atoi( char * str ) {   str in $a0
atoi:
#   int result = 0;
#   int p;
#
# REGISTER USAGE
#	result in $t0
#	p      in $t1

	li	$t0,0
#   for ( p = 0; str[p] != 0; p++ ) 
	li  	$t1,0
atoiLoopStart:
	move $t3,$t1
	add  $t3,$t3,$a0
	lb   $t2,($t3)              # str[p] now in $t2
	beq  $t2,$0,atoiLoopEnd
	
#   	if ( 0 <= str[p] && str[p] <= '9' ) {
  	
  	li   $t3,'0'
  	slt  $t3,$t2,$t3
  	bne  $t3,$0,atoiIfElse
  	
#    	  result = result * 10 + str[p]-`'0'`;
	subi	$t2,$t2,'0'
	li 	$t3,10
	mult	$t3,$t0
	mflo	$t0
	add	$t0,$t0,$t2
	j	atoiIfJoin
	
#       } else {
atoiIfElse:
#   	  return result;
	j	atoiLoopEnd
#   	}	
atoiIfJoin:
	addi $t1,$t1,1
	j atoiLoopStart
#    }
atoiLoopEnd:
	move  	$v0,$t0
	jr	$ra

#}






# 
# // Swap two parameters passed by reference
# void swap( int *x, int * y ) {
swap:
#   int temp;
#   
# REGISTER USAGE:
#	x = $a0, y=$a1, temp = $t0, 

#   temp = *x;
	lw	$t0,0($a0)
	
#   *x = *y;
	lw	$t1,0($a1)
	sw	$t1,0($a0)
	
#   *y = temp;
	sw	$t0,0($a1)
	
# }
	jr	$ra
# 







# // Split the array into two sections so that all
# // values in the first section are less than those
# // in the second
# int partition( int list[], int low, int high ) {
#   int left, right, mid, pivot;
partition:
#
# REGISTER USAGE/FRAME LAYOUT:
#
#	$s0 = list (from a0)	saved at 24($sp)
#       $s1 = low  (from a1)	saved at 20($sp)
#       $s2 = high (from a2)	saved at 16($sp)
# 	$s3 = left		saved at 12($sp)
# 	$s4 = right		saved at 8($sp)
# 	$s5 = pivot		saved at 4($sp)
# 	$ra			saved at 0($sp)
#				
# 	$t0 = mid

	subi	$sp,$sp,28
	sw	$ra,0($sp)
	sw	$s5,4($sp)
	sw	$s4,8($sp)
	sw	$s3,12($sp)
	sw	$s2,16($sp)
	sw	$s1,20($sp)
	sw	$s0,24($sp)
	
	move	$s0,$a0
	move	$s1,$a1
	move	$s2,$a2
	
#   mid = (low + high )/2;
	add	$t0,$s1,$s2
	sra	$t0,$t0,1
	
#   swap(&list[low],&list[mid]);
	sll	$t1,$s1,2
	add	$a0,$t1,$s0
	sll	$a1,$t0,2
	add	$a1,$s0,$a1
	jal	swap
		
#   pivot = list[low];
	sll	$t1,$s1,2
	add	$t1,$t1,$s0
	lw	$s5,($t1)
	
#   left = low+1;
	addi	$s3,$s1,1
	
#   right = high;
	move	$s4,$s2
	
#   while(left <= right) {
partitionLoop:
	slt	$t1,$s4,$s3
	bne	$t1,$0,partitionLoopEnd

#       while((left <= high) && (list[left] <= pivot)) {
leftLoop:
	slt	$t1,$s2,$s3
	bne	$t1,$0,leftLoopEnd
	sll	$t1,$s3,2
	add	$t1,$t1,$s0
	lw	$t1,0($t1)
	slt	$t1,$s5,$t1
	bne	$t1,$0,leftLoopEnd
	
# 	left++;
	addi	$s3,$s3,1
	j	leftLoop
#       }
leftLoopEnd:
#       while((right >= low) && (list[right] > pivot)) {
rightLoop:
	slt	$t1,$s4,$s1
	bne	$t1,$0,rightLoopEnd
	sll	$t1,$s4,2
	add	$t1,$t1,$s0
	lw	$t1,($t1)
	slt	$t1,$s5,$t1
	beq	$t1,$0,rightLoopEnd
	
# 	right--;
	addi	$s4,$s4,-1
	j	rightLoop
#       }
rightLoopEnd:
#       if( left < right) {
	slt	$t1,$s3,$s4
	beq	$t1,$0,partitionIfSkip
	
# 	swap(&list[left],&list[right]);
	sll	$a0,$s3,2
	add	$a0,$a0,$s0
	sll	$a1,$s4,2
	add	$a1,$s0,$a1
	jal	swap


partitionIfSkip:
#       }
	j 	partitionLoop
#     }
partitionLoopEnd:
#   // swap two elements
#   swap(&list[low],&list[right]);
	sll	$a0,$s1,2
	add	$a0,$a0,$s0
	sll	$a1,$s4,2
	add	$a1,$s0,$a1
	jal	swap

#   return right;
	move	$v0,$s4

	lw	$ra,0($sp)
	lw	$s5,4($sp)
	lw	$s4,8($sp)
	lw	$s3,12($sp)
	lw	$s2,16($sp)
	lw	$s1,20($sp)
	lw	$s0,24($sp)
	addi	$sp,$sp,28
	jr	$ra
# }
# 
# // Sort an array of integers using the quicksort algorithm
# void quicksort(int list[], int low, int high ) {
#   int mid;

quicksort:
# REGISTER USAGE                STACK FRAME
#	list = a0               saved at 16($sp)
#       low  = a1		saved at 12($sp)
#       high = a2		saved at 8($sp)
#       mid = s0		saved at 4($sp)
#	$ra			saved at 0($sp)
#
# PROLOGUE:
    	addiu 	$sp,$sp,-20
    	sw	$a0,16($sp)
    	sw	$a1,12($sp)
    	sw      $a2,8($sp)
    	sw      $s0,4($sp)
    	sw      $ra,0($sp)
    	
    	   	
#   if( low < high) {
    	slt	$t0,$a1,$a2
    	beq	$t0,$0,skipIf
    	
#     // partition the list into two sublists
#     mid = partition( list, low, high );
    	jal		partition
    	move	$s0,$v0
# 
#     // recursively sort the lesser list
#    quicksort(list, low, mid-1);
	lw	$a0,16($sp)
	lw	$a1,12($sp)
    	addi	$a2,$s0,-1
    	jal		quicksort
    
#     quicksort(list, mid+1, high);
	lw	$a0,16($sp)	
    	addi	$a1,$s0,1
    	lw	$a2,8($sp)
    	jal	quicksort
#   }
skipIf:

# EPILOGUE
# Note: no need to restore $ai registers
   	lw	$s0,4($sp)
    	lw	$ra,0($sp)
    	addiu	$sp,$sp,20
    	jr	$ra

# }
# 
# 
# 
# // Takes up to 20 numeric arguments and sorts them in descending order
# int main( int argc, char * argv[] ) {
#   int p;
main:
# REGISTER USAGE:
#	argc = $s0
#	argv = $s1
#	p    = $s2
# 
	move	$s0,$a0
	move	$s1,$a1

#   for ( p = 0; p < argc; p++ ) {
	li	$s2,0
inputLoop:
	slt	$t0,$s2,$s0
	beq	$t0,$0,inputLoopEnd
	
#     values[p] = atoi( argv[p] );
	sll	$a0,$s2,2
	add	$a0,$a0,$s1
	lw	$a0,($a0)
	jal	atoi
	la	$t0,values
	sll	$t1,$s2,2
	add	$t0,$t0,$t1
	sw	$v0,($t0)

	addi	$s2,$s2,1
	j inputLoop
inputLoopEnd:
#   }
# 
# 
#   // HEAP SORT!
# 
#   quicksort( values, 0, argc-1 );
	la	$a0,values
	li	$a1,0
	addi	$a2,$s0,-1
	jal	quicksort
# 
#  // Print the result
#  for ( p = 0; p < valc; p++ ) {    

	li	$s2,0
printLoopStart:
	slt	$t0,$s2,$s0
	beq	$t0,$0,printLoopEnd
	
	
#    printf( "%d ", values[p] );
	li	$v0,1
	move	$t0,$s2
	sll	$t0,$t0,2
	la	$t1,values
	add	$t0,$t0,$t1
	lw	$a0,($t0)
	syscall
	
	li	$v0,4
	la	$a0,blank
	syscall

	addi	$s2,$s2,1
	j printLoopStart
printLoopEnd:
#  }
#
#  printf( "\n" );
	li	$v0,4
	la	$a0,newLine
	syscall
#
#  
#}
	li	$v0,10
	syscall

.data
blank:	.asciiz " "
newLine: .asciiz "\n"
quickSrt: .asciiz "quickSort( [ "
comma:		.asciiz ", "
rightBrace: .asciiz "], "
rightParen: .asciiz ")\n"
