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

 | take floating point to integer and fractional pieces
 | 
 | C interface
 |  double modf( double value, double *iptr)
 |  returns fractional part of value
 |	   in *iptr returns the integral part
 |	   such that (*iptr + fractional) == value
 | 
 |-----------------------------------------------------------------------------
 | ported to 68000 by Kai-Uwe Bloem, 12/89
 |  #1  original author: Peter S. Housel 9/21/88,01/17/89,03/19/89,5/24/89
 |  #2  replaced shifts by swap if possible for speed increase	-kub-, 01/90
 |  #3  ported to gcc ++jrb 03/90
 |-----------------------------------------------------------------------------

BIAS8	=	0x3ff - 1

	.text; .even
	.globl _modf
_modf:
	lea	sp@(4),a0	| a0 -> float argument
	movel	sp@(12),a1	| a1 -> ipart result
	moveml	d2-d7,sp@-	| save d2-d7

	movew	a0@,d0		| extract value.exp
	movew	d0,d2		| extract value.sign
	lsrw	#4,d0
	andw	#0x7ff,d0	| kill sign bit

	cmpw	#BIAS8,d0
	bge	1f		| fabs(value) >= 1.0

	clrl	a1@		| store zero as the integer part
	clrl	a1@(4)
	moveml	a0@,d0-d1	| return entire value as fractional part
	jra	L0

1:
	cmpw	#BIAS8+53,d0	| all integer, with no fractional part ?
	blt	2f		| no, mixed

	movel	a0@,a1@		| store entire value as the integer part
	movel	a0@(4),a1@(4)
	moveq	#0,d0		| return zero as fractional part
	moveq	#0,d1
L0:
	moveml	sp@+,d2-d7	| restore saved d2-d7
	rts
2:
|	moveml	d3-d7,sp@-	| save some registers (d2 is pushed already)
	moveml	a0@,d4-d5	| get value

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

	moveq	#0,d6		| zero fractional part
	moveq	#0,d7
3:
	cmpw	#BIAS8+37,d0	| fast shift, 16 bits ?
	bgt	4f
	movew	d6,d7		| shift down 16 bits
	movew	d5,d6
	movew	d4,d5
	clrw	d4
	swap	d7
	swap	d6
	swap	d5
	swap	d4
	addw	#16,d0
	bra	3b
4:
	cmpw	#BIAS8+53,d0	| done ?
	bge	5f
	lsrl	#1,d4		| shift integer part
	roxrl	#1,d5

	roxrl	#1,d6		| shift high bit into fractional part
	roxrl	#1,d7

	addw	#1,d0		| increment ipart exponent
	bra	4b		| keep shifting
5:
	| normalize ipart (all values are in correct reggies)
 	| save  a1, save d2-d7 that norm_df will pop
	movel	a1,sp@-
	pea	L1		| set up return address
	moveml	d2-d7,sp@-	| norm_df will pop this
	clrw	d1
	jmp	norm_df		| go do it
L1:				| norm_df will rts to here
	movel	sp@+,a1		| pop saved a1
	moveml	d0-d1,a1@	| store result into ipart
	
	| norm fractional part
	movel	d6,d4		| get frac into d4/d5
	movel	d7,d5
	clrw	d1		| rounding = 0
	movew	#BIAS8-11,d0	| set frac part exponent, sign already in d2
	jmp	norm_df		| norm_df will pop d2/d7 we save before
				| it will return to our caller via rts
				| with result in d0-d1

#endif	/* __M68881__, sfp004	*/
#ifdef	__M68881__
|
| modf: compiled by gcc from math-68881.h
|       manually optimized by Michael Ritzert
|
|	double modf( double X, double * IP )
|	
|	30.11.92
|	ritzert@dfg.dbp.de
|

	.text; .even

.globl _modf

_modf:
	fmoved	sp@(4),fp0	| load arg
	movel	sp@(12),a0	| get pointer to IP
	fintrzx	fp0,fp1		| get int part
	fmoved	fp1,a0@		| return it to IP
	fsubx 	fp1,fp0		| get remainder
	fmoved	fp0,sp@-	| return it
	moveml	sp@+,d0-d1	|
	rts

#endif __M68881__
#ifdef sfp004

comm =	 -6
resp =	-16
zahl =	  0

.even
.text
	.globl _modf
.even
_modf:
	movel	a1,a7@-			| save a1 (necessary?)
	lea	0xfffffa50:w,a0
	movew	#0x5403,a0@(comm)	| fintrz X -> fp0
	cmpiw	#0x8900,a0@(resp)	| check
	movel	a7@(8),a0@		| load X_hi
	movel	a7@(12),a0@		| load X_low

	movew	#0x5480,a0@(comm)	| X -> fp1
	.long	0x0c688900, 0xfff067f8
	movel	a7@(8),a0@		| load X_hi
	movel	a7@(12),a0@		| load X_low

|	000 000 001 0101000		| sub fp0 -> fp1
	movew	#0x00a8,a0@(comm)	| sub fp0 -> fp1
	.word	0x4a68,0xfff0,0x6bfa	| test

	movew	#0x7400,a0@(comm)	| fp0 to IntPart
	moveal	a7@(16),a1		| address of IntPart while the fpu is active
| wait
	.long	0x0c688900, 0xfff067f8
	movel	a0@,a1@+
	movel	a0@,a1@+
	movew	#0x7480,a0@(comm)	| Rest to d0/d1
| wait
	.long	0x0c688900, 0xfff067f8
	movel	a0@,d0
	movel	a0@,d1
	movel	a7@+,a1			| restore a1
 	rts

#endif	sfp004
