.TITLE DIV64
.IDENT /V1.0/
.SBTTL 64-BIT BY 64-BIT DIVISION ROUTINE

; ROUTINE TO DIVIDE A 64 BIT NUMBER BY A 64 BIT NUMBER AND
; RETURN A 64 BIT RESULT AND 64 BIT REMAINDER
;
; LAST EDIT: 6-NOV-1987 12:53:40 
;
; AUTHOR:	PETER STADICK
;		CARGILL INC
;		P.O. DRAWER AR
;		RESERVE, LA 70084
;
; EDIT HISTORY:	CREATED MAY-87 PJS
;		MADE SEPERATE MODULE OCT-87 PJS
;
; CALLING PARAMETER LIST
;	 2(R5) = DIVIDEND ( INPUT PRESERVED )
;	 4(R5) = DIVISOR ( INPUT PRESERVED )
;	 6(R5) = REMAINDER ( OUTPUT )
;	10(R5) = QUOTIENT (OUTPUT)
;	12(R5) = STATUS 1=SUCCESS OR -3=OVERFLOW ( OUTPUT )
;
; THIS ROUTINE WILL DIVIDE THE DIVIDEND BY THE DIVISOR TO YEILD
; A QUOTIENT AND A REMAINDER. IF YOU TRY TO DIVIDE BY ZERO THE
; STATUS OF -3 WILL BE RETURNED. 
;
; THIS ROUTINE UTILIZES THE BIT SHIFT AND TEST SUBTRACT METHOD OF 
; DIVISION. A WORST CASE DIVISION WILL TAKE APPROX 15,000 INSTRUCTIONS.
;
; 2(R5) / 4(R5) = 10(R5) R 6(R5)
;            OR
; (R0) / (R1) = (R3) R (R2)
;
; CARRY BIT SET ON RETURN INDICATES OVERFLOW
;
;  REGISTER USAGE AFTER THIS POINT
; (R0) = DIVIDEND
; (R1) = DIVISOR
; (R2) = REMAINDER
; (R3) = QUOTIENT
;  R4  = DIVIDEND SHIFT COUNT OR STATUS
; (R5) = DIVISOR BIT SET BUFFER
;
; ALL REGISTERS ARE PRESERVED

.PSECT CLUNK,RO,I,LCL,REL
DIV64::
	MOV R0, -(SP)		; PRESERVE ALL REGISTERS
	MOV R1, -(SP)
	MOV R2, -(SP)
	MOV R3, -(SP)
	MOV R4, -(SP)
	MOV R5, -(SP)

	MOV 2(R5),R0		; DIVIDEND
	MOV 4(R5),R1		; DIVISOR
	MOV 6(R5),R2		; REMAINDER
	MOV 10(R5),R3		; QUOTIENT

	TST (R0)		; CHECK FOR ZERO DIVIDEND
	BNE D10
	TST 2(R0)
	BNE D10
	TST 4(R0)
	BNE D10
	TST 6(R0)
	BNE D10
	
	CLR (R3)		; DIVIDEND IS ZERO SO RESULT IS ZERO AND
	CLR 2(R3)		
	CLR 4(R3)
	CLR 6(R3)
	CLR (R2)		; REMAINDER IS ZERO AS WELL
	CLR 2(R2)
	CLR 4(R2)
	CLR 6(R2)

	MOV #1,R4		; ALL DONE SO EXIT WITH GOOD STATUS
	CLC
	JMP D99

D10:	TST (R1)		; TEST FOR DIVIDE BY ZERO
	BNE D20
	TST 2(R1)
	BNE D20
	TST 4(R1)
	BNE D20
	TST 6(R1)
        BNE D20			; IF ZERO EXIT WITH OVERFLOW STATUS

	MOV #-3,R4		; OVERFLOW CONDITION PRESENT
	SEC
	JMP D99

D20:
	MOV (R0),-(SP)		; PRESERVE DIVIDEND
	MOV 2(R0),-(SP)
	MOV 4(R0),-(SP)
	MOV 6(R0),-(SP)

	MOV (R1),-(SP)		; PRESERVE DIVISOR
	MOV 2(R1),-(SP)
	MOV 4(R1),-(SP)
	MOV 6(R1),-(SP)

	CLR (R3)		; CLEAR QUOTIENT
	CLR 2(R3)
	CLR 4(R3)
	CLR 6(R3)

	CLR R4			; DIVIDEND SHIFT COUNTER

	MOV #0,-(SP)		; QUOTIENT SET WORD STORAGE ON STACK
	MOV #0,-(SP)
	MOV #0,-(SP)
	MOV #1,-(SP)
	MOV SP,R5		; QUOITENT SET WORD LOCATION ON STACK

; ALL SET TO START DIVIDE LOOP OPERATION
	
D40:	

	; SHIFT DIVISOR INTO LEFT MOST PART OF BUFFER

	TST 6(R1)		; CHECK IF ALREADY IN LEFT MOST PART
	BMI D50

