#----------------------------------------------------------------------------------
#        This program contains 2 procedires:
#
#		div: Perform division arithmetic
#
#		main: Test the division for different numbers
#
#
#
#----------------------------------------------------------------------------------

		.text

#----------------------------------------------------------------------------------
#		Procedure name: div
#			It divides one 32-bit number by another
#
#
#		Register allocation
# 		Inputs:
#			$4 = dividend  - the number to divide
#			$5 = divisor   - the number to divide by
#		Output:
#			$6 = quotient  - the result of the division
#			$7 = remainder - what remains after the division
#			$12: 	0->divion was a success
#				1->Division was a failure
#		Other registers used
#			$13 Temporary test register
#			$14 Temporary test register
#			$15 More Random testing and "shifts"
#			$16 dividend_sign
#			$17 divisor_sign
#
#----------------------------------------------------------------------------------
#		First, cover our tracks with the stack
#---------------------------------------------------------------------------------

divi:	addi $29, $29, -28	#Decrement stack pointer
		sw $4, 24($29)		#Saves $4 for restore on exit (stackE-1)
		sw $5, 20($29)		#Saves $5 for restore on exit (stackE-2)
		sw $13, 16($29)		#Save $13 for restore on exit (StackE-3)
		sw $14, 12($29)		#Save $14 for restore on exit (StackE-4)
		sw $15, 8($29)		#Save $15 for restore on exit (StackE-5)
		sw $16, 4($29)		#Save $16 for restore on exit (StackE-6)
		sw $17, 0($29)		#Save $17 for restore on exit (StackE-7)


#--------------------------------------------------------------------------------
#		Check for divide by zero or 0x80000000
#		C source code:
#		  if (divisor == 0 || divisor == 0x80000000 || dividend == 0x80000000)
#				{
#   				return ERROR;
# 				}
#		We also determin the value returned by the function, stored in $12
#			$12=0 ->Success
#			$12=1 ->Error
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#		Initially, i was passing the actual elements in $4 and $5. I changed it to
#		passing the adress, but my "div" was already done and working great. This is why
#		I will "recycle" those registers. Since the elements have already been printed,
#		once they are loaded, there is no deed to save their adress anymore.
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

		lw $4, 0($4)			#loads the dividend in $4 from its address in $4
		lw $5, 0($5)			#Loads the divisor in $5 from its address in $5


		beq $5, $0, failnout	#If divisor !=0, proceed with devision
		lui $15, 0x8000			#Equivalent to $15=0x8000 0000
		beq $5, $15, failnout	#If divisor !=0x80000000, proceed with devision
		beq $4, $15, failnout	#If dividend !=0x80000000, proceed with division

#------If we didnt fail any test, we can go ahead and devide----------------------------
		addi $12, $0, 0		#loads 0 for success in the "success" register
		b div10				#Jumps to the division

#-------Otherwise, we need to return an error code---------------------------------
failnout:	addi $12, $0, 1		#Failure code loaded in success register
			b Exitdiv			#Not much more to do but go back to main and share the bad news


#----------------------------------------------------------------------------------
#		Now that the illegal operation tests are passed we can devide.
#
#		First step: Check and remove signs from dividend and divisor
#
#		C source code:
#			dividend_sign = 0;
#			divisor_sign = 0;
#
#			if (dividend < 0)
#				{
#				dividend_sign = 1;
#				dividend = -dividend;
#				}
#
#			if (divisor < 0) {
#				divisor_sign = 1;
#				divisor = -divisor;
#				}
#----------------------------------------------------------------------------------


div10:	slt $16, $4, $0			#If dividend($4)<0, dividend sign($16)=1
		beq $16, $0, div20		#If dividend +, skip the next step
		sub $4, $0, $4			# 0-(-dividend) = (+dividend)

div20:	slt $17, $5, $0			#If divisor($5)<0, divisor sign($17)=1
		beq $17, $0, div30		#If dividend +, skip the next step
		sub $5, $0, $5			# 0-(-dividend) = (+dividend)


#----------------------------------------------------------------------------------
#		initialisation of division
#		Source C code:
#
#			shifts = 0;
#			*remainder = dividend;
#			*quotient = 0;
#----------------------------------------------------------------------------------

div30:	addi $15, $0, 1		#shifts ($15)=1 (because of the nature of subsequent testing)
		add $7, $0, $4		#remainder($7) = dividend($4)
		add $6, $0, $0		#Quotient ($6) = 0


#----------------------------------------------------------------------------------
#		Shift divisor until most significant bit is set
#		Source C code
#			while ((divisor & 0x40000000) != 0x40000000) {
#			    divisor = divisor << 1;
#			    ++shifts;
#				  }
#-----------------------------------------------------------------------------------

