

;	DIVISION UTILITY SUBROUTINE
;	R0-R1-R2-R2=DIVIDEND
;	R4-R5=DIVISOR
;	R0-R1=REMAINDER AFTER DIVISION
;	R2-R3=QUOTIENT AFTER DIVISION
;	ENTER WITH JSR	PC,M.DPID
;
MDPID:	MOV	#40,-(SP)	;COUNTER FOR DIVISION CYCLES
	MOV	R4,-(SP)	;HIGH ORDER
	MOV	R5,-(SP)	;LOW ORDER DIVISOR TO THE STACK
	NEG	2(SP)		;FORM NEGATIVE
	NEG	@SP		;VERSION OF THE DIVISOR
	SBC	2(SP)
	ADD	@SP,R1
	ADC	R0		;PERFORM THE INITIAL SUBTRACTION
	ADD	2(SP),R0
	BCS	M.DP50		;IF CARRY THEN OVERFLOW HAS OCCURRED
	CLR	-(SP)		;THIS IS A LONGER LASTING CARRY BIT
M.DP40:	ROL	R3
	ROL	R2
	ROL	R1
	ROL	R0
	TST	@SP		;TEST "CARRY" INDICATOR
	BEQ	M.DP41		;IF NO "CARRY" THEN ADD ELSE SUBTRACT
	CLR	@SP		;CLEAR UP FOR NEXT TIME
	ADD	2(SP),R1
	ADC	R0		;ADD -(DIVISOR)
	ADC	@SP	;  I	;SET "CARRY"
	ADD	4(SP),R0;<-
	BR	M.DP42
M.DP41:	ADD	R5,R1
	ADC	R0		;ADD +(DIVISOR)
	ADC	@SP	;  I	;SET "CARRY"
	ADD	R4,R0	;<-
M.DP42:	ADC	@SP		;SET "CARRY"
	TST	@SP		;TEST THE UPDATE INDICATOR
	BEQ	.+4	;->	;IF ZERO FORGET IT
	INC	R3	;  I	;NO CARRY POSSIBLE HERE
	DEC	6(SP)	;<-	;DECREMENT COUNTER
	BGT	M.DP40		;BRANCH IF MORE TO DO
	ROR	R3
	BCS	M.DP44
	ADD	R5,R1
	ADC	R0
	ADD	R4,R0
	CLC
M.DP44:	ROL	R3
	ADD	#10,SP		;ADJUST STACK BY 4 WORDS
	CLV
	RTS	PC
M.DP50:	ADD	#6,SP
	DVFERR
	SEV
	RTS	PC
ADDF00:	MOV	R5,-(SP)	;SAVE R5
	MOV	R0,-(SP)	;SAVE DEFA
	MOV	(R1)+,-(SP)	;MOVE SOURCE TO R3,R5,EXPA ON STACK
	MOV	(R1)+,-(SP)
	MOV	@R1,-(SP)
	MOV	(R0)+,R2	;MOVE DESTINATION TO R2,R1,R0 IN REGISTERS
	MOV	(R0)+,R1
	MOV	@R0,R0
	CMP	R0,@SP		;IF R0>EXPA SWAP
	BLOS	M.FAD2		;FLOATING POINT NUMBERS
	MOV	SP,R4	
	MOV	R0,R3
	MOV	@R4,R0
	MOV	R3,(R4)+
	MOV	R1,R3
	MOV	@R4,R1
	MOV	R3,(R4)+
	MOV	R2,R3
	MOV	@R4,R2
	MOV	R3,(R4)+
M.FAD2:	SUB	@SP,R0		;R0=R0-EXPA
	BEQ	M.FAD8		;IF ZERO OMIT ALIGNMENT
	BPL	M.FAD3		;IF POSITIVE THEN NO ADD
	CMP	R0,#-37
	BGE	M.FAD4
M.FAD3:	MOV	2(SP),R5
	MOV	4(SP),R3
	BR	M.FAD7