D41:	ASL (R5)		; SHIFT BIT SET WORD
	ROL 2(R5)
	ROL 4(R5)
	ROL 6(R5)

	ASL (R1)		; SHIFT DIVISOR
	ROL 2(R1)
	ROL 4(R1)
	ROL 6(R1)
	
	BPL D41
	
D50:	

	; SHIFT DIVIDEND TO THE LEFT MOST PART OF BUFFER
	; COMPENSATE QUOITENT BIT SET IN PROCESS

	TST 6(R0)		; CHECK IF ALREADY IN LEFT MOST PART
	BMI D60

D51:	CLC			; CLEAR CARRY
	ROR 6(R5)		; COMPENSATE QUOITENT BIT SET
	ROR 4(R5)
	ROR 2(R5)
	ROR (R5)
	BCS D80			; ALL DONE WITH DIVISION, SHIFTED QUOITENT
				; BIT SET UNDER ONE

	INC R4			; DIVIDEND SHIFT COUNT

	ASL (R0)		; SHIFT DIVIDEND LEFT
	ROL 2(R0)
	ROL 4(R0)
	ROL 6(R0)

	BPL D51

D60:				; BUILD DEC STANDARD CALL SITE
	MOV R5,-(SP)		; SAVE R5 TO STACK
	MOV R5,-(SP)		; IDS VALUE LOCATION
	MOV SP,R5
	MOV R5,-(SP)		; ADDRESS OF IDS
	MOV R2,-(SP)
	MOV R1,-(SP)
	MOV R0,-(SP)
	MOV SP,R5
	SUB #2,R5		; ADJUST ADDRESS
	JSR PC,SUB64		; TEST SUBTRACT TO CHECK FOR SIGN CHANGE
	MOV (SP)+,R5		; ADJUST SPACK BACK
	MOV (SP)+,R5	
	MOV (SP)+,R5	
	MOV (SP)+,R5	
	MOV (SP)+,R5	
	MOV (SP)+,R5		; RESTORE R5

	BCC D70			; BRANCH IF NO SIGN CHANGE

	; SUBTRACTION RESULT NEGITIVE SO DIVIDE DIVISOR BY 2 AND TRY AGAIN

	CLC			; ADJUST DIVISOR
	ROR 6(R1)
	ROR 4(R1)
	ROR 2(R1)
	ROR (R1)

	CLC			; ADJUST QUOITENT BIT SET
	ROR 6(R5)
	ROR 4(R5)
	ROR 2(R5)
	ROR (R5)

	BCS D80			; ALL DONE WITH DIVISION, SHIFTED QUOITENT
				; BIT SET UNDER ONE

	BR D60

D70:	; SUBTRACTION POSITIVE

	BIS (R5),(R3)		; SET BIT IN QUOITENT
	BIS 2(R5),2(R3)
	BIS 4(R5),4(R3)
	BIS 6(R5),6(R3)

	MOV (R2),(R0)		; MOVE RESULT OF SUBTRACTION TO NEW DIVIDEND
	MOV 2(R2),2(R0)
	MOV 4(R2),4(R0)
	MOV 6(R2),6(R0)

	TST (R0)		; CHECK THAT DIVIDEND IS NOT ZERO
	BNE D40
	TST 2(R0)
	BNE D40
	TST 4(R0)
	BNE D40
	TST 6(R0)
	BNE D40

D80:	; ALL DONE. JUST CLEAN SOME STUFF UP NOW

	MOV (R0),(R2)		; MOVE DIVIDEND TO REMAINDER
	MOV 2(R0),2(R2)
	MOV 4(R0),4(R2)
	MOV 6(R0),6(R2)

	TST R4
	BEQ D89

D88:	CLC			; ADJUST REMAINDER BACK TO RIGHT
	ROR 6(R2)
	ROR 4(R2)
	ROR 2(R2)
	ROR (R2)
	SOB R4,D88

D89:	MOV #1,R4		; SET GOOD STATUS	
	CLC

	MOV (SP)+,R5		; CLEAN UP QUOITENT SET BUFFER ON STACK
	MOV (SP)+,R5
	MOV (SP)+,R5
	MOV (SP)+,R5

	MOV (SP)+,6(R1)		; RESTORE DIVISOR
	MOV (SP)+,4(R1)
	MOV (SP)+,2(R1)
	MOV (SP)+,(R1)

	MOV (SP)+,6(R0)		; RESTORE DIVIDEND
	MOV (SP)+,4(R0)
	MOV (SP)+,2(R0)
	MOV (SP)+,(R0)

D99:
	MOV (SP)+,R5		; RESTORE R5
	MOV R4,@12(R5)		; PUT STATUS IN IDS RETURN
	MOV (SP)+,R4		; RESTORE THE OTHER REGISTERS
	MOV (SP)+,R3
	MOV (SP)+,R2
	MOV (SP)+,R1
	MOV (SP)+,R0

	RTS PC

	.END
