# INEL 4206 - Microprocessors
# University of Puerto Rico Mayaguez
#
# Instructional Objectives
# + teach fundamentals of array implementations
	.data				
array:	.word	0			
	.word	1			
	.word	2
	.word	3			
	.word	4			
	.word	5
	.word	6			
	.word	7
	.word	8
	.word	9
length:	.word	10
obsize:	.word	4
newline:.asciiz "\n"
finish:	.asciiz "Finished!\n"
invert:	.asciiz "Inverted!\n"
	.globl	main
	.text
# main function 
main:					# void main() {
	sub	$sp, $sp, 40		# Push main stack frame
	sw	$a0, 36($sp)		# Save argument registers
	sw	$a1, 32($sp)		# 
	sw	$a2, 28($sp)		# 
	sw	$a3, 24($sp)		
	sw	$ra, 20($sp)		# Save other registers as needed
	sw	$fp, 16($sp)		
	sw	$s0, 12($sp)		# Save callee saved registers ($sx)
	sw	$s1, 8($sp)		
	sw	$s2, 4($sp)		#
	sw	$s3, 0($sp)		# 
	addu	$fp, $sp, 36		# Establish frame pointer
					# Allocate registers for locals
	la	$t0, array
	move	$a0, $t0
	la	$t0, length
	lw	$a1, 0($t0)
	jal	parray			#   parray(array, length)

	la	$a0, array
	la	$t0, length
	lw	$a1, 0($t0)
	jal	iarray			#   iarray(array, length)

	la	$a0, invert
	li	$v0, 4			#
	syscall				#     printf("Finished!\n"); 
	
	la	$a0, array
	la	$t0, length
	lw	$a1, 0($t0)
	jal	parray			#   parray(array, length)

	la	$a0, finish
	li	$v0, 4			#
	syscall				#     printf("Finished!\n"); 
	
	lw	$a0, 36($sp)		#   restore caller's registers
	lw	$a1, 32($sp)		# 
	lw	$a2, 28($sp)		# 
	lw	$a3, 24($sp)		
	lw	$ra, 20($sp)		#   
	lw	$fp, 16($sp)		
	lw	$s0, 12($sp)		#   
	lw	$s1, 8($sp)		
	lw	$s2, 4($sp)		# 
	lw	$s3, 0($sp)		# 
	addu	$sp, $sp, 40		#   pop stack frame
	jr	$ra			# }

parray:	
	sub	$sp, $sp, 40		# Push main stack frame
	sw	$a0, 36($sp)		# Save argument registers
	sw	$a1, 32($sp)		# 
	sw	$a2, 28($sp)		# 
	sw	$a3, 24($sp)		
	sw	$ra, 20($sp)		# Save other registers as needed
	sw	$fp, 16($sp)		
	sw	$s0, 12($sp)		# Save callee saved registers ($sx)
	sw	$s1, 8($sp)		
	sw	$s2, 4($sp)		# 
	sw	$s3, 0($sp)		#
	addu	$fp, $sp, 36		# Establish frame pointer
					# Allocate registers for locals
	move	$s0, $a0		#   array base address in $s0
	move	$s1, $a1		#   array length in $s1
	li	$s2, 0			#   loop index i in $s2
	la	$t0, obsize		#   object size in $s3
	lw	$s3, 0($t0)		#   
	blez	$s1, endfor1
for1:	multu	$s3, $s2		#   for(int i=0; i<length; i++) {
	mflo	$t0
	addu	$t0, $t0, $s0
	lw	$a0, 0($t0)
	li	$v0, 1			#
	syscall				#     printf("%d", array[i]); 
	la	$a0, newline
	li	$v0, 4			#
	syscall				#     printf("%d", array[i]); 
	addi	$s2, 1
	blt	$s2, $s1, for1		#   }
endfor1:	
	lw	$a0, 36($sp)		# Save argument registers
	lw	$a1, 32($sp)		# 
	lw	$a2, 28($sp)		# 
	lw	$a3, 24($sp)		
	lw	$ra, 20($sp)		# Save other registers as needed
	lw	$fp, 16($sp)		
	lw	$s0, 12($sp)		# Save callee saved registers ($sx)
	lw	$s1, 8($sp)		
	lw	$s2, 4($sp)		# 
	lw	$s3, 0($sp)		#
	addu	$sp, $sp, 40		# Establish frame pointer
	jr	$ra			#   return; 
					# }
iarray:	
	sub	$sp, $sp, 44		# Push main stack frame
	sw	$a0, 40($sp)		# Save argument registers
	sw	$a1, 36($sp)		# 
	sw	$a2, 32($sp)		# 
	sw	$a3, 28($sp)		
	sw	$ra, 24($sp)		# Save other registers as needed
	sw	$fp, 20($sp)		
	sw	$s0, 16($sp)		# Save callee saved registers ($sx)
	sw	$s1, 12($sp)		
	sw	$s2, 8($sp)		# 
	sw	$s3, 4($sp)		#
	sw	$s4, 0($sp)		#
	addu	$fp, $sp, 40		# Establish frame pointer
					# Allocate registers for locals
	move	$s0, $a0		#   array base address in $s0
	move	$s1, $a1		#   array length in $s1
	li	$s2, 0			#   loop index i in $s2
	la	$t0, obsize		#   object size in $s3
	lw	$s3, 0($t0)		#   
	blez	$s1, endfor2
	sra	$s4,$s1,1
for2:					#   for(int i=0; i<length/2; i++) {
	multu	$s3, $s2		#     
	mflo	$t0			#     
	addu	$t0, $t0, $s0		#     // address of array[i] in t0
	lw	$t1, 0($t0)		#     temp(t1) = array[i];
	li	$t4, 1
	subu	$t2, $s1, $t4	
	subu	$t2, $t2, $s2
	multu	$s3, $t2		#     
	mflo	$t2			#     
	addu	$t2, $t2, $s0		#     // address of array[n-i-1] in t2
	lw	$t3, 0($t2)		#
	sw	$t3, 0($t0)		#     array[i] = array[n-i-1]
	sw	$t1, 0($t2)		#     array[n-i-1] = temp
	addi	$s2, 1
	blt	$s2, $s4, for2		#   }
endfor2:
	lw	$a0, 40($sp)		# Save argument registers
	lw	$a1, 36($sp)		# 
	lw	$a2, 32($sp)		# 
	lw	$a3, 28($sp)		
	lw	$ra, 24($sp)		# Save other registers as needed
	lw	$fp, 20($sp)		
	lw	$s0, 16($sp)		# Save callee saved registers ($sx)
	lw	$s1, 12($sp)		
	lw	$s2, 8($sp)		# 
	lw	$s3, 4($sp)		#
	lw	$s4, 0($sp)		#
	addu	$sp, $sp, 44		# Establish frame pointer
	jr	$ra			#   return; 
					# }