div40:	lui $13, 0x4000		#$13= 10000...31 zeros...0


div41:	and $14, $13, $5	#Masks the most significant bit of divisor
		beq $13, $14, div50	#Once MSB divisor=1, $13=$14. We can branch out
		sll $5, $5, 1		#divisor = divisor<<1
		addi $15, $15, 1	#Increment Shift counter by 1
		b div41				#Jump back to the start of the loop to do the test


#------------------------------------------------------------------------------------
#		Subtract and shift loop
#		Source C code
#			for (i = 0; i <= shifts; ++i)
#				{
#				*quotient = *quotient << 1;
#				if (*remainder - divisor >= 0)
#					{
#					*remainder -= divisor;
#					*quotient += 1;
#					}
#				divisor = divisor >> 1;
#				}
#--------------------------------------------------------------------------------------

div50:	beq $15, $0, div70	#Once shift = 0, we and jump out of the loop and adjust signs
		sll $6, $6, 1		#Quotient = Quotient <<1
		sub $13, $7, $5		#$13 = remainder - divisor
		slt $14, $13, $0	#If remainder - divisor >=0 $14=0
		bne $14, $0, div60	#If remainder - divisor <0, skip the next 2 lines
		sub $7, $7, $5		#remainder = remainder - divisor
		addi $6, $6, 1		#Quotient +=1

div60:	srl $5, $5, 1		#divisor = divisor >>1
		addi $15, $15, -1	#Shift is decremented by 1
		beq $0, $0, div50	#Jump back to the top of the loop

#----------------------------------------------------------------------------------
#		Restoring the sign on the result
#
#		C source code
#			 if (divisor_sign ^ dividend_sign)
# 				{
#   			*quotient = -*quotient;
#  				}
#
#			if (dividend_sign)
#				{
#			   *remainder = -*remainder;
#				 }
#
#----------------------------------------------------------------------------------
#		If the signs were ++ or -- (11 and 00), we dont need to adjust the quotient
#----------------------------------------------------------------------------------

div70:	addi $15, $0, 0		#Set $15=0
		xor $15, $16, $17	#If signs were 1 0 xor 0 1, $15=1
		beq $15, $0, div80	#If $15=0, +/+ or -/-, skip next step
		sub $6, $0, $6		#Flip the sign on the quotient

div80:	beq$16, $0, Exitdiv	#if the dividend +, reminader+. Skip next step
		sub $7, $0, $7		#If dividend-, flip the sign of the remainder


#---------Prety much done here. Restore registers and teleport to main--------------

Exitdiv:	lw $4, 24($29)		#Restores $4 (stackE-1)
		lw $5, 20($29)		#Restores $5 (stackE-2)
		lw $13, 16($29)		#Restores $13 (StackE-3)
		lw $14, 12($29)		#Restores $14 (StackE-4)
		lw $15, 8($29)		#Restores $15 (StackE-5)
		lw $16, 4($29)		#Restores $16 (StackE-6)
		lw $17, 0($29)		#Restores $17 (StackE-7)

		addi $29, $29, 28	#Reincrement stack pointer to top of stack

		jr $31				#Go back to main with our precious results


#----------------------------------------------------------------------------------
#       Procedure Name: Main
#
#       Description: Performs the following tests to div
#			Divide by 0:  1 / 0
#			Divide positive by negative:  9 / -4
#			Divide negative by positive: -9 /  4
#			Divide negative by negative: -9 / -4
#			Use max as dividend:  2147483647 /  4
#			Use max as divisor:   4 / 2147483647
#			Use min as dividend: -2147483648 / 4
#			Use min as divisor:  4 / -214783648
#			Divide by 1: 4 / 1
#			Divide by -1: 4 / -1
#
#       Register Allocation:
#				$4  address of Dividend
#  				$5  address of Divisor
#				$6  Quotient
#				$7  Remainder
#				$8	slt for test loop
#				$9	Dividendt start address
#				$10	Divisort start address
#				$12 Division success value
#				$16	Offset for array access
#				$17 "i" to access array element
#
#
#
#----------------------------------------------------------------------------------

	.globl main

main:	addi $16, $0, 0			#Sets the offset [i] to 0
		la $9, Dividendt		#Saves address of dividendtestarray[0] in $9
		la $10, Divisort		#Saves address of start of Divisortestarray[0] in $10





#__________________________________________________________________________________
#		C source code
#
#  for (i = 0; i < TESTS; ++i)
#  {
#    printf("%d divided by %d ", dividend[i], divisor[i]);
#
#
#----------------------------------------------------------------------------
#		First we load and print dividend[i]
#----------------------------------------------------------------------------


main10:	add $4, $9, $16		#Adds the offset+start adress of dividendarray (sets[i])
		
