	IFND	INT64VER
	;------------------------------------------------------------------
	; 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 9th Jan.
	; And yet more on 10th Jan.
	;------------------------------------------------------------------
	; $MUSIC="Vince Jones/It all ends up in tears, Enya/Watermark,
	;         Paul Simon/Graceland, Clannad/Fuaim, Phil Keaggy/Master
	;         and the Musician, Farrell & Farrell/SuperPower, Paul
	;	  Simon/The Rhythm of the Saints"
	;------------------------------------------------------------------
	;  Numbers are all integers.
	;  Only registers containing results, and/or d1, are altered by
	; these macros.
	;  These macros may require up to 80 bytes of stack space.
	; 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.
	;------------------------------------------------------------------

	INCLUDE	"LongInts.i"

INT64VER	EQU	100

	;- MUL64 macro - general 64 bit multiply.
	;- Input:	d0 and d1 contain a 64-bit signed or unsigned number
	;-		in the order least to most significant longword.
	;-		d2 and d3 contain a 64-bit signed or unsigned number
	;-		in the order least to most significant longword.
	;- Output:	d0 and d1 contain the product of the inputs in the
	;-		order least to most significant longword.

MUL64:	MACRO			; d0 d1 d2 d3 d4 d5 d6 d7 a4
	movem.l	d2-d7/a4,-(SP)	; cd ab 34 12 -- -- -- -- --
	move.l	d1,d7
	swap	d7
	mulu	d2,d7		;make A4
	move.l	d2,a4
	move.l	d3,d4
	swap	d4
	mulu	d0,d4		;make D1
	add.l	d4,d7		; cd ab 34 12 D1 -- -- \3 34
	move.l	d2,d4
	swap	d4
	move.l	d0,d6
	mulu	d4,d6		;make D3
	move.l	d4,d5
	mulu	d1,d4		;make B3
	add.l	d4,d7		; cd ab 34 12 B3 43 D3 \3 34
	move.l	d0,d4
	swap	d4
	mulu	d4,d5		; cd ab 34 12 dc C3 D3 \3 34
	mulu	d4,d2		; cd ab C4 12 dc C3 D3 \3 34
	add.l	d2,d6
	mulu	d3,d4		; cd ab C4 12 C2 C3 \4 \3 34
	addx.l	d4,d7
	mulu	d0,d3		; cd ab C4 D2 C2 C3 \4 \3 34
	move.l	a4,d2		; cd ab 34 D2 C2 C3 \4 \3 34
	mulu	d2,d0		; D4 ab 34 D2 C2 C3 \4 \3 34
	mulu	d2,d1		; D4 B2 34 D2 C2 C3 \4 \3 34
	add.l	d3,d5
	add.l	d5,d1
	swap	d7
	swap	d6
	move.w	d6,d7
	clr.w	d6
	add.l	d6,d0
	addx.l	d7,d1
	movem.l	(SP)+,d2-d7/a4
	ENDM

	;- SSQR64 macro - signed 64 bit square.
	;- Input:	d0 and d1 contain a 64-bit signed number in the
	;-		order least to most significant longword.
	;- Output:	d0 and d1 contain the square of the input in the
	;-		order least to most significant longword.

SSQR64:	MACRO
	tst.l	d1
	bpl.S	*+4	;->ss64a
	neg.l	d0
	SQR3264		;ss64a:
	ENDM

	;- USQR64 macro - unsigned 64 bit square.
	;- Input:	d0 contains the least significant longword of a
	;-		64-bit unsigned number.
	;-		d1 is ignored.
	;- Output:	d0 and d1 contain the square of the input in the
	;-		order least to most significant longword.

USQR64:	MACRO
	SQR3264
	ENDM

	;- GSQR64 macro - general 64 bit square.
	;- Input:	d0 and d1 contain a 64-bit signed or unsigned number
	;-		in the order least to most significant longword.
	;- Output:	d0 and d1 contain the square of the input in the
	;-		order least to most significant longword.