M.FAD4:	CMP	R0,#-20		;IF DIFFERENCE BETWEEN EXPONENTS IS
				;>15 AND <31 DO A FAST RIGHT SHIFT
	BGT	M.FAD5		;ADD 15 TO THE EXPONENT,MOVE HIGH TO
	ADD	#20,R0
	MOV	R1,R2
	CLR	R1
	TST	R2
	BPL	M.FAD5
	COM	R1
M.FAD5:	TST	R0		;IF DIFFERENCE BETWEEN EXPONENTS IS 0
				;THEN SKIP R3IGNMENT LOOP
	BEQ	M.FAD8
M.FAD6:	ASR	R1		;SHIFT FRACTION RIGHT  AND CHECK
	ROR	R2		;IF EXPONENTS ARE R3IGNED YET
	INC	R0
	BNE	M.FAD6
M.FAD8:	MOV	2(SP),R5	;PUT FRACTION A INTO REGISTERS
	MOV	4(SP),R3
	ADD	R2,R3		;DO A DOUR2E PRECISION ADD TO SUM
	ADC	R5		;THE FRACTIONS
	BVS	M.FAD9
	ADD	R1,R5
	BVC	.+10	;->	 IF AN OVERFLOW OCCURS
M.FAD1:	ROR	R5	;  I	 THEN SHIFT THE CARRY BIT
	ROR	R3	;  I	 BACK INTO THE NUMBER AND
	INC	@SP	;  I	 INCREMENT THE EXPONENT
M.FAD7:	MOV	6(SP),R0;<-	 PUT DEFA IN A REGISTER
	MOV	R0,R1		;SAVE DEFA FOR LATER
	MOV	R3,(R0)+	;MOVE FRACTION TO DESTINATION
	MOV	R5,(R0)+
	MOV	@SP,(R0)+
	MOV	R1,R0		;GET UN TOUCHED DEFA
	ADD	#10,SP		;FIX UP STACK
	MOV	(SP)+,R5	;RESTORE R5
	JMP	NORM00
M.FAD9:	ADD	R1,R5
	BCS	M.FAD7		;IF A CARRY NO REAL OVERFLOW
	BR	M.FAD1
;FLOATING POINT SUBTRACTION SUBROUTINE.
;LENGTH = 26 BYTES
;EXECTION TIME = 32 CYCLES + ADDF TIME

SUBF00:	MOV	R0,R4		;SAVE DEFA
	SUB	#6,SP
	MOV	SP,R0
	NEGF			;NEGATE
	MOV	R4,R0
	MOV	SP,R1
	ADDF			;AND ADD
	ADD	#6,SP
	RTS	PC
;NEGATION SUBROUTINE.NEGATES SOURCE AND PUTS
;RESULT IN DESTINATION
;LENGTH = 22 BYTES

;EXECUTION TIME = 18 CYCLES
ABS00:	MOVF
	TST	2(R1)		;TEST FOR NEGATIVE
	BGE	NEGF01		;EXIT IF POSITIVE
NEGF00:	MOV	(R1)+,R2	;MOVE SOURCE FRACTION TO REGISTERS
	MOV	(R1)+,R3	
	NEG	R3		;NEGATE FRACTION IN REGISTERS
	NEG	R2
	SBC	R3
	MOV	R2,(R0)+	;MOVE NEGATIVE FRACTION TO DESTINATION
	MOV	R3,(R0)+
	MOV	(R1)+,(R0)+	;MOVE EXPONENT TO DESTINATION
NEGF01:	RTS	PC
;
; SGN00 - GET THE SIGN OF THE OPERAND
;
SGN00:	MOVF			;MOVE TO DEST.
	MOV	#M.TEN+6,R1	;ADDRESS OF 1.
	TST	2(R0)		;TEST ORIGINAL
	BGT	SGN01
	BEQ	SGN02		;IF ZERO WE EXIT
	NEGF			;STORE -1.
	RTS	PC