#----------------------------------------------------------------------------
#		Since we are forced by the assignment to use $4 for passing dividend
#		address, and we need $4 like a million times for syscall, we save the
#		value of it on the stack for now
#----------------------------------------------------------------------------

		addi $29, $29, -4	#Decrements the stack pointer
		sw $4, 0($29)		#Pushes $4 on the stack

#----------------------------------------------------------------------------
#		Finally we can use syscall with peice of mind  :)
#		We print out "... devided by -divisor[i]-..."
#----------------------------------------------------------------------------

		lw $4, 0($4)		#Loads the ith element of the dividend array in $17
		li $2, 1			#Code for printing integer
		syscall				#Prints dividend[i]

		la $4, String1		#Pointing to the string " divided by "
		li $2, 4			#Syscall code for printing strings
		syscall				#Prints out " divided by "

		add $5, $10, $16	#Adds the offset+start address of the diviser array (sets[i])
		lw $4, 0($5)		#Pust divisor[i] in $4 for printing
		li $2, 1			#Code for printing integers
		syscall				#Prints divisor[i]


#------------------------------------------------------------------------------
#		Now the magic begins!
#		The computer will devide both munbers
#
#		C code:
#		 result = div32 (dividend[i], divisor[i], &quotient, &remainder);
#
#		We will pass on the values $4=dividend[i] and $5=divisor[i]
#
#
#------------------------------------------------------------------------------

		lw $4, 0($29)		#Restore the dividend to $4, as per assignment requirements
		addi $29, $29, 4	#Align the pointer with the stack
		jal divi			#Jumps to divi and saves return address
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#		For some reason SPIM keeps giving me error when i call the functinon 
#		div or div32, so i had to call it divi, but everything else was already
#		labled div10, div20, div30, etc..., wuth brances and all.
#		Sorry for the incinsistency.Im sure you'll still be able to follow what goes on.
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


#-------------------------------------------------------------------------------
#
#			Now we evaluate the success of the division
#			Success:
#			$12: 0->divion was a success
#				 1->Division was a failure
#-------------------------------------------------------------------------------

		beq $12, $0, main20	#If everything was cool, skip the next part

#-----------Otherwise, there was a problem in the division----------------------
		la $4, Error		#loads the Error string in $4
		li $2, 4			#Syscall code for printing strings
		syscall				#Will print out error message

#-----------Now we go back to to our for loop------------------------------------
		b main30			#Branches to end of code. Will evaluate loop status




#--------------------------------------------------------------------------------
#
#		At this point, everything was cool in the division
#		All we have left to do is print out the result
#		C source code:
#    		else
#    			{
#      			printf("is %d remainder %d\n", quotient, remainder);
#    			}
#		Comming from div, we have
#				$6  Quotient
#				$7  Remainder
#
#---------------------------------------------------------------------------------

main20: la $4, Is		#Loads the "is" string in $4
		li $2, 4		#syscall code for printing strings
		syscall			#Prints out " is "

		add $4, $6, $0	#Puts the quotient in $4
		li $2, 1		#syscall code for printing integers
		syscall			#prints the value of the quotient

		la $4, Remainder#Loads the string " remainder " in $4
		li $2, 4		#siscall for printing out strings
		syscall			#Prints out " remainder "

		add $4, $7, $0	#The remainder is moved in $4
		li $2, 1		#Syscall code for printing integers
		syscall			#Prints out the remainder

		la $4, Enter	#Need to change the line
		li $2, 4		#Syscall code for printing strings
		syscall			#Equivalent of pressing enter=change line



#-----------------------------------------------------------------------------------
#		This is the end of the "for loop"
#		i < TESTS; ++i
#		We increment i by 1 and if i<TEST, we start over
#-----------------------------------------------------------------------------------

main30:	addi $16,$16, 4		#Increment the testarray pointer to the next address
		slti $8, $16, 37	#We have 10 elements to test = 0 + 9x4 = 36
		bne $8, $0, main10	#As long as $16<37, branch back to main10










#----------------------------------------------------------------------------------
#	Now that our tests are done, the program can terminate
#----------------------------------------------------------------------------------



Done:	li $2, 10			#Load exit code in $2
		syscall				#Done dizzle





#----------------------------------------------------------------------------------
#		Data
#----------------------------------------------------------------------------------

	.data

String1: 	.asciiz 	" divided by "
Is:			.asciiz		" is "
Remainder:	.asciiz		" remainder "
Enter:		.asciiz		"\n"
Error:		.asciiz		" Gives an error\n"

Dividendt: 	.word 		1 9 -9 -9 2147483647 4 0x80000000 4 4 4
Divisort: 	.word 		0 -4 4 -4 4 2147483647 4 0x80000000 1 -1