GSQR64:	MACRO			; d0 d1 d2 d3 d4 d5 d6 d7
	movem.l	d2-d7,-(SP)	; cd ab -- -- -- -- -- --
	move.l	d1,d7
	swap	d7
	mulu	d0,d7		; cd ab -- -- -- -- -- AD
	move.l	d0,d4
	swap	d4
	move.l	d0,d6		; cd ab -- -- dc -- cd AD
	mulu	d4,d6		; cd ab -- -- dc -- CD AD
	move.l	d1,d5
	mulu	d4,d5		; cd ab -- -- dc CB CD AD
	add.l	d5,d7		; cd ab -- -- dc CB /3 /4
	swap	d7
	swap	d6
	move.w	d6,d7
	clr.w	d6	
	move.l	d1,d5
	mulu	d0,d5		;make BD
	add.l	d5,d7
	add.l	d6,d6
	addx.l	d7,d7
	mulu	d0,d0		;make DD
	move.l	d4,d1
	mulu	d1,d1		;make CC
	add.l	d6,d0
	addx.l	d7,d1
	movem.l	(SP)+,d2-d7
	ENDM

	;- UDIV64 macro - unsigned 64 bit division.
	;- Input:	d0 and d1 contain an unsigned 64-bit dividend in
	;-		the order least to most significant longword.
	;-		d2 and d3 contain an unsigned 64-bit divisor in
	;-		the order least to most significant longword.
	;- Output:	d0 and d1 contain an unsigned 64-bit quotient in
	;-		the order least to most significant longword.
	;-		d2 and d3 contain an unsigned 64-bit remainder in
	;-		the order least to most significant longword.

UDIV64:	MACRO
	movem.l	d4-d6,-(SP)
	moveq	#0,d4
	moveq	#0,d5
	moveq	#63,d6
	lsl.l	#1,d0
	roxl.l	#1,d1
	roxl.l	#1,d4		;ud64a:
	roxl.l	#1,d5
	sub.l	d2,d4
	subx.l	d3,d5
	bcc.S	*+6		;->ud64b
	add.l	d2,d4
	addx.l	d3,d5
	roxl.l	#1,d0		;ud64b:
	roxl.l	#1,d1
	dbra	d6,*-$12	;->ud64a
	not.l	d0
	not.l	d1
	move.l	d4,d2
	move.l	d5,d3
	movem.l	(SP)+,d4-d6
	ENDM

	;- SDIV64 macro - signed 64 bit division.
	;- Input:	d0 and d1 contain a signed 64-bit dividend in the
	;-		order least to most significant longword.
	;-		d2 and d3 contain a signed 64-bit divisor in the
	;-		order least to most significant longword.
	;- Output:	d0 and d1 contain a signed 64-bit quotient in the
	;-		order least to most significant longword.
	;-		d2 and d3 contain a signed 64-bit remainder in the
	;-		order least to most significant longword.
	;- Let a be the dividend, b the divisor, c the quotient and d the
	;- remainder. Then both of the following hold:
	;- 		(1) a = b*c+d
	;-		(2) abs(a) = abs(b)*abs(c)+abs(d)

SDIV64:	MACRO
	movem.l	d4-d5,-(SP)
	move.l	d1,d4
	eor.l	d3,d4
	move.l	d1,d5
	bpl.S	*+6		;->sd64a
	neg.l	d0
	negx.l	d1
	tst.l	d3		;sd64a:
	bpl.S	*+6		;->sd64b
	neg.l	d2
	negx.l	d3
	UDIV64			;sd64b:
	tst.l	d5
	bpl.S	*+6		;->sd64c
	neg.l	d2
	negx.l	d3
	tst.l	d4		;sd64c:
	bpl.S	*+6		;->sd64d
	neg.l	d0
	negx.l	d1
	movem.l	(SP)+,d4-d5	;sd64d:
	ENDM

	ENDC
