|
|  double float to long conversion routine
|
| M. Ritzert (ritzert@DFG.DBP.DE)

	.text
	.even

#ifdef ERROR_CHECK

_Overflow:
	.ascii "OVERFLOW\0"
_Error_String:
	.ascii "_fixdfsi: %s error\n\0"
.even

#endif ERROR_CHECK

#ifdef sfp004
|
| 4.10.1990/10.1.1992
|
| 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

	.globl	__fixdfsi, ___fixdfsi
__fixdfsi:
___fixdfsi:
	lea	0xfffa50,a0
	movew	#0x5403,a0@(comm)	| fintrz to fp0
	cmpiw	#0x8900,a0@(resp)	| check
	movel	a7@(4),a0@
	movel	a7@(8),a0@
	movew	#0x6000,a0@(comm)	| result to d0
	.long	0x0c688900, 0xfff067f8
	movel	a0@,d0
		
#endif	sfp004
#ifdef	__M68881__

|
| floating point stuff for Atari-gcc using
| an 68030/68881
| developed with gcc/gas
|
| double float to long conversion routine
|
| M. Ritzert (mjr@dfg.dbp.de)
|
| 30.11.1991/10.1.1992
|

	.globl	__fixdfsi, ___fixdfsi
__fixdfsi:
___fixdfsi:
	fintrzd sp@(4),fp0		| convert the arg
	fmovel fp0,d0			| return

#endif	__M68881__


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

| double float to long conversion 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.3, kub 01-90 :
| added support for denormalized numbers
|
| Revision 1.2, kub 01-90 :
| replace far shifts by swaps to gain speed
|
| 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	__fixdfsi, ___fixdfsi

__fixdfsi:
___fixdfsi:
	lea	sp@(4),a0	| pointer to parameters
	moveml	d2/d4/d5,sp@-	| save registers
	moveml	a0@,d4-d5	| get the number
	movew	a0@,d0		| extract exp
	movew	d0,d2		| extract sign
	lsrw	#4,d0
	andw	#0x07ff,d0	| kill sign bit

	andl	#0x0fffff,d4	| remove exponent from mantissa
	orl	#0x100000,d4	| restore implied leading "1"

	cmpw	#BIAS8,d0	| check exponent
	blt	zero		| strictly factional, no integer part ?
	cmpw	#BIAS8+32,d0	| is it too big to fit in a 32-bit integer ?
	bgt	toobig

	subw	#BIAS8+21,d0	| adjust exponent
	bgt	2f		| shift up
	beq	3f		| no shift

	cmpw	#-8,d0		| replace far shifts by swap
	bgt	1f
	movew	d4,d5		| shift fast, 16 bits
	swap	d5
	clrw	d4
	swap	d4
	addw	#16,d0		| account for swap
	bgt	2f
	beq	3f

1:	lsrl	#1,d4		| shift down to align radix point;
	addw	#1,d0		| extra bits fall off the end (no rounding)
	blt	1b		| shifted all the way down yet ?
	bra	3f

2:	addl	d5,d5		| shift up to align radix point
	addxl	d4,d4
	subw	#1,d0
	bgt	2b

3:	movel	d4,d0		| put integer into result register
	cmpl	#0x80000000,d0	| -2147483648 is a nasty evil special case
	bne	6f
	tstw	d2		| this had better be -2^31 and not 2^31
	bpl	toobig
	bra	8f
6:	tstl	d0		| sign bit set ? (i.e. too big)
	bmi	toobig
7:
	tstw	d2		| is it negative ?
	bpl	8f
	negl	d0		| negate
8:
	moveml	sp@+,d2/d4/d5
	rts

zero:
	clrl	d0		| make the whole thing zero
	bra	7b

toobig:
	movel	#0x7fffffff,d0	| ugh. Should cause a trap here.

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

#ifdef	ERROR_CHECK

| all three versions
	cmpil	#0x7fffffff,d0	| >= long_max
	bge	error_plus	|
	cmpil	#-0x7fffffff,d0	| <= long_min ?
	ble	error_minus	|
	rts			|
error_minus:
	moveml	d0-d1,a7@-
	movel	#63,_errno	| errno = ERANGE
	pea	_Overflow	| for printf
	bra	error_exit	|
error_plus:
	moveml	d0-d1,a7@-
	movel	#63,_errno	| errno = ERANGE
	pea	_Overflow	| for printf
	bra	error_exit	|

error_exit:
	pea	_Error_String	|
	pea	__iob+52	|
	jbsr	_fprintf	|
	addl	#12,a7		|
	moveml	a7@+,d0-d1
#endif	ERROR_CHECK

# if !defined (sfp004) && !defined (__M68881__)
	bra	7b
#else
	rts
#endif
