18c2ecf20Sopenharmony_ci|
28c2ecf20Sopenharmony_ci|	do_func.sa 3.4 2/18/91
38c2ecf20Sopenharmony_ci|
48c2ecf20Sopenharmony_ci| Do_func performs the unimplemented operation.  The operation
58c2ecf20Sopenharmony_ci| to be performed is determined from the lower 7 bits of the
68c2ecf20Sopenharmony_ci| extension word (except in the case of fmovecr and fsincos).
78c2ecf20Sopenharmony_ci| The opcode and tag bits form an index into a jump table in
88c2ecf20Sopenharmony_ci| tbldo.sa.  Cases of zero, infinity and NaN are handled in
98c2ecf20Sopenharmony_ci| do_func by forcing the default result.  Normalized and
108c2ecf20Sopenharmony_ci| denormalized (there are no unnormalized numbers at this
118c2ecf20Sopenharmony_ci| point) are passed onto the emulation code.
128c2ecf20Sopenharmony_ci|
138c2ecf20Sopenharmony_ci| CMDREG1B and STAG are extracted from the fsave frame
148c2ecf20Sopenharmony_ci| and combined to form the table index.  The function called
158c2ecf20Sopenharmony_ci| will start with a0 pointing to the ETEMP operand.  Dyadic
168c2ecf20Sopenharmony_ci| functions can find FPTEMP at -12(a0).
178c2ecf20Sopenharmony_ci|
188c2ecf20Sopenharmony_ci| Called functions return their result in fp0.  Sincos returns
198c2ecf20Sopenharmony_ci| sin(x) in fp0 and cos(x) in fp1.
208c2ecf20Sopenharmony_ci|
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
238c2ecf20Sopenharmony_ci|			All Rights Reserved
248c2ecf20Sopenharmony_ci|
258c2ecf20Sopenharmony_ci|       For details on the license for this file, please see the
268c2ecf20Sopenharmony_ci|       file, README, in this same directory.
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciDO_FUNC:	|idnt    2,1 | Motorola 040 Floating Point Software Package
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	|section	8
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#include "fpsp.h"
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	|xref	t_dz2
358c2ecf20Sopenharmony_ci	|xref	t_operr
368c2ecf20Sopenharmony_ci	|xref	t_inx2
378c2ecf20Sopenharmony_ci	|xref	t_resdnrm
388c2ecf20Sopenharmony_ci	|xref	dst_nan
398c2ecf20Sopenharmony_ci	|xref	src_nan
408c2ecf20Sopenharmony_ci	|xref	nrm_set
418c2ecf20Sopenharmony_ci	|xref	sto_cos
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	|xref	tblpre
448c2ecf20Sopenharmony_ci	|xref	slognp1,slogn,slog10,slog2
458c2ecf20Sopenharmony_ci	|xref	slognd,slog10d,slog2d
468c2ecf20Sopenharmony_ci	|xref	smod,srem
478c2ecf20Sopenharmony_ci	|xref	sscale
488c2ecf20Sopenharmony_ci	|xref	smovcr
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ciPONE:	.long	0x3fff0000,0x80000000,0x00000000	|+1
518c2ecf20Sopenharmony_ciMONE:	.long	0xbfff0000,0x80000000,0x00000000	|-1
528c2ecf20Sopenharmony_ciPZERO:	.long	0x00000000,0x00000000,0x00000000	|+0
538c2ecf20Sopenharmony_ciMZERO:	.long	0x80000000,0x00000000,0x00000000	|-0
548c2ecf20Sopenharmony_ciPINF:	.long	0x7fff0000,0x00000000,0x00000000	|+inf
558c2ecf20Sopenharmony_ciMINF:	.long	0xffff0000,0x00000000,0x00000000	|-inf
568c2ecf20Sopenharmony_ciQNAN:	.long	0x7fff0000,0xffffffff,0xffffffff	|non-signaling nan
578c2ecf20Sopenharmony_ciPPIBY2:  .long	0x3FFF0000,0xC90FDAA2,0x2168C235	|+PI/2
588c2ecf20Sopenharmony_ciMPIBY2:  .long	0xbFFF0000,0xC90FDAA2,0x2168C235	|-PI/2
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	.global	do_func
618c2ecf20Sopenharmony_cido_func:
628c2ecf20Sopenharmony_ci	clrb	CU_ONLY(%a6)
638c2ecf20Sopenharmony_ci|
648c2ecf20Sopenharmony_ci| Check for fmovecr.  It does not follow the format of fp gen
658c2ecf20Sopenharmony_ci| unimplemented instructions.  The test is on the upper 6 bits;
668c2ecf20Sopenharmony_ci| if they are $17, the inst is fmovecr.  Call entry smovcr
678c2ecf20Sopenharmony_ci| directly.
688c2ecf20Sopenharmony_ci|
698c2ecf20Sopenharmony_ci	bfextu	CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
708c2ecf20Sopenharmony_ci	cmpil	#0x17,%d0		|if op class and size fields are $17,
718c2ecf20Sopenharmony_ci|				;it is FMOVECR; if not, continue
728c2ecf20Sopenharmony_ci	bnes	not_fmovecr
738c2ecf20Sopenharmony_ci	jmp	smovcr		|fmovecr; jmp directly to emulation
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cinot_fmovecr:
768c2ecf20Sopenharmony_ci	movew	CMDREG1B(%a6),%d0
778c2ecf20Sopenharmony_ci	andl	#0x7F,%d0
788c2ecf20Sopenharmony_ci	cmpil	#0x38,%d0		|if the extension is >= $38,
798c2ecf20Sopenharmony_ci	bge	serror		|it is illegal
808c2ecf20Sopenharmony_ci	bfextu	STAG(%a6){#0:#3},%d1
818c2ecf20Sopenharmony_ci	lsll	#3,%d0		|make room for STAG
828c2ecf20Sopenharmony_ci	addl	%d1,%d0		|combine for final index into table
838c2ecf20Sopenharmony_ci	leal	tblpre,%a1	|start of monster jump table
848c2ecf20Sopenharmony_ci	movel	(%a1,%d0.w*4),%a1	|real target address
858c2ecf20Sopenharmony_ci	leal	ETEMP(%a6),%a0	|a0 is pointer to src op
868c2ecf20Sopenharmony_ci	movel	USER_FPCR(%a6),%d1
878c2ecf20Sopenharmony_ci	andl	#0xFF,%d1		| discard all but rounding mode/prec
888c2ecf20Sopenharmony_ci	fmovel	#0,%fpcr
898c2ecf20Sopenharmony_ci	jmp	(%a1)
908c2ecf20Sopenharmony_ci|
918c2ecf20Sopenharmony_ci|	ERROR
928c2ecf20Sopenharmony_ci|
938c2ecf20Sopenharmony_ci	.global	serror
948c2ecf20Sopenharmony_ciserror:
958c2ecf20Sopenharmony_ci	st	STORE_FLG(%a6)
968c2ecf20Sopenharmony_ci	rts
978c2ecf20Sopenharmony_ci|
988c2ecf20Sopenharmony_ci| These routines load forced values into fp0.  They are called
998c2ecf20Sopenharmony_ci| by index into tbldo.
1008c2ecf20Sopenharmony_ci|
1018c2ecf20Sopenharmony_ci| Load a signed zero to fp0 and set inex2/ainex
1028c2ecf20Sopenharmony_ci|
1038c2ecf20Sopenharmony_ci	.global	snzrinx
1048c2ecf20Sopenharmony_cisnzrinx:
1058c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|get sign of source operand
1068c2ecf20Sopenharmony_ci	bnes	ld_mzinx	|if negative, branch
1078c2ecf20Sopenharmony_ci	bsr	ld_pzero	|bsr so we can return and set inx
1088c2ecf20Sopenharmony_ci	bra	t_inx2		|now, set the inx for the next inst
1098c2ecf20Sopenharmony_cild_mzinx:
1108c2ecf20Sopenharmony_ci	bsr	ld_mzero	|if neg, load neg zero, return here
1118c2ecf20Sopenharmony_ci	bra	t_inx2		|now, set the inx for the next inst
1128c2ecf20Sopenharmony_ci|
1138c2ecf20Sopenharmony_ci| Load a signed zero to fp0; do not set inex2/ainex
1148c2ecf20Sopenharmony_ci|
1158c2ecf20Sopenharmony_ci	.global	szero
1168c2ecf20Sopenharmony_ciszero:
1178c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0) |get sign of source operand
1188c2ecf20Sopenharmony_ci	bne	ld_mzero	|if neg, load neg zero
1198c2ecf20Sopenharmony_ci	bra	ld_pzero	|load positive zero
1208c2ecf20Sopenharmony_ci|
1218c2ecf20Sopenharmony_ci| Load a signed infinity to fp0; do not set inex2/ainex
1228c2ecf20Sopenharmony_ci|
1238c2ecf20Sopenharmony_ci	.global	sinf
1248c2ecf20Sopenharmony_cisinf:
1258c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|get sign of source operand
1268c2ecf20Sopenharmony_ci	bne	ld_minf			|if negative branch
1278c2ecf20Sopenharmony_ci	bra	ld_pinf
1288c2ecf20Sopenharmony_ci|
1298c2ecf20Sopenharmony_ci| Load a signed one to fp0; do not set inex2/ainex
1308c2ecf20Sopenharmony_ci|
1318c2ecf20Sopenharmony_ci	.global	sone
1328c2ecf20Sopenharmony_cisone:
1338c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
1348c2ecf20Sopenharmony_ci	bne	ld_mone
1358c2ecf20Sopenharmony_ci	bra	ld_pone
1368c2ecf20Sopenharmony_ci|
1378c2ecf20Sopenharmony_ci| Load a signed pi/2 to fp0; do not set inex2/ainex
1388c2ecf20Sopenharmony_ci|
1398c2ecf20Sopenharmony_ci	.global	spi_2
1408c2ecf20Sopenharmony_cispi_2:
1418c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
1428c2ecf20Sopenharmony_ci	bne	ld_mpi2
1438c2ecf20Sopenharmony_ci	bra	ld_ppi2
1448c2ecf20Sopenharmony_ci|
1458c2ecf20Sopenharmony_ci| Load either a +0 or +inf for plus/minus operand
1468c2ecf20Sopenharmony_ci|
1478c2ecf20Sopenharmony_ci	.global	szr_inf
1488c2ecf20Sopenharmony_ciszr_inf:
1498c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
1508c2ecf20Sopenharmony_ci	bne	ld_pzero
1518c2ecf20Sopenharmony_ci	bra	ld_pinf
1528c2ecf20Sopenharmony_ci|
1538c2ecf20Sopenharmony_ci| Result is either an operr or +inf for plus/minus operand
1548c2ecf20Sopenharmony_ci| [Used by slogn, slognp1, slog10, and slog2]
1558c2ecf20Sopenharmony_ci|
1568c2ecf20Sopenharmony_ci	.global	sopr_inf
1578c2ecf20Sopenharmony_cisopr_inf:
1588c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
1598c2ecf20Sopenharmony_ci	bne	t_operr
1608c2ecf20Sopenharmony_ci	bra	ld_pinf
1618c2ecf20Sopenharmony_ci|
1628c2ecf20Sopenharmony_ci|	FLOGNP1
1638c2ecf20Sopenharmony_ci|
1648c2ecf20Sopenharmony_ci	.global	sslognp1
1658c2ecf20Sopenharmony_cisslognp1:
1668c2ecf20Sopenharmony_ci	fmovemx (%a0),%fp0-%fp0
1678c2ecf20Sopenharmony_ci	fcmpb	#-1,%fp0
1688c2ecf20Sopenharmony_ci	fbgt	slognp1
1698c2ecf20Sopenharmony_ci	fbeq	t_dz2		|if = -1, divide by zero exception
1708c2ecf20Sopenharmony_ci	fmovel	#0,%FPSR		|clr N flag
1718c2ecf20Sopenharmony_ci	bra	t_operr		|take care of operands < -1
1728c2ecf20Sopenharmony_ci|
1738c2ecf20Sopenharmony_ci|	FETOXM1
1748c2ecf20Sopenharmony_ci|
1758c2ecf20Sopenharmony_ci	.global	setoxm1i
1768c2ecf20Sopenharmony_cisetoxm1i:
1778c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
1788c2ecf20Sopenharmony_ci	bne	ld_mone
1798c2ecf20Sopenharmony_ci	bra	ld_pinf
1808c2ecf20Sopenharmony_ci|
1818c2ecf20Sopenharmony_ci|	FLOGN
1828c2ecf20Sopenharmony_ci|
1838c2ecf20Sopenharmony_ci| Test for 1.0 as an input argument, returning +zero.  Also check
1848c2ecf20Sopenharmony_ci| the sign and return operr if negative.
1858c2ecf20Sopenharmony_ci|
1868c2ecf20Sopenharmony_ci	.global	sslogn
1878c2ecf20Sopenharmony_cisslogn:
1888c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
1898c2ecf20Sopenharmony_ci	bne	t_operr		|take care of operands < 0
1908c2ecf20Sopenharmony_ci	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
1918c2ecf20Sopenharmony_ci	bne	slogn
1928c2ecf20Sopenharmony_ci	cmpil	#0x80000000,LOCAL_HI(%a0)
1938c2ecf20Sopenharmony_ci	bne	slogn
1948c2ecf20Sopenharmony_ci	tstl	LOCAL_LO(%a0)
1958c2ecf20Sopenharmony_ci	bne	slogn
1968c2ecf20Sopenharmony_ci	fmovex	PZERO,%fp0
1978c2ecf20Sopenharmony_ci	rts
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	.global	sslognd
2008c2ecf20Sopenharmony_cisslognd:
2018c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
2028c2ecf20Sopenharmony_ci	beq	slognd
2038c2ecf20Sopenharmony_ci	bra	t_operr		|take care of operands < 0
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci|
2068c2ecf20Sopenharmony_ci|	FLOG10
2078c2ecf20Sopenharmony_ci|
2088c2ecf20Sopenharmony_ci	.global	sslog10
2098c2ecf20Sopenharmony_cisslog10:
2108c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
2118c2ecf20Sopenharmony_ci	bne	t_operr		|take care of operands < 0
2128c2ecf20Sopenharmony_ci	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
2138c2ecf20Sopenharmony_ci	bne	slog10
2148c2ecf20Sopenharmony_ci	cmpil	#0x80000000,LOCAL_HI(%a0)
2158c2ecf20Sopenharmony_ci	bne	slog10
2168c2ecf20Sopenharmony_ci	tstl	LOCAL_LO(%a0)
2178c2ecf20Sopenharmony_ci	bne	slog10
2188c2ecf20Sopenharmony_ci	fmovex	PZERO,%fp0
2198c2ecf20Sopenharmony_ci	rts
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	.global	sslog10d
2228c2ecf20Sopenharmony_cisslog10d:
2238c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
2248c2ecf20Sopenharmony_ci	beq	slog10d
2258c2ecf20Sopenharmony_ci	bra	t_operr		|take care of operands < 0
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci|
2288c2ecf20Sopenharmony_ci|	FLOG2
2298c2ecf20Sopenharmony_ci|
2308c2ecf20Sopenharmony_ci	.global	sslog2
2318c2ecf20Sopenharmony_cisslog2:
2328c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
2338c2ecf20Sopenharmony_ci	bne	t_operr		|take care of operands < 0
2348c2ecf20Sopenharmony_ci	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
2358c2ecf20Sopenharmony_ci	bne	slog2
2368c2ecf20Sopenharmony_ci	cmpil	#0x80000000,LOCAL_HI(%a0)
2378c2ecf20Sopenharmony_ci	bne	slog2
2388c2ecf20Sopenharmony_ci	tstl	LOCAL_LO(%a0)
2398c2ecf20Sopenharmony_ci	bne	slog2
2408c2ecf20Sopenharmony_ci	fmovex	PZERO,%fp0
2418c2ecf20Sopenharmony_ci	rts
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	.global	sslog2d
2448c2ecf20Sopenharmony_cisslog2d:
2458c2ecf20Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
2468c2ecf20Sopenharmony_ci	beq	slog2d
2478c2ecf20Sopenharmony_ci	bra	t_operr		|take care of operands < 0
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci|
2508c2ecf20Sopenharmony_ci|	FMOD
2518c2ecf20Sopenharmony_ci|
2528c2ecf20Sopenharmony_cipmodt:
2538c2ecf20Sopenharmony_ci|				;$21 fmod
2548c2ecf20Sopenharmony_ci|				;dtag,stag
2558c2ecf20Sopenharmony_ci	.long	smod		|  00,00  norm,norm = normal
2568c2ecf20Sopenharmony_ci	.long	smod_oper	|  00,01  norm,zero = nan with operr
2578c2ecf20Sopenharmony_ci	.long	smod_fpn	|  00,10  norm,inf  = fpn
2588c2ecf20Sopenharmony_ci	.long	smod_snan	|  00,11  norm,nan  = nan
2598c2ecf20Sopenharmony_ci	.long	smod_zro	|  01,00  zero,norm = +-zero
2608c2ecf20Sopenharmony_ci	.long	smod_oper	|  01,01  zero,zero = nan with operr
2618c2ecf20Sopenharmony_ci	.long	smod_zro	|  01,10  zero,inf  = +-zero
2628c2ecf20Sopenharmony_ci	.long	smod_snan	|  01,11  zero,nan  = nan
2638c2ecf20Sopenharmony_ci	.long	smod_oper	|  10,00  inf,norm  = nan with operr
2648c2ecf20Sopenharmony_ci	.long	smod_oper	|  10,01  inf,zero  = nan with operr
2658c2ecf20Sopenharmony_ci	.long	smod_oper	|  10,10  inf,inf   = nan with operr
2668c2ecf20Sopenharmony_ci	.long	smod_snan	|  10,11  inf,nan   = nan
2678c2ecf20Sopenharmony_ci	.long	smod_dnan	|  11,00  nan,norm  = nan
2688c2ecf20Sopenharmony_ci	.long	smod_dnan	|  11,01  nan,zero  = nan
2698c2ecf20Sopenharmony_ci	.long	smod_dnan	|  11,10  nan,inf   = nan
2708c2ecf20Sopenharmony_ci	.long	smod_dnan	|  11,11  nan,nan   = nan
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	.global	pmod
2738c2ecf20Sopenharmony_cipmod:
2748c2ecf20Sopenharmony_ci	clrb	FPSR_QBYTE(%a6) | clear quotient field
2758c2ecf20Sopenharmony_ci	bfextu	STAG(%a6){#0:#3},%d0 |stag = d0
2768c2ecf20Sopenharmony_ci	bfextu	DTAG(%a6){#0:#3},%d1 |dtag = d1
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci|
2798c2ecf20Sopenharmony_ci| Alias extended denorms to norms for the jump table.
2808c2ecf20Sopenharmony_ci|
2818c2ecf20Sopenharmony_ci	bclrl	#2,%d0
2828c2ecf20Sopenharmony_ci	bclrl	#2,%d1
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	lslb	#2,%d1
2858c2ecf20Sopenharmony_ci	orb	%d0,%d1		|d1{3:2} = dtag, d1{1:0} = stag
2868c2ecf20Sopenharmony_ci|				;Tag values:
2878c2ecf20Sopenharmony_ci|				;00 = norm or denorm
2888c2ecf20Sopenharmony_ci|				;01 = zero
2898c2ecf20Sopenharmony_ci|				;10 = inf
2908c2ecf20Sopenharmony_ci|				;11 = nan
2918c2ecf20Sopenharmony_ci	lea	pmodt,%a1
2928c2ecf20Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1
2938c2ecf20Sopenharmony_ci	jmp	(%a1)
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cismod_snan:
2968c2ecf20Sopenharmony_ci	bra	src_nan
2978c2ecf20Sopenharmony_cismod_dnan:
2988c2ecf20Sopenharmony_ci	bra	dst_nan
2998c2ecf20Sopenharmony_cismod_oper:
3008c2ecf20Sopenharmony_ci	bra	t_operr
3018c2ecf20Sopenharmony_cismod_zro:
3028c2ecf20Sopenharmony_ci	moveb	ETEMP(%a6),%d1	|get sign of src op
3038c2ecf20Sopenharmony_ci	moveb	FPTEMP(%a6),%d0	|get sign of dst op
3048c2ecf20Sopenharmony_ci	eorb	%d0,%d1		|get exor of sign bits
3058c2ecf20Sopenharmony_ci	btstl	#7,%d1		|test for sign
3068c2ecf20Sopenharmony_ci	beqs	smod_zsn	|if clr, do not set sign big
3078c2ecf20Sopenharmony_ci	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
3088c2ecf20Sopenharmony_cismod_zsn:
3098c2ecf20Sopenharmony_ci	btstl	#7,%d0		|test if + or -
3108c2ecf20Sopenharmony_ci	beq	ld_pzero	|if pos then load +0
3118c2ecf20Sopenharmony_ci	bra	ld_mzero	|else neg load -0
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_cismod_fpn:
3148c2ecf20Sopenharmony_ci	moveb	ETEMP(%a6),%d1	|get sign of src op
3158c2ecf20Sopenharmony_ci	moveb	FPTEMP(%a6),%d0	|get sign of dst op
3168c2ecf20Sopenharmony_ci	eorb	%d0,%d1		|get exor of sign bits
3178c2ecf20Sopenharmony_ci	btstl	#7,%d1		|test for sign
3188c2ecf20Sopenharmony_ci	beqs	smod_fsn	|if clr, do not set sign big
3198c2ecf20Sopenharmony_ci	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
3208c2ecf20Sopenharmony_cismod_fsn:
3218c2ecf20Sopenharmony_ci	tstb	DTAG(%a6)	|filter out denormal destination case
3228c2ecf20Sopenharmony_ci	bpls	smod_nrm	|
3238c2ecf20Sopenharmony_ci	leal	FPTEMP(%a6),%a0	|a0<- addr(FPTEMP)
3248c2ecf20Sopenharmony_ci	bra	t_resdnrm	|force UNFL(but exact) result
3258c2ecf20Sopenharmony_cismod_nrm:
3268c2ecf20Sopenharmony_ci	fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
3278c2ecf20Sopenharmony_ci	fmovex FPTEMP(%a6),%fp0	|return dest to fp0
3288c2ecf20Sopenharmony_ci	rts
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci|
3318c2ecf20Sopenharmony_ci|	FREM
3328c2ecf20Sopenharmony_ci|
3338c2ecf20Sopenharmony_cipremt:
3348c2ecf20Sopenharmony_ci|				;$25 frem
3358c2ecf20Sopenharmony_ci|				;dtag,stag
3368c2ecf20Sopenharmony_ci	.long	srem		|  00,00  norm,norm = normal
3378c2ecf20Sopenharmony_ci	.long	srem_oper	|  00,01  norm,zero = nan with operr
3388c2ecf20Sopenharmony_ci	.long	srem_fpn	|  00,10  norm,inf  = fpn
3398c2ecf20Sopenharmony_ci	.long	srem_snan	|  00,11  norm,nan  = nan
3408c2ecf20Sopenharmony_ci	.long	srem_zro	|  01,00  zero,norm = +-zero
3418c2ecf20Sopenharmony_ci	.long	srem_oper	|  01,01  zero,zero = nan with operr
3428c2ecf20Sopenharmony_ci	.long	srem_zro	|  01,10  zero,inf  = +-zero
3438c2ecf20Sopenharmony_ci	.long	srem_snan	|  01,11  zero,nan  = nan
3448c2ecf20Sopenharmony_ci	.long	srem_oper	|  10,00  inf,norm  = nan with operr
3458c2ecf20Sopenharmony_ci	.long	srem_oper	|  10,01  inf,zero  = nan with operr
3468c2ecf20Sopenharmony_ci	.long	srem_oper	|  10,10  inf,inf   = nan with operr
3478c2ecf20Sopenharmony_ci	.long	srem_snan	|  10,11  inf,nan   = nan
3488c2ecf20Sopenharmony_ci	.long	srem_dnan	|  11,00  nan,norm  = nan
3498c2ecf20Sopenharmony_ci	.long	srem_dnan	|  11,01  nan,zero  = nan
3508c2ecf20Sopenharmony_ci	.long	srem_dnan	|  11,10  nan,inf   = nan
3518c2ecf20Sopenharmony_ci	.long	srem_dnan	|  11,11  nan,nan   = nan
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	.global	prem
3548c2ecf20Sopenharmony_ciprem:
3558c2ecf20Sopenharmony_ci	clrb	FPSR_QBYTE(%a6)   |clear quotient field
3568c2ecf20Sopenharmony_ci	bfextu	STAG(%a6){#0:#3},%d0 |stag = d0
3578c2ecf20Sopenharmony_ci	bfextu	DTAG(%a6){#0:#3},%d1 |dtag = d1
3588c2ecf20Sopenharmony_ci|
3598c2ecf20Sopenharmony_ci| Alias extended denorms to norms for the jump table.
3608c2ecf20Sopenharmony_ci|
3618c2ecf20Sopenharmony_ci	bclr	#2,%d0
3628c2ecf20Sopenharmony_ci	bclr	#2,%d1
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	lslb	#2,%d1
3658c2ecf20Sopenharmony_ci	orb	%d0,%d1		|d1{3:2} = dtag, d1{1:0} = stag
3668c2ecf20Sopenharmony_ci|				;Tag values:
3678c2ecf20Sopenharmony_ci|				;00 = norm or denorm
3688c2ecf20Sopenharmony_ci|				;01 = zero
3698c2ecf20Sopenharmony_ci|				;10 = inf
3708c2ecf20Sopenharmony_ci|				;11 = nan
3718c2ecf20Sopenharmony_ci	lea	premt,%a1
3728c2ecf20Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1
3738c2ecf20Sopenharmony_ci	jmp	(%a1)
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_cisrem_snan:
3768c2ecf20Sopenharmony_ci	bra	src_nan
3778c2ecf20Sopenharmony_cisrem_dnan:
3788c2ecf20Sopenharmony_ci	bra	dst_nan
3798c2ecf20Sopenharmony_cisrem_oper:
3808c2ecf20Sopenharmony_ci	bra	t_operr
3818c2ecf20Sopenharmony_cisrem_zro:
3828c2ecf20Sopenharmony_ci	moveb	ETEMP(%a6),%d1	|get sign of src op
3838c2ecf20Sopenharmony_ci	moveb	FPTEMP(%a6),%d0	|get sign of dst op
3848c2ecf20Sopenharmony_ci	eorb	%d0,%d1		|get exor of sign bits
3858c2ecf20Sopenharmony_ci	btstl	#7,%d1		|test for sign
3868c2ecf20Sopenharmony_ci	beqs	srem_zsn	|if clr, do not set sign big
3878c2ecf20Sopenharmony_ci	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
3888c2ecf20Sopenharmony_cisrem_zsn:
3898c2ecf20Sopenharmony_ci	btstl	#7,%d0		|test if + or -
3908c2ecf20Sopenharmony_ci	beq	ld_pzero	|if pos then load +0
3918c2ecf20Sopenharmony_ci	bra	ld_mzero	|else neg load -0
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_cisrem_fpn:
3948c2ecf20Sopenharmony_ci	moveb	ETEMP(%a6),%d1	|get sign of src op
3958c2ecf20Sopenharmony_ci	moveb	FPTEMP(%a6),%d0	|get sign of dst op
3968c2ecf20Sopenharmony_ci	eorb	%d0,%d1		|get exor of sign bits
3978c2ecf20Sopenharmony_ci	btstl	#7,%d1		|test for sign
3988c2ecf20Sopenharmony_ci	beqs	srem_fsn	|if clr, do not set sign big
3998c2ecf20Sopenharmony_ci	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
4008c2ecf20Sopenharmony_cisrem_fsn:
4018c2ecf20Sopenharmony_ci	tstb	DTAG(%a6)	|filter out denormal destination case
4028c2ecf20Sopenharmony_ci	bpls	srem_nrm	|
4038c2ecf20Sopenharmony_ci	leal	FPTEMP(%a6),%a0	|a0<- addr(FPTEMP)
4048c2ecf20Sopenharmony_ci	bra	t_resdnrm	|force UNFL(but exact) result
4058c2ecf20Sopenharmony_cisrem_nrm:
4068c2ecf20Sopenharmony_ci	fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
4078c2ecf20Sopenharmony_ci	fmovex FPTEMP(%a6),%fp0	|return dest to fp0
4088c2ecf20Sopenharmony_ci	rts
4098c2ecf20Sopenharmony_ci|
4108c2ecf20Sopenharmony_ci|	FSCALE
4118c2ecf20Sopenharmony_ci|
4128c2ecf20Sopenharmony_cipscalet:
4138c2ecf20Sopenharmony_ci|				;$26 fscale
4148c2ecf20Sopenharmony_ci|				;dtag,stag
4158c2ecf20Sopenharmony_ci	.long	sscale		|  00,00  norm,norm = result
4168c2ecf20Sopenharmony_ci	.long	sscale		|  00,01  norm,zero = fpn
4178c2ecf20Sopenharmony_ci	.long	scl_opr		|  00,10  norm,inf  = nan with operr
4188c2ecf20Sopenharmony_ci	.long	scl_snan	|  00,11  norm,nan  = nan
4198c2ecf20Sopenharmony_ci	.long	scl_zro		|  01,00  zero,norm = +-zero
4208c2ecf20Sopenharmony_ci	.long	scl_zro		|  01,01  zero,zero = +-zero
4218c2ecf20Sopenharmony_ci	.long	scl_opr		|  01,10  zero,inf  = nan with operr
4228c2ecf20Sopenharmony_ci	.long	scl_snan	|  01,11  zero,nan  = nan
4238c2ecf20Sopenharmony_ci	.long	scl_inf		|  10,00  inf,norm  = +-inf
4248c2ecf20Sopenharmony_ci	.long	scl_inf		|  10,01  inf,zero  = +-inf
4258c2ecf20Sopenharmony_ci	.long	scl_opr		|  10,10  inf,inf   = nan with operr
4268c2ecf20Sopenharmony_ci	.long	scl_snan	|  10,11  inf,nan   = nan
4278c2ecf20Sopenharmony_ci	.long	scl_dnan	|  11,00  nan,norm  = nan
4288c2ecf20Sopenharmony_ci	.long	scl_dnan	|  11,01  nan,zero  = nan
4298c2ecf20Sopenharmony_ci	.long	scl_dnan	|  11,10  nan,inf   = nan
4308c2ecf20Sopenharmony_ci	.long	scl_dnan	|  11,11  nan,nan   = nan
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	.global	pscale
4338c2ecf20Sopenharmony_cipscale:
4348c2ecf20Sopenharmony_ci	bfextu	STAG(%a6){#0:#3},%d0 |stag in d0
4358c2ecf20Sopenharmony_ci	bfextu	DTAG(%a6){#0:#3},%d1 |dtag in d1
4368c2ecf20Sopenharmony_ci	bclrl	#2,%d0		|alias  denorm into norm
4378c2ecf20Sopenharmony_ci	bclrl	#2,%d1		|alias  denorm into norm
4388c2ecf20Sopenharmony_ci	lslb	#2,%d1
4398c2ecf20Sopenharmony_ci	orb	%d0,%d1		|d1{4:2} = dtag, d1{1:0} = stag
4408c2ecf20Sopenharmony_ci|				;dtag values     stag values:
4418c2ecf20Sopenharmony_ci|				;000 = norm      00 = norm
4428c2ecf20Sopenharmony_ci|				;001 = zero	 01 = zero
4438c2ecf20Sopenharmony_ci|				;010 = inf	 10 = inf
4448c2ecf20Sopenharmony_ci|				;011 = nan	 11 = nan
4458c2ecf20Sopenharmony_ci|				;100 = dnrm
4468c2ecf20Sopenharmony_ci|
4478c2ecf20Sopenharmony_ci|
4488c2ecf20Sopenharmony_ci	leal	pscalet,%a1	|load start of jump table
4498c2ecf20Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1	|load a1 with label depending on tag
4508c2ecf20Sopenharmony_ci	jmp	(%a1)		|go to the routine
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ciscl_opr:
4538c2ecf20Sopenharmony_ci	bra	t_operr
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ciscl_dnan:
4568c2ecf20Sopenharmony_ci	bra	dst_nan
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ciscl_zro:
4598c2ecf20Sopenharmony_ci	btstb	#sign_bit,FPTEMP_EX(%a6)	|test if + or -
4608c2ecf20Sopenharmony_ci	beq	ld_pzero		|if pos then load +0
4618c2ecf20Sopenharmony_ci	bra	ld_mzero		|if neg then load -0
4628c2ecf20Sopenharmony_ciscl_inf:
4638c2ecf20Sopenharmony_ci	btstb	#sign_bit,FPTEMP_EX(%a6)	|test if + or -
4648c2ecf20Sopenharmony_ci	beq	ld_pinf			|if pos then load +inf
4658c2ecf20Sopenharmony_ci	bra	ld_minf			|else neg load -inf
4668c2ecf20Sopenharmony_ciscl_snan:
4678c2ecf20Sopenharmony_ci	bra	src_nan
4688c2ecf20Sopenharmony_ci|
4698c2ecf20Sopenharmony_ci|	FSINCOS
4708c2ecf20Sopenharmony_ci|
4718c2ecf20Sopenharmony_ci	.global	ssincosz
4728c2ecf20Sopenharmony_cissincosz:
4738c2ecf20Sopenharmony_ci	btstb	#sign_bit,ETEMP(%a6)	|get sign
4748c2ecf20Sopenharmony_ci	beqs	sincosp
4758c2ecf20Sopenharmony_ci	fmovex	MZERO,%fp0
4768c2ecf20Sopenharmony_ci	bras	sincoscom
4778c2ecf20Sopenharmony_cisincosp:
4788c2ecf20Sopenharmony_ci	fmovex PZERO,%fp0
4798c2ecf20Sopenharmony_cisincoscom:
4808c2ecf20Sopenharmony_ci	fmovemx PONE,%fp1-%fp1	|do not allow FPSR to be affected
4818c2ecf20Sopenharmony_ci	bra	sto_cos		|store cosine result
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	.global	ssincosi
4848c2ecf20Sopenharmony_cissincosi:
4858c2ecf20Sopenharmony_ci	fmovex QNAN,%fp1	|load NAN
4868c2ecf20Sopenharmony_ci	bsr	sto_cos		|store cosine result
4878c2ecf20Sopenharmony_ci	fmovex QNAN,%fp0	|load NAN
4888c2ecf20Sopenharmony_ci	bra	t_operr
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	.global	ssincosnan
4918c2ecf20Sopenharmony_cissincosnan:
4928c2ecf20Sopenharmony_ci	movel	ETEMP_EX(%a6),FP_SCR1(%a6)
4938c2ecf20Sopenharmony_ci	movel	ETEMP_HI(%a6),FP_SCR1+4(%a6)
4948c2ecf20Sopenharmony_ci	movel	ETEMP_LO(%a6),FP_SCR1+8(%a6)
4958c2ecf20Sopenharmony_ci	bsetb	#signan_bit,FP_SCR1+4(%a6)
4968c2ecf20Sopenharmony_ci	fmovemx FP_SCR1(%a6),%fp1-%fp1
4978c2ecf20Sopenharmony_ci	bsr	sto_cos
4988c2ecf20Sopenharmony_ci	bra	src_nan
4998c2ecf20Sopenharmony_ci|
5008c2ecf20Sopenharmony_ci| This code forces default values for the zero, inf, and nan cases
5018c2ecf20Sopenharmony_ci| in the transcendentals code.  The CC bits must be set in the
5028c2ecf20Sopenharmony_ci| stacked FPSR to be correctly reported.
5038c2ecf20Sopenharmony_ci|
5048c2ecf20Sopenharmony_ci|**Returns +PI/2
5058c2ecf20Sopenharmony_ci	.global	ld_ppi2
5068c2ecf20Sopenharmony_cild_ppi2:
5078c2ecf20Sopenharmony_ci	fmovex PPIBY2,%fp0		|load +pi/2
5088c2ecf20Sopenharmony_ci	bra	t_inx2			|set inex2 exc
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci|**Returns -PI/2
5118c2ecf20Sopenharmony_ci	.global	ld_mpi2
5128c2ecf20Sopenharmony_cild_mpi2:
5138c2ecf20Sopenharmony_ci	fmovex MPIBY2,%fp0		|load -pi/2
5148c2ecf20Sopenharmony_ci	orl	#neg_mask,USER_FPSR(%a6)	|set N bit
5158c2ecf20Sopenharmony_ci	bra	t_inx2			|set inex2 exc
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci|**Returns +inf
5188c2ecf20Sopenharmony_ci	.global	ld_pinf
5198c2ecf20Sopenharmony_cild_pinf:
5208c2ecf20Sopenharmony_ci	fmovex PINF,%fp0		|load +inf
5218c2ecf20Sopenharmony_ci	orl	#inf_mask,USER_FPSR(%a6)	|set I bit
5228c2ecf20Sopenharmony_ci	rts
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci|**Returns -inf
5258c2ecf20Sopenharmony_ci	.global	ld_minf
5268c2ecf20Sopenharmony_cild_minf:
5278c2ecf20Sopenharmony_ci	fmovex MINF,%fp0		|load -inf
5288c2ecf20Sopenharmony_ci	orl	#neg_mask+inf_mask,USER_FPSR(%a6)	|set N and I bits
5298c2ecf20Sopenharmony_ci	rts
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci|**Returns +1
5328c2ecf20Sopenharmony_ci	.global	ld_pone
5338c2ecf20Sopenharmony_cild_pone:
5348c2ecf20Sopenharmony_ci	fmovex PONE,%fp0		|load +1
5358c2ecf20Sopenharmony_ci	rts
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci|**Returns -1
5388c2ecf20Sopenharmony_ci	.global	ld_mone
5398c2ecf20Sopenharmony_cild_mone:
5408c2ecf20Sopenharmony_ci	fmovex MONE,%fp0		|load -1
5418c2ecf20Sopenharmony_ci	orl	#neg_mask,USER_FPSR(%a6)	|set N bit
5428c2ecf20Sopenharmony_ci	rts
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci|**Returns +0
5458c2ecf20Sopenharmony_ci	.global	ld_pzero
5468c2ecf20Sopenharmony_cild_pzero:
5478c2ecf20Sopenharmony_ci	fmovex PZERO,%fp0		|load +0
5488c2ecf20Sopenharmony_ci	orl	#z_mask,USER_FPSR(%a6)	|set Z bit
5498c2ecf20Sopenharmony_ci	rts
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci|**Returns -0
5528c2ecf20Sopenharmony_ci	.global	ld_mzero
5538c2ecf20Sopenharmony_cild_mzero:
5548c2ecf20Sopenharmony_ci	fmovex MZERO,%fp0		|load -0
5558c2ecf20Sopenharmony_ci	orl	#neg_mask+z_mask,USER_FPSR(%a6)	|set N and Z bits
5568c2ecf20Sopenharmony_ci	rts
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	|end
559