
; Routinen für Mathematik.  Compress-Tab 8.










; 16-Bit-Arithmetik.  Alle Werte werden	als 32-Bit-Werte gestackt.

	IFD	MulDiv16

	XDEF	_IDivS,_IDivU,_IMulS,_IMulU,_sdiv,_smuls,_umuls



; IDivS	(arg1, arg2)
; Teile	arg1 (32 Bit) durch arg2 (16 Bit) vorzeichenbehaftet.
; Rückgabe: 32-Bit-Ergebnis vorzeichenbehaftet.

_sdiv
_IDivS
	move.l	4(SP),d0
	divs	8+2(SP),d0
	ext.l	d0
	rts



; IDivU	(arg1, arg2)
; Teile	arg1 (32 Bit) durch arg2 (16 Bit) vorzeichenlos.
; Rückgabe: 32-Bit-Ergebnis vorzeichenlos.

_IDivU
	move.l	4(SP),d0
	divu	8+2(SP),d0
	swap	d0
	clr.w	d0
	swap	d0
	rts



; IMulS	(arg1, arg2)
; Multipliziere	arg1 (16 Bit) mit arg2 (16 Bit)	vorzeichenbehaftet.
; Rückgabe: 32-Bit-Ergebnis vorzeichenbehaftet.

_smuls
_IMulS
	move	4+2(SP),d0
	muls	8+2(SP),d0
	rts



; IMulU	(arg1, arg2)
; Multipliziere	arg1 (16 Bit) mit arg2 (16 Bit)	vorzeichenlos.
; Rückgabe: 32-Bit-Ergebnis vorzeichenlos.

_umuls
_IMulU
	move	4+2(SP),d0
	mulu	8+2(SP),d0
	rts

	ENDC










; 32-Bit-Arithmetik für	Assembler-Anwendung.  Das erste	Argument wird in D0
; übergeben, das zweite	in D1.	Rückgabe in D0.

	IFD	MulDiv32

	XDEF	lmult,ulmult,ldivt,uldivt,lmodt,ulmodt





lmult
ulmult
	; D0 = D0 * D1	vorzeichenlos oder vorzeichenbehaftet.
	movem.l	d1-d3,-(SP)
	move.l	d0,d2
	swap	d2
	move.l	d1,d3
	swap	d3
	mulu	d1,d2			; Kreuzprodukt 1
	mulu	d0,d3			; Kreuzprodukt 2
	mulu	d1,d0			; unteres Langwort
	add.l	d3,d2			; addiere Kreuzprodukte
	swap	d2			; verwende nur unteres Wort
	clr.w	d2
	add.l	d2,d0			; unteres Langwort + Kreuzprodukt-Summe
	movem.l	(SP)+,d1-d3
	rts





ldivt
	; D0 = D0 / D1	vorzeichenbehaftet.
	; Ergebnis negativ, wenn ENTWEDER Dividend ODER	Divisor	negativ.
	movem.l	d1-d4,-(SP)
	move.l	d0,d4
	bpl.s	1$
	neg.l	d0
1$	eor.l	d1,d4			; ergibt Vorzeichenbit in Bit 31
	tst.l	d1
	bpl.s	2$
	neg.l	d1
2$	bsr.s	Divide
	tst.l	d4			; Ergebnis negativ ?
	bpl.s	3$
	neg.l	d0			; ja
3$	movem.l	(SP)+,d1-d4
	rts





lmodt
	; D0 = D0 mod D1  vorzeichenbehaftet.
	; Ergebnis negativ, wenn Dividend negativ.
	movem.l	d1-d4,-(SP)
	move.l	d0,d4
	bpl.s	1$
	neg.l	d0
1$	tst.l	d1
	bpl.s	2$
	neg.l	d1
2$	bsr.s	Divide
	move.l	d1,d0
	tst.l	d4			; Ergebnis negativ ?
	bpl.s	3$
	neg.l	d0			; ja
3$	movem.l	(SP)+,d1-d4
	rts





uldivt
	; D0 = D0 / D1	vorzeichenlos.	Zusätzlich: Modulo in D1.
	movem.l	d2-d3,-(SP)
	bsr.s	Divide
	movem.l	(SP)+,d2-d3
	rts





ulmodt
	; D0 = D0 mod D1  vorzeichenlos.  Zusätzlich: Quotient in D1.
	movem.l	d2-d3,-(SP)
	bsr.s	Divide
	exg	d1,d0			; Modulo
	movem.l	(SP)+,d2-d3
	rts





Divide
	; Hilfsroutine.	 D0 = D0 / D1  vorzeichenlos.  D1 enthält den Modulo.
	move.l	d1,d2			; Divisor nach D2
	swap	d1
	tst.w	d1
	bne.s	1$			; wenn Divisor größer $FFFF
	move.l	d0,d3
	clr.w	d0
	swap	d0
	divu	d2,d0
	move.l	d0,d1
	swap	d0			; oberer Quotient nach oben
	move.w	d3,d1
	divu	d2,d1
	move.w	d1,d0			; ergibt 32-Bit-Quotient
	clr.w	d1
	swap	d1			; Modulo
	rts

	; Divisor > $FFFF.  Die	Division ergibt	einen 16-Bit-Wert.
1$	move.l	d0,d1
	swap	d0			; beginne schon	mit 16-Bit-Verschiebung	!
	clr.w	d0
	clr.w	d1
	swap	d1
	moveq	#16-1,d3		; schiebe nur noch 16 mal für den Rest
3$	add.l	d0,d0			; ADD ist schneller als	LSL #1 !
	addx.l	d1,d1			; Übertrag berücksichtigen
	cmp.l	d1,d2			; kann schon eine Eins ins Ergebnis ?
	bhi.s	2$
	addq	#1,d0			; ja, setze die	Eins
	sub.l	d2,d1			; und kürze den	Modulo
2$	dbra	d3,3$
	rts





	ENDC










	END

