#if !defined (__M68881__) && !defined (sfp004)
#
 |-----------------------------------------------------------------------------
 | remove exponent from floating point number
 | C Interface
 | double frexp(double value, int *eptr)
 |
 | returns significand (|significand| < 1)
 |	   in *eptr returns n such that value = significand * 2**n
 |-----------------------------------------------------------------------------
 | 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	added support for denormalized numbers			-kub-, 01/90
 |  #   ported to gcc  ++jrb 04/90
 |-----------------------------------------------------------------------------

BIAS8	=	0x3ff - 1

	.text; .even
	.globl _frexp
_frexp:
	movel	sp@(12),a0	| initialize exponent for loop
#ifdef __MSHORT__
	clrw	a0@
#else
	clrl	a0@
#endif
	tstl	sp@(4)		| 1st arg == 0 ?
	bne	nonzero
	tstl	sp@(8)
	bne	nonzero
	clrl	d0
	clrl	d1
	rts
nonzero:
	lea	sp@(4),a1
	moveml	d2-d7,sp@-
2:
	movew	a1@,d0		| extract value.exp
	movew	d0,d2		| extract value.sign	++jrb
	lsrw	#4,d0
	andw	#0x7ff,d0	| kill sign bit
	cmpw	#BIAS8,d0	| get out of loop if finally (a1) in [0.5,1.0)
	beq	3f

	andw	#0x0f,a1@	| remove exponent from value.mantissa
	tstw	d0		| check for zero exponent - no leading 1
	beq	0f
	orw	#0x10,a1@	| restore implied leading 1
	bra	1f
0:	addw	#1,d0
1:
	movel	a1@,d1		| check for zero
	orl	a1@(4),d1
	beq	3f		| if zero, all done : exp = 0, num = 0.0

	subw	#BIAS8,d0	| remove bias
#ifdef __MSHORT__		
	addw	d0,a0@		| add current exponent in
#else
	extl	d0
	addl	d0,a0@		| add current exponent in
#endif

	movew	#BIAS8,d0	| set bias for return value
	clrw	d1		| rounding = 0
	pea	L0		| call to norm_df (dirty, but dont ...
	moveml	d2-d7,sp@-	| ... need to copy with -mshort)
	moveml	a1@,d4-d5
	jmp	norm_df		| normalize result
L0:
	moveml	d0-d1,a1@
	bra	2b		| loop around to catch denormalized numbers
3:
	moveml	a1@,d0-d1
	moveml	sp@+,d2-d7
				| d0-d1 has normalized mantissa
	rts

#endif	!__M68881__ && !sfp004
#ifdef	__M68881__

|
| remove exponent from floating point number
| C Interface
| double frexp(double value, int *eptr)
|
| returns significand (#significand# < 1)
|	   in *eptr returns n such that value = significand * 2**n
|#######################################################################
| hacked for the 68881 by Michael Ritzert, 5.10.90
|#######################################################################
| ported from sfp004 board to real 68881, mjr, August 1991
|#######################################################################
| a0:	pointer to n
| 	sp@(12) address of resulting exponent (n)
	
	.text; .even

.globl _frexp

_frexp:
	moveal	a7@(12),a1		| address of n
	fmoved	a7@(4),fp0		| load first_argument to fp0
	fcmpd	#0r0.0,fp0		| 1st arg == 0 ?
	fjeq	null_			| both parts of result are 0
	fgetexpx fp0,fp1		| get expnent
	fgetmanx fp0,fp0		| get mantissa
	fscaleb #-1,fp0			|
#ifdef __MSHORT__
	fmovew	fp1,a1@			| fetch exp (fmovew from fp1)
	addqw	#1,a1@			| correct result
#else
	fmovel	fp1,a1@			| fetch exp (fmovel from fp1)
	addql	#1,a1@			| correct result
#endif
	fmoved	fp0,a7@-		| now fetch significand
	moveml	a7@+,d0-d1
	rts
null_:
	moveml	a7@(4),d0-d1
#ifdef __MSHORT__
	clrw	a1@
#else
	clrl	a1@
#endif
	rts

#endif	__M68881__
#ifdef	sfp004

| remove exponent from floating point number
| C Interface
| double frexp(double value, int *eptr)
|
| returns significand (|significand| < 1)
|	   in *eptr returns n such that value = significand * 2**n
|
| hacked for the 68881 by Michael Ritzert, 5.10.90/18.12.91
|
| addresses of the 68881 data port. This choice is fastest when much data is
| transferred between the two processors.

comm =	 -6	|	fpu command reg
resp =	-16	|	fpu response reg
zahl =	  0	|	fpu data reg

| a1:	fpu base register
| a0:	pointer to n
| 	sp@(12) address of resulting exponent (n)

| waiting loop ...
|
| wait:
| ww:	cmpiw	#0x8900,a0@(resp)
| 	beq	ww
| is coded directly by
|	.long	0x0c688900, 0xfff067f8                 (fpu base a1)
| and
| www:	tst.w	a0@(resp)
|	bmi.b	www
| is coded by
|	.word	0x4a68,0xfff0,0x6bfa		| test
	
	.text; .even

.globl _frexp
	
	tstl	sp@(4)		| 1st arg == 0 ?
	bne	nonzero
	tstl	sp@(8)
	bne	nonzero
	movel	sp@(12),a0
#ifdef __MSHORT__
	clrw	a0@
#else
	clrl	a0@
#endif
	clrl	d0
	clrl	d1
	rts
nonzero:

	lea	0xfffffa50:w,a0
	movew	#0x5418,a0@(comm)	| load first argument to fp0
	cmpiw	#0x8900,a0@(resp)	| check
	movel	a7@(4),a0@
	movel	a7@(8),a0@

	movew	#0x009f,a0@(comm)	| fgetman fp0,fp1
	.word	0x4a68,0xfff0,0x6bfa	| test

	movew	#0x001e,a0@(comm)	| fgetexp fp0,fp0
	moveal	a7@(12),a1		| address of n while the fpu is active
	.word	0x4a68,0xfff0,0x6bfa	| test

	movew	#5026,a0@(comm)		| fscalew #-1,fp0
	.long	0x0c688900, 0xfff067f8
	movew	#-1,a0@

#ifdef __MSHORT__
	movew	#0x7080,a0@(comm)	| fetch exp (fmovew from fp1)
	.long	0x0c688900, 0xfff067f8
	movew	a0@,a1@			| return exp
#else
	movew	#0x7880,a0@(comm)	| fetch exp (fmovel from fp1)
	.long	0x0c688900, 0xfff067f8
	movel	a0@,a1@			| return exp
#endif
	movew	#0x7400,a0@(comm)	| now fetch significand
	.long	0x0c688900, 0xfff067f8
	movel	a0@,d0
	movel	a0@,d1
	btst	#31,a7@(4)		| test sign of 1st arg
	bge	fini			| arg neg ?
	bset	#31,d0			| =>  negate result
fini:	rts

#endif	sfp004
