V9/libc/sun/Ffltd.s

	.data
	.asciz	"@(#)Ffltd.s 1.1 86/02/03 Copyr 1985 Sun Micro"
	.even
	.text

|	Copyright (c) 1985 by Sun Microsystems, Inc.

/*
 *	double-precision floating math run-time support
 *
 *	copyright 1981, 1982 Richard E. James III
 *	translated to SUN idiom 10/11 March 1983 rt
 *	parameter passing re-done 22 July 1983 rt
 */
#include "fpcrtdefs.h"

	SAVEMASK = 0x3c00
	RESTMASK = 0x003c

/*
 * type conversion operators
 *
 * integer-to-double conversion: fflti
 * input:
 *	d0	integer
 * output:
 *	d0/d1	double floating value
 */

RTENTRY(Ffltd)
	movel	d0,a0		| a0 saves x.
	movel	d2,a1		| a1 saves d2.
	movel	#0x41e,d2  	| d2 accumulates exponent.
	tstl	d0
	bpls	3f		| Branch if x is non-negative.
	negl	d0		| d0 gets abs(x).
3:
	bmis	2f		| Branch if d0 is normalized.
	bnes	1f		| Branch if x not zero.
	clrl	d1
	bras	Ffltddone	| Branch if zero.
1:
	subqw	#1,d2		| Adjust exponent.
	lsll	#1,d0		| Normalize.
	bpls	1b		| Branch if already normalized.
2:
	bclr	#31,d0		| Clear I bit.
	movel	d0,d1		| d1 gets significand.
	lsrl	#8,d0		| Align high order bits.
	lsrl	#3,d0		| Align high order bits.
	swap	d2
	lsll	#4,d2		| Align exponent.
	orl	d2,d0		| Stick exponent.
	movel	#21,d2
	lsll	d2,d1		| Align low order bits.
	cmpl	#0,a0
	bges	Ffltddone	| Branch if x was non-negative.
	bset	#31,d0		| Set sign if negative.
Ffltddone:
	movel	a1,d2		| Restore d2.
	RET

/*
 * double-to-integer conversion: ffixi
 * input:
 *	d0/d1	double floating value
 * output:
 *	d0	integer
 */

RTENTRY(Fintd)
        moveml  d2-d3,sp@-
        movel   d0,d3           | d3 gets top(x).
        bclr    #31,d0          | d0 gets top(abs(x)).
        cmpl    #0x3ff00000,d0
        bges    1f            	| Branch if abs(x) >= 1.
        clrl    d0
        bras    Fintddone
1:
        cmpl    #0x41f00000,d0
        blts    2f       	| Branch if 1 <= |x| < 2**32.
        movel	#0x80000000,d0	| Maximum negative integer.
        bras    Fintddone
2:
        movel	d0,d2		| d2 gets abs(x).
	andl	#0xfffff,d0	| Clear sign and exponent.
	bset	#20,d0		| Set I bit.
	roll    #8,d2
        roll    #4,d2
        andw    #0xfff,d2       | d2 gets biased exponent.
        subw    #0x3ff+20,d2
        bges    3f           	| Branch if exp >= 20.
        negw	d2
        lsrl	d2,d0
	bras    Fintdsign
3:
        beqs    Fintdsign      	| Branch if exponent = 20 exactly.
	lsll	d2,d0		| Upper shift.
	negw	d2
	addw	#32,d2		| Compute right shift.
	lsrl	d2,d1		| This part goes from lower to upper.
	orl	d1,d0
Fintdsign:
	tstl	d3
	bpls	Fintddone	| Branch if x was not negative.
	negl	d0
Fintddone:
        moveml  sp@+,d2-d3
        RET

RTENTRY(Fnintd)
        moveml  d2-d4,sp@-
        movel   d0,d3           | d3 gets top(x).
        bclr    #31,d0          | d0 gets top(abs(x)).
        cmpl    #0x3fe00000,d0
        bges    1f            	| Branch if abs(x) >= 0.5.
        clrl    d0
        bras    Fnintddone
1:
        cmpl    #0x41f00000,d0
        blts    2f       	| Branch if 0.5 <= |x| < 2**32.
        movel	#0x80000000,d0	| Maximum negative integer.
        bras    Fnintddone
2:
        movel	d0,d2		| d2 gets abs(x).
	andl	#0xfffff,d0	| Clear sign and exponent.
	bset	#20,d0		| Set I bit.
	roll    #8,d2
        roll    #4,d2
        andw    #0xfff,d2       | d2 gets biased exponent.
        subw    #0x3ff+20,d2
        bges    3f           	| Branch if exp >= 20.
	negw	d2
        subqw	#1,d2
	lsrl	d2,d0		| Upper part.
	addql	#1,d0		| Round bit.
	lsrl	#1,d0		| Finish shift.
	bras    Fnintdsign
3:
        beqs    Fnintdround     | Branch if exponent = 20 exactly.
	movel	d1,d4		| d4 will get lower to upper part.
	lsll	d2,d0		| Upper shift.
	lsll	d2,d1		| Lower shift.
	negw	d2
	addw	#32,d2		| Compute right shift.
	lsrl	d2,d4		| This part goes from lower to upper.
	orl	d4,d0
Fnintdround:
	addl	#0x80000000,d1
	bccs	Fnintdsign	| Branch if no rounding carry propagate.
	addql	#1,d0
Fnintdsign:
	tstl	d3
	bpls	Fnintddone	| Branch if x was not negative.
	negl	d0
Fnintddone:
        moveml  sp@+,d2-d4
        RET

RTENTRY(Frintd)
        moveml  d2-d4,sp@-
        movel   d0,d3           | d3 gets top(x).
        bclr    #31,d0          | d0 gets top(abs(x)).
        cmpl    #0x3fe00000,d0
        bges    1f            	| Branch if abs(x) >= 0.5.
        clrl    d0
        bras    Fnintddone
1:
        cmpl    #0x41f00000,d0
        blts    2f       	| Branch if 0.5 <= |x| < 2**32.
        movel	#0x80000000,d0	| Maximum negative integer.
        bras    Fnintddone
2:
        movel	d0,d2		| d2 gets abs(x).
	andl	#0xfffff,d0	| Clear sign and exponent.
	bset	#20,d0		| Set I bit.
	roll    #8,d2
        roll    #4,d2
        andw    #0xfff,d2       | d2 gets biased exponent.
        subw    #0x3ff+20,d2
        bges    3f           	| Branch if exp >= 20.
	movel	d1,d4		| d4 saves lower part.
	movel	d0,d1
	negw	d2
	lsrl	d2,d0		| Upper part.
	negw	d2
	addw	#32,d2
	lsll	d2,d1		| Lower part.
	tstl	d4
	beqs	Frintdround	| Branch if original low part clear.
	bset	#30,d1		| Set sticky bit to influence rounding.
	bras    Frintdround
3:
        beqs    Frintdround     | Branch if exponent = 20 exactly.
	movel	d1,d4		| d4 will get lower to upper part.
	lsll	d2,d0		| Upper shift.
	lsll	d2,d1		| Lower shift.
	negw	d2
	addw	#32,d2		| Compute right shift.
	lsrl	d2,d4		| This part goes from lower to upper.
	orl	d4,d0
Frintdround:
	addl	#0x80000000,d1
	jcc	Fnintdsign	| Branch if no rounding carry propagate.
	addql	#1,d0
	tstl	d1
	jne	Fnintdsign	| Branch if not ambiguous.
	bclr	#0,d0		| Force round to even.
	jra	Fnintdsign