	.TITLE	QUAMTH	QUAD WORD MATH PACKAGE
	.IDENT	/1.01/			;FILE "QUAMTH.MAR"

;
;	COPYRIGHT (C) 1979
;		MANAGEMENT SCIENCE ASSOCIATES, INC.
;		5100 CENTRE AVENUE
;		PITTSBURGH, PENNSYLVANIA  15232
;
;	THIS SOFTWARE IS DISTRIBUTED WITHOUT COST, AND MAY BE
;	REPRODUCED ONLY WITH THE INCLUSION OF THIS COPYRIGHT
;	STATEMENT.  MANAGEMENT SCIENCE ASSOCIATES ASSUMES NO
;	RESPONSIBILITY FOR THE PERFORMANCE OF THIS SOFTWARE.
;
	.PAGE
	.SBTTL	QUAADD	QUAD ADD

	.PSECT	$CODE,PIC,CON,REL,SHR,LCL,EXE,RD,NOWRT,LONG
;++
;	CALL QUAADD(<ADDEND1>,<ADDEND2>,<SUM>)
;
;	ADDEND1, ADDEND2 AND SUM ARE QUADWORDS
;	THE FIRST TWO ARE READ, THE LAST WRITTEN
;--
	.ENTRY	QUAADD	^M<>
	MOVL	12(AP),R0		;ADDRESS OF SUM
	MOVL	8(AP),R1		;ADDRESS OF ADDEND2
	MOVQ	@4(AP),(R0)		;SUM IS ADDEND1
	ADDL	(R1),(R0)		;PLUS LOW PART OF ADDEND2
	ADWC	4(R1),4(R0)		;PLUS HIGH PART OF ADDEND2
	RET				;RETURN TO CALLER
	.PAGE
	.SBTTL	QUASUB	QUAD SUBTRACT

	.PSECT	$CODE,PIC,CON,REL,SHR,LCL,EXE,RD,NOWRT,LONG
;++
;	CALL QUASUB(<MINUEND>,<SUBTRAHEND>,<DIFFERENCE>)
;
;	MINUEND, SUBTRAHEND AND DIFFERENCE ARE QUADWORDS
;	THE FIRST TWO ARE READ, THE LAST WRITTEN
;--
	.ENTRY	QUASUB	^M<>
	MOVL	12(AP),R0		;ADDRESS OF DIFFERENCE
	MOVL	8(AP),R1		;ADDRESS OF SUBTRAHEND
	MOVQ	@4(AP),(R0)		;DIFFERENCE IS MINUEND
	SUBL	(R1),(R0)		;MINUS LOW PART OF SUBTRAHEND
	SBWC	4(R1),4(R0)		;MINUS HIGH PART OF SUBTRAHEND
	RET				;RETURN TO CALLER
	.PAGE
	.SBTTL	QUAMUL	QUAD MULTIPLY

	.PSECT	$CODE,PIC,CON,REL,SHR,LCL,EXE,RD,NOWRT,LONG
;++
;	CALL QUAMUL(<MULTIPLIER>,<MULTIPLICAND>,<PRODUCT>)
;
;	MULTIPLIER, MULTIPLICAND AND PRODUCT ARE QUADWORDS
;	THE FIRST TWO ARE READ, THE LAST WRITTEN
;--
	.ENTRY	QUAMUL	^M<R2,R3,R4>
	MOVL	4(AP),R3		;ADDRESS OF MULTIPLIER
	MOVL	8(AP),R4		;ADDRESS OF MULTIPLICAND
	EMUL	(R3),(R4),#0,R0		;LOW PRODUCT
	EMUL	(R3),4(R4),R1,R1	;FIRST CROSS TERM PRODUCT
	EMUL	4(R3),(R4),R1,R1	;SECOND CROSS TERM PRODUCT
	TSTL	(R3)			;CHECK SIGN
	BGEQ	1$			;NO SIGN PROBLEMS
	ADDL	(R4),R1			;SIGN COMPENSATION
1$:	TSTL	(R4)			;CHECK OTHER SIGN
	BGEQ	2$			;NO SIGN PROBLEMS
	ADDL	(R3),R1			;SIGN COMPENSATION
2$:	MOVQ	R0,@12(AP)		;GIVE THE ANSWER
	RET				;RETURN TO CALLER
	.PAGE
	.SBTTL	QUADIV	QUAD DIVIDE

	.PSECT	$CODE,PIC,CON,REL,SHR,LCL,EXE,RD,NOWRT,LONG
;++
;	CALL QUADIV (<NUMERATOR>,<DENOMINATOR>,<QUOTIENT>{,<REMAINDER>})
;
;	NUMERATOR, DENOMINATOR, QUOTIENT AND REMAINDER ARE QUADWORDS
;	THE FIRST TWO ARGUMENTS ARE READ, THE LAST TWO WRITTEN
;	THE REMAINDER ARGUMENT IS OPTIONAL
;--
	.ENTRY	QUADIV	^M<R2,R3,R4,R5,R6,R7,R8>
	CLRB	R6			;PRESUME POS NUM AND DEN
	MOVL	12(AP),R8		;GET QUOTIENT ADDRESS
	MOVQ	@4(AP),(R8)		;GET THE NUMERATOR
	BGEQ	1$			;XFER IF POSITIVE
	MCOML	(R8),(R8)		;MAKE TWO'S COMPLEMENT
	MCOML	4(R8),4(R8)		;
	INCL	(R8)			;
	ADWC	#0,4(R8)		;
	MOVB	#3,R6			;FLAG THE SIGN SWITCH
1$:	MOVQ	@8(AP),R0		;GET THE DENOMINATOR
	BGEQ	2$			;XFER IF POSITIVE
	MCOML	R0,R0			;MAKE TWO'S COMPLEMENT
	MCOML	R1,R1			;
	INCL	R0			;
	ADWC	#0,R1			;
	XORB	#1,R6			;FLAG THE SIGN SWITCH
2$:	CLRQ	R2			;CLEAR QUOTIENT
	CLRQ	R4			;CLEAR REMAINDER
	MOVZBL	#63,R7			;SET COUNT AND BIT POINTER
3$:	ASHQ	#1,R2,R2		;ROOM FOR NEXT QUOTIENT BIT
	ASHQ	#1,R4,R4		;ROOM FOR NEXT NUMERATOR BIT
	BBC	R7,(R8),4$		;CHECK NEXT NUMERATOR BIT
	INCB	R4			;MOVE IT TO THE REMAINDER
4$:	CMPL	R5,R1			;COMPARE REMAINDER AND DENOM
	BLSS	6$			;NO SUBTRACT IF REMAINDER LESS
	BGTR	5$			;CERTAIN SUBTRACT IF LARGER
	CMPL	R4,R0			;HIGH PARTS EQUAL SO COMPARE LOW
	BLSSU	6$			;NO SUBTRACT IF REMAINDER LESS
5$:	SUBL	R0,R4			;SUBTRACT DENOM FROM REMAINDER
	SBWC	R1,R5			;
	INCB	R2			;INCREMENT THE QUOTIENT
6$:	SOBGEQ	R7,3$			;LOOP FOR EACH BIT
	BLBC	R6,7$			;CHECK QUOTIENT SIGN SWITCH
	MCOML	R2,R2			;MAKE QUOTIENT NEGATIVE
	MCOML	R3,R3			;
	INCL	R2			;
	ADWC	#0,R3			;
7$:	MOVQ	R2,(R8)			;RETURN THE QUOTIENT
	BBC	#2,0(AP),9$		;CHECK FOR FOUR ARGS
	BBC	#1,R6,8$		;CHECK REMAINDER SIGN SWITCH
	MCOML	R4,R4			;MAKE REMAINDER NEGATIVE
	MCOML	R5,R5			;
	INCL	R4			;
	ADWC	#0,R5			;
8$:	MOVQ	R4,@16(AP)		;RETURN THE REMAINDER
9$:	RET				;RETURN TO CALLER
	.PAGE
	.SBTTL	QUACMP	QUAD COMPARE

	.PSECT	$CODE,PIC,CON,REL,SHR,LCL,EXE,RD,NOWRT,LONG
;++
;	STS = QUACMP(QUAD1,QUAD2)
;
;	QUAD1 AND QUAD2 ARE QUADWORDS, STS IS A LONGWORD
;	THE FIRST TWO ARE READ, THE LAST IS RETURNED IN R0
;
;	STS =	-1 IF QUAD1 < QUAD2
;		 0 IF QUAD1 = QUAD2
;		+1 IF QUAD1 > QUAD2
;--
	.ENTRY	QUACMP^M<>
	MOVAL	@4(AP),R0		;ADDRESS OF QUAD1
	MOVAL	@8(AP),R1		;ADDRESS OF QUAD2
	CMPL	4(R0),4(R1)		;COMPARE HIGH PARTS FIRST
	BLSS	10$			;XFER FOR -1
	BGTR	30$			;XFER FOR +1
	CMPL	(R0),(R1)		;COMPARE LOW PARTS SINCE HIGH SAME
	BLSSU	10$			;XFER FOR -1
	BGTRU	30$			;XFER FOR +1
	CLRL	R0			;SAME - RETURN 0
	RET				;
10$:	CVTBL	#-1,R0			;FIRST LESS - RETURN -1
	RET				;
30$:	MOVZBL	#1,R0			;FIRST GREATER - RETURN +1
	RET

	.END				;THAT'S ALL, FOLKS!
