All pastes #914820 Raw Edit

k4st

public text v1 · immutable
#914820 ·published 2008-02-23 05:53 UTC
rendered paste body
! ****************************************************************************
! Peter Goodman
! Student ID: 250 379 503
! Assignment: 3
! File: divide.m:
! Description:
! 	Perform 32 bit signed integer division.
!
! 	To determine the sign of the quotient, one can test the high order bits
!	and xor them. If both zero, then result (0) is positive. If one is
!	negative, then the result (1) is negative. If both are negative, then the
!	result (0) is positive.
!
!	Given that we can test if we are working with negative numbers, we can take
!	advantage of the unsigned integer division algorithm and negate registers
!	where necessar. Then, negate the final answer if necessary.
! ****************************************************************************

! macro definitions

define(divisor_r, l0)
define(quotient_r, l1)
define(remainder_r, l2)
define(garbage_r, g0)

define(bit_counter_r, l3)
define(negative_test_r, l4)

define(PROMPT, '>')
define(NEW_LINE, '\n')
define(DIVIDE_BY_ZERO, 'X')

define(LOW_ORDER_BIT, 1)
define(NUM_BITS, 32)

! begin program

	.global main

main:	
	save %sp, -96, %sp
	
	/* Initialize the registers */
	mov 0, %divisor_r
	mov 0, %remainder_r
	mov 0, %negative_test_r
	mov NUM_BITS, %bit_counter_r
	
	/* Display a prompt and begin reading in a division expression */
	
	call writeChar								! write out the prompt
	mov PROMPT, %o0
	
	call readInt								! read in the numerator
	nop
	mov %o0, %quotient_r
	
	/* Check to see if numerator is negative, if so, set %negative_test_r to
	   1, i.e. true.
	 */
	addcc %quotient_r, %quotient_r, %garbage_r
	bcc 1f
	nop
	
	neg %quotient_r								! negate the quotient
	mov 1, %negative_test_r	
	
1:	call readChar								! ignore the '/'
	nop
	
	call readInt								! read in the denominator
	nop
	mov %o0, %divisor_r
	
	/* Check to see if denominator is negative, if so, XOR with
	   %negative_test_r to see if the result of divison will be positive or
	   negative.
	 */	
	addcc %divisor_r, %divisor_r, %garbage_r
	bcc 2f
	nop
	
	/* We got a negative number, XOR with negative_test_r to see if final
	   result of division will be zero or 1.
	 */
	neg %divisor_r
	xor %negative_test_r, 1, %negative_test_r

	/* check for division by zero, skip over to return error */
2:	addcc %divisor_r, 0, %garbage_r
	be error
	nop
	
	/* Shift quotient_r one bit left, moving its high order bit into the
	   remainder_r.
	 */
divide:				
	
	add %remainder_r, %remainder_r, %remainder_r
	addcc %quotient_r, %quotient_r, %quotient_r
	
	bcc 1f										! the MSB was 0, ignore
	nop
	
	bset LOW_ORDER_BIT, %remainder_r			! set the LSB

	/* Subtract the divisor from the remainder. If the result is:
	 	negative: ignore
		positive: set the LSB of the quotient to 1
	*/
1:	subcc %remainder_r, %divisor_r, %remainder_r
	
	bneg 2f
	nop
	
	bset LOW_ORDER_BIT, %quotient_r				! set the LSB of the quotient
												! when remainder_r > divisor_r

	ba 3f
	nop
	
2:	add %divisor_r, %remainder_r, %remainder_r 	! restore it

	/* The bit counter keeps track of how many bits we've modified. When the
	   counter reaches zero, we are done.
	 */
3:	subcc %bit_counter_r, 1, %bit_counter_r
	be success
	nop
	
	/* Bit counter is greater than zero, go back and continue to divide. */
	
	ba divide									! repeat the division process
	nop
	
	/* Division algorithm has successfully completed. See if the quotient
	   needs to be negated, if so do that. Then, print out the quotient on one
	   line, followed by the remainder on another line.
	 */
success:
	
	/* Modify the sign of the quotient if necessary */
	orcc %negative_test_r, 0, %garbage_r
	be 1f
	nop
	
	/* quotient needs to be negative, so negate it */
	neg %quotient_r
	
	/* write out the final results. */
1:	call writeInt								! print out the quotient
	mov %quotient_r, %o0
	
	call writeChar
	mov NEW_LINE, %o0							! print a new line
	
	call writeInt								! print the remainder
	mov %remainder_r, %o0
	
	ba done										! done
	nop
	
	/* If there is a division-by-zero error, we will end up here. */
error:									
	call writeChar
	mov DIVIDE_BY_ZERO, %o0						! show 'X' as the error

done:
	
	call writeChar								! print a new line
	mov NEW_LINE, %o0
	
	ret											! done.
	restore