SGN01:	MOVF			;STORE +1.
SGN02:	RTS	PC
DIVF00:	MOV	R5,-(SP)	;SAVE R5
	MOV	R0,-(SP)	;SAVE DEFA
	CLR	-(SP)		;SIGN CONTROL WORD
	MOV	(R1)+,R5	;PICK UP THE DIVISOR
	MOV	(R1)+,R4	;HIGH ORDER WORD
	TST	R4		;TEST FOR DIVISION BY ZERO
	BEQ	M.DIVV		;DIVISION BY ZERO IS A NO-NO
	BGE	.+12	;->	IF NEGATIVE
	NEG	R4	;  I	CHANGE THE SIGN
	NEG	R5	;  I	BUT STILL KEEP
	SBC	R4	;  I	TRACK OF THE ORIGINAL
	INC	@SP	;  I	SIGN ON THE STACK
	MOV	(R0)+,R3;<-
	MOV	(R0)+,R2	;PICK UP THE DIVIDEND
	BEQ	M.MUL0		;IF ZERO THEN SHORT DIVIDE
	BGT	.+12	;->	IF NEGATIVE
	NEG	R2	;  I	CHANGE THE SIGN
	NEG	R3	;  I	BUT STILL KEEP
	SBC	R2	;  I	TRACK OF THE ORIGINAL
	DEC	@SP	;  I	SIGN ON THE STACK WORD
	MOV	@R1,R1	;<-	;GET THE EXPONENTS
	NEG	R1		;AND SUBTRACT
	ADD	@R0,R1		;TO CHECK FOR OVER-UNDER-FLOW
	ROR	R1		;AND PUT IT ON THE STACK
	ROL	R1		;WHEN DONE
	BVC	M.DIVV
	ADD	#100000,R1
	MOV	R1,-(SP)
	MOV	R3,R1
	MOV	R2,R0
	CLR	R2		;SET UP TO DO THE DIVIDE
	CLR	R3
	ROR	R0
	ROR	R1
	ROR	R2
	M.DPID			;CALL THE DIVIDE ROUTINE
	NEG	R4		;CHANGE THE SIGN OF THE DIVISOR
	NEG	R5
	SBC	R4
	ASL	R1		;DOUBLE THE REMAINDER
	ROL	R0
	ADD	R5,R1		;ADD -(DIVISOR)
	ADC	R0
	ADD	R4,R0
	BLT	M.DIV2
	ADD	#1,R3		;ROUND UP THE RESULT
	ADC	R2
M.DIV2:	CLC
	ROR	R2
	ROR	R3
	INC	@SP
	TST	2(SP)		;CHECK SIGN  WORD
	BEQ	.+10	;->
	NEG	R2	;  I
	NEG	R3	;  I
	SBC	R2	;  I
	MOV	4(SP),R0;<-	 GET DEFA
	MOV	R3,(R0)+
	MOV	R2,(R0)+
	MOV	(SP)+,@R0
	CMP	(SP)+,(SP)+	;FIX UP THE STACK POINTER
	MOV	(SP)+,R5	;RESTORE R5
	CMP	-(R0),-(R0)	;POINT TO THE DESTINATION
	MOV	R0,R1
	JMP	NORM00
M.DIVV:	CMP	(SP)+,(SP)+	;FIX UP THE STACK
	DVFERR
	MOV	(SP)+,R5	;RESTORE R5
	SEV
	RTS	PC
MULF00:	MOV	R5,-(SP)	;SAVE R5
	MOV	R0,-(SP)	;SAVE DEFA
	MOV	(R1)+,R5	;FETCH SOURCE
	MOV	(R1)+,R4
	MOV	@R1,R1
	CLR	-(SP)		;SIGN CONTROL WORD
	TST	R4
	BEQ	M.MUL0		;SHORT CIRCUIT IF ZERO
	BPL	M.MUL2		;IF NEG MAKE POSITIVE
	NEG	R4		;ZIP-ZAP-
	NEG	R5		;ZOWIE-AND-
	SBC	R4		;SWOSH
	DEC	@SP		;FIDDLE WHITH THE SIGN
