18c2ecf20Sopenharmony_ci|
28c2ecf20Sopenharmony_ci|	round.sa 3.4 7/29/91
38c2ecf20Sopenharmony_ci|
48c2ecf20Sopenharmony_ci|	handle rounding and normalization tasks
58c2ecf20Sopenharmony_ci|
68c2ecf20Sopenharmony_ci|
78c2ecf20Sopenharmony_ci|
88c2ecf20Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
98c2ecf20Sopenharmony_ci|			All Rights Reserved
108c2ecf20Sopenharmony_ci|
118c2ecf20Sopenharmony_ci|       For details on the license for this file, please see the
128c2ecf20Sopenharmony_ci|       file, README, in this same directory.
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci|ROUND	idnt    2,1 | Motorola 040 Floating Point Software Package
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	|section	8
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "fpsp.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci|
218c2ecf20Sopenharmony_ci|	round --- round result according to precision/mode
228c2ecf20Sopenharmony_ci|
238c2ecf20Sopenharmony_ci|	a0 points to the input operand in the internal extended format
248c2ecf20Sopenharmony_ci|	d1(high word) contains rounding precision:
258c2ecf20Sopenharmony_ci|		ext = $0000xxxx
268c2ecf20Sopenharmony_ci|		sgl = $0001xxxx
278c2ecf20Sopenharmony_ci|		dbl = $0002xxxx
288c2ecf20Sopenharmony_ci|	d1(low word) contains rounding mode:
298c2ecf20Sopenharmony_ci|		RN  = $xxxx0000
308c2ecf20Sopenharmony_ci|		RZ  = $xxxx0001
318c2ecf20Sopenharmony_ci|		RM  = $xxxx0010
328c2ecf20Sopenharmony_ci|		RP  = $xxxx0011
338c2ecf20Sopenharmony_ci|	d0{31:29} contains the g,r,s bits (extended)
348c2ecf20Sopenharmony_ci|
358c2ecf20Sopenharmony_ci|	On return the value pointed to by a0 is correctly rounded,
368c2ecf20Sopenharmony_ci|	a0 is preserved and the g-r-s bits in d0 are cleared.
378c2ecf20Sopenharmony_ci|	The result is not typed - the tag field is invalid.  The
388c2ecf20Sopenharmony_ci|	result is still in the internal extended format.
398c2ecf20Sopenharmony_ci|
408c2ecf20Sopenharmony_ci|	The INEX bit of USER_FPSR will be set if the rounded result was
418c2ecf20Sopenharmony_ci|	inexact (i.e. if any of the g-r-s bits were set).
428c2ecf20Sopenharmony_ci|
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	.global	round
458c2ecf20Sopenharmony_ciround:
468c2ecf20Sopenharmony_ci| If g=r=s=0 then result is exact and round is done, else set
478c2ecf20Sopenharmony_ci| the inex flag in status reg and continue.
488c2ecf20Sopenharmony_ci|
498c2ecf20Sopenharmony_ci	bsrs	ext_grs			|this subroutine looks at the
508c2ecf20Sopenharmony_ci|					:rounding precision and sets
518c2ecf20Sopenharmony_ci|					;the appropriate g-r-s bits.
528c2ecf20Sopenharmony_ci	tstl	%d0			|if grs are zero, go force
538c2ecf20Sopenharmony_ci	bne	rnd_cont		|lower bits to zero for size
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	swap	%d1			|set up d1.w for round prec.
568c2ecf20Sopenharmony_ci	bra	truncate
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cirnd_cont:
598c2ecf20Sopenharmony_ci|
608c2ecf20Sopenharmony_ci| Use rounding mode as an index into a jump table for these modes.
618c2ecf20Sopenharmony_ci|
628c2ecf20Sopenharmony_ci	orl	#inx2a_mask,USER_FPSR(%a6) |set inex2/ainex
638c2ecf20Sopenharmony_ci	lea	mode_tab,%a1
648c2ecf20Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1
658c2ecf20Sopenharmony_ci	jmp	(%a1)
668c2ecf20Sopenharmony_ci|
678c2ecf20Sopenharmony_ci| Jump table indexed by rounding mode in d1.w.  All following assumes
688c2ecf20Sopenharmony_ci| grs != 0.
698c2ecf20Sopenharmony_ci|
708c2ecf20Sopenharmony_cimode_tab:
718c2ecf20Sopenharmony_ci	.long	rnd_near
728c2ecf20Sopenharmony_ci	.long	rnd_zero
738c2ecf20Sopenharmony_ci	.long	rnd_mnus
748c2ecf20Sopenharmony_ci	.long	rnd_plus
758c2ecf20Sopenharmony_ci|
768c2ecf20Sopenharmony_ci|	ROUND PLUS INFINITY
778c2ecf20Sopenharmony_ci|
788c2ecf20Sopenharmony_ci|	If sign of fp number = 0 (positive), then add 1 to l.
798c2ecf20Sopenharmony_ci|
808c2ecf20Sopenharmony_cirnd_plus:
818c2ecf20Sopenharmony_ci	swap	%d1			|set up d1 for round prec.
828c2ecf20Sopenharmony_ci	tstb	LOCAL_SGN(%a0)		|check for sign
838c2ecf20Sopenharmony_ci	bmi	truncate		|if positive then truncate
848c2ecf20Sopenharmony_ci	movel	#0xffffffff,%d0		|force g,r,s to be all f's
858c2ecf20Sopenharmony_ci	lea	add_to_l,%a1
868c2ecf20Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1
878c2ecf20Sopenharmony_ci	jmp	(%a1)
888c2ecf20Sopenharmony_ci|
898c2ecf20Sopenharmony_ci|	ROUND MINUS INFINITY
908c2ecf20Sopenharmony_ci|
918c2ecf20Sopenharmony_ci|	If sign of fp number = 1 (negative), then add 1 to l.
928c2ecf20Sopenharmony_ci|
938c2ecf20Sopenharmony_cirnd_mnus:
948c2ecf20Sopenharmony_ci	swap	%d1			|set up d1 for round prec.
958c2ecf20Sopenharmony_ci	tstb	LOCAL_SGN(%a0)		|check for sign
968c2ecf20Sopenharmony_ci	bpl	truncate		|if negative then truncate
978c2ecf20Sopenharmony_ci	movel	#0xffffffff,%d0		|force g,r,s to be all f's
988c2ecf20Sopenharmony_ci	lea	add_to_l,%a1
998c2ecf20Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1
1008c2ecf20Sopenharmony_ci	jmp	(%a1)
1018c2ecf20Sopenharmony_ci|
1028c2ecf20Sopenharmony_ci|	ROUND ZERO
1038c2ecf20Sopenharmony_ci|
1048c2ecf20Sopenharmony_ci|	Always truncate.
1058c2ecf20Sopenharmony_cirnd_zero:
1068c2ecf20Sopenharmony_ci	swap	%d1			|set up d1 for round prec.
1078c2ecf20Sopenharmony_ci	bra	truncate
1088c2ecf20Sopenharmony_ci|
1098c2ecf20Sopenharmony_ci|
1108c2ecf20Sopenharmony_ci|	ROUND NEAREST
1118c2ecf20Sopenharmony_ci|
1128c2ecf20Sopenharmony_ci|	If (g=1), then add 1 to l and if (r=s=0), then clear l
1138c2ecf20Sopenharmony_ci|	Note that this will round to even in case of a tie.
1148c2ecf20Sopenharmony_ci|
1158c2ecf20Sopenharmony_cirnd_near:
1168c2ecf20Sopenharmony_ci	swap	%d1			|set up d1 for round prec.
1178c2ecf20Sopenharmony_ci	asll	#1,%d0			|shift g-bit to c-bit
1188c2ecf20Sopenharmony_ci	bcc	truncate		|if (g=1) then
1198c2ecf20Sopenharmony_ci	lea	add_to_l,%a1
1208c2ecf20Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1
1218c2ecf20Sopenharmony_ci	jmp	(%a1)
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci|
1248c2ecf20Sopenharmony_ci|	ext_grs --- extract guard, round and sticky bits
1258c2ecf20Sopenharmony_ci|
1268c2ecf20Sopenharmony_ci| Input:	d1 =		PREC:ROUND
1278c2ecf20Sopenharmony_ci| Output:	d0{31:29}=	guard, round, sticky
1288c2ecf20Sopenharmony_ci|
1298c2ecf20Sopenharmony_ci| The ext_grs extract the guard/round/sticky bits according to the
1308c2ecf20Sopenharmony_ci| selected rounding precision. It is called by the round subroutine
1318c2ecf20Sopenharmony_ci| only.  All registers except d0 are kept intact. d0 becomes an
1328c2ecf20Sopenharmony_ci| updated guard,round,sticky in d0{31:29}
1338c2ecf20Sopenharmony_ci|
1348c2ecf20Sopenharmony_ci| Notes: the ext_grs uses the round PREC, and therefore has to swap d1
1358c2ecf20Sopenharmony_ci|	 prior to usage, and needs to restore d1 to original.
1368c2ecf20Sopenharmony_ci|
1378c2ecf20Sopenharmony_ciext_grs:
1388c2ecf20Sopenharmony_ci	swap	%d1			|have d1.w point to round precision
1398c2ecf20Sopenharmony_ci	cmpiw	#0,%d1
1408c2ecf20Sopenharmony_ci	bnes	sgl_or_dbl
1418c2ecf20Sopenharmony_ci	bras	end_ext_grs
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cisgl_or_dbl:
1448c2ecf20Sopenharmony_ci	moveml	%d2/%d3,-(%a7)		|make some temp registers
1458c2ecf20Sopenharmony_ci	cmpiw	#1,%d1
1468c2ecf20Sopenharmony_ci	bnes	grs_dbl
1478c2ecf20Sopenharmony_cigrs_sgl:
1488c2ecf20Sopenharmony_ci	bfextu	LOCAL_HI(%a0){#24:#2},%d3	|sgl prec. g-r are 2 bits right
1498c2ecf20Sopenharmony_ci	movel	#30,%d2			|of the sgl prec. limits
1508c2ecf20Sopenharmony_ci	lsll	%d2,%d3			|shift g-r bits to MSB of d3
1518c2ecf20Sopenharmony_ci	movel	LOCAL_HI(%a0),%d2		|get word 2 for s-bit test
1528c2ecf20Sopenharmony_ci	andil	#0x0000003f,%d2		|s bit is the or of all other
1538c2ecf20Sopenharmony_ci	bnes	st_stky			|bits to the right of g-r
1548c2ecf20Sopenharmony_ci	tstl	LOCAL_LO(%a0)		|test lower mantissa
1558c2ecf20Sopenharmony_ci	bnes	st_stky			|if any are set, set sticky
1568c2ecf20Sopenharmony_ci	tstl	%d0			|test original g,r,s
1578c2ecf20Sopenharmony_ci	bnes	st_stky			|if any are set, set sticky
1588c2ecf20Sopenharmony_ci	bras	end_sd			|if words 3 and 4 are clr, exit
1598c2ecf20Sopenharmony_cigrs_dbl:
1608c2ecf20Sopenharmony_ci	bfextu	LOCAL_LO(%a0){#21:#2},%d3	|dbl-prec. g-r are 2 bits right
1618c2ecf20Sopenharmony_ci	movel	#30,%d2			|of the dbl prec. limits
1628c2ecf20Sopenharmony_ci	lsll	%d2,%d3			|shift g-r bits to the MSB of d3
1638c2ecf20Sopenharmony_ci	movel	LOCAL_LO(%a0),%d2		|get lower mantissa  for s-bit test
1648c2ecf20Sopenharmony_ci	andil	#0x000001ff,%d2		|s bit is the or-ing of all
1658c2ecf20Sopenharmony_ci	bnes	st_stky			|other bits to the right of g-r
1668c2ecf20Sopenharmony_ci	tstl	%d0			|test word original g,r,s
1678c2ecf20Sopenharmony_ci	bnes	st_stky			|if any are set, set sticky
1688c2ecf20Sopenharmony_ci	bras	end_sd			|if clear, exit
1698c2ecf20Sopenharmony_cist_stky:
1708c2ecf20Sopenharmony_ci	bset	#rnd_stky_bit,%d3
1718c2ecf20Sopenharmony_ciend_sd:
1728c2ecf20Sopenharmony_ci	movel	%d3,%d0			|return grs to d0
1738c2ecf20Sopenharmony_ci	moveml	(%a7)+,%d2/%d3		|restore scratch registers
1748c2ecf20Sopenharmony_ciend_ext_grs:
1758c2ecf20Sopenharmony_ci	swap	%d1			|restore d1 to original
1768c2ecf20Sopenharmony_ci	rts
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci|*******************  Local Equates
1798c2ecf20Sopenharmony_ci	.set	ad_1_sgl,0x00000100	|  constant to add 1 to l-bit in sgl prec
1808c2ecf20Sopenharmony_ci	.set	ad_1_dbl,0x00000800	|  constant to add 1 to l-bit in dbl prec
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci|Jump table for adding 1 to the l-bit indexed by rnd prec
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ciadd_to_l:
1868c2ecf20Sopenharmony_ci	.long	add_ext
1878c2ecf20Sopenharmony_ci	.long	add_sgl
1888c2ecf20Sopenharmony_ci	.long	add_dbl
1898c2ecf20Sopenharmony_ci	.long	add_dbl
1908c2ecf20Sopenharmony_ci|
1918c2ecf20Sopenharmony_ci|	ADD SINGLE
1928c2ecf20Sopenharmony_ci|
1938c2ecf20Sopenharmony_ciadd_sgl:
1948c2ecf20Sopenharmony_ci	addl	#ad_1_sgl,LOCAL_HI(%a0)
1958c2ecf20Sopenharmony_ci	bccs	scc_clr			|no mantissa overflow
1968c2ecf20Sopenharmony_ci	roxrw  LOCAL_HI(%a0)		|shift v-bit back in
1978c2ecf20Sopenharmony_ci	roxrw  LOCAL_HI+2(%a0)		|shift v-bit back in
1988c2ecf20Sopenharmony_ci	addw	#0x1,LOCAL_EX(%a0)	|and incr exponent
1998c2ecf20Sopenharmony_ciscc_clr:
2008c2ecf20Sopenharmony_ci	tstl	%d0			|test for rs = 0
2018c2ecf20Sopenharmony_ci	bnes	sgl_done
2028c2ecf20Sopenharmony_ci	andiw  #0xfe00,LOCAL_HI+2(%a0)	|clear the l-bit
2038c2ecf20Sopenharmony_cisgl_done:
2048c2ecf20Sopenharmony_ci	andil	#0xffffff00,LOCAL_HI(%a0) |truncate bits beyond sgl limit
2058c2ecf20Sopenharmony_ci	clrl	LOCAL_LO(%a0)		|clear d2
2068c2ecf20Sopenharmony_ci	rts
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci|
2098c2ecf20Sopenharmony_ci|	ADD EXTENDED
2108c2ecf20Sopenharmony_ci|
2118c2ecf20Sopenharmony_ciadd_ext:
2128c2ecf20Sopenharmony_ci	addql  #1,LOCAL_LO(%a0)		|add 1 to l-bit
2138c2ecf20Sopenharmony_ci	bccs	xcc_clr			|test for carry out
2148c2ecf20Sopenharmony_ci	addql  #1,LOCAL_HI(%a0)		|propagate carry
2158c2ecf20Sopenharmony_ci	bccs	xcc_clr
2168c2ecf20Sopenharmony_ci	roxrw  LOCAL_HI(%a0)		|mant is 0 so restore v-bit
2178c2ecf20Sopenharmony_ci	roxrw  LOCAL_HI+2(%a0)		|mant is 0 so restore v-bit
2188c2ecf20Sopenharmony_ci	roxrw	LOCAL_LO(%a0)
2198c2ecf20Sopenharmony_ci	roxrw	LOCAL_LO+2(%a0)
2208c2ecf20Sopenharmony_ci	addw	#0x1,LOCAL_EX(%a0)	|and inc exp
2218c2ecf20Sopenharmony_cixcc_clr:
2228c2ecf20Sopenharmony_ci	tstl	%d0			|test rs = 0
2238c2ecf20Sopenharmony_ci	bnes	add_ext_done
2248c2ecf20Sopenharmony_ci	andib	#0xfe,LOCAL_LO+3(%a0)	|clear the l bit
2258c2ecf20Sopenharmony_ciadd_ext_done:
2268c2ecf20Sopenharmony_ci	rts
2278c2ecf20Sopenharmony_ci|
2288c2ecf20Sopenharmony_ci|	ADD DOUBLE
2298c2ecf20Sopenharmony_ci|
2308c2ecf20Sopenharmony_ciadd_dbl:
2318c2ecf20Sopenharmony_ci	addl	#ad_1_dbl,LOCAL_LO(%a0)
2328c2ecf20Sopenharmony_ci	bccs	dcc_clr
2338c2ecf20Sopenharmony_ci	addql	#1,LOCAL_HI(%a0)		|propagate carry
2348c2ecf20Sopenharmony_ci	bccs	dcc_clr
2358c2ecf20Sopenharmony_ci	roxrw	LOCAL_HI(%a0)		|mant is 0 so restore v-bit
2368c2ecf20Sopenharmony_ci	roxrw	LOCAL_HI+2(%a0)		|mant is 0 so restore v-bit
2378c2ecf20Sopenharmony_ci	roxrw	LOCAL_LO(%a0)
2388c2ecf20Sopenharmony_ci	roxrw	LOCAL_LO+2(%a0)
2398c2ecf20Sopenharmony_ci	addw	#0x1,LOCAL_EX(%a0)	|incr exponent
2408c2ecf20Sopenharmony_cidcc_clr:
2418c2ecf20Sopenharmony_ci	tstl	%d0			|test for rs = 0
2428c2ecf20Sopenharmony_ci	bnes	dbl_done
2438c2ecf20Sopenharmony_ci	andiw	#0xf000,LOCAL_LO+2(%a0)	|clear the l-bit
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_cidbl_done:
2468c2ecf20Sopenharmony_ci	andil	#0xfffff800,LOCAL_LO(%a0) |truncate bits beyond dbl limit
2478c2ecf20Sopenharmony_ci	rts
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cierror:
2508c2ecf20Sopenharmony_ci	rts
2518c2ecf20Sopenharmony_ci|
2528c2ecf20Sopenharmony_ci| Truncate all other bits
2538c2ecf20Sopenharmony_ci|
2548c2ecf20Sopenharmony_citrunct:
2558c2ecf20Sopenharmony_ci	.long	end_rnd
2568c2ecf20Sopenharmony_ci	.long	sgl_done
2578c2ecf20Sopenharmony_ci	.long	dbl_done
2588c2ecf20Sopenharmony_ci	.long	dbl_done
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_citruncate:
2618c2ecf20Sopenharmony_ci	lea	trunct,%a1
2628c2ecf20Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1
2638c2ecf20Sopenharmony_ci	jmp	(%a1)
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ciend_rnd:
2668c2ecf20Sopenharmony_ci	rts
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci|
2698c2ecf20Sopenharmony_ci|	NORMALIZE
2708c2ecf20Sopenharmony_ci|
2718c2ecf20Sopenharmony_ci| These routines (nrm_zero & nrm_set) normalize the unnorm.  This
2728c2ecf20Sopenharmony_ci| is done by shifting the mantissa left while decrementing the
2738c2ecf20Sopenharmony_ci| exponent.
2748c2ecf20Sopenharmony_ci|
2758c2ecf20Sopenharmony_ci| NRM_SET shifts and decrements until there is a 1 set in the integer
2768c2ecf20Sopenharmony_ci| bit of the mantissa (msb in d1).
2778c2ecf20Sopenharmony_ci|
2788c2ecf20Sopenharmony_ci| NRM_ZERO shifts and decrements until there is a 1 set in the integer
2798c2ecf20Sopenharmony_ci| bit of the mantissa (msb in d1) unless this would mean the exponent
2808c2ecf20Sopenharmony_ci| would go less than 0.  In that case the number becomes a denorm - the
2818c2ecf20Sopenharmony_ci| exponent (d0) is set to 0 and the mantissa (d1 & d2) is not
2828c2ecf20Sopenharmony_ci| normalized.
2838c2ecf20Sopenharmony_ci|
2848c2ecf20Sopenharmony_ci| Note that both routines have been optimized (for the worst case) and
2858c2ecf20Sopenharmony_ci| therefore do not have the easy to follow decrement/shift loop.
2868c2ecf20Sopenharmony_ci|
2878c2ecf20Sopenharmony_ci|	NRM_ZERO
2888c2ecf20Sopenharmony_ci|
2898c2ecf20Sopenharmony_ci|	Distance to first 1 bit in mantissa = X
2908c2ecf20Sopenharmony_ci|	Distance to 0 from exponent = Y
2918c2ecf20Sopenharmony_ci|	If X < Y
2928c2ecf20Sopenharmony_ci|	Then
2938c2ecf20Sopenharmony_ci|	  nrm_set
2948c2ecf20Sopenharmony_ci|	Else
2958c2ecf20Sopenharmony_ci|	  shift mantissa by Y
2968c2ecf20Sopenharmony_ci|	  set exponent = 0
2978c2ecf20Sopenharmony_ci|
2988c2ecf20Sopenharmony_ci|input:
2998c2ecf20Sopenharmony_ci|	FP_SCR1 = exponent, ms mantissa part, ls mantissa part
3008c2ecf20Sopenharmony_ci|output:
3018c2ecf20Sopenharmony_ci|	L_SCR1{4} = fpte15 or ete15 bit
3028c2ecf20Sopenharmony_ci|
3038c2ecf20Sopenharmony_ci	.global	nrm_zero
3048c2ecf20Sopenharmony_cinrm_zero:
3058c2ecf20Sopenharmony_ci	movew	LOCAL_EX(%a0),%d0
3068c2ecf20Sopenharmony_ci	cmpw   #64,%d0          |see if exp > 64
3078c2ecf20Sopenharmony_ci	bmis	d0_less
3088c2ecf20Sopenharmony_ci	bsr	nrm_set		|exp > 64 so exp won't exceed 0
3098c2ecf20Sopenharmony_ci	rts
3108c2ecf20Sopenharmony_cid0_less:
3118c2ecf20Sopenharmony_ci	moveml	%d2/%d3/%d5/%d6,-(%a7)
3128c2ecf20Sopenharmony_ci	movel	LOCAL_HI(%a0),%d1
3138c2ecf20Sopenharmony_ci	movel	LOCAL_LO(%a0),%d2
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	bfffo	%d1{#0:#32},%d3	|get the distance to the first 1
3168c2ecf20Sopenharmony_ci|				;in ms mant
3178c2ecf20Sopenharmony_ci	beqs	ms_clr		|branch if no bits were set
3188c2ecf20Sopenharmony_ci	cmpw	%d3,%d0		|of X>Y
3198c2ecf20Sopenharmony_ci	bmis	greater		|then exp will go past 0 (neg) if
3208c2ecf20Sopenharmony_ci|				;it is just shifted
3218c2ecf20Sopenharmony_ci	bsr	nrm_set		|else exp won't go past 0
3228c2ecf20Sopenharmony_ci	moveml	(%a7)+,%d2/%d3/%d5/%d6
3238c2ecf20Sopenharmony_ci	rts
3248c2ecf20Sopenharmony_cigreater:
3258c2ecf20Sopenharmony_ci	movel	%d2,%d6		|save ls mant in d6
3268c2ecf20Sopenharmony_ci	lsll	%d0,%d2		|shift ls mant by count
3278c2ecf20Sopenharmony_ci	lsll	%d0,%d1		|shift ms mant by count
3288c2ecf20Sopenharmony_ci	movel	#32,%d5
3298c2ecf20Sopenharmony_ci	subl	%d0,%d5		|make op a denorm by shifting bits
3308c2ecf20Sopenharmony_ci	lsrl	%d5,%d6		|by the number in the exp, then
3318c2ecf20Sopenharmony_ci|				;set exp = 0.
3328c2ecf20Sopenharmony_ci	orl	%d6,%d1		|shift the ls mant bits into the ms mant
3338c2ecf20Sopenharmony_ci	movel	#0,%d0		|same as if decremented exp to 0
3348c2ecf20Sopenharmony_ci|				;while shifting
3358c2ecf20Sopenharmony_ci	movew	%d0,LOCAL_EX(%a0)
3368c2ecf20Sopenharmony_ci	movel	%d1,LOCAL_HI(%a0)
3378c2ecf20Sopenharmony_ci	movel	%d2,LOCAL_LO(%a0)
3388c2ecf20Sopenharmony_ci	moveml	(%a7)+,%d2/%d3/%d5/%d6
3398c2ecf20Sopenharmony_ci	rts
3408c2ecf20Sopenharmony_cims_clr:
3418c2ecf20Sopenharmony_ci	bfffo	%d2{#0:#32},%d3	|check if any bits set in ls mant
3428c2ecf20Sopenharmony_ci	beqs	all_clr		|branch if none set
3438c2ecf20Sopenharmony_ci	addw	#32,%d3
3448c2ecf20Sopenharmony_ci	cmpw	%d3,%d0		|if X>Y
3458c2ecf20Sopenharmony_ci	bmis	greater		|then branch
3468c2ecf20Sopenharmony_ci	bsr	nrm_set		|else exp won't go past 0
3478c2ecf20Sopenharmony_ci	moveml	(%a7)+,%d2/%d3/%d5/%d6
3488c2ecf20Sopenharmony_ci	rts
3498c2ecf20Sopenharmony_ciall_clr:
3508c2ecf20Sopenharmony_ci	movew	#0,LOCAL_EX(%a0)	|no mantissa bits set. Set exp = 0.
3518c2ecf20Sopenharmony_ci	moveml	(%a7)+,%d2/%d3/%d5/%d6
3528c2ecf20Sopenharmony_ci	rts
3538c2ecf20Sopenharmony_ci|
3548c2ecf20Sopenharmony_ci|	NRM_SET
3558c2ecf20Sopenharmony_ci|
3568c2ecf20Sopenharmony_ci	.global	nrm_set
3578c2ecf20Sopenharmony_cinrm_set:
3588c2ecf20Sopenharmony_ci	movel	%d7,-(%a7)
3598c2ecf20Sopenharmony_ci	bfffo	LOCAL_HI(%a0){#0:#32},%d7 |find first 1 in ms mant to d7)
3608c2ecf20Sopenharmony_ci	beqs	lower		|branch if ms mant is all 0's
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	movel	%d6,-(%a7)
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	subw	%d7,LOCAL_EX(%a0)	|sub exponent by count
3658c2ecf20Sopenharmony_ci	movel	LOCAL_HI(%a0),%d0	|d0 has ms mant
3668c2ecf20Sopenharmony_ci	movel	LOCAL_LO(%a0),%d1 |d1 has ls mant
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	lsll	%d7,%d0		|shift first 1 to j bit position
3698c2ecf20Sopenharmony_ci	movel	%d1,%d6		|copy ls mant into d6
3708c2ecf20Sopenharmony_ci	lsll	%d7,%d6		|shift ls mant by count
3718c2ecf20Sopenharmony_ci	movel	%d6,LOCAL_LO(%a0)	|store ls mant into memory
3728c2ecf20Sopenharmony_ci	moveql	#32,%d6
3738c2ecf20Sopenharmony_ci	subl	%d7,%d6		|continue shift
3748c2ecf20Sopenharmony_ci	lsrl	%d6,%d1		|shift off all bits but those that will
3758c2ecf20Sopenharmony_ci|				;be shifted into ms mant
3768c2ecf20Sopenharmony_ci	orl	%d1,%d0		|shift the ls mant bits into the ms mant
3778c2ecf20Sopenharmony_ci	movel	%d0,LOCAL_HI(%a0)	|store ms mant into memory
3788c2ecf20Sopenharmony_ci	moveml	(%a7)+,%d7/%d6	|restore registers
3798c2ecf20Sopenharmony_ci	rts
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci|
3828c2ecf20Sopenharmony_ci| We get here if ms mant was = 0, and we assume ls mant has bits
3838c2ecf20Sopenharmony_ci| set (otherwise this would have been tagged a zero not a denorm).
3848c2ecf20Sopenharmony_ci|
3858c2ecf20Sopenharmony_cilower:
3868c2ecf20Sopenharmony_ci	movew	LOCAL_EX(%a0),%d0	|d0 has exponent
3878c2ecf20Sopenharmony_ci	movel	LOCAL_LO(%a0),%d1	|d1 has ls mant
3888c2ecf20Sopenharmony_ci	subw	#32,%d0		|account for ms mant being all zeros
3898c2ecf20Sopenharmony_ci	bfffo	%d1{#0:#32},%d7	|find first 1 in ls mant to d7)
3908c2ecf20Sopenharmony_ci	subw	%d7,%d0		|subtract shift count from exp
3918c2ecf20Sopenharmony_ci	lsll	%d7,%d1		|shift first 1 to integer bit in ms mant
3928c2ecf20Sopenharmony_ci	movew	%d0,LOCAL_EX(%a0)	|store ms mant
3938c2ecf20Sopenharmony_ci	movel	%d1,LOCAL_HI(%a0)	|store exp
3948c2ecf20Sopenharmony_ci	clrl	LOCAL_LO(%a0)	|clear ls mant
3958c2ecf20Sopenharmony_ci	movel	(%a7)+,%d7
3968c2ecf20Sopenharmony_ci	rts
3978c2ecf20Sopenharmony_ci|
3988c2ecf20Sopenharmony_ci|	denorm --- denormalize an intermediate result
3998c2ecf20Sopenharmony_ci|
4008c2ecf20Sopenharmony_ci|	Used by underflow.
4018c2ecf20Sopenharmony_ci|
4028c2ecf20Sopenharmony_ci| Input:
4038c2ecf20Sopenharmony_ci|	a0	 points to the operand to be denormalized
4048c2ecf20Sopenharmony_ci|		 (in the internal extended format)
4058c2ecf20Sopenharmony_ci|
4068c2ecf20Sopenharmony_ci|	d0:	 rounding precision
4078c2ecf20Sopenharmony_ci| Output:
4088c2ecf20Sopenharmony_ci|	a0	 points to the denormalized result
4098c2ecf20Sopenharmony_ci|		 (in the internal extended format)
4108c2ecf20Sopenharmony_ci|
4118c2ecf20Sopenharmony_ci|	d0	is guard,round,sticky
4128c2ecf20Sopenharmony_ci|
4138c2ecf20Sopenharmony_ci| d0 comes into this routine with the rounding precision. It
4148c2ecf20Sopenharmony_ci| is then loaded with the denormalized exponent threshold for the
4158c2ecf20Sopenharmony_ci| rounding precision.
4168c2ecf20Sopenharmony_ci|
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	.global	denorm
4198c2ecf20Sopenharmony_cidenorm:
4208c2ecf20Sopenharmony_ci	btstb	#6,LOCAL_EX(%a0)	|check for exponents between $7fff-$4000
4218c2ecf20Sopenharmony_ci	beqs	no_sgn_ext
4228c2ecf20Sopenharmony_ci	bsetb	#7,LOCAL_EX(%a0)	|sign extend if it is so
4238c2ecf20Sopenharmony_cino_sgn_ext:
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	cmpib	#0,%d0		|if 0 then extended precision
4268c2ecf20Sopenharmony_ci	bnes	not_ext		|else branch
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	clrl	%d1		|load d1 with ext threshold
4298c2ecf20Sopenharmony_ci	clrl	%d0		|clear the sticky flag
4308c2ecf20Sopenharmony_ci	bsr	dnrm_lp		|denormalize the number
4318c2ecf20Sopenharmony_ci	tstb	%d1		|check for inex
4328c2ecf20Sopenharmony_ci	beq	no_inex		|if clr, no inex
4338c2ecf20Sopenharmony_ci	bras	dnrm_inex	|if set, set inex
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_cinot_ext:
4368c2ecf20Sopenharmony_ci	cmpil	#1,%d0		|if 1 then single precision
4378c2ecf20Sopenharmony_ci	beqs	load_sgl	|else must be 2, double prec
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ciload_dbl:
4408c2ecf20Sopenharmony_ci	movew	#dbl_thresh,%d1	|put copy of threshold in d1
4418c2ecf20Sopenharmony_ci	movel	%d1,%d0		|copy d1 into d0
4428c2ecf20Sopenharmony_ci	subw	LOCAL_EX(%a0),%d0	|diff = threshold - exp
4438c2ecf20Sopenharmony_ci	cmpw	#67,%d0		|if diff > 67 (mant + grs bits)
4448c2ecf20Sopenharmony_ci	bpls	chk_stky	|then branch (all bits would be
4458c2ecf20Sopenharmony_ci|				; shifted off in denorm routine)
4468c2ecf20Sopenharmony_ci	clrl	%d0		|else clear the sticky flag
4478c2ecf20Sopenharmony_ci	bsr	dnrm_lp		|denormalize the number
4488c2ecf20Sopenharmony_ci	tstb	%d1		|check flag
4498c2ecf20Sopenharmony_ci	beqs	no_inex		|if clr, no inex
4508c2ecf20Sopenharmony_ci	bras	dnrm_inex	|if set, set inex
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ciload_sgl:
4538c2ecf20Sopenharmony_ci	movew	#sgl_thresh,%d1	|put copy of threshold in d1
4548c2ecf20Sopenharmony_ci	movel	%d1,%d0		|copy d1 into d0
4558c2ecf20Sopenharmony_ci	subw	LOCAL_EX(%a0),%d0	|diff = threshold - exp
4568c2ecf20Sopenharmony_ci	cmpw	#67,%d0		|if diff > 67 (mant + grs bits)
4578c2ecf20Sopenharmony_ci	bpls	chk_stky	|then branch (all bits would be
4588c2ecf20Sopenharmony_ci|				; shifted off in denorm routine)
4598c2ecf20Sopenharmony_ci	clrl	%d0		|else clear the sticky flag
4608c2ecf20Sopenharmony_ci	bsr	dnrm_lp		|denormalize the number
4618c2ecf20Sopenharmony_ci	tstb	%d1		|check flag
4628c2ecf20Sopenharmony_ci	beqs	no_inex		|if clr, no inex
4638c2ecf20Sopenharmony_ci	bras	dnrm_inex	|if set, set inex
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_cichk_stky:
4668c2ecf20Sopenharmony_ci	tstl	LOCAL_HI(%a0)	|check for any bits set
4678c2ecf20Sopenharmony_ci	bnes	set_stky
4688c2ecf20Sopenharmony_ci	tstl	LOCAL_LO(%a0)	|check for any bits set
4698c2ecf20Sopenharmony_ci	bnes	set_stky
4708c2ecf20Sopenharmony_ci	bras	clr_mant
4718c2ecf20Sopenharmony_ciset_stky:
4728c2ecf20Sopenharmony_ci	orl	#inx2a_mask,USER_FPSR(%a6) |set inex2/ainex
4738c2ecf20Sopenharmony_ci	movel	#0x20000000,%d0	|set sticky bit in return value
4748c2ecf20Sopenharmony_ciclr_mant:
4758c2ecf20Sopenharmony_ci	movew	%d1,LOCAL_EX(%a0)		|load exp with threshold
4768c2ecf20Sopenharmony_ci	movel	#0,LOCAL_HI(%a0)	|set d1 = 0 (ms mantissa)
4778c2ecf20Sopenharmony_ci	movel	#0,LOCAL_LO(%a0)		|set d2 = 0 (ms mantissa)
4788c2ecf20Sopenharmony_ci	rts
4798c2ecf20Sopenharmony_cidnrm_inex:
4808c2ecf20Sopenharmony_ci	orl	#inx2a_mask,USER_FPSR(%a6) |set inex2/ainex
4818c2ecf20Sopenharmony_cino_inex:
4828c2ecf20Sopenharmony_ci	rts
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci|
4858c2ecf20Sopenharmony_ci|	dnrm_lp --- normalize exponent/mantissa to specified threshold
4868c2ecf20Sopenharmony_ci|
4878c2ecf20Sopenharmony_ci| Input:
4888c2ecf20Sopenharmony_ci|	a0		points to the operand to be denormalized
4898c2ecf20Sopenharmony_ci|	d0{31:29}	initial guard,round,sticky
4908c2ecf20Sopenharmony_ci|	d1{15:0}	denormalization threshold
4918c2ecf20Sopenharmony_ci| Output:
4928c2ecf20Sopenharmony_ci|	a0		points to the denormalized operand
4938c2ecf20Sopenharmony_ci|	d0{31:29}	final guard,round,sticky
4948c2ecf20Sopenharmony_ci|	d1.b		inexact flag:  all ones means inexact result
4958c2ecf20Sopenharmony_ci|
4968c2ecf20Sopenharmony_ci| The LOCAL_LO and LOCAL_GRS parts of the value are copied to FP_SCR2
4978c2ecf20Sopenharmony_ci| so that bfext can be used to extract the new low part of the mantissa.
4988c2ecf20Sopenharmony_ci| Dnrm_lp can be called with a0 pointing to ETEMP or WBTEMP and there
4998c2ecf20Sopenharmony_ci| is no LOCAL_GRS scratch word following it on the fsave frame.
5008c2ecf20Sopenharmony_ci|
5018c2ecf20Sopenharmony_ci	.global	dnrm_lp
5028c2ecf20Sopenharmony_cidnrm_lp:
5038c2ecf20Sopenharmony_ci	movel	%d2,-(%sp)		|save d2 for temp use
5048c2ecf20Sopenharmony_ci	btstb	#E3,E_BYTE(%a6)		|test for type E3 exception
5058c2ecf20Sopenharmony_ci	beqs	not_E3			|not type E3 exception
5068c2ecf20Sopenharmony_ci	bfextu	WBTEMP_GRS(%a6){#6:#3},%d2	|extract guard,round, sticky  bit
5078c2ecf20Sopenharmony_ci	movel	#29,%d0
5088c2ecf20Sopenharmony_ci	lsll	%d0,%d2			|shift g,r,s to their positions
5098c2ecf20Sopenharmony_ci	movel	%d2,%d0
5108c2ecf20Sopenharmony_cinot_E3:
5118c2ecf20Sopenharmony_ci	movel	(%sp)+,%d2		|restore d2
5128c2ecf20Sopenharmony_ci	movel	LOCAL_LO(%a0),FP_SCR2+LOCAL_LO(%a6)
5138c2ecf20Sopenharmony_ci	movel	%d0,FP_SCR2+LOCAL_GRS(%a6)
5148c2ecf20Sopenharmony_ci	movel	%d1,%d0			|copy the denorm threshold
5158c2ecf20Sopenharmony_ci	subw	LOCAL_EX(%a0),%d1		|d1 = threshold - uns exponent
5168c2ecf20Sopenharmony_ci	bles	no_lp			|d1 <= 0
5178c2ecf20Sopenharmony_ci	cmpw	#32,%d1
5188c2ecf20Sopenharmony_ci	blts	case_1			|0 = d1 < 32
5198c2ecf20Sopenharmony_ci	cmpw	#64,%d1
5208c2ecf20Sopenharmony_ci	blts	case_2			|32 <= d1 < 64
5218c2ecf20Sopenharmony_ci	bra	case_3			|d1 >= 64
5228c2ecf20Sopenharmony_ci|
5238c2ecf20Sopenharmony_ci| No normalization necessary
5248c2ecf20Sopenharmony_ci|
5258c2ecf20Sopenharmony_cino_lp:
5268c2ecf20Sopenharmony_ci	clrb	%d1			|set no inex2 reported
5278c2ecf20Sopenharmony_ci	movel	FP_SCR2+LOCAL_GRS(%a6),%d0	|restore original g,r,s
5288c2ecf20Sopenharmony_ci	rts
5298c2ecf20Sopenharmony_ci|
5308c2ecf20Sopenharmony_ci| case (0<d1<32)
5318c2ecf20Sopenharmony_ci|
5328c2ecf20Sopenharmony_cicase_1:
5338c2ecf20Sopenharmony_ci	movel	%d2,-(%sp)
5348c2ecf20Sopenharmony_ci	movew	%d0,LOCAL_EX(%a0)		|exponent = denorm threshold
5358c2ecf20Sopenharmony_ci	movel	#32,%d0
5368c2ecf20Sopenharmony_ci	subw	%d1,%d0			|d0 = 32 - d1
5378c2ecf20Sopenharmony_ci	bfextu	LOCAL_EX(%a0){%d0:#32},%d2
5388c2ecf20Sopenharmony_ci	bfextu	%d2{%d1:%d0},%d2		|d2 = new LOCAL_HI
5398c2ecf20Sopenharmony_ci	bfextu	LOCAL_HI(%a0){%d0:#32},%d1	|d1 = new LOCAL_LO
5408c2ecf20Sopenharmony_ci	bfextu	FP_SCR2+LOCAL_LO(%a6){%d0:#32},%d0	|d0 = new G,R,S
5418c2ecf20Sopenharmony_ci	movel	%d2,LOCAL_HI(%a0)		|store new LOCAL_HI
5428c2ecf20Sopenharmony_ci	movel	%d1,LOCAL_LO(%a0)		|store new LOCAL_LO
5438c2ecf20Sopenharmony_ci	clrb	%d1
5448c2ecf20Sopenharmony_ci	bftst	%d0{#2:#30}
5458c2ecf20Sopenharmony_ci	beqs	c1nstky
5468c2ecf20Sopenharmony_ci	bsetl	#rnd_stky_bit,%d0
5478c2ecf20Sopenharmony_ci	st	%d1
5488c2ecf20Sopenharmony_cic1nstky:
5498c2ecf20Sopenharmony_ci	movel	FP_SCR2+LOCAL_GRS(%a6),%d2	|restore original g,r,s
5508c2ecf20Sopenharmony_ci	andil	#0xe0000000,%d2		|clear all but G,R,S
5518c2ecf20Sopenharmony_ci	tstl	%d2			|test if original G,R,S are clear
5528c2ecf20Sopenharmony_ci	beqs	grs_clear
5538c2ecf20Sopenharmony_ci	orl	#0x20000000,%d0		|set sticky bit in d0
5548c2ecf20Sopenharmony_cigrs_clear:
5558c2ecf20Sopenharmony_ci	andil	#0xe0000000,%d0		|clear all but G,R,S
5568c2ecf20Sopenharmony_ci	movel	(%sp)+,%d2
5578c2ecf20Sopenharmony_ci	rts
5588c2ecf20Sopenharmony_ci|
5598c2ecf20Sopenharmony_ci| case (32<=d1<64)
5608c2ecf20Sopenharmony_ci|
5618c2ecf20Sopenharmony_cicase_2:
5628c2ecf20Sopenharmony_ci	movel	%d2,-(%sp)
5638c2ecf20Sopenharmony_ci	movew	%d0,LOCAL_EX(%a0)		|unsigned exponent = threshold
5648c2ecf20Sopenharmony_ci	subw	#32,%d1			|d1 now between 0 and 32
5658c2ecf20Sopenharmony_ci	movel	#32,%d0
5668c2ecf20Sopenharmony_ci	subw	%d1,%d0			|d0 = 32 - d1
5678c2ecf20Sopenharmony_ci	bfextu	LOCAL_EX(%a0){%d0:#32},%d2
5688c2ecf20Sopenharmony_ci	bfextu	%d2{%d1:%d0},%d2		|d2 = new LOCAL_LO
5698c2ecf20Sopenharmony_ci	bfextu	LOCAL_HI(%a0){%d0:#32},%d1	|d1 = new G,R,S
5708c2ecf20Sopenharmony_ci	bftst	%d1{#2:#30}
5718c2ecf20Sopenharmony_ci	bnes	c2_sstky		|bra if sticky bit to be set
5728c2ecf20Sopenharmony_ci	bftst	FP_SCR2+LOCAL_LO(%a6){%d0:#32}
5738c2ecf20Sopenharmony_ci	bnes	c2_sstky		|bra if sticky bit to be set
5748c2ecf20Sopenharmony_ci	movel	%d1,%d0
5758c2ecf20Sopenharmony_ci	clrb	%d1
5768c2ecf20Sopenharmony_ci	bras	end_c2
5778c2ecf20Sopenharmony_cic2_sstky:
5788c2ecf20Sopenharmony_ci	movel	%d1,%d0
5798c2ecf20Sopenharmony_ci	bsetl	#rnd_stky_bit,%d0
5808c2ecf20Sopenharmony_ci	st	%d1
5818c2ecf20Sopenharmony_ciend_c2:
5828c2ecf20Sopenharmony_ci	clrl	LOCAL_HI(%a0)		|store LOCAL_HI = 0
5838c2ecf20Sopenharmony_ci	movel	%d2,LOCAL_LO(%a0)		|store LOCAL_LO
5848c2ecf20Sopenharmony_ci	movel	FP_SCR2+LOCAL_GRS(%a6),%d2	|restore original g,r,s
5858c2ecf20Sopenharmony_ci	andil	#0xe0000000,%d2		|clear all but G,R,S
5868c2ecf20Sopenharmony_ci	tstl	%d2			|test if original G,R,S are clear
5878c2ecf20Sopenharmony_ci	beqs	clear_grs
5888c2ecf20Sopenharmony_ci	orl	#0x20000000,%d0		|set sticky bit in d0
5898c2ecf20Sopenharmony_ciclear_grs:
5908c2ecf20Sopenharmony_ci	andil	#0xe0000000,%d0		|get rid of all but G,R,S
5918c2ecf20Sopenharmony_ci	movel	(%sp)+,%d2
5928c2ecf20Sopenharmony_ci	rts
5938c2ecf20Sopenharmony_ci|
5948c2ecf20Sopenharmony_ci| d1 >= 64 Force the exponent to be the denorm threshold with the
5958c2ecf20Sopenharmony_ci| correct sign.
5968c2ecf20Sopenharmony_ci|
5978c2ecf20Sopenharmony_cicase_3:
5988c2ecf20Sopenharmony_ci	movew	%d0,LOCAL_EX(%a0)
5998c2ecf20Sopenharmony_ci	tstw	LOCAL_SGN(%a0)
6008c2ecf20Sopenharmony_ci	bges	c3con
6018c2ecf20Sopenharmony_cic3neg:
6028c2ecf20Sopenharmony_ci	orl	#0x80000000,LOCAL_EX(%a0)
6038c2ecf20Sopenharmony_cic3con:
6048c2ecf20Sopenharmony_ci	cmpw	#64,%d1
6058c2ecf20Sopenharmony_ci	beqs	sixty_four
6068c2ecf20Sopenharmony_ci	cmpw	#65,%d1
6078c2ecf20Sopenharmony_ci	beqs	sixty_five
6088c2ecf20Sopenharmony_ci|
6098c2ecf20Sopenharmony_ci| Shift value is out of range.  Set d1 for inex2 flag and
6108c2ecf20Sopenharmony_ci| return a zero with the given threshold.
6118c2ecf20Sopenharmony_ci|
6128c2ecf20Sopenharmony_ci	clrl	LOCAL_HI(%a0)
6138c2ecf20Sopenharmony_ci	clrl	LOCAL_LO(%a0)
6148c2ecf20Sopenharmony_ci	movel	#0x20000000,%d0
6158c2ecf20Sopenharmony_ci	st	%d1
6168c2ecf20Sopenharmony_ci	rts
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_cisixty_four:
6198c2ecf20Sopenharmony_ci	movel	LOCAL_HI(%a0),%d0
6208c2ecf20Sopenharmony_ci	bfextu	%d0{#2:#30},%d1
6218c2ecf20Sopenharmony_ci	andil	#0xc0000000,%d0
6228c2ecf20Sopenharmony_ci	bras	c3com
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_cisixty_five:
6258c2ecf20Sopenharmony_ci	movel	LOCAL_HI(%a0),%d0
6268c2ecf20Sopenharmony_ci	bfextu	%d0{#1:#31},%d1
6278c2ecf20Sopenharmony_ci	andil	#0x80000000,%d0
6288c2ecf20Sopenharmony_ci	lsrl	#1,%d0			|shift high bit into R bit
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_cic3com:
6318c2ecf20Sopenharmony_ci	tstl	%d1
6328c2ecf20Sopenharmony_ci	bnes	c3ssticky
6338c2ecf20Sopenharmony_ci	tstl	LOCAL_LO(%a0)
6348c2ecf20Sopenharmony_ci	bnes	c3ssticky
6358c2ecf20Sopenharmony_ci	tstb	FP_SCR2+LOCAL_GRS(%a6)
6368c2ecf20Sopenharmony_ci	bnes	c3ssticky
6378c2ecf20Sopenharmony_ci	clrb	%d1
6388c2ecf20Sopenharmony_ci	bras	c3end
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_cic3ssticky:
6418c2ecf20Sopenharmony_ci	bsetl	#rnd_stky_bit,%d0
6428c2ecf20Sopenharmony_ci	st	%d1
6438c2ecf20Sopenharmony_cic3end:
6448c2ecf20Sopenharmony_ci	clrl	LOCAL_HI(%a0)
6458c2ecf20Sopenharmony_ci	clrl	LOCAL_LO(%a0)
6468c2ecf20Sopenharmony_ci	rts
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	|end
649