#if !defined (__M68881__) && !defined (sfp004)

| double floating point divide routine
|
| written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
| Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
|
|
| Revision 1.2, kub 01-90 :
| added support for denormalized numbers
|
| Revision 1.1, kub 12-89 :
| Ported over to 68k assembler
|
| Revision 1.0:
| original 8088 code from P.S.Housel

BIAS8	=	0x3FF-1

	.text
	.even
	.globl	__divdf3, ___divdf3
	.globl	__infinitydf

# ifdef	ERROR_CHECK
LC0:
	.ascii "floating point division by 0\12\15\0"
	.even
# endif	ERROR_CHECK

__divdf3:
___divdf3:

# ifdef	ERROR_CHECK
	tstl	a7@(12)			| check if divisor is 0
	bne	continue
	tstl	a7@(16)
	bne	continue

	moveml	d0-d1,a7@-
	pea	LC0
	pea	__iob+52	|
	jbsr	_fprintf	|
	addql	#8,a7		|
	moveml	a7@+,d0-d1
					| set _errno to ERANGE
#  ifdef __MSHORT__
	movew	#63,_errno
#  else
	movel	#63,_errno
#  endif
	movel	#0x7ff00000,d0		| return signed infinity 
	clrl	d1			|
	btst	#31,a7@(4)		| transfer sign of dividend
	beq	clear			| (mjr++)
	bset	#31,d0			|
	rts				|
clear:					|
	bclr	#31,d0			|
	rts
continue:

# endif	ERROR_CHECK

	lea	sp@(4),a0	| pointer to parameters u and v
	moveml	d2-d7,sp@-	| save registers
	moveml	a0@,d4-d5/d6-d7	| d4-d5 = u, d6-d7 = v

	movel	d4,d0		| d0 = u.exp
	swap	d0
	movew	d0,d2		| d2 = u.sign
	lsrw	#4,d0
	andw	#0x07ff,d0	| kill sign bit

	movel	d6,d1		| d1 = v.exp
	swap	d1
	eorw	d1,d2		| d2 = u.sign ^ v.sign (in bit 31)
	lsrw	#4,d1
	andw	#0x07ff,d1	| kill sign bit

	andl	#0x0fffff,d4	| remove exponent from u.mantissa
	tstw	d0		| check for zero exponent - no leading "1"
	beq	0f
	orl	#0x100000,d4	| restore implied leading "1"
	bra	1f
0:	addw	#1,d0		| "normalize" exponent
1:	movel	d4,d3
	orl	d5,d3
	beq	retz		| dividing zero

	andl	#0x0fffff,d6	| remove exponent from v.mantissa
	tstw	d1		| check for zero exponent - no leading "1"
	beq	0f
	orl	#0x100000,d6	| restore implied leading "1"
	bra	1f
0:	addw	#1,d1		| "normalize" exponent
1:	movel	d6,d3
	orl	d7,d3

#ifndef	ERROR_CHECK
	beq	divz		| divide by zero
#endif	ERROR_CHECK

	movew	d2,a0		| save sign

	subw	d1,d0		| subtract exponents,
	addw	#BIAS8-11+1,d0	|  add bias back in, account for shift
	addw	#66,d0		|  add loop offset, +2 for extra rounding bits
				|   for denormalized numbers (2 implied by dbra)
	movew	#24,d1		| bit number for "implied" pos (+4 for rounding)
	movel	#-1,d2		| zero the quotient
	movel	#-1,d3		|  (for speed it is a one''s complement)
	subl	d7,d5		| initial subtraction,
	subxl	d6,d4		| u = u - v
2:
	btst	d1,d2		| divide until 1 in implied position
	beq	5f

	addl	d5,d5
	addxl	d4,d4
	bcs	4f		| if carry is set, add, else subtract

	addxl	d3,d3		| shift quotient and set bit zero
	addxl	d2,d2
	subl	d7,d5		| subtract
	subxl	d6,d4		| u = u - v
	dbra	d0,2b		| give up if result is denormalized
	bra	5f
4:
	addxl	d3,d3		| shift quotient and clear bit zero
	addxl	d2,d2
	addl	d7,d5		| add (restore)
	addxl	d6,d4		| u = u + v
	dbra	d0,2b		| give up if result is denormalized
5:	subw	#2,d0		| remove rounding offset for denormalized nums
	notl	d2		| invert quotient to get it right
	notl	d3

	movel	d2,d4		| save quotient mantissa
	movel	d3,d5
	movew	a0,d2		| get sign back
	clrw	d1		| zero rounding bits
	jmp	norm_df		| (registers on stack removed by norm_df)

retz:	clrl	d0		| zero destination
	clrl	d1
	moveml	sp@+,d2-d7
	rts			| no normalization needed

#ifndef	ERROR_CHECK
divz:	moveml	__infinitydf,d0-d1 | return infinty value
	moveml	sp@+,d2-d7	| should really cause trap ?!?

	btst	#31,a7@(4)		| transfer sign of dividend
	beq	clear			| (mjr++)
	bset	#31,d0			|
	rts				|
clear:					|
	bclr	#31,d0			|
	rts

#endif	ERROR_CHECK

#endif
#ifdef	sfp004

| double precision floating point stuff for Atari-gcc using the SFP004
| developed with gas
|
| double precision division
|
| M. Ritzert (mjr at dmzrzu71)
|
| 4.10.1990
|
| no NAN checking implemented to gain compatibility with the TT-lib
|
| addresses of the 68881 data port. This choice is fastest when much data is
| transferred between the two processors.

comm =	 -6
resp =	-16
zahl =	  0

| waiting loop ...
|
| wait:
| ww:	cmpiw	#0x8900,a0@(resp)
| 	beq	ww
| is coded directly by
|	.long	0x0c688900, 0xfff067f8

# ifdef	ERROR_CHECK
LC0:
	.ascii "floating point division by 0\12\15\0"
	.even
# endif	ERROR_CHECK

	.text
	.even
	.globl	__divdf3, ___divdf3

__divdf3:
___divdf3:

# ifdef	ERROR_CHECK
	tstl	a7@(12)			| check if divisor is 0
	bne	continue
	tstl	a7@(16)
	bne	continue

	moveml	d0-d7/a0-a6,a7@-	| print error message
	pea	LC0
	movew	#9,a7@-
	trap	#1
	addql	#6,a7
	moveml	a7@+,d0-d7/a0-a6
					| set _errno to ERANGE
#  ifdef __MSHORT__
	movew	#63,_errno
#  else
	movel	#63,_errno
#  endif
	movel	#0x7ff00000,d0		| return signed infinity 
	clrl	d1			|
	btst	#31,a7@(4)		| transfer sign of dividend
	beq	clear			| (mjr++)
	bset	#31,d0			|
	rts				|
clear:					|
	bclr	#31,d0			|
	rts
continue:

# endif	ERROR_CHECK

	lea	0xfffa50,a0
	movew	#0x5400,a0@(comm)	| load first argument to fp0
	cmpiw	#0x8900,a0@(resp)	| check
	movel	a7@(4),a0@
	movel	a7@(8),a0@
	movew	#0x5420,a0@(comm)
	.long	0x0c688900, 0xfff067f8
	movel	a7@(12),a0@
	movel	a7@(16),a0@
	movew	#0x7400,a0@(comm)	| result to d0
	.long	0x0c688900, 0xfff067f8
	movel	a0@,d0
	movel	a0@,d1
 	rts
#endif	sfp004
