18c2ecf20Sopenharmony_ci|
28c2ecf20Sopenharmony_ci|	kernel_ex.sa 3.3 12/19/90
38c2ecf20Sopenharmony_ci|
48c2ecf20Sopenharmony_ci| This file contains routines to force exception status in the
58c2ecf20Sopenharmony_ci| fpu for exceptional cases detected or reported within the
68c2ecf20Sopenharmony_ci| transcendental functions.  Typically, the t_xx routine will
78c2ecf20Sopenharmony_ci| set the appropriate bits in the USER_FPSR word on the stack.
88c2ecf20Sopenharmony_ci| The bits are tested in gen_except.sa to determine if an exceptional
98c2ecf20Sopenharmony_ci| situation needs to be created on return from the FPSP.
108c2ecf20Sopenharmony_ci|
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
138c2ecf20Sopenharmony_ci|			All Rights Reserved
148c2ecf20Sopenharmony_ci|
158c2ecf20Sopenharmony_ci|       For details on the license for this file, please see the
168c2ecf20Sopenharmony_ci|       file, README, in this same directory.
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ciKERNEL_EX:    |idnt    2,1 | Motorola 040 Floating Point Software Package
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	|section    8
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include "fpsp.h"
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_cimns_inf:  .long 0xffff0000,0x00000000,0x00000000
258c2ecf20Sopenharmony_cipls_inf:  .long 0x7fff0000,0x00000000,0x00000000
268c2ecf20Sopenharmony_cinan:      .long 0x7fff0000,0xffffffff,0xffffffff
278c2ecf20Sopenharmony_cihuge:     .long 0x7ffe0000,0xffffffff,0xffffffff
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	|xref	  ovf_r_k
308c2ecf20Sopenharmony_ci	|xref	  unf_sub
318c2ecf20Sopenharmony_ci	|xref	  nrm_set
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	.global	  t_dz
348c2ecf20Sopenharmony_ci	.global      t_dz2
358c2ecf20Sopenharmony_ci	.global      t_operr
368c2ecf20Sopenharmony_ci	.global      t_unfl
378c2ecf20Sopenharmony_ci	.global      t_ovfl
388c2ecf20Sopenharmony_ci	.global      t_ovfl2
398c2ecf20Sopenharmony_ci	.global      t_inx2
408c2ecf20Sopenharmony_ci	.global	  t_frcinx
418c2ecf20Sopenharmony_ci	.global	  t_extdnrm
428c2ecf20Sopenharmony_ci	.global	  t_resdnrm
438c2ecf20Sopenharmony_ci	.global	  dst_nan
448c2ecf20Sopenharmony_ci	.global	  src_nan
458c2ecf20Sopenharmony_ci|
468c2ecf20Sopenharmony_ci|	DZ exception
478c2ecf20Sopenharmony_ci|
488c2ecf20Sopenharmony_ci|
498c2ecf20Sopenharmony_ci|	if dz trap disabled
508c2ecf20Sopenharmony_ci|		store properly signed inf (use sign of etemp) into fp0
518c2ecf20Sopenharmony_ci|		set FPSR exception status dz bit, condition code
528c2ecf20Sopenharmony_ci|		inf bit, and accrued dz bit
538c2ecf20Sopenharmony_ci|		return
548c2ecf20Sopenharmony_ci|		frestore the frame into the machine (done by unimp_hd)
558c2ecf20Sopenharmony_ci|
568c2ecf20Sopenharmony_ci|	else dz trap enabled
578c2ecf20Sopenharmony_ci|		set exception status bit & accrued bits in FPSR
588c2ecf20Sopenharmony_ci|		set flag to disable sto_res from corrupting fp register
598c2ecf20Sopenharmony_ci|		return
608c2ecf20Sopenharmony_ci|		frestore the frame into the machine (done by unimp_hd)
618c2ecf20Sopenharmony_ci|
628c2ecf20Sopenharmony_ci| t_dz2 is used by monadic functions such as flogn (from do_func).
638c2ecf20Sopenharmony_ci| t_dz is used by monadic functions such as satanh (from the
648c2ecf20Sopenharmony_ci| transcendental function).
658c2ecf20Sopenharmony_ci|
668c2ecf20Sopenharmony_cit_dz2:
678c2ecf20Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set neg bit in FPSR
688c2ecf20Sopenharmony_ci	fmovel	#0,%FPSR			|clr status bits (Z set)
698c2ecf20Sopenharmony_ci	btstb	#dz_bit,FPCR_ENABLE(%a6)	|test FPCR for dz exc enabled
708c2ecf20Sopenharmony_ci	bnes	dz_ena_end
718c2ecf20Sopenharmony_ci	bras	m_inf			|flogx always returns -inf
728c2ecf20Sopenharmony_cit_dz:
738c2ecf20Sopenharmony_ci	fmovel	#0,%FPSR			|clr status bits (Z set)
748c2ecf20Sopenharmony_ci	btstb	#dz_bit,FPCR_ENABLE(%a6)	|test FPCR for dz exc enabled
758c2ecf20Sopenharmony_ci	bnes	dz_ena
768c2ecf20Sopenharmony_ci|
778c2ecf20Sopenharmony_ci|	dz disabled
788c2ecf20Sopenharmony_ci|
798c2ecf20Sopenharmony_ci	btstb	#sign_bit,ETEMP_EX(%a6)	|check sign for neg or pos
808c2ecf20Sopenharmony_ci	beqs	p_inf			|branch if pos sign
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cim_inf:
838c2ecf20Sopenharmony_ci	fmovemx mns_inf,%fp0-%fp0		|load -inf
848c2ecf20Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set neg bit in FPSR
858c2ecf20Sopenharmony_ci	bras	set_fpsr
868c2ecf20Sopenharmony_cip_inf:
878c2ecf20Sopenharmony_ci	fmovemx pls_inf,%fp0-%fp0		|load +inf
888c2ecf20Sopenharmony_ciset_fpsr:
898c2ecf20Sopenharmony_ci	orl	#dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
908c2ecf20Sopenharmony_ci	rts
918c2ecf20Sopenharmony_ci|
928c2ecf20Sopenharmony_ci|	dz enabled
938c2ecf20Sopenharmony_ci|
948c2ecf20Sopenharmony_cidz_ena:
958c2ecf20Sopenharmony_ci	btstb	#sign_bit,ETEMP_EX(%a6)	|check sign for neg or pos
968c2ecf20Sopenharmony_ci	beqs	dz_ena_end
978c2ecf20Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set neg bit in FPSR
988c2ecf20Sopenharmony_cidz_ena_end:
998c2ecf20Sopenharmony_ci	orl	#dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
1008c2ecf20Sopenharmony_ci	st	STORE_FLG(%a6)
1018c2ecf20Sopenharmony_ci	rts
1028c2ecf20Sopenharmony_ci|
1038c2ecf20Sopenharmony_ci|	OPERR exception
1048c2ecf20Sopenharmony_ci|
1058c2ecf20Sopenharmony_ci|	if (operr trap disabled)
1068c2ecf20Sopenharmony_ci|		set FPSR exception status operr bit, condition code
1078c2ecf20Sopenharmony_ci|		nan bit; Store default NAN into fp0
1088c2ecf20Sopenharmony_ci|		frestore the frame into the machine (done by unimp_hd)
1098c2ecf20Sopenharmony_ci|
1108c2ecf20Sopenharmony_ci|	else (operr trap enabled)
1118c2ecf20Sopenharmony_ci|		set FPSR exception status operr bit, accrued operr bit
1128c2ecf20Sopenharmony_ci|		set flag to disable sto_res from corrupting fp register
1138c2ecf20Sopenharmony_ci|		frestore the frame into the machine (done by unimp_hd)
1148c2ecf20Sopenharmony_ci|
1158c2ecf20Sopenharmony_cit_operr:
1168c2ecf20Sopenharmony_ci	orl	#opnan_mask,USER_FPSR(%a6) |set NaN, OPERR, AIOP
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	btstb	#operr_bit,FPCR_ENABLE(%a6) |test FPCR for operr enabled
1198c2ecf20Sopenharmony_ci	bnes	op_ena
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	fmovemx nan,%fp0-%fp0		|load default nan
1228c2ecf20Sopenharmony_ci	rts
1238c2ecf20Sopenharmony_ciop_ena:
1248c2ecf20Sopenharmony_ci	st	STORE_FLG(%a6)		|do not corrupt destination
1258c2ecf20Sopenharmony_ci	rts
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci|
1288c2ecf20Sopenharmony_ci|	t_unfl --- UNFL exception
1298c2ecf20Sopenharmony_ci|
1308c2ecf20Sopenharmony_ci| This entry point is used by all routines requiring unfl, inex2,
1318c2ecf20Sopenharmony_ci| aunfl, and ainex to be set on exit.
1328c2ecf20Sopenharmony_ci|
1338c2ecf20Sopenharmony_ci| On entry, a0 points to the exceptional operand.  The final exceptional
1348c2ecf20Sopenharmony_ci| operand is built in FP_SCR1 and only the sign from the original operand
1358c2ecf20Sopenharmony_ci| is used.
1368c2ecf20Sopenharmony_ci|
1378c2ecf20Sopenharmony_cit_unfl:
1388c2ecf20Sopenharmony_ci	clrl	FP_SCR1(%a6)		|set exceptional operand to zero
1398c2ecf20Sopenharmony_ci	clrl	FP_SCR1+4(%a6)
1408c2ecf20Sopenharmony_ci	clrl	FP_SCR1+8(%a6)
1418c2ecf20Sopenharmony_ci	tstb	(%a0)			|extract sign from caller's exop
1428c2ecf20Sopenharmony_ci	bpls	unfl_signok
1438c2ecf20Sopenharmony_ci	bset	#sign_bit,FP_SCR1(%a6)
1448c2ecf20Sopenharmony_ciunfl_signok:
1458c2ecf20Sopenharmony_ci	leal	FP_SCR1(%a6),%a0
1468c2ecf20Sopenharmony_ci	orl	#unfinx_mask,USER_FPSR(%a6)
1478c2ecf20Sopenharmony_ci|					;set UNFL, INEX2, AUNFL, AINEX
1488c2ecf20Sopenharmony_ciunfl_con:
1498c2ecf20Sopenharmony_ci	btstb	#unfl_bit,FPCR_ENABLE(%a6)
1508c2ecf20Sopenharmony_ci	beqs	unfl_dis
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ciunfl_ena:
1538c2ecf20Sopenharmony_ci	bfclr	STAG(%a6){#5:#3}		|clear wbtm66,wbtm1,wbtm0
1548c2ecf20Sopenharmony_ci	bsetb	#wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
1558c2ecf20Sopenharmony_ci	bsetb	#sticky_bit,STICKY(%a6)	|set sticky bit
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	bclrb	#E1,E_BYTE(%a6)
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ciunfl_dis:
1608c2ecf20Sopenharmony_ci	bfextu	FPCR_MODE(%a6){#0:#2},%d0	|get round precision
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)
1638c2ecf20Sopenharmony_ci	sne	LOCAL_SGN(%a0)		|convert to internal ext format
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	bsr	unf_sub			|returns IEEE result at a0
1668c2ecf20Sopenharmony_ci|					;and sets FPSR_CC accordingly
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	bfclr	LOCAL_SGN(%a0){#0:#8}	|convert back to IEEE ext format
1698c2ecf20Sopenharmony_ci	beqs	unfl_fin
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
1728c2ecf20Sopenharmony_ci	bsetb	#sign_bit,FP_SCR1(%a6)	|set sign bit of exc operand
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ciunfl_fin:
1758c2ecf20Sopenharmony_ci	fmovemx (%a0),%fp0-%fp0		|store result in fp0
1768c2ecf20Sopenharmony_ci	rts
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci|
1808c2ecf20Sopenharmony_ci|	t_ovfl2 --- OVFL exception (without inex2 returned)
1818c2ecf20Sopenharmony_ci|
1828c2ecf20Sopenharmony_ci| This entry is used by scale to force catastrophic overflow.  The
1838c2ecf20Sopenharmony_ci| ovfl, aovfl, and ainex bits are set, but not the inex2 bit.
1848c2ecf20Sopenharmony_ci|
1858c2ecf20Sopenharmony_cit_ovfl2:
1868c2ecf20Sopenharmony_ci	orl	#ovfl_inx_mask,USER_FPSR(%a6)
1878c2ecf20Sopenharmony_ci	movel	ETEMP(%a6),FP_SCR1(%a6)
1888c2ecf20Sopenharmony_ci	movel	ETEMP_HI(%a6),FP_SCR1+4(%a6)
1898c2ecf20Sopenharmony_ci	movel	ETEMP_LO(%a6),FP_SCR1+8(%a6)
1908c2ecf20Sopenharmony_ci|
1918c2ecf20Sopenharmony_ci| Check for single or double round precision.  If single, check if
1928c2ecf20Sopenharmony_ci| the lower 40 bits of ETEMP are zero; if not, set inex2.  If double,
1938c2ecf20Sopenharmony_ci| check if the lower 21 bits are zero; if not, set inex2.
1948c2ecf20Sopenharmony_ci|
1958c2ecf20Sopenharmony_ci	moveb	FPCR_MODE(%a6),%d0
1968c2ecf20Sopenharmony_ci	andib	#0xc0,%d0
1978c2ecf20Sopenharmony_ci	beq	t_work		|if extended, finish ovfl processing
1988c2ecf20Sopenharmony_ci	cmpib	#0x40,%d0		|test for single
1998c2ecf20Sopenharmony_ci	bnes	t_dbl
2008c2ecf20Sopenharmony_cit_sgl:
2018c2ecf20Sopenharmony_ci	tstb	ETEMP_LO(%a6)
2028c2ecf20Sopenharmony_ci	bnes	t_setinx2
2038c2ecf20Sopenharmony_ci	movel	ETEMP_HI(%a6),%d0
2048c2ecf20Sopenharmony_ci	andil	#0xff,%d0		|look at only lower 8 bits
2058c2ecf20Sopenharmony_ci	bnes	t_setinx2
2068c2ecf20Sopenharmony_ci	bra	t_work
2078c2ecf20Sopenharmony_cit_dbl:
2088c2ecf20Sopenharmony_ci	movel	ETEMP_LO(%a6),%d0
2098c2ecf20Sopenharmony_ci	andil	#0x7ff,%d0	|look at only lower 11 bits
2108c2ecf20Sopenharmony_ci	beq	t_work
2118c2ecf20Sopenharmony_cit_setinx2:
2128c2ecf20Sopenharmony_ci	orl	#inex2_mask,USER_FPSR(%a6)
2138c2ecf20Sopenharmony_ci	bras	t_work
2148c2ecf20Sopenharmony_ci|
2158c2ecf20Sopenharmony_ci|	t_ovfl --- OVFL exception
2168c2ecf20Sopenharmony_ci|
2178c2ecf20Sopenharmony_ci|** Note: the exc operand is returned in ETEMP.
2188c2ecf20Sopenharmony_ci|
2198c2ecf20Sopenharmony_cit_ovfl:
2208c2ecf20Sopenharmony_ci	orl	#ovfinx_mask,USER_FPSR(%a6)
2218c2ecf20Sopenharmony_cit_work:
2228c2ecf20Sopenharmony_ci	btstb	#ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled
2238c2ecf20Sopenharmony_ci	beqs	ovf_dis
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ciovf_ena:
2268c2ecf20Sopenharmony_ci	clrl	FP_SCR1(%a6)		|set exceptional operand
2278c2ecf20Sopenharmony_ci	clrl	FP_SCR1+4(%a6)
2288c2ecf20Sopenharmony_ci	clrl	FP_SCR1+8(%a6)
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	bfclr	STAG(%a6){#5:#3}		|clear wbtm66,wbtm1,wbtm0
2318c2ecf20Sopenharmony_ci	bclrb	#wbtemp15_bit,WB_BYTE(%a6) |clear wbtemp15
2328c2ecf20Sopenharmony_ci	bsetb	#sticky_bit,STICKY(%a6)	|set sticky bit
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	bclrb	#E1,E_BYTE(%a6)
2358c2ecf20Sopenharmony_ci|					;fall through to disabled case
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci| For disabled overflow call 'ovf_r_k'.  This routine loads the
2388c2ecf20Sopenharmony_ci| correct result based on the rounding precision, destination
2398c2ecf20Sopenharmony_ci| format, rounding mode and sign.
2408c2ecf20Sopenharmony_ci|
2418c2ecf20Sopenharmony_ciovf_dis:
2428c2ecf20Sopenharmony_ci	bsr	ovf_r_k			|returns unsigned ETEMP_EX
2438c2ecf20Sopenharmony_ci|					;and sets FPSR_CC accordingly.
2448c2ecf20Sopenharmony_ci	bfclr	ETEMP_SGN(%a6){#0:#8}	|fix sign
2458c2ecf20Sopenharmony_ci	beqs	ovf_pos
2468c2ecf20Sopenharmony_ci	bsetb	#sign_bit,ETEMP_EX(%a6)
2478c2ecf20Sopenharmony_ci	bsetb	#sign_bit,FP_SCR1(%a6)	|set exceptional operand sign
2488c2ecf20Sopenharmony_ciovf_pos:
2498c2ecf20Sopenharmony_ci	fmovemx ETEMP(%a6),%fp0-%fp0		|move the result to fp0
2508c2ecf20Sopenharmony_ci	rts
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci|
2548c2ecf20Sopenharmony_ci|	INEX2 exception
2558c2ecf20Sopenharmony_ci|
2568c2ecf20Sopenharmony_ci| The inex2 and ainex bits are set.
2578c2ecf20Sopenharmony_ci|
2588c2ecf20Sopenharmony_cit_inx2:
2598c2ecf20Sopenharmony_ci	orl	#inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
2608c2ecf20Sopenharmony_ci	rts
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci|
2638c2ecf20Sopenharmony_ci|	Force Inex2
2648c2ecf20Sopenharmony_ci|
2658c2ecf20Sopenharmony_ci| This routine is called by the transcendental routines to force
2668c2ecf20Sopenharmony_ci| the inex2 exception bits set in the FPSR.  If the underflow bit
2678c2ecf20Sopenharmony_ci| is set, but the underflow trap was not taken, the aunfl bit in
2688c2ecf20Sopenharmony_ci| the FPSR must be set.
2698c2ecf20Sopenharmony_ci|
2708c2ecf20Sopenharmony_cit_frcinx:
2718c2ecf20Sopenharmony_ci	orl	#inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
2728c2ecf20Sopenharmony_ci	btstb	#unfl_bit,FPSR_EXCEPT(%a6) |test for unfl bit set
2738c2ecf20Sopenharmony_ci	beqs	no_uacc1		|if clear, do not set aunfl
2748c2ecf20Sopenharmony_ci	bsetb	#aunfl_bit,FPSR_AEXCEPT(%a6)
2758c2ecf20Sopenharmony_cino_uacc1:
2768c2ecf20Sopenharmony_ci	rts
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci|
2798c2ecf20Sopenharmony_ci|	DST_NAN
2808c2ecf20Sopenharmony_ci|
2818c2ecf20Sopenharmony_ci| Determine if the destination nan is signalling or non-signalling,
2828c2ecf20Sopenharmony_ci| and set the FPSR bits accordingly.  See the MC68040 User's Manual
2838c2ecf20Sopenharmony_ci| section 3.2.2.5 NOT-A-NUMBERS.
2848c2ecf20Sopenharmony_ci|
2858c2ecf20Sopenharmony_cidst_nan:
2868c2ecf20Sopenharmony_ci	btstb	#sign_bit,FPTEMP_EX(%a6) |test sign of nan
2878c2ecf20Sopenharmony_ci	beqs	dst_pos			|if clr, it was positive
2888c2ecf20Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set N bit
2898c2ecf20Sopenharmony_cidst_pos:
2908c2ecf20Sopenharmony_ci	btstb	#signan_bit,FPTEMP_HI(%a6) |check if signalling
2918c2ecf20Sopenharmony_ci	beqs	dst_snan		|branch if signalling
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	fmovel	%d1,%fpcr			|restore user's rmode/prec
2948c2ecf20Sopenharmony_ci	fmovex FPTEMP(%a6),%fp0		|return the non-signalling nan
2958c2ecf20Sopenharmony_ci|
2968c2ecf20Sopenharmony_ci| Check the source nan.  If it is signalling, snan will be reported.
2978c2ecf20Sopenharmony_ci|
2988c2ecf20Sopenharmony_ci	moveb	STAG(%a6),%d0
2998c2ecf20Sopenharmony_ci	andib	#0xe0,%d0
3008c2ecf20Sopenharmony_ci	cmpib	#0x60,%d0
3018c2ecf20Sopenharmony_ci	bnes	no_snan
3028c2ecf20Sopenharmony_ci	btstb	#signan_bit,ETEMP_HI(%a6) |check if signalling
3038c2ecf20Sopenharmony_ci	bnes	no_snan
3048c2ecf20Sopenharmony_ci	orl	#snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
3058c2ecf20Sopenharmony_cino_snan:
3068c2ecf20Sopenharmony_ci	rts
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cidst_snan:
3098c2ecf20Sopenharmony_ci	btstb	#snan_bit,FPCR_ENABLE(%a6) |check if trap enabled
3108c2ecf20Sopenharmony_ci	beqs	dst_dis			|branch if disabled
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	orb	#nan_tag,DTAG(%a6)	|set up dtag for nan
3138c2ecf20Sopenharmony_ci	st	STORE_FLG(%a6)		|do not store a result
3148c2ecf20Sopenharmony_ci	orl	#snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
3158c2ecf20Sopenharmony_ci	rts
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cidst_dis:
3188c2ecf20Sopenharmony_ci	bsetb	#signan_bit,FPTEMP_HI(%a6) |set SNAN bit in sop
3198c2ecf20Sopenharmony_ci	fmovel	%d1,%fpcr			|restore user's rmode/prec
3208c2ecf20Sopenharmony_ci	fmovex FPTEMP(%a6),%fp0		|load non-sign. nan
3218c2ecf20Sopenharmony_ci	orl	#snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
3228c2ecf20Sopenharmony_ci	rts
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci|
3258c2ecf20Sopenharmony_ci|	SRC_NAN
3268c2ecf20Sopenharmony_ci|
3278c2ecf20Sopenharmony_ci| Determine if the source nan is signalling or non-signalling,
3288c2ecf20Sopenharmony_ci| and set the FPSR bits accordingly.  See the MC68040 User's Manual
3298c2ecf20Sopenharmony_ci| section 3.2.2.5 NOT-A-NUMBERS.
3308c2ecf20Sopenharmony_ci|
3318c2ecf20Sopenharmony_cisrc_nan:
3328c2ecf20Sopenharmony_ci	btstb	#sign_bit,ETEMP_EX(%a6) |test sign of nan
3338c2ecf20Sopenharmony_ci	beqs	src_pos			|if clr, it was positive
3348c2ecf20Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set N bit
3358c2ecf20Sopenharmony_cisrc_pos:
3368c2ecf20Sopenharmony_ci	btstb	#signan_bit,ETEMP_HI(%a6) |check if signalling
3378c2ecf20Sopenharmony_ci	beqs	src_snan		|branch if signalling
3388c2ecf20Sopenharmony_ci	fmovel	%d1,%fpcr			|restore user's rmode/prec
3398c2ecf20Sopenharmony_ci	fmovex ETEMP(%a6),%fp0		|return the non-signalling nan
3408c2ecf20Sopenharmony_ci	rts
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_cisrc_snan:
3438c2ecf20Sopenharmony_ci	btstb	#snan_bit,FPCR_ENABLE(%a6) |check if trap enabled
3448c2ecf20Sopenharmony_ci	beqs	src_dis			|branch if disabled
3458c2ecf20Sopenharmony_ci	bsetb	#signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop
3468c2ecf20Sopenharmony_ci	orb	#norm_tag,DTAG(%a6)	|set up dtag for norm
3478c2ecf20Sopenharmony_ci	orb	#nan_tag,STAG(%a6)	|set up stag for nan
3488c2ecf20Sopenharmony_ci	st	STORE_FLG(%a6)		|do not store a result
3498c2ecf20Sopenharmony_ci	orl	#snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
3508c2ecf20Sopenharmony_ci	rts
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_cisrc_dis:
3538c2ecf20Sopenharmony_ci	bsetb	#signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop
3548c2ecf20Sopenharmony_ci	fmovel	%d1,%fpcr			|restore user's rmode/prec
3558c2ecf20Sopenharmony_ci	fmovex ETEMP(%a6),%fp0		|load non-sign. nan
3568c2ecf20Sopenharmony_ci	orl	#snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
3578c2ecf20Sopenharmony_ci	rts
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci|
3608c2ecf20Sopenharmony_ci| For all functions that have a denormalized input and that f(x)=x,
3618c2ecf20Sopenharmony_ci| this is the entry point
3628c2ecf20Sopenharmony_ci|
3638c2ecf20Sopenharmony_cit_extdnrm:
3648c2ecf20Sopenharmony_ci	orl	#unfinx_mask,USER_FPSR(%a6)
3658c2ecf20Sopenharmony_ci|					;set UNFL, INEX2, AUNFL, AINEX
3668c2ecf20Sopenharmony_ci	bras	xdnrm_con
3678c2ecf20Sopenharmony_ci|
3688c2ecf20Sopenharmony_ci| Entry point for scale with extended denorm.  The function does
3698c2ecf20Sopenharmony_ci| not set inex2, aunfl, or ainex.
3708c2ecf20Sopenharmony_ci|
3718c2ecf20Sopenharmony_cit_resdnrm:
3728c2ecf20Sopenharmony_ci	orl	#unfl_mask,USER_FPSR(%a6)
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cixdnrm_con:
3758c2ecf20Sopenharmony_ci	btstb	#unfl_bit,FPCR_ENABLE(%a6)
3768c2ecf20Sopenharmony_ci	beqs	xdnrm_dis
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci|
3798c2ecf20Sopenharmony_ci| If exceptions are enabled, the additional task of setting up WBTEMP
3808c2ecf20Sopenharmony_ci| is needed so that when the underflow exception handler is entered,
3818c2ecf20Sopenharmony_ci| the user perceives no difference between what the 040 provides vs.
3828c2ecf20Sopenharmony_ci| what the FPSP provides.
3838c2ecf20Sopenharmony_ci|
3848c2ecf20Sopenharmony_cixdnrm_ena:
3858c2ecf20Sopenharmony_ci	movel	%a0,-(%a7)
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	movel	LOCAL_EX(%a0),FP_SCR1(%a6)
3888c2ecf20Sopenharmony_ci	movel	LOCAL_HI(%a0),FP_SCR1+4(%a6)
3898c2ecf20Sopenharmony_ci	movel	LOCAL_LO(%a0),FP_SCR1+8(%a6)
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	lea	FP_SCR1(%a6),%a0
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)
3948c2ecf20Sopenharmony_ci	sne	LOCAL_SGN(%a0)		|convert to internal ext format
3958c2ecf20Sopenharmony_ci	tstw	LOCAL_EX(%a0)		|check if input is denorm
3968c2ecf20Sopenharmony_ci	beqs	xdnrm_dn		|if so, skip nrm_set
3978c2ecf20Sopenharmony_ci	bsr	nrm_set			|normalize the result (exponent
3988c2ecf20Sopenharmony_ci|					;will be negative
3998c2ecf20Sopenharmony_cixdnrm_dn:
4008c2ecf20Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)	|take off false sign
4018c2ecf20Sopenharmony_ci	bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format
4028c2ecf20Sopenharmony_ci	beqs	xdep
4038c2ecf20Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
4048c2ecf20Sopenharmony_cixdep:
4058c2ecf20Sopenharmony_ci	bfclr	STAG(%a6){#5:#3}		|clear wbtm66,wbtm1,wbtm0
4068c2ecf20Sopenharmony_ci	bsetb	#wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
4078c2ecf20Sopenharmony_ci	bclrb	#sticky_bit,STICKY(%a6)	|clear sticky bit
4088c2ecf20Sopenharmony_ci	bclrb	#E1,E_BYTE(%a6)
4098c2ecf20Sopenharmony_ci	movel	(%a7)+,%a0
4108c2ecf20Sopenharmony_cixdnrm_dis:
4118c2ecf20Sopenharmony_ci	bfextu	FPCR_MODE(%a6){#0:#2},%d0	|get round precision
4128c2ecf20Sopenharmony_ci	bnes	not_ext			|if not round extended, store
4138c2ecf20Sopenharmony_ci|					;IEEE defaults
4148c2ecf20Sopenharmony_ciis_ext:
4158c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
4168c2ecf20Sopenharmony_ci	beqs	xdnrm_store
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set N bit in FPSR_CC
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	bras	xdnrm_store
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_cinot_ext:
4238c2ecf20Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)
4248c2ecf20Sopenharmony_ci	sne	LOCAL_SGN(%a0)		|convert to internal ext format
4258c2ecf20Sopenharmony_ci	bsr	unf_sub			|returns IEEE result pointed by
4268c2ecf20Sopenharmony_ci|					;a0; sets FPSR_CC accordingly
4278c2ecf20Sopenharmony_ci	bfclr	LOCAL_SGN(%a0){#0:#8}	|convert back to IEEE ext format
4288c2ecf20Sopenharmony_ci	beqs	xdnrm_store
4298c2ecf20Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
4308c2ecf20Sopenharmony_cixdnrm_store:
4318c2ecf20Sopenharmony_ci	fmovemx (%a0),%fp0-%fp0		|store result in fp0
4328c2ecf20Sopenharmony_ci	rts
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci|
4358c2ecf20Sopenharmony_ci| This subroutine is used for dyadic operations that use an extended
4368c2ecf20Sopenharmony_ci| denorm within the kernel. The approach used is to capture the frame,
4378c2ecf20Sopenharmony_ci| fix/restore.
4388c2ecf20Sopenharmony_ci|
4398c2ecf20Sopenharmony_ci	.global	t_avoid_unsupp
4408c2ecf20Sopenharmony_cit_avoid_unsupp:
4418c2ecf20Sopenharmony_ci	link	%a2,#-LOCAL_SIZE		|so that a2 fpsp.h negative
4428c2ecf20Sopenharmony_ci|					;offsets may be used
4438c2ecf20Sopenharmony_ci	fsave	-(%a7)
4448c2ecf20Sopenharmony_ci	tstb	1(%a7)			|check if idle, exit if so
4458c2ecf20Sopenharmony_ci	beq	idle_end
4468c2ecf20Sopenharmony_ci	btstb	#E1,E_BYTE(%a2)		|check for an E1 exception if
4478c2ecf20Sopenharmony_ci|					;enabled, there is an unsupp
4488c2ecf20Sopenharmony_ci	beq	end_avun		|else, exit
4498c2ecf20Sopenharmony_ci	btstb	#7,DTAG(%a2)		|check for denorm destination
4508c2ecf20Sopenharmony_ci	beqs	src_den			|else, must be a source denorm
4518c2ecf20Sopenharmony_ci|
4528c2ecf20Sopenharmony_ci| handle destination denorm
4538c2ecf20Sopenharmony_ci|
4548c2ecf20Sopenharmony_ci	lea	FPTEMP(%a2),%a0
4558c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
4568c2ecf20Sopenharmony_ci	sne	LOCAL_SGN(%a0)		|convert to internal ext format
4578c2ecf20Sopenharmony_ci	bclrb	#7,DTAG(%a2)		|set DTAG to norm
4588c2ecf20Sopenharmony_ci	bsr	nrm_set			|normalize result, exponent
4598c2ecf20Sopenharmony_ci|					;will become negative
4608c2ecf20Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)	|get rid of fake sign
4618c2ecf20Sopenharmony_ci	bfclr	LOCAL_SGN(%a0){#0:#8}	|convert back to IEEE ext format
4628c2ecf20Sopenharmony_ci	beqs	ck_src_den		|check if source is also denorm
4638c2ecf20Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
4648c2ecf20Sopenharmony_cick_src_den:
4658c2ecf20Sopenharmony_ci	btstb	#7,STAG(%a2)
4668c2ecf20Sopenharmony_ci	beqs	end_avun
4678c2ecf20Sopenharmony_cisrc_den:
4688c2ecf20Sopenharmony_ci	lea	ETEMP(%a2),%a0
4698c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
4708c2ecf20Sopenharmony_ci	sne	LOCAL_SGN(%a0)		|convert to internal ext format
4718c2ecf20Sopenharmony_ci	bclrb	#7,STAG(%a2)		|set STAG to norm
4728c2ecf20Sopenharmony_ci	bsr	nrm_set			|normalize result, exponent
4738c2ecf20Sopenharmony_ci|					;will become negative
4748c2ecf20Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)	|get rid of fake sign
4758c2ecf20Sopenharmony_ci	bfclr	LOCAL_SGN(%a0){#0:#8}	|convert back to IEEE ext format
4768c2ecf20Sopenharmony_ci	beqs	den_com
4778c2ecf20Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
4788c2ecf20Sopenharmony_ciden_com:
4798c2ecf20Sopenharmony_ci	moveb	#0xfe,CU_SAVEPC(%a2)	|set continue frame
4808c2ecf20Sopenharmony_ci	clrw	NMNEXC(%a2)		|clear NMNEXC
4818c2ecf20Sopenharmony_ci	bclrb	#E1,E_BYTE(%a2)
4828c2ecf20Sopenharmony_ci|	fmove.l	%FPSR,FPSR_SHADOW(%a2)
4838c2ecf20Sopenharmony_ci|	bset.b	#SFLAG,E_BYTE(%a2)
4848c2ecf20Sopenharmony_ci|	bset.b	#XFLAG,T_BYTE(%a2)
4858c2ecf20Sopenharmony_ciend_avun:
4868c2ecf20Sopenharmony_ci	frestore (%a7)+
4878c2ecf20Sopenharmony_ci	unlk	%a2
4888c2ecf20Sopenharmony_ci	rts
4898c2ecf20Sopenharmony_ciidle_end:
4908c2ecf20Sopenharmony_ci	addl	#4,%a7
4918c2ecf20Sopenharmony_ci	unlk	%a2
4928c2ecf20Sopenharmony_ci	rts
4938c2ecf20Sopenharmony_ci	|end
494