
*	Maxon C++ Library:
*	Modul "math_64Bit"
*	Jens Gelhar 02.09.92, 15.04.94, 07.11.95

	xdef	lib_64bit_add,lib_64bit_sub
	xdef	lib_64bit_neg,lib_64bit_cmp
	xdef	lib_64bit_mult,lib_64bit_multS
	xdef	lib_64bit_div,lib_64bit_divS
	xdef	lib_64bit_mod,lib_64bit_modS
	xdef	lib_64bit_shl,lib_64bit_shr,lib_64bit_shrS
	xdef	_vlongtostr,_uvlongtostr

	xref	exit__i,uintmult

lib_64bit_add:	; d0|d1 += d2|d3
	add.l d2,d0
	bhs.b .1
	addq.l #1,d1
.1	add.l d3,d1
	rts

lib_64bit_sub:	; d0|d1 -= d2|d3
	sub.l d2,d0
	bhs.b .1
	subq.l #1,d1
.1	sub.l d3,d1
	rts

lib_64bit_neg:	; d0|d1
	movem.l d2/d3,-(a7)
	move.l d0,d2
	move.l d1,d3
	moveq #0,d0
	moveq #0,d1
	bsr.b lib_64bit_sub
	movem.l (a7)+,d2/d3
	rts

Neg64bitd23:	; d0|d3
	exg d0,d2
	exg d1,d3
	bsr.b lib_64bit_neg
	exg d0,d2
	exg d1,d3
	rts

lib_64bit_multS:	; vorzeichenbehaftet:
	tst.l d1
	bpl.b m64s1
	bsr.b lib_64bit_neg
	tst.l d3
	bpl.b m64sNeg
	bsr.b Neg64bitd23
	bra.b lib_64bit_mult
m64s1:	tst.l d3
	bpl.b lib_64bit_mult
	bsr.b Neg64bitd23
m64sNeg:	bsr.b lib_64bit_mult
	bra.b lib_64bit_neg


lib_64bit_mult:	; d0|d1 *= d2|d3
	movem.l d4-d7,-(a7)
	exg d1,d3               ; d1 in d3 retten
	move.l d0,d6            ; d0 in d6 retten
	jsr uintmult
	move.l d0,d5            ; d5 = d0*d3
	move.l d3,d0
	move.l d2,d1
	jsr uintmult
	add.l d5,d0             ; d0 = d0*d3 + d1*d2
	exg d6,d0               ;    nach d6 retten
	move.l d2,d1
	; d0|d1 = d0*d2 berechnen:

	; d0|d1 = d0*d1, Trash d4/d5/d7
	move.l d0,d4
	swap d4
	mulu d1,d4              ; d4 = H0*L1
	move.l d1,d7
	swap d7
	mulu d0,d7              ; d7 = L0*H1
	moveq #0,d5
	add.l d7,d4
	bhs.b mul1
	move.l #$10000,d5
mul1	swap d4
	move.w d4,d5
	clr.w d4                ; d4|d5 = (H0*L1 + L0*H1)'
	move.l d0,d7
	mulu d1,d7              ; d7 = L0+L1
	swap d0
	swap d1
	mulu d0,d1              ; d1 = H0*H1
	move.l d7,d0            ; d0|d1 = L0*L1 + (H0*H1)''
	add.l d5,d1
	add.l d4,d0
	bhs.b mul2
	addq.l #1,d1
mul2	; Hi-Longwords addieren:
	add.l d6,d1             ; d0|d1 = d0*d2 + [d0*d3 + d1*d2]'
	movem.l (a7)+,d4-d7
	rts


lib_64bit_divS:	; vorzeichenbehaftet dividieren
	tst.l d1
	bmi.b d64bs1
	tst.l d3
	bpl.b lib_64bit_div
	bsr Neg64bitd23
	bra.b d64bs3
d64bs1	bsr lib_64bit_neg
	tst.l d3
	bpl.b d64bs2
	bsr Neg64bitd23
	bra.b lib_64bit_div
d64bs2	bsr.b lib_64bit_div
d64bs3	bsr lib_64bit_neg
	bra Neg64bitd23

lib_64bit_div:	; d0|d1 /= d2|d3, d2|d3 = d0|d1 % d2|d3
	movem.l d4-d7/a0,-(a7)
	lea 65.w,a0             ; Schleifenzähler
	moveq #0,d4
	moveq #0,d5             ; d4|d5: Hi-Bits von d0|d1
	moveq #0,d6
	moveq #0,d7             ; d6|d7: Ergebnis
	tst.l d2
	bne.b d64bLoop
	tst.l d3
	bne.b d64bLoop
	move.l #9999,-(a7)
	jsr exit__i
d64bLoop
	subq.l #1,a0
	cmp.l #0,a0
	beq.b d64bEnd
	asl.l #1,d6
	roxl.l #1,d7
	asl.l #1,d0
	roxl.l #1,d1
	roxl.l #1,d4
	roxl.l #1,d5
	cmp.l d3,d5
	blo.b d64bLoop
	bhi.b d64b1
	cmp.l d2,d4
	blo.b d64bLoop
d64b1	; subtrahieren:
	sub.l d2,d4
	bhs.b d64b2
	subq.l #1,d5
d64b2	sub.l d3,d5
	; Erg. inkrementieren:
	addq.l #1,d6
	bne.b d64bLoop
	addq.l #1,d7
	bra.b d64bLoop
d64bEnd	move.l d6,d0
	move.l d7,d1
	move.l d4,d2
	move.l d5,d3
	movem.l (a7)+,d4-d7/a0
	rts

lib_64bit_mod:
	bsr.b lib_64bit_div
	move.l d2,d0
	move.l d3,d1
	rts

lib_64bit_modS:
	bsr lib_64bit_divS
	move.l d2,d0
	move.l d3,d1
	rts

lib_64bit_cmp:	; cmp.d d2|d3, d0|d1
	cmp.l d3,d1
	bne.b cmp64b1
	cmp.l d2,d0
	beq.b cmp64b1
	; Zahlen unterscheiden sich nur in untersten 64 Bit
	swap d0
	swap d2
	move.w d0,d1
	move.w d2,d3
	bra.b lib_64bit_cmp
cmp64b1	rts

lib_64bit_shl:	; d0|d1 <<= d2|d3
	tst.l	d3
	bne.b	.0
	cmp.l	#64,d2
	bhi.b	.0
.loop	asl.l	#1,d0
	roxl.l	#1,d1
	subq.l	#1,d2
	bne.b	.loop
	rts
.0	moveq	#0,d0
	moveq	#0,d1
	rts

	SECTION "Shift",CODE

lib_64bit_shr:	; d0|d1 >>= d2|d3
	tst.l	d3
	bne.b	.0
	cmp.l	#64,d2
	bhi.b	.0
.loop	lsr.l	#1,d1
	roxr.l	#1,d0
	subq.l	#1,d2
	bne.b	.loop
	rts
.0	moveq	#0,d0
	moveq	#0,d1
	rts

lib_64bit_shrS:	; d0|d1 >>= d2|d3
	tst.l	d3
	bne.b	.0
	cmp.l	#64,d2
	bhi.b	.0
.loop	asr.l	#1,d1
	roxr.l	#1,d0
	subq.l	#1,d2
	bne.b	.loop
	rts
.0	moveq	#0,d0
	moveq	#0,d1
	rts

	SECTION "Convert",CODE

ConvDecimal:	; a0 -> d0|d1
	moveq #0,d0
	moveq #0,d1
coDc1	moveq #0,d4
	move.b (a0)+,d4
	sub.b #'0',d4
	cmp.w #10,d4
	bhs.b coDc2
	moveq #10,d2
	moveq #0,d3
	jsr lib_64bit_mult
	add.l d4,d0
	bhs.b coDc1
	addq.l #1,d1
	bra.b coDc1
coDc2	rts

_vlongtostr:	; Stack-Parameter: Doppelwort, Buffer.L, Base.W
	tst.l	4+4(a7)
	bpl.b	_uvlongtostr
	movem.l	d1-d4/a0,-(a7)
	movem.l	20+4(a7),d0/d1/a0
	jsr	lib_64bit_neg
	move.b	#'-',(a0)+
	bra.b	ltsIn

_uvlongtostr:
	movem.l	d1-d4/a0,-(a7)
	movem.l	20+4(a7),d0/d1/a0
ltsIn
	moveq	#0,d4
	move.w	20+4+12(a7),d4           ; Basis
	clr.w	-(a7)
ltsLoop	move.l	d4,d2
	moveq	#0,d3
	jsr	lib_64bit_div
	add.w	#'0',d2
	cmp.w	#'9',d2
	bls.b	lts1
	add.w	#'a'-'0'-10,d2
lts1	move.w	d2,-(a7)
	tst.l	d0
	bne.b	ltsLoop
	tst.l	d1
	bne.b	ltsLoop
ltsCopy	move.w	(a7)+,d0
	move.b d0,(a0)+
	bne.b ltsCopy
	movem.l (a7)+,d1-d4/a0
	move.l 4+8(a7),d0
	rts

	end