M.MUL2:	MOV	(R0)+,R3	;PICK UP DESTINATION
	MOV	(R0)+,R2
	BEQ	M.MUL0		;FAST IF ZERO
	BPL	M.MUL3		;OMIT SIGN CHANGE IF POSITIVE
	NEG	R2
	NEG	R3
	SBC	R2
	INC	@SP		;DO A GOOD JOB ON THE SIGN
M.MUL3:	ADD	@R0,R1		;COMPUTE A TRY AT THE NEW EXPONENT
	ROR	R1
	ROL	R1
	BVC	M.DIVV		;HANDLE OVER-UNDER-FLOW
	ADD	#100000,R1
	MOV	R1,-(SP)
	M.DPIM			;DO THE MULTIPLICATION
	INC	@SP		;ADJUST THE EXPONENT AFTER MULTIPLY
M.MUL8:	ROL	R2		;NOW NORMALIZE
	ROL	R1
	ROL	R0
	BVS	M.MUL4
	DEC	@SP
	BR	M.MUL8
M.MUL4:	ROR	R0
	ROR	R1
	ADC	R1		;ROUND OFF THE RESULT
	ADC	R0
	BVC	M.MUL6
	INC	@SP
	BR	M.MUL4
M.MUL6:	MOV	(SP)+,R2	;DO THE FANCY FOOT WORK
	TST	(SP)+		;REMEMBER THE SIGN WORD WE SAVED?
	BEQ	M.MUL7		;BRANCH FOR POSITIVE RESULT
	NEG	R0
	NEG	R1
	SBC	R0
M.MUL7:	MOV	(SP)+,R3	;WE SAVED THE DESTINATION FOR JUST SUCH A CAUSE
	MOV	R1,(R3)+
	MOV	R0,(R3)+
	MOV	R2,@R3
	MOV	(SP)+,R5
	RTS	PC
M.MUL0:	CLR	R0		;QUICK AND DIRTY
	CLR	R1
	CLR	R2
	TST	(SP)+		;GET RID OF THE SIGN CONTROL WORD
	BR	M.MUL7
;
; CONVERSION OF SINGLE PRECISION INTEGERS TO FLOATING POINT NUMBERS
;
FLT00:	CLR	(R0)+
	MOV	R1,(R0)+
	MOV	#100017,@R0
	CMP	-(R0),-(R0)
	MOV	R0,R1
;
;SUBROUTINE TO NORMALIZE AN UN-NORMALIZED FLOATING POINT NUMBER
;
NORM00:	MOV	(R1)+,R4	;MOVE SOURCE TO REGISTERS
	MOV	(R1)+,R2
	MOV	(R1)+,R3
	MOV	R3,R1		;SAVE FOR LATER CHECK
	TST	R2		;CHECK FOR A ZERO FRACTION
	BNE	M.NOR2
	TST	R4
	BNE	M.NOR2
	CLR	R3		;RETURN 0.0 CAUSE FRACTION=0
	BR	M.RET2
M.NOR2:	INC	R3
M.NORL:	DEC	R3		;NORMR4IZATION LOOP
	ASL	R4		;SHIFT FRACTION LEFT
	ROL	R2
	BVC	M.NORL		;NORMR4IZED YET?
	BCC	M.NOR3		;SPECIR4 -1 FRACTION CHECK
	BNE	M.NOR3		;IF NOT -(2^N) THEN EXIT NOW
	TST	R4
	BNE	M.NOR4
	SEC			;IT WAS -1 TO MAKE IT -1/2
	ROR	R2
	INC	R3
	INC	R1
M.NOR4:	SEC
M.NOR3:	ROR	R2
	ROR	R4
M.RET2:	MOV	R4,(R0)+
	MOV	R2,(R0)+
	MOV	R3,(R0)+
	CMP	R3,R1
	BHI	.+6	;->	;MAKE SURE THE VALUE DIDN'T DECREASE
	CLV		;  I
	RTS	PC	;  I
	SEV		;<-
	RTS	PC
