		mc68020
		multipass

		debug	on,lattice4

		xdef	_FixedMul
		xdef	@FixedMul_040
		xdef	@FixedMul_060
		xdef	_FixedDiv
		xdef	@FixedDiv_040
		xdef	@FixedDiv_060fpu

; pointers to CPU-specific FixedMul and FixedDiv routine

_FixedMul	dc.l	0
_FixedDiv	dc.l	0

; fixed_t FixedMul (fixed_t a, fixed_t b)

@FixedMul_040	muls.l	d1,d1:d0
		move.w	d1,d0
		swap	d0
		rts

; special version for 68060 which traps and emulates 64-bit muls.l

@FixedMul_060	movem.l d2-d5,-(sp)

		clr.b	d5          ; clear sign tag
		tst.l	d0          ; multiplier negative?
		bge	.not1
		neg.l	d0
		or.b	#1,d5
.not1
		tst.l	d1          ; multiplicand negative?
		bge	.not2
		neg.l	d1
		eor.b	#1,d5
.not2
		move.l	d0,d2       ; mr
		move.l	d0,d3       ; mr
		move.l	d1,d4       ; md
		swap	d3          ; hi_mr in lo d3
		swap	d4          ; hi_md in lo d4

		mulu.w	d1,d0       ; [1] lo_mr * lo_md
		mulu.w	d3,d1       ; [2] hi_mr * lo_md
		mulu.w	d4,d2       ; [3] lo_mr * hi_md
		mulu.w	d4,d3       ; [4] hi_mr * hi_md

		clr.l	d4
		swap	d0
		add.w	d1,d0
		addx.l	d4,d3
		add.w	d2,d0
		addx.l	d4,d3
		swap	d0

		clr.w	d1
		clr.w	d2

		swap	d1
		swap	d2
		add.l	d2,d1
		add.l	d3,d1

		tst.b	d5          ; check sign of result
		beq	.skip

		not.l	d0
		not.l	d1
		addq.l	#1,d0
		addx.l	d4,d1

.skip
		move.w	d1,d0
		swap	d0

		movem.l	(sp)+,d2-d5
		rts


; fixed_t FixedDiv (fixed_t a, fixed_t b)

@FixedDiv_040	movem.l	d2/d3,-(sp)
		move.l	d0,d3
		swap	d0
		move.w	d0,d2
		ext.l	d2
		move.w	#0,d0
		tst.l	d1
		beq.l	3$
		divs.l	d1,d2:d0
		bvc.b	1$
3$		eor.l	d1,d3
		bmi.b	2$
		move.l	#$7fffffff,d0
		bra.b	1$
2$		move.l	#$80000000,d0
1$		movem.l	(sp)+,d2/d3
		rts


		mc68881

; a m68060fpu fixed division

@FixedDiv_060fpu
		tst.l	d1
		beq.b	3$		; check for divide by 0 !
		fmove.l	d0,fp0
		fmove.l	d1,fp1
		fdiv.x	fp1,fp0
		fmove.s	#65536.0,fp1
		fmul.x	fp1,fp0
		fmove.l	fp0,d0
		rts

3$		eor.l	d1,d0
		bmi.b	2$
		move.l	#$7fffffff,d0
		bra.b	1$
2$		move.l	#$80000000,d0
1$		rts

		end
