162306a36Sopenharmony_ci|
262306a36Sopenharmony_ci|	kernel_ex.sa 3.3 12/19/90
362306a36Sopenharmony_ci|
462306a36Sopenharmony_ci| This file contains routines to force exception status in the
562306a36Sopenharmony_ci| fpu for exceptional cases detected or reported within the
662306a36Sopenharmony_ci| transcendental functions.  Typically, the t_xx routine will
762306a36Sopenharmony_ci| set the appropriate bits in the USER_FPSR word on the stack.
862306a36Sopenharmony_ci| The bits are tested in gen_except.sa to determine if an exceptional
962306a36Sopenharmony_ci| situation needs to be created on return from the FPSP.
1062306a36Sopenharmony_ci|
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
1362306a36Sopenharmony_ci|			All Rights Reserved
1462306a36Sopenharmony_ci|
1562306a36Sopenharmony_ci|       For details on the license for this file, please see the
1662306a36Sopenharmony_ci|       file, README, in this same directory.
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciKERNEL_EX:    |idnt    2,1 | Motorola 040 Floating Point Software Package
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	|section    8
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include "fpsp.h"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cimns_inf:  .long 0xffff0000,0x00000000,0x00000000
2562306a36Sopenharmony_cipls_inf:  .long 0x7fff0000,0x00000000,0x00000000
2662306a36Sopenharmony_cinan:      .long 0x7fff0000,0xffffffff,0xffffffff
2762306a36Sopenharmony_cihuge:     .long 0x7ffe0000,0xffffffff,0xffffffff
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	|xref	  ovf_r_k
3062306a36Sopenharmony_ci	|xref	  unf_sub
3162306a36Sopenharmony_ci	|xref	  nrm_set
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	.global	  t_dz
3462306a36Sopenharmony_ci	.global      t_dz2
3562306a36Sopenharmony_ci	.global      t_operr
3662306a36Sopenharmony_ci	.global      t_unfl
3762306a36Sopenharmony_ci	.global      t_ovfl
3862306a36Sopenharmony_ci	.global      t_ovfl2
3962306a36Sopenharmony_ci	.global      t_inx2
4062306a36Sopenharmony_ci	.global	  t_frcinx
4162306a36Sopenharmony_ci	.global	  t_extdnrm
4262306a36Sopenharmony_ci	.global	  t_resdnrm
4362306a36Sopenharmony_ci	.global	  dst_nan
4462306a36Sopenharmony_ci	.global	  src_nan
4562306a36Sopenharmony_ci|
4662306a36Sopenharmony_ci|	DZ exception
4762306a36Sopenharmony_ci|
4862306a36Sopenharmony_ci|
4962306a36Sopenharmony_ci|	if dz trap disabled
5062306a36Sopenharmony_ci|		store properly signed inf (use sign of etemp) into fp0
5162306a36Sopenharmony_ci|		set FPSR exception status dz bit, condition code
5262306a36Sopenharmony_ci|		inf bit, and accrued dz bit
5362306a36Sopenharmony_ci|		return
5462306a36Sopenharmony_ci|		frestore the frame into the machine (done by unimp_hd)
5562306a36Sopenharmony_ci|
5662306a36Sopenharmony_ci|	else dz trap enabled
5762306a36Sopenharmony_ci|		set exception status bit & accrued bits in FPSR
5862306a36Sopenharmony_ci|		set flag to disable sto_res from corrupting fp register
5962306a36Sopenharmony_ci|		return
6062306a36Sopenharmony_ci|		frestore the frame into the machine (done by unimp_hd)
6162306a36Sopenharmony_ci|
6262306a36Sopenharmony_ci| t_dz2 is used by monadic functions such as flogn (from do_func).
6362306a36Sopenharmony_ci| t_dz is used by monadic functions such as satanh (from the
6462306a36Sopenharmony_ci| transcendental function).
6562306a36Sopenharmony_ci|
6662306a36Sopenharmony_cit_dz2:
6762306a36Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set neg bit in FPSR
6862306a36Sopenharmony_ci	fmovel	#0,%FPSR			|clr status bits (Z set)
6962306a36Sopenharmony_ci	btstb	#dz_bit,FPCR_ENABLE(%a6)	|test FPCR for dz exc enabled
7062306a36Sopenharmony_ci	bnes	dz_ena_end
7162306a36Sopenharmony_ci	bras	m_inf			|flogx always returns -inf
7262306a36Sopenharmony_cit_dz:
7362306a36Sopenharmony_ci	fmovel	#0,%FPSR			|clr status bits (Z set)
7462306a36Sopenharmony_ci	btstb	#dz_bit,FPCR_ENABLE(%a6)	|test FPCR for dz exc enabled
7562306a36Sopenharmony_ci	bnes	dz_ena
7662306a36Sopenharmony_ci|
7762306a36Sopenharmony_ci|	dz disabled
7862306a36Sopenharmony_ci|
7962306a36Sopenharmony_ci	btstb	#sign_bit,ETEMP_EX(%a6)	|check sign for neg or pos
8062306a36Sopenharmony_ci	beqs	p_inf			|branch if pos sign
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cim_inf:
8362306a36Sopenharmony_ci	fmovemx mns_inf,%fp0-%fp0		|load -inf
8462306a36Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set neg bit in FPSR
8562306a36Sopenharmony_ci	bras	set_fpsr
8662306a36Sopenharmony_cip_inf:
8762306a36Sopenharmony_ci	fmovemx pls_inf,%fp0-%fp0		|load +inf
8862306a36Sopenharmony_ciset_fpsr:
8962306a36Sopenharmony_ci	orl	#dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
9062306a36Sopenharmony_ci	rts
9162306a36Sopenharmony_ci|
9262306a36Sopenharmony_ci|	dz enabled
9362306a36Sopenharmony_ci|
9462306a36Sopenharmony_cidz_ena:
9562306a36Sopenharmony_ci	btstb	#sign_bit,ETEMP_EX(%a6)	|check sign for neg or pos
9662306a36Sopenharmony_ci	beqs	dz_ena_end
9762306a36Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set neg bit in FPSR
9862306a36Sopenharmony_cidz_ena_end:
9962306a36Sopenharmony_ci	orl	#dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
10062306a36Sopenharmony_ci	st	STORE_FLG(%a6)
10162306a36Sopenharmony_ci	rts
10262306a36Sopenharmony_ci|
10362306a36Sopenharmony_ci|	OPERR exception
10462306a36Sopenharmony_ci|
10562306a36Sopenharmony_ci|	if (operr trap disabled)
10662306a36Sopenharmony_ci|		set FPSR exception status operr bit, condition code
10762306a36Sopenharmony_ci|		nan bit; Store default NAN into fp0
10862306a36Sopenharmony_ci|		frestore the frame into the machine (done by unimp_hd)
10962306a36Sopenharmony_ci|
11062306a36Sopenharmony_ci|	else (operr trap enabled)
11162306a36Sopenharmony_ci|		set FPSR exception status operr bit, accrued operr bit
11262306a36Sopenharmony_ci|		set flag to disable sto_res from corrupting fp register
11362306a36Sopenharmony_ci|		frestore the frame into the machine (done by unimp_hd)
11462306a36Sopenharmony_ci|
11562306a36Sopenharmony_cit_operr:
11662306a36Sopenharmony_ci	orl	#opnan_mask,USER_FPSR(%a6) |set NaN, OPERR, AIOP
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	btstb	#operr_bit,FPCR_ENABLE(%a6) |test FPCR for operr enabled
11962306a36Sopenharmony_ci	bnes	op_ena
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	fmovemx nan,%fp0-%fp0		|load default nan
12262306a36Sopenharmony_ci	rts
12362306a36Sopenharmony_ciop_ena:
12462306a36Sopenharmony_ci	st	STORE_FLG(%a6)		|do not corrupt destination
12562306a36Sopenharmony_ci	rts
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci|
12862306a36Sopenharmony_ci|	t_unfl --- UNFL exception
12962306a36Sopenharmony_ci|
13062306a36Sopenharmony_ci| This entry point is used by all routines requiring unfl, inex2,
13162306a36Sopenharmony_ci| aunfl, and ainex to be set on exit.
13262306a36Sopenharmony_ci|
13362306a36Sopenharmony_ci| On entry, a0 points to the exceptional operand.  The final exceptional
13462306a36Sopenharmony_ci| operand is built in FP_SCR1 and only the sign from the original operand
13562306a36Sopenharmony_ci| is used.
13662306a36Sopenharmony_ci|
13762306a36Sopenharmony_cit_unfl:
13862306a36Sopenharmony_ci	clrl	FP_SCR1(%a6)		|set exceptional operand to zero
13962306a36Sopenharmony_ci	clrl	FP_SCR1+4(%a6)
14062306a36Sopenharmony_ci	clrl	FP_SCR1+8(%a6)
14162306a36Sopenharmony_ci	tstb	(%a0)			|extract sign from caller's exop
14262306a36Sopenharmony_ci	bpls	unfl_signok
14362306a36Sopenharmony_ci	bset	#sign_bit,FP_SCR1(%a6)
14462306a36Sopenharmony_ciunfl_signok:
14562306a36Sopenharmony_ci	leal	FP_SCR1(%a6),%a0
14662306a36Sopenharmony_ci	orl	#unfinx_mask,USER_FPSR(%a6)
14762306a36Sopenharmony_ci|					;set UNFL, INEX2, AUNFL, AINEX
14862306a36Sopenharmony_ciunfl_con:
14962306a36Sopenharmony_ci	btstb	#unfl_bit,FPCR_ENABLE(%a6)
15062306a36Sopenharmony_ci	beqs	unfl_dis
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ciunfl_ena:
15362306a36Sopenharmony_ci	bfclr	STAG(%a6){#5:#3}		|clear wbtm66,wbtm1,wbtm0
15462306a36Sopenharmony_ci	bsetb	#wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
15562306a36Sopenharmony_ci	bsetb	#sticky_bit,STICKY(%a6)	|set sticky bit
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	bclrb	#E1,E_BYTE(%a6)
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ciunfl_dis:
16062306a36Sopenharmony_ci	bfextu	FPCR_MODE(%a6){#0:#2},%d0	|get round precision
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)
16362306a36Sopenharmony_ci	sne	LOCAL_SGN(%a0)		|convert to internal ext format
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	bsr	unf_sub			|returns IEEE result at a0
16662306a36Sopenharmony_ci|					;and sets FPSR_CC accordingly
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	bfclr	LOCAL_SGN(%a0){#0:#8}	|convert back to IEEE ext format
16962306a36Sopenharmony_ci	beqs	unfl_fin
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
17262306a36Sopenharmony_ci	bsetb	#sign_bit,FP_SCR1(%a6)	|set sign bit of exc operand
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ciunfl_fin:
17562306a36Sopenharmony_ci	fmovemx (%a0),%fp0-%fp0		|store result in fp0
17662306a36Sopenharmony_ci	rts
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci|
18062306a36Sopenharmony_ci|	t_ovfl2 --- OVFL exception (without inex2 returned)
18162306a36Sopenharmony_ci|
18262306a36Sopenharmony_ci| This entry is used by scale to force catastrophic overflow.  The
18362306a36Sopenharmony_ci| ovfl, aovfl, and ainex bits are set, but not the inex2 bit.
18462306a36Sopenharmony_ci|
18562306a36Sopenharmony_cit_ovfl2:
18662306a36Sopenharmony_ci	orl	#ovfl_inx_mask,USER_FPSR(%a6)
18762306a36Sopenharmony_ci	movel	ETEMP(%a6),FP_SCR1(%a6)
18862306a36Sopenharmony_ci	movel	ETEMP_HI(%a6),FP_SCR1+4(%a6)
18962306a36Sopenharmony_ci	movel	ETEMP_LO(%a6),FP_SCR1+8(%a6)
19062306a36Sopenharmony_ci|
19162306a36Sopenharmony_ci| Check for single or double round precision.  If single, check if
19262306a36Sopenharmony_ci| the lower 40 bits of ETEMP are zero; if not, set inex2.  If double,
19362306a36Sopenharmony_ci| check if the lower 21 bits are zero; if not, set inex2.
19462306a36Sopenharmony_ci|
19562306a36Sopenharmony_ci	moveb	FPCR_MODE(%a6),%d0
19662306a36Sopenharmony_ci	andib	#0xc0,%d0
19762306a36Sopenharmony_ci	beq	t_work		|if extended, finish ovfl processing
19862306a36Sopenharmony_ci	cmpib	#0x40,%d0		|test for single
19962306a36Sopenharmony_ci	bnes	t_dbl
20062306a36Sopenharmony_cit_sgl:
20162306a36Sopenharmony_ci	tstb	ETEMP_LO(%a6)
20262306a36Sopenharmony_ci	bnes	t_setinx2
20362306a36Sopenharmony_ci	movel	ETEMP_HI(%a6),%d0
20462306a36Sopenharmony_ci	andil	#0xff,%d0		|look at only lower 8 bits
20562306a36Sopenharmony_ci	bnes	t_setinx2
20662306a36Sopenharmony_ci	bra	t_work
20762306a36Sopenharmony_cit_dbl:
20862306a36Sopenharmony_ci	movel	ETEMP_LO(%a6),%d0
20962306a36Sopenharmony_ci	andil	#0x7ff,%d0	|look at only lower 11 bits
21062306a36Sopenharmony_ci	beq	t_work
21162306a36Sopenharmony_cit_setinx2:
21262306a36Sopenharmony_ci	orl	#inex2_mask,USER_FPSR(%a6)
21362306a36Sopenharmony_ci	bras	t_work
21462306a36Sopenharmony_ci|
21562306a36Sopenharmony_ci|	t_ovfl --- OVFL exception
21662306a36Sopenharmony_ci|
21762306a36Sopenharmony_ci|** Note: the exc operand is returned in ETEMP.
21862306a36Sopenharmony_ci|
21962306a36Sopenharmony_cit_ovfl:
22062306a36Sopenharmony_ci	orl	#ovfinx_mask,USER_FPSR(%a6)
22162306a36Sopenharmony_cit_work:
22262306a36Sopenharmony_ci	btstb	#ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled
22362306a36Sopenharmony_ci	beqs	ovf_dis
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ciovf_ena:
22662306a36Sopenharmony_ci	clrl	FP_SCR1(%a6)		|set exceptional operand
22762306a36Sopenharmony_ci	clrl	FP_SCR1+4(%a6)
22862306a36Sopenharmony_ci	clrl	FP_SCR1+8(%a6)
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	bfclr	STAG(%a6){#5:#3}		|clear wbtm66,wbtm1,wbtm0
23162306a36Sopenharmony_ci	bclrb	#wbtemp15_bit,WB_BYTE(%a6) |clear wbtemp15
23262306a36Sopenharmony_ci	bsetb	#sticky_bit,STICKY(%a6)	|set sticky bit
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	bclrb	#E1,E_BYTE(%a6)
23562306a36Sopenharmony_ci|					;fall through to disabled case
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci| For disabled overflow call 'ovf_r_k'.  This routine loads the
23862306a36Sopenharmony_ci| correct result based on the rounding precision, destination
23962306a36Sopenharmony_ci| format, rounding mode and sign.
24062306a36Sopenharmony_ci|
24162306a36Sopenharmony_ciovf_dis:
24262306a36Sopenharmony_ci	bsr	ovf_r_k			|returns unsigned ETEMP_EX
24362306a36Sopenharmony_ci|					;and sets FPSR_CC accordingly.
24462306a36Sopenharmony_ci	bfclr	ETEMP_SGN(%a6){#0:#8}	|fix sign
24562306a36Sopenharmony_ci	beqs	ovf_pos
24662306a36Sopenharmony_ci	bsetb	#sign_bit,ETEMP_EX(%a6)
24762306a36Sopenharmony_ci	bsetb	#sign_bit,FP_SCR1(%a6)	|set exceptional operand sign
24862306a36Sopenharmony_ciovf_pos:
24962306a36Sopenharmony_ci	fmovemx ETEMP(%a6),%fp0-%fp0		|move the result to fp0
25062306a36Sopenharmony_ci	rts
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci|
25462306a36Sopenharmony_ci|	INEX2 exception
25562306a36Sopenharmony_ci|
25662306a36Sopenharmony_ci| The inex2 and ainex bits are set.
25762306a36Sopenharmony_ci|
25862306a36Sopenharmony_cit_inx2:
25962306a36Sopenharmony_ci	orl	#inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
26062306a36Sopenharmony_ci	rts
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci|
26362306a36Sopenharmony_ci|	Force Inex2
26462306a36Sopenharmony_ci|
26562306a36Sopenharmony_ci| This routine is called by the transcendental routines to force
26662306a36Sopenharmony_ci| the inex2 exception bits set in the FPSR.  If the underflow bit
26762306a36Sopenharmony_ci| is set, but the underflow trap was not taken, the aunfl bit in
26862306a36Sopenharmony_ci| the FPSR must be set.
26962306a36Sopenharmony_ci|
27062306a36Sopenharmony_cit_frcinx:
27162306a36Sopenharmony_ci	orl	#inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
27262306a36Sopenharmony_ci	btstb	#unfl_bit,FPSR_EXCEPT(%a6) |test for unfl bit set
27362306a36Sopenharmony_ci	beqs	no_uacc1		|if clear, do not set aunfl
27462306a36Sopenharmony_ci	bsetb	#aunfl_bit,FPSR_AEXCEPT(%a6)
27562306a36Sopenharmony_cino_uacc1:
27662306a36Sopenharmony_ci	rts
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci|
27962306a36Sopenharmony_ci|	DST_NAN
28062306a36Sopenharmony_ci|
28162306a36Sopenharmony_ci| Determine if the destination nan is signalling or non-signalling,
28262306a36Sopenharmony_ci| and set the FPSR bits accordingly.  See the MC68040 User's Manual
28362306a36Sopenharmony_ci| section 3.2.2.5 NOT-A-NUMBERS.
28462306a36Sopenharmony_ci|
28562306a36Sopenharmony_cidst_nan:
28662306a36Sopenharmony_ci	btstb	#sign_bit,FPTEMP_EX(%a6) |test sign of nan
28762306a36Sopenharmony_ci	beqs	dst_pos			|if clr, it was positive
28862306a36Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set N bit
28962306a36Sopenharmony_cidst_pos:
29062306a36Sopenharmony_ci	btstb	#signan_bit,FPTEMP_HI(%a6) |check if signalling
29162306a36Sopenharmony_ci	beqs	dst_snan		|branch if signalling
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	fmovel	%d1,%fpcr			|restore user's rmode/prec
29462306a36Sopenharmony_ci	fmovex FPTEMP(%a6),%fp0		|return the non-signalling nan
29562306a36Sopenharmony_ci|
29662306a36Sopenharmony_ci| Check the source nan.  If it is signalling, snan will be reported.
29762306a36Sopenharmony_ci|
29862306a36Sopenharmony_ci	moveb	STAG(%a6),%d0
29962306a36Sopenharmony_ci	andib	#0xe0,%d0
30062306a36Sopenharmony_ci	cmpib	#0x60,%d0
30162306a36Sopenharmony_ci	bnes	no_snan
30262306a36Sopenharmony_ci	btstb	#signan_bit,ETEMP_HI(%a6) |check if signalling
30362306a36Sopenharmony_ci	bnes	no_snan
30462306a36Sopenharmony_ci	orl	#snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
30562306a36Sopenharmony_cino_snan:
30662306a36Sopenharmony_ci	rts
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cidst_snan:
30962306a36Sopenharmony_ci	btstb	#snan_bit,FPCR_ENABLE(%a6) |check if trap enabled
31062306a36Sopenharmony_ci	beqs	dst_dis			|branch if disabled
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	orb	#nan_tag,DTAG(%a6)	|set up dtag for nan
31362306a36Sopenharmony_ci	st	STORE_FLG(%a6)		|do not store a result
31462306a36Sopenharmony_ci	orl	#snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
31562306a36Sopenharmony_ci	rts
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cidst_dis:
31862306a36Sopenharmony_ci	bsetb	#signan_bit,FPTEMP_HI(%a6) |set SNAN bit in sop
31962306a36Sopenharmony_ci	fmovel	%d1,%fpcr			|restore user's rmode/prec
32062306a36Sopenharmony_ci	fmovex FPTEMP(%a6),%fp0		|load non-sign. nan
32162306a36Sopenharmony_ci	orl	#snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
32262306a36Sopenharmony_ci	rts
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci|
32562306a36Sopenharmony_ci|	SRC_NAN
32662306a36Sopenharmony_ci|
32762306a36Sopenharmony_ci| Determine if the source nan is signalling or non-signalling,
32862306a36Sopenharmony_ci| and set the FPSR bits accordingly.  See the MC68040 User's Manual
32962306a36Sopenharmony_ci| section 3.2.2.5 NOT-A-NUMBERS.
33062306a36Sopenharmony_ci|
33162306a36Sopenharmony_cisrc_nan:
33262306a36Sopenharmony_ci	btstb	#sign_bit,ETEMP_EX(%a6) |test sign of nan
33362306a36Sopenharmony_ci	beqs	src_pos			|if clr, it was positive
33462306a36Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set N bit
33562306a36Sopenharmony_cisrc_pos:
33662306a36Sopenharmony_ci	btstb	#signan_bit,ETEMP_HI(%a6) |check if signalling
33762306a36Sopenharmony_ci	beqs	src_snan		|branch if signalling
33862306a36Sopenharmony_ci	fmovel	%d1,%fpcr			|restore user's rmode/prec
33962306a36Sopenharmony_ci	fmovex ETEMP(%a6),%fp0		|return the non-signalling nan
34062306a36Sopenharmony_ci	rts
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_cisrc_snan:
34362306a36Sopenharmony_ci	btstb	#snan_bit,FPCR_ENABLE(%a6) |check if trap enabled
34462306a36Sopenharmony_ci	beqs	src_dis			|branch if disabled
34562306a36Sopenharmony_ci	bsetb	#signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop
34662306a36Sopenharmony_ci	orb	#norm_tag,DTAG(%a6)	|set up dtag for norm
34762306a36Sopenharmony_ci	orb	#nan_tag,STAG(%a6)	|set up stag for nan
34862306a36Sopenharmony_ci	st	STORE_FLG(%a6)		|do not store a result
34962306a36Sopenharmony_ci	orl	#snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
35062306a36Sopenharmony_ci	rts
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_cisrc_dis:
35362306a36Sopenharmony_ci	bsetb	#signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop
35462306a36Sopenharmony_ci	fmovel	%d1,%fpcr			|restore user's rmode/prec
35562306a36Sopenharmony_ci	fmovex ETEMP(%a6),%fp0		|load non-sign. nan
35662306a36Sopenharmony_ci	orl	#snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
35762306a36Sopenharmony_ci	rts
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci|
36062306a36Sopenharmony_ci| For all functions that have a denormalized input and that f(x)=x,
36162306a36Sopenharmony_ci| this is the entry point
36262306a36Sopenharmony_ci|
36362306a36Sopenharmony_cit_extdnrm:
36462306a36Sopenharmony_ci	orl	#unfinx_mask,USER_FPSR(%a6)
36562306a36Sopenharmony_ci|					;set UNFL, INEX2, AUNFL, AINEX
36662306a36Sopenharmony_ci	bras	xdnrm_con
36762306a36Sopenharmony_ci|
36862306a36Sopenharmony_ci| Entry point for scale with extended denorm.  The function does
36962306a36Sopenharmony_ci| not set inex2, aunfl, or ainex.
37062306a36Sopenharmony_ci|
37162306a36Sopenharmony_cit_resdnrm:
37262306a36Sopenharmony_ci	orl	#unfl_mask,USER_FPSR(%a6)
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_cixdnrm_con:
37562306a36Sopenharmony_ci	btstb	#unfl_bit,FPCR_ENABLE(%a6)
37662306a36Sopenharmony_ci	beqs	xdnrm_dis
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci|
37962306a36Sopenharmony_ci| If exceptions are enabled, the additional task of setting up WBTEMP
38062306a36Sopenharmony_ci| is needed so that when the underflow exception handler is entered,
38162306a36Sopenharmony_ci| the user perceives no difference between what the 040 provides vs.
38262306a36Sopenharmony_ci| what the FPSP provides.
38362306a36Sopenharmony_ci|
38462306a36Sopenharmony_cixdnrm_ena:
38562306a36Sopenharmony_ci	movel	%a0,-(%a7)
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	movel	LOCAL_EX(%a0),FP_SCR1(%a6)
38862306a36Sopenharmony_ci	movel	LOCAL_HI(%a0),FP_SCR1+4(%a6)
38962306a36Sopenharmony_ci	movel	LOCAL_LO(%a0),FP_SCR1+8(%a6)
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	lea	FP_SCR1(%a6),%a0
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)
39462306a36Sopenharmony_ci	sne	LOCAL_SGN(%a0)		|convert to internal ext format
39562306a36Sopenharmony_ci	tstw	LOCAL_EX(%a0)		|check if input is denorm
39662306a36Sopenharmony_ci	beqs	xdnrm_dn		|if so, skip nrm_set
39762306a36Sopenharmony_ci	bsr	nrm_set			|normalize the result (exponent
39862306a36Sopenharmony_ci|					;will be negative
39962306a36Sopenharmony_cixdnrm_dn:
40062306a36Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)	|take off false sign
40162306a36Sopenharmony_ci	bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format
40262306a36Sopenharmony_ci	beqs	xdep
40362306a36Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
40462306a36Sopenharmony_cixdep:
40562306a36Sopenharmony_ci	bfclr	STAG(%a6){#5:#3}		|clear wbtm66,wbtm1,wbtm0
40662306a36Sopenharmony_ci	bsetb	#wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
40762306a36Sopenharmony_ci	bclrb	#sticky_bit,STICKY(%a6)	|clear sticky bit
40862306a36Sopenharmony_ci	bclrb	#E1,E_BYTE(%a6)
40962306a36Sopenharmony_ci	movel	(%a7)+,%a0
41062306a36Sopenharmony_cixdnrm_dis:
41162306a36Sopenharmony_ci	bfextu	FPCR_MODE(%a6){#0:#2},%d0	|get round precision
41262306a36Sopenharmony_ci	bnes	not_ext			|if not round extended, store
41362306a36Sopenharmony_ci|					;IEEE defaults
41462306a36Sopenharmony_ciis_ext:
41562306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
41662306a36Sopenharmony_ci	beqs	xdnrm_store
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	bsetb	#neg_bit,FPSR_CC(%a6)	|set N bit in FPSR_CC
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	bras	xdnrm_store
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_cinot_ext:
42362306a36Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)
42462306a36Sopenharmony_ci	sne	LOCAL_SGN(%a0)		|convert to internal ext format
42562306a36Sopenharmony_ci	bsr	unf_sub			|returns IEEE result pointed by
42662306a36Sopenharmony_ci|					;a0; sets FPSR_CC accordingly
42762306a36Sopenharmony_ci	bfclr	LOCAL_SGN(%a0){#0:#8}	|convert back to IEEE ext format
42862306a36Sopenharmony_ci	beqs	xdnrm_store
42962306a36Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
43062306a36Sopenharmony_cixdnrm_store:
43162306a36Sopenharmony_ci	fmovemx (%a0),%fp0-%fp0		|store result in fp0
43262306a36Sopenharmony_ci	rts
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci|
43562306a36Sopenharmony_ci| This subroutine is used for dyadic operations that use an extended
43662306a36Sopenharmony_ci| denorm within the kernel. The approach used is to capture the frame,
43762306a36Sopenharmony_ci| fix/restore.
43862306a36Sopenharmony_ci|
43962306a36Sopenharmony_ci	.global	t_avoid_unsupp
44062306a36Sopenharmony_cit_avoid_unsupp:
44162306a36Sopenharmony_ci	link	%a2,#-LOCAL_SIZE		|so that a2 fpsp.h negative
44262306a36Sopenharmony_ci|					;offsets may be used
44362306a36Sopenharmony_ci	fsave	-(%a7)
44462306a36Sopenharmony_ci	tstb	1(%a7)			|check if idle, exit if so
44562306a36Sopenharmony_ci	beq	idle_end
44662306a36Sopenharmony_ci	btstb	#E1,E_BYTE(%a2)		|check for an E1 exception if
44762306a36Sopenharmony_ci|					;enabled, there is an unsupp
44862306a36Sopenharmony_ci	beq	end_avun		|else, exit
44962306a36Sopenharmony_ci	btstb	#7,DTAG(%a2)		|check for denorm destination
45062306a36Sopenharmony_ci	beqs	src_den			|else, must be a source denorm
45162306a36Sopenharmony_ci|
45262306a36Sopenharmony_ci| handle destination denorm
45362306a36Sopenharmony_ci|
45462306a36Sopenharmony_ci	lea	FPTEMP(%a2),%a0
45562306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
45662306a36Sopenharmony_ci	sne	LOCAL_SGN(%a0)		|convert to internal ext format
45762306a36Sopenharmony_ci	bclrb	#7,DTAG(%a2)		|set DTAG to norm
45862306a36Sopenharmony_ci	bsr	nrm_set			|normalize result, exponent
45962306a36Sopenharmony_ci|					;will become negative
46062306a36Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)	|get rid of fake sign
46162306a36Sopenharmony_ci	bfclr	LOCAL_SGN(%a0){#0:#8}	|convert back to IEEE ext format
46262306a36Sopenharmony_ci	beqs	ck_src_den		|check if source is also denorm
46362306a36Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
46462306a36Sopenharmony_cick_src_den:
46562306a36Sopenharmony_ci	btstb	#7,STAG(%a2)
46662306a36Sopenharmony_ci	beqs	end_avun
46762306a36Sopenharmony_cisrc_den:
46862306a36Sopenharmony_ci	lea	ETEMP(%a2),%a0
46962306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
47062306a36Sopenharmony_ci	sne	LOCAL_SGN(%a0)		|convert to internal ext format
47162306a36Sopenharmony_ci	bclrb	#7,STAG(%a2)		|set STAG to norm
47262306a36Sopenharmony_ci	bsr	nrm_set			|normalize result, exponent
47362306a36Sopenharmony_ci|					;will become negative
47462306a36Sopenharmony_ci	bclrb	#sign_bit,LOCAL_EX(%a0)	|get rid of fake sign
47562306a36Sopenharmony_ci	bfclr	LOCAL_SGN(%a0){#0:#8}	|convert back to IEEE ext format
47662306a36Sopenharmony_ci	beqs	den_com
47762306a36Sopenharmony_ci	bsetb	#sign_bit,LOCAL_EX(%a0)
47862306a36Sopenharmony_ciden_com:
47962306a36Sopenharmony_ci	moveb	#0xfe,CU_SAVEPC(%a2)	|set continue frame
48062306a36Sopenharmony_ci	clrw	NMNEXC(%a2)		|clear NMNEXC
48162306a36Sopenharmony_ci	bclrb	#E1,E_BYTE(%a2)
48262306a36Sopenharmony_ci|	fmove.l	%FPSR,FPSR_SHADOW(%a2)
48362306a36Sopenharmony_ci|	bset.b	#SFLAG,E_BYTE(%a2)
48462306a36Sopenharmony_ci|	bset.b	#XFLAG,T_BYTE(%a2)
48562306a36Sopenharmony_ciend_avun:
48662306a36Sopenharmony_ci	frestore (%a7)+
48762306a36Sopenharmony_ci	unlk	%a2
48862306a36Sopenharmony_ci	rts
48962306a36Sopenharmony_ciidle_end:
49062306a36Sopenharmony_ci	addl	#4,%a7
49162306a36Sopenharmony_ci	unlk	%a2
49262306a36Sopenharmony_ci	rts
49362306a36Sopenharmony_ci	|end
494