	IFND	LONGINTSVER

	;-------------------------------------------------------------------
	; Created by Peter Thompson
	; Multiply/square routines written on New Year's Day 1992
	; & debugged on 2nd January, when I was feeling better....
	; Division macros written & partially debugged on 2nd Jan.
	; Further testing and debugging on 10th Jan.
	;-------------------------------------------------------------------
	; $MUSIC="Vince Jones/It all ends up in tears, Enya/Watermark, Paul
	;         Simon/Graceland, Clannad/Fuaim, Paul Simon/The Rhythm of
	;         the Saints, Greg X. Volz/No Room in the Middle, Greg X.
	;	  Volz/The Exodus"
	;-------------------------------------------------------------------
	;  All numbers are integers.
	;  Only registers containing results, and/or d1, are altered by
	; these macros.
	; Flag	State after any multiply/square macro
	; X	undefined.
	; N	Set if result is negative, clear otherwise.
	; Z	Set if result is zero, clear otherwise.
	; V	if set, an overflow HAS taken place;
	;	if clear, an overflow MAY have taken place.
	; C	undefined.
	;  None of these routines can be trusted to return a correct
	; overflow flag, unless specified by name to do so. It is your
	; responsiblity to make sure your numbers are small enoungh.
	;-------------------------------------------------------------------

LONGINTSVER	EQU	100

	;- MUL3264 macro - 32x32->64 bit multiply.
	;- Input:	d0 contains a 32-bit number (treated as unsigned).
	;-		d1 contains a 32-bit number (treated as unsigned).
	;- Output:	d0 and d1 contain the product of the inputs in the
	;		order least to most significant longword.

MUL3264:	MACRO		; d0 d1 d2 d3 d4
	movem.l	d2-d4,-(SP)	; ab cd -- -- --
	move.l	d1,d2		; ab cd cd -- --
	swap	d1		; ab dc cd -- --
	move.l	d1,d3		; ab dc cd dc --
	move.l	d0,d4		; ab dc cd dc ab
	swap	d4		; ab dc cd dc ba
	mulu	d4,d1		; ab AC cd dc ba
	mulu	d0,d3		; ab AC cd BC ba
	mulu	d2,d0		; BD AC cd BC ba
	mulu	d4,d2		; BD AC AD BC ba
	moveq	#0,d4		; BD AC AD BC 00
	add.l	d2,d3		; BD AC AD 12 00
	addx.w	d4,d4		; BD AC AD 12 0+
	swap	d3		; BD AC AD 21 0+
	swap	d4		; BD AC AD 21 +0
	move.w	d3,d4		; BD AC AD 21 +1
	clr.w	d3		; BD AC AD 20 +1
	add.l	d3,d0		; ++ AC AD 20 +1
	addx.l	d4,d1		; ++ ++ AD 20 +1
	movem.l	(SP)+,d2-d4	; ++ ++ -- -- --
	ENDM

	;- SQR3264 macro - 32->64 bit (unsigned) square.
	;- Input:	d0 contains a 32-bit number (treated as unsigned).
	;- Output:	d0 and d1 contain the square of the input in the
	;-		order least to most significant longword.

SQR3264:	MACRO		; d0 d1 d2 d3
	movem.l	d2-d3,-(SP)	; ab -- -- --
	moveq	#0,d1
	move.l	d0,d2		
	swap	d2		; ab 00 ba --
	move.l	d2,d3		; ab 00 ba ba 
	mulu	d0,d2		; ab 00 AB ba
	mulu	d0,d0		; BB 00 AB ba
	mulu	d3,d3		; BB 00 AB AA
	swap	d2
	move.w	d2,d1
	clr.w	d2		; BB A0 B0 AA
	add.l	d2,d2
	addx.l	d1,d1		; double AB0
	add.l	d2,d0
	addx.l	d3,d1		; add both parts
	movem.l	(SP)+,d2-d3
	ENDM

	;- MUL64128 macro - 64x64->128 bit multiply.
	;- Input:	d0 and d1 contain a 64-bit number (treated as
	;-		unsigned) in the order least to most significant
	;-		longword.
	;-		d2 and d3 contain a 64-bit number (treated as
	;-		unsigned) in the order least to most significant
	;-		longword.
	;- Output:	d0,d1,d2 and d3 contain the product of the inputs
	;-		in the order least to most significant longword.
	
MUL64128:	MACRO
				; d0 d1 d2 d3 d4 d5 d6 d7
				; a0 a1 a2 a3 a4 a5 a6
	movem.l	d4-d7/a0-a6,-(SP)
				; cd ab 34 12 -- -- -- --
	move.l	d2,a4
	move.l	d2,d5
	swap	d5
	move.l	d5,a3		; cd ab 34 12 -- 43 -- --
				; -- -- -- 43 34 -- --
	move.l	d3,a2
	move.l	d3,d6
	swap	d6
	move.l	d6,a1		; cd ab 34 12 -- 43 21 --
				; -- 21 12 43 34 -- --
	mulu	d0,d2		;make D4 (=4 done)
	mulu	d0,d3		;make D2
	mulu	d0,d5		;make D3
	mulu	d0,d6		;make D1
				; cd ab D4 D2 -- D3 D1 --
				; -- 21 12 43 34 -- --		
	move.l	d2,a0
	swap	d0
	moveq	#0,d7
	move.l	a4,d2
	mulu	d0,d2		;make C4 (/4 done)
	add.l	d2,d5		; dc ab C4 D2 -- /4 D1 00
				; D4 21 12 43 34 -- --
	move.l	a2,d2
	mulu	d0,d2		;make C2
	addx.l	d2,d6		; dc ab C2 D2 -- /4 /3 00
				; D4 21 12 43 34 -- --
	move.l	a1,d2
	mulu	d1,d2		;make B1
	addx.l	d2,d7
	move.l	d5,a6		; dc ab B1 D2 -- /4 /3 /2
				; D4 21 12 43 34 -- /4
	moveq	#0,d5
	move.l	a1,d4
	mulu	d0,d4		;make C1
	move.l	a3,d2
	mulu	d0,d2		;make C3
	add.l	d2,d3		; dc ab C3 =3 C1 00 /3 /2
				; D4 21 12 43 34 -- /4
	move.l	d1,d0
	swap	d0
	move.l	a2,d2
	mulu	d1,d2		;make B2
	addx.l	d2,d4		; ba ab B2 =3 =2 00 /3 /2
				; D4 21 12 43 34 -- /4
	move.l	a1,d2
	mulu	d0,d2		;make A1
	addx.l	d2,d5		; ba ab B2 =3 =2 =1 /3 /2
				; D4 21 12 43 34 -- /4
	move.l	a4,d2
	mulu	d1,d2		;make B4 (=3 done)
	add.l	d2,d3		; ba ab B4 =3 =2 =1 /3 /2
				; D4 21 12 43 34 -- /4
	move.l	d3,a5
	move.l	a3,d2
	mulu	d2,d1		;make B3
	moveq	#0,d3
	move.l	a3,d2
	mulu	d0,d2		;make A3 (=2 done)
	addx.l	d2,d4		;(=1 done)
	addx.l	d3,d5		; ba B3 A3 00 =2 =1 /3 /2
				; D4 21 12 43 34 =3 /4
	add.l	d1,d6
	move.l	a2,d2
	mulu	d0,d2		;make A2
	addx.l	d2,d7
	addx.w	d3,d3		; ba B3 A2 /1 =2 =1 /3 /2
				; D4 21 12 43 34 =3 /4
	moveq	#0,d2
	move.l	a4,d1
	mulu	d1,d0		;make A4
	add.l	d0,d6
	addx.l	d2,d7
	addx.w	d2,d3		; A4 34 00 /1 =2 =1 /3 /2
				; D4 21 12 43 34 =3 /4
	move.l	a6,d0
	move.l	a5,d1
	swap	d3
	swap	d7
	move.w	d7,d3
	swap	d6
	move.w	d6,d7
	swap	d0
	move.w	d0,d6
	clr.w	d0		; 40 =3 00 1/ =2 =1 3/ 2/
				; D4 21 12 43 34 =3 /4
	add.l	a0,d0
	addx.l	d6,d1
	move.l	d4,d2
	addx.l	d7,d2
	addx.l	d5,d3		; ++ ++ ++ ++ =2 =1 3/ 2/
				; D4 21 12 43 34 =3 /4
	movem.l	(SP)+,d4-d7/a0-a6
	ENDM

	;- SQR64128 macro - 64->128 bit (unsigned) square.
	;- Input:	d0 and d1 contain a 64-bit number (treated as
	;-		unsigned) in the order least to most significant
	;-		longword.
	;- Output:	d0,d1,d2 and d3 contain the square of the input in
	;-		the order least to most significant longword.

SQR64128:	MACRO		; d0 d1 d2 d3 d4 d5 d6 d7
				; a0 a1 a2 a3
	movem.l	d4-d7/a0-a3,-(SP)
				; cd ab -- -- -- -- -- --
	move.l	d0,d6
	move.l	d1,d7
	swap	d6
	swap	d7
	move.l	d0,a0
	move.l	d1,a1		; cd ab -- -- -- -- dc ba
				; cd ab -- --
	mulu	d0,d1		;make BD
	move.l	d1,a2
	mulu	d0,d0		;make DD
	move.l	d0,a3		; DD BD -- -- -- -- dc ba
				; cd ab BD DD
	moveq	#0,d2
	move.l	a0,d0
	mulu	d6,d0		;make CD
	move.l	a1,d1
	mulu	d6,d1		;make BC
	move.l	a0,d3
	mulu	d7,d3		;make AD
	add.l	d3,d1
	move.l	a1,d3
	mulu	d7,d3		;make AB
	addx.l	d3,d2		; /3 /2 /1 AB -- -- dc ba
				; cd ab BD DD
	moveq	#0,d3
	swap	d2
	move.w	d2,d3
	swap	d1
	move.w	d1,d2
	swap	d0
	move.w	d0,d1
	clr.w	d0		; 0/ 3/ 2/ 10 -- -- dc ba
				; cd ab BD DD
	moveq	#0,d4
	move.l	d6,d5
	mulu	d7,d5		;make AC
	add.l	a2,d1
	addx.l	d5,d2
	addx.l	d4,d3
	add.l	d0,d0		;double
	addx.l	d1,d1
	addx.l	d2,d2
	addx.l	d3,d3		; =4 =3 =2 =1 00 AC dc ba
				; cd ab BD DD
	mulu	d6,d6		;make CC
	move.l	a1,d5
	mulu	d5,d5		;make BB
	mulu	d7,d7		;make AA
	add.l	a3,d0		; =4 =3 =2 =1 00 BB CC AA
				; cd ab BD DD
	addx.l	d6,d1
	addx.l	d5,d2
	addx.l	d7,d3
	movem.l	(SP)+,d4-d7/a0-a3
	ENDM

	;- DIV6331 macro - 63/31 bit division.
	;- Note: use UDIV64 (in Int64.i) for a 64/32 bit division.
	;- Input:	d0 and d1 contain a 63-bit (positive) dividend in
	;-		the order least to most significant longword.
	;-		d2 contains a 31-bit (positive) divisor.
	;- Output:	d0 contains a 32-bit (unsigned) quotient.
	;- 		d1 contains a 31-bit (positive) remainder.

DIV6331:	MACRO
	movem.l	d2-d4,-(SP)
	moveq	#0,d3
	moveq	#63,d4
	lsl.l	#1,d0
	roxl.l	#1,d1
	roxl.l	#1,d3		;d6432a:
	sub.l	d2,d3
	bcc.S	*+4		;->d6432b
	add.l	d2,d3
	roxl.l	#1,d0		;d6432b:
	roxl.l	#1,d1
	dbra	d4,*-$C		;->d6432a
	not.l	d0
	move.l	d3,d1
	movem.l	(SP)+,d2-d4
	ENDM

	;- DIV12763 macro - 127/63 bit division.
	;- Input:	d0,d1,d2 and d3 contain a 127-bit (positive)
	;-		dividend in the order least to most significant
	;-		longword.
	;-		d4 and d5 contain a 63-bit (positive) divisor in
	;-		the order least to most significant longword.
	;- Output:	d0 and d1 contain a 64-bit (unsigned) quotient in
	;-		the order least to most significant longword.
	;- 		d2 and d3 contain a 63-bit (positive) remainder in
	;-		the order least to most significant longword.

DIV12763:	MACRO
	movem.l	d4-d7/a0,-(SP)
	moveq	#0,d6
	moveq	#0,d7
	move.l	d4,a0
	moveq	#127,d4
	lsl.l	#1,d0
	roxl.l	#1,d1
	roxl.l	#1,d2
	roxl.l	#1,d3
	roxl.l	#1,d6		;d12763a:
	roxl.l	#1,d7
	sub.l	a0,d6
	subx.l	d5,d7
	bcc.S	*+6		;->d12763b
	add.l	a0,d6
	addx.l	d5,d7
	roxl.l	#1,d0		;d12763b:
	roxl.l	#1,d1	
	roxl.l	#1,d2
	roxl.l	#1,d3
	dbra	d4,*-$16	;->d12763a
	not.l	d0
	not.l	d1
	move.l	d6,d2
	move.l	d7,d3
	movem.l	(SP)+,d4-d7/a0
	ENDM

	ENDC
