# INEL 4206 - Microprocessors
# University of Puerto Rico Mayaguez
#
# Program that performs division by repeated subtraction
# The operands reside in global variables x and y
# The result of x/y ends up in global variable res
# The remainder of the division ends up in x
#
# Instructional Objectives
# + teach how to program control structures (while)
# + teach load and store pseudo instructions
# + teach how to use I/O system calls
# + teach how to implement simple procedures
#   (no params, no recursion, no return values)
# + teach how to implement procedures using stacks
#   (support recursion and procedures calling other procedures)
	.data				# Use HLL program as a comment
x:	.word	0			#   int x = 0;
y:	.word	0			#   int y = 0;
res:	.word	0			#   int res = 0;
pf1:	.asciiz "Result = "
pf2:	.asciiz "\nRemainder = "
	.globl	main
	.text
# main function 
# PENDING ISSUES: main must allocate a stack frame as well
main:					# main assumes registers sx unused
	sub	$sp, $sp, 28		# Alloc space for 28 byte stack frame
	sw	$a0, 24($sp)		# Save argument registers
	sw	$a1, 20($sp)		# a in $a0
	sw	$ra, 16($sp)		# Save other registers as needed
	sw	$s1, 12($sp)		# Save callee saved registers ($sx)
	sw	$s2, 8($sp)		
	sw	$s3, 4($sp)		# No need to save $s4, since not used
	sw	$s4, 0($sp)		# No need to save $s4, since not used
	li	$s1, 12			# x = 12;
	la	$s0, x
	sw	$s1, 0($s0)
	li	$s2, 5			# y = 5;
	la	$s0, y
	sw	$s1, 0($s0)
	li	$s3, 0			# res = 0;
	usw	$s3, res
	move	$s4, $ra		# Save $ra in $s4, callee saved

	move	$a0, $s1
	move	$a1, $s2
	jal	d			# res = div(a, b);
	move	$s3, $v0

	move	$ra, $s4		# Restore $ra
	la	$a0, pf1		# printf("Result = %d \n");
	li	$v0, 4			#   //system call to print_str
	syscall
	move	$a0, $s3		
	li	$v0, 1			#   //system call to print_int
	syscall
	lw	$a0, 24($sp)		# Restore saved registers
	lw	$a1, 20($sp)		# a in $a0
	lw	$ra, 16($sp)		# Save other registers as needed
	lw	$s1, 12($sp)		# Save callee saved registers ($sx)
	lw	$s2, 8($sp)		
	lw	$s3, 4($sp)		# No need to save $s4, since not used
	lw	$s3, 0($sp)		# No need to save $s4, since not used
	addu	$sp, $sp, 28		# pop stack frame
	jr	$ra			# return; 

# div function
# 
					# int div(int a, int b) {
d:	sub	$sp, $sp, 28		# Alloc space for 28 byte stack frame
	sw	$a0, 24($sp)		# Save argument registers
	sw	$a1, 20($sp)		# a in $a0
	sw	$ra, 16($sp)		# Save other registers as needed
	sw	$s1, 12($sp)		# Save callee saved registers ($sx)
	sw	$s2, 8($sp)		
	sw	$s3, 4($sp)		# No need to save $s4, since not used
	li      $s3, 0
	sw	$s3, 0($sp)		# int res = 0;
					# Allocate registers for locals
	lw	$s1, 24($sp) 		#   a in $s1
	lw	$s2, 20($sp)		#   b in $s2
	lw	$s3, 0($sp)		#   res in $s3

if:	bgt	$s2, $s1, else		# if (a >= b) {
	sub	$a0, $s1, $s2		#   
	move	$a1, $s2
	jal	d			#   
	addi	$s3, $v0, 1		#   res = div(a-b, b) + 1;
	j	endif			# }
else:	li	$s3, 0			# else { res = 0; }
endif:				
	sw	$s1, 32($sp) 		#   a in $s1
	sw	$s2, 28($sp)		#   b in $s2
	sw	$s3, 0($sp)		#   res in $s3
	move	$v0, $s3		# return res

	lw	$a0, 24($sp)		# Restore saved registers
	lw	$a1, 20($sp)		# a in $a0
	lw	$ra, 16($sp)		# Save other registers as needed
	lw	$s1, 12($sp)		# Save callee saved registers ($sx)
	lw	$s2, 8($sp)		
	lw	$s3, 4($sp)		# No need to save $s4, since not used
	addu	$sp, $sp, 28		# pop stack frame
enddiv:	jr	$ra			# return; 
#