;PDP-11 FLOATING POINT PACKAGE
;FIX,FIXD,FLT,FLTD,CMPF,MOVF
;
;
;ROUTINE FOR MOVING FLOATING POINT NUMBERS FROM SOURCE ADDDRESS TO
;DESTINATION ADDRESS
;
MOVF00:	MOV R1,R2
	MOV R0,R4
	MOV (R2)+,(R4)+
	MOV (R2)+,(R4)+
	MOV (R2)+,(R4)+
	RTS	PC

;
;SUBROUTINE FOR COMPARING TWO FLOATING POINT NUMBERS AND SETTING
;THE INDICATORS WITH OUT MODIFYING EITHER NUMBER.THE INDICATORS
;ARE SET FROM THE SOURCE MINUS DESTINATION.
;
CMPF00:	MOV	R1,-(SP)	;SAVE SEFA
	M.MOVE			;PUT DESTINATION ON THE STACK
	MOV	SP,R0		;SP IS NOW THE DEFA
	MOV	6(SP),R1	;RESTORE SEFA TO R1
	SUBF			;S-D TO TOP OF STACK
	MOV	2(SP),R1	;SAVE HIGH ORDER FRACTION IN R1
	ADD	#10,SP		;GET RID OF TRASH ON STACK
	NEG	R1		;SET THE INDICATORS PROPERLY
	RTS	PC

;SUBROUTINE TO PUT THE NUMBER POINTED TO BY R0 ON THE STACK
;
MMOVE:	MOV	(SP)+,R2	;MAKE STACK SAME HEIGHT AS AT CALL
	ADD	#6,R0		;MAKE RO POINT TO TOP OF NUMBER
	MOV	-(R0),-(SP)	;MOVE THE NUMBER BACKWARD TO THE
	MOV	-(R0),-(SP)	;STACK SO IT COMES OUT CORRECTLY
	MOV	-(R0),-(SP)
	MOV	R2,PC		;RETURN FAST
INT00:	MOV	(R1)+,R3	;PICK UP THE NUMBER
	MOV	(R1)+,R2	;AND PUT IT IN REGESTERS
	MOV	@R1,R4
	BPL	INT03		;BRANCH IF THE ANSWER IS ZERO
	CMP	-(R1),-(R1)
	CMP	R4,#100037	;SEE IF WE NEED TO DO ANYTHING
	BHIS	MOVF00		;BRANCH IF NO FRACTION PART
	SUB	#100037,R4	;COMPUTE # OF FRACTION BITS
INT01:	ASR	R2
	ROR	R3
	INC	R4		;  INTO PLACE
	BLT	INT01
	MOV	R0,R1
	MOV	R3,(R0)+
	MOV	R2,(R0)+
	MOV	#100037,@R0
	MOV	R1,R0
	BR	NORM00
INT03:	TST	R2
	BPL	INT02
	MOV	#M.ONE,R1
	JMP	NEGF00
INT02:	CLR	(R0)+
	CLR	(R0)+		;CLEAR THREE WORDS-FLT PT 0.
	CLR	(R0)
	RTS	PC
;
; FIX- FIX00, NUMBER IN R2,R3,R4 FIXED TO NUMBER IN R0.
;	REGISTERS USED - R0,R1,R2,R3,R4.
;
FIXS00:	MOV	(R1)+,R2
	MOV	(R1)+,R3
	MOV	@R1,R4
FIX00:	CMP	R4,#100017	;CHECK FOR EXPONENT TOO LARGE
	BHI	FIX04		;JUMP IF EXPONENT TOO LARGE
	BEQ	FIX03		;JUMP IF NO WORK NEEDED
	CMP	R4,#100000	;CHECK FOR ZERO EXPONENT
	BLO	FIX05		;JUMP IF ZERO
	SUB	#100017,R4	;GENERATE BACKWARDS COUNTER
FIX02:	ASR	R3		;MOVE IT ONCE
	INC	R4
	BNE	FIX02		;LOOP UNTIL COUNT EQUALS ZERO
FIX03:	MOV	R3,R0		;PUT RESULT IN R0
	RTS	PC
FIX04:	FIXERR
FIX05:	CLR	R0		;RESULT CAN BE ZERO
	RTS	PC

	.EOT			;END OF TAPE 7
