162306a36Sopenharmony_ci|
262306a36Sopenharmony_ci|	do_func.sa 3.4 2/18/91
362306a36Sopenharmony_ci|
462306a36Sopenharmony_ci| Do_func performs the unimplemented operation.  The operation
562306a36Sopenharmony_ci| to be performed is determined from the lower 7 bits of the
662306a36Sopenharmony_ci| extension word (except in the case of fmovecr and fsincos).
762306a36Sopenharmony_ci| The opcode and tag bits form an index into a jump table in
862306a36Sopenharmony_ci| tbldo.sa.  Cases of zero, infinity and NaN are handled in
962306a36Sopenharmony_ci| do_func by forcing the default result.  Normalized and
1062306a36Sopenharmony_ci| denormalized (there are no unnormalized numbers at this
1162306a36Sopenharmony_ci| point) are passed onto the emulation code.
1262306a36Sopenharmony_ci|
1362306a36Sopenharmony_ci| CMDREG1B and STAG are extracted from the fsave frame
1462306a36Sopenharmony_ci| and combined to form the table index.  The function called
1562306a36Sopenharmony_ci| will start with a0 pointing to the ETEMP operand.  Dyadic
1662306a36Sopenharmony_ci| functions can find FPTEMP at -12(a0).
1762306a36Sopenharmony_ci|
1862306a36Sopenharmony_ci| Called functions return their result in fp0.  Sincos returns
1962306a36Sopenharmony_ci| sin(x) in fp0 and cos(x) in fp1.
2062306a36Sopenharmony_ci|
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci|		Copyright (C) Motorola, Inc. 1990
2362306a36Sopenharmony_ci|			All Rights Reserved
2462306a36Sopenharmony_ci|
2562306a36Sopenharmony_ci|       For details on the license for this file, please see the
2662306a36Sopenharmony_ci|       file, README, in this same directory.
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ciDO_FUNC:	|idnt    2,1 | Motorola 040 Floating Point Software Package
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	|section	8
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#include "fpsp.h"
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	|xref	t_dz2
3562306a36Sopenharmony_ci	|xref	t_operr
3662306a36Sopenharmony_ci	|xref	t_inx2
3762306a36Sopenharmony_ci	|xref	t_resdnrm
3862306a36Sopenharmony_ci	|xref	dst_nan
3962306a36Sopenharmony_ci	|xref	src_nan
4062306a36Sopenharmony_ci	|xref	nrm_set
4162306a36Sopenharmony_ci	|xref	sto_cos
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	|xref	tblpre
4462306a36Sopenharmony_ci	|xref	slognp1,slogn,slog10,slog2
4562306a36Sopenharmony_ci	|xref	slognd,slog10d,slog2d
4662306a36Sopenharmony_ci	|xref	smod,srem
4762306a36Sopenharmony_ci	|xref	sscale
4862306a36Sopenharmony_ci	|xref	smovcr
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ciPONE:	.long	0x3fff0000,0x80000000,0x00000000	|+1
5162306a36Sopenharmony_ciMONE:	.long	0xbfff0000,0x80000000,0x00000000	|-1
5262306a36Sopenharmony_ciPZERO:	.long	0x00000000,0x00000000,0x00000000	|+0
5362306a36Sopenharmony_ciMZERO:	.long	0x80000000,0x00000000,0x00000000	|-0
5462306a36Sopenharmony_ciPINF:	.long	0x7fff0000,0x00000000,0x00000000	|+inf
5562306a36Sopenharmony_ciMINF:	.long	0xffff0000,0x00000000,0x00000000	|-inf
5662306a36Sopenharmony_ciQNAN:	.long	0x7fff0000,0xffffffff,0xffffffff	|non-signaling nan
5762306a36Sopenharmony_ciPPIBY2:  .long	0x3FFF0000,0xC90FDAA2,0x2168C235	|+PI/2
5862306a36Sopenharmony_ciMPIBY2:  .long	0xbFFF0000,0xC90FDAA2,0x2168C235	|-PI/2
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	.global	do_func
6162306a36Sopenharmony_cido_func:
6262306a36Sopenharmony_ci	clrb	CU_ONLY(%a6)
6362306a36Sopenharmony_ci|
6462306a36Sopenharmony_ci| Check for fmovecr.  It does not follow the format of fp gen
6562306a36Sopenharmony_ci| unimplemented instructions.  The test is on the upper 6 bits;
6662306a36Sopenharmony_ci| if they are $17, the inst is fmovecr.  Call entry smovcr
6762306a36Sopenharmony_ci| directly.
6862306a36Sopenharmony_ci|
6962306a36Sopenharmony_ci	bfextu	CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
7062306a36Sopenharmony_ci	cmpil	#0x17,%d0		|if op class and size fields are $17,
7162306a36Sopenharmony_ci|				;it is FMOVECR; if not, continue
7262306a36Sopenharmony_ci	bnes	not_fmovecr
7362306a36Sopenharmony_ci	jmp	smovcr		|fmovecr; jmp directly to emulation
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cinot_fmovecr:
7662306a36Sopenharmony_ci	movew	CMDREG1B(%a6),%d0
7762306a36Sopenharmony_ci	andl	#0x7F,%d0
7862306a36Sopenharmony_ci	cmpil	#0x38,%d0		|if the extension is >= $38,
7962306a36Sopenharmony_ci	bge	serror		|it is illegal
8062306a36Sopenharmony_ci	bfextu	STAG(%a6){#0:#3},%d1
8162306a36Sopenharmony_ci	lsll	#3,%d0		|make room for STAG
8262306a36Sopenharmony_ci	addl	%d1,%d0		|combine for final index into table
8362306a36Sopenharmony_ci	leal	tblpre,%a1	|start of monster jump table
8462306a36Sopenharmony_ci	movel	(%a1,%d0.w*4),%a1	|real target address
8562306a36Sopenharmony_ci	leal	ETEMP(%a6),%a0	|a0 is pointer to src op
8662306a36Sopenharmony_ci	movel	USER_FPCR(%a6),%d1
8762306a36Sopenharmony_ci	andl	#0xFF,%d1		| discard all but rounding mode/prec
8862306a36Sopenharmony_ci	fmovel	#0,%fpcr
8962306a36Sopenharmony_ci	jmp	(%a1)
9062306a36Sopenharmony_ci|
9162306a36Sopenharmony_ci|	ERROR
9262306a36Sopenharmony_ci|
9362306a36Sopenharmony_ci	.global	serror
9462306a36Sopenharmony_ciserror:
9562306a36Sopenharmony_ci	st	STORE_FLG(%a6)
9662306a36Sopenharmony_ci	rts
9762306a36Sopenharmony_ci|
9862306a36Sopenharmony_ci| These routines load forced values into fp0.  They are called
9962306a36Sopenharmony_ci| by index into tbldo.
10062306a36Sopenharmony_ci|
10162306a36Sopenharmony_ci| Load a signed zero to fp0 and set inex2/ainex
10262306a36Sopenharmony_ci|
10362306a36Sopenharmony_ci	.global	snzrinx
10462306a36Sopenharmony_cisnzrinx:
10562306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|get sign of source operand
10662306a36Sopenharmony_ci	bnes	ld_mzinx	|if negative, branch
10762306a36Sopenharmony_ci	bsr	ld_pzero	|bsr so we can return and set inx
10862306a36Sopenharmony_ci	bra	t_inx2		|now, set the inx for the next inst
10962306a36Sopenharmony_cild_mzinx:
11062306a36Sopenharmony_ci	bsr	ld_mzero	|if neg, load neg zero, return here
11162306a36Sopenharmony_ci	bra	t_inx2		|now, set the inx for the next inst
11262306a36Sopenharmony_ci|
11362306a36Sopenharmony_ci| Load a signed zero to fp0; do not set inex2/ainex
11462306a36Sopenharmony_ci|
11562306a36Sopenharmony_ci	.global	szero
11662306a36Sopenharmony_ciszero:
11762306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0) |get sign of source operand
11862306a36Sopenharmony_ci	bne	ld_mzero	|if neg, load neg zero
11962306a36Sopenharmony_ci	bra	ld_pzero	|load positive zero
12062306a36Sopenharmony_ci|
12162306a36Sopenharmony_ci| Load a signed infinity to fp0; do not set inex2/ainex
12262306a36Sopenharmony_ci|
12362306a36Sopenharmony_ci	.global	sinf
12462306a36Sopenharmony_cisinf:
12562306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|get sign of source operand
12662306a36Sopenharmony_ci	bne	ld_minf			|if negative branch
12762306a36Sopenharmony_ci	bra	ld_pinf
12862306a36Sopenharmony_ci|
12962306a36Sopenharmony_ci| Load a signed one to fp0; do not set inex2/ainex
13062306a36Sopenharmony_ci|
13162306a36Sopenharmony_ci	.global	sone
13262306a36Sopenharmony_cisone:
13362306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
13462306a36Sopenharmony_ci	bne	ld_mone
13562306a36Sopenharmony_ci	bra	ld_pone
13662306a36Sopenharmony_ci|
13762306a36Sopenharmony_ci| Load a signed pi/2 to fp0; do not set inex2/ainex
13862306a36Sopenharmony_ci|
13962306a36Sopenharmony_ci	.global	spi_2
14062306a36Sopenharmony_cispi_2:
14162306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
14262306a36Sopenharmony_ci	bne	ld_mpi2
14362306a36Sopenharmony_ci	bra	ld_ppi2
14462306a36Sopenharmony_ci|
14562306a36Sopenharmony_ci| Load either a +0 or +inf for plus/minus operand
14662306a36Sopenharmony_ci|
14762306a36Sopenharmony_ci	.global	szr_inf
14862306a36Sopenharmony_ciszr_inf:
14962306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
15062306a36Sopenharmony_ci	bne	ld_pzero
15162306a36Sopenharmony_ci	bra	ld_pinf
15262306a36Sopenharmony_ci|
15362306a36Sopenharmony_ci| Result is either an operr or +inf for plus/minus operand
15462306a36Sopenharmony_ci| [Used by slogn, slognp1, slog10, and slog2]
15562306a36Sopenharmony_ci|
15662306a36Sopenharmony_ci	.global	sopr_inf
15762306a36Sopenharmony_cisopr_inf:
15862306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
15962306a36Sopenharmony_ci	bne	t_operr
16062306a36Sopenharmony_ci	bra	ld_pinf
16162306a36Sopenharmony_ci|
16262306a36Sopenharmony_ci|	FLOGNP1
16362306a36Sopenharmony_ci|
16462306a36Sopenharmony_ci	.global	sslognp1
16562306a36Sopenharmony_cisslognp1:
16662306a36Sopenharmony_ci	fmovemx (%a0),%fp0-%fp0
16762306a36Sopenharmony_ci	fcmpb	#-1,%fp0
16862306a36Sopenharmony_ci	fbgt	slognp1
16962306a36Sopenharmony_ci	fbeq	t_dz2		|if = -1, divide by zero exception
17062306a36Sopenharmony_ci	fmovel	#0,%FPSR		|clr N flag
17162306a36Sopenharmony_ci	bra	t_operr		|take care of operands < -1
17262306a36Sopenharmony_ci|
17362306a36Sopenharmony_ci|	FETOXM1
17462306a36Sopenharmony_ci|
17562306a36Sopenharmony_ci	.global	setoxm1i
17662306a36Sopenharmony_cisetoxm1i:
17762306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
17862306a36Sopenharmony_ci	bne	ld_mone
17962306a36Sopenharmony_ci	bra	ld_pinf
18062306a36Sopenharmony_ci|
18162306a36Sopenharmony_ci|	FLOGN
18262306a36Sopenharmony_ci|
18362306a36Sopenharmony_ci| Test for 1.0 as an input argument, returning +zero.  Also check
18462306a36Sopenharmony_ci| the sign and return operr if negative.
18562306a36Sopenharmony_ci|
18662306a36Sopenharmony_ci	.global	sslogn
18762306a36Sopenharmony_cisslogn:
18862306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
18962306a36Sopenharmony_ci	bne	t_operr		|take care of operands < 0
19062306a36Sopenharmony_ci	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
19162306a36Sopenharmony_ci	bne	slogn
19262306a36Sopenharmony_ci	cmpil	#0x80000000,LOCAL_HI(%a0)
19362306a36Sopenharmony_ci	bne	slogn
19462306a36Sopenharmony_ci	tstl	LOCAL_LO(%a0)
19562306a36Sopenharmony_ci	bne	slogn
19662306a36Sopenharmony_ci	fmovex	PZERO,%fp0
19762306a36Sopenharmony_ci	rts
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	.global	sslognd
20062306a36Sopenharmony_cisslognd:
20162306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
20262306a36Sopenharmony_ci	beq	slognd
20362306a36Sopenharmony_ci	bra	t_operr		|take care of operands < 0
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci|
20662306a36Sopenharmony_ci|	FLOG10
20762306a36Sopenharmony_ci|
20862306a36Sopenharmony_ci	.global	sslog10
20962306a36Sopenharmony_cisslog10:
21062306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
21162306a36Sopenharmony_ci	bne	t_operr		|take care of operands < 0
21262306a36Sopenharmony_ci	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
21362306a36Sopenharmony_ci	bne	slog10
21462306a36Sopenharmony_ci	cmpil	#0x80000000,LOCAL_HI(%a0)
21562306a36Sopenharmony_ci	bne	slog10
21662306a36Sopenharmony_ci	tstl	LOCAL_LO(%a0)
21762306a36Sopenharmony_ci	bne	slog10
21862306a36Sopenharmony_ci	fmovex	PZERO,%fp0
21962306a36Sopenharmony_ci	rts
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	.global	sslog10d
22262306a36Sopenharmony_cisslog10d:
22362306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
22462306a36Sopenharmony_ci	beq	slog10d
22562306a36Sopenharmony_ci	bra	t_operr		|take care of operands < 0
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci|
22862306a36Sopenharmony_ci|	FLOG2
22962306a36Sopenharmony_ci|
23062306a36Sopenharmony_ci	.global	sslog2
23162306a36Sopenharmony_cisslog2:
23262306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
23362306a36Sopenharmony_ci	bne	t_operr		|take care of operands < 0
23462306a36Sopenharmony_ci	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
23562306a36Sopenharmony_ci	bne	slog2
23662306a36Sopenharmony_ci	cmpil	#0x80000000,LOCAL_HI(%a0)
23762306a36Sopenharmony_ci	bne	slog2
23862306a36Sopenharmony_ci	tstl	LOCAL_LO(%a0)
23962306a36Sopenharmony_ci	bne	slog2
24062306a36Sopenharmony_ci	fmovex	PZERO,%fp0
24162306a36Sopenharmony_ci	rts
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	.global	sslog2d
24462306a36Sopenharmony_cisslog2d:
24562306a36Sopenharmony_ci	btstb	#sign_bit,LOCAL_EX(%a0)
24662306a36Sopenharmony_ci	beq	slog2d
24762306a36Sopenharmony_ci	bra	t_operr		|take care of operands < 0
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci|
25062306a36Sopenharmony_ci|	FMOD
25162306a36Sopenharmony_ci|
25262306a36Sopenharmony_cipmodt:
25362306a36Sopenharmony_ci|				;$21 fmod
25462306a36Sopenharmony_ci|				;dtag,stag
25562306a36Sopenharmony_ci	.long	smod		|  00,00  norm,norm = normal
25662306a36Sopenharmony_ci	.long	smod_oper	|  00,01  norm,zero = nan with operr
25762306a36Sopenharmony_ci	.long	smod_fpn	|  00,10  norm,inf  = fpn
25862306a36Sopenharmony_ci	.long	smod_snan	|  00,11  norm,nan  = nan
25962306a36Sopenharmony_ci	.long	smod_zro	|  01,00  zero,norm = +-zero
26062306a36Sopenharmony_ci	.long	smod_oper	|  01,01  zero,zero = nan with operr
26162306a36Sopenharmony_ci	.long	smod_zro	|  01,10  zero,inf  = +-zero
26262306a36Sopenharmony_ci	.long	smod_snan	|  01,11  zero,nan  = nan
26362306a36Sopenharmony_ci	.long	smod_oper	|  10,00  inf,norm  = nan with operr
26462306a36Sopenharmony_ci	.long	smod_oper	|  10,01  inf,zero  = nan with operr
26562306a36Sopenharmony_ci	.long	smod_oper	|  10,10  inf,inf   = nan with operr
26662306a36Sopenharmony_ci	.long	smod_snan	|  10,11  inf,nan   = nan
26762306a36Sopenharmony_ci	.long	smod_dnan	|  11,00  nan,norm  = nan
26862306a36Sopenharmony_ci	.long	smod_dnan	|  11,01  nan,zero  = nan
26962306a36Sopenharmony_ci	.long	smod_dnan	|  11,10  nan,inf   = nan
27062306a36Sopenharmony_ci	.long	smod_dnan	|  11,11  nan,nan   = nan
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	.global	pmod
27362306a36Sopenharmony_cipmod:
27462306a36Sopenharmony_ci	clrb	FPSR_QBYTE(%a6) | clear quotient field
27562306a36Sopenharmony_ci	bfextu	STAG(%a6){#0:#3},%d0 |stag = d0
27662306a36Sopenharmony_ci	bfextu	DTAG(%a6){#0:#3},%d1 |dtag = d1
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci|
27962306a36Sopenharmony_ci| Alias extended denorms to norms for the jump table.
28062306a36Sopenharmony_ci|
28162306a36Sopenharmony_ci	bclrl	#2,%d0
28262306a36Sopenharmony_ci	bclrl	#2,%d1
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	lslb	#2,%d1
28562306a36Sopenharmony_ci	orb	%d0,%d1		|d1{3:2} = dtag, d1{1:0} = stag
28662306a36Sopenharmony_ci|				;Tag values:
28762306a36Sopenharmony_ci|				;00 = norm or denorm
28862306a36Sopenharmony_ci|				;01 = zero
28962306a36Sopenharmony_ci|				;10 = inf
29062306a36Sopenharmony_ci|				;11 = nan
29162306a36Sopenharmony_ci	lea	pmodt,%a1
29262306a36Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1
29362306a36Sopenharmony_ci	jmp	(%a1)
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cismod_snan:
29662306a36Sopenharmony_ci	bra	src_nan
29762306a36Sopenharmony_cismod_dnan:
29862306a36Sopenharmony_ci	bra	dst_nan
29962306a36Sopenharmony_cismod_oper:
30062306a36Sopenharmony_ci	bra	t_operr
30162306a36Sopenharmony_cismod_zro:
30262306a36Sopenharmony_ci	moveb	ETEMP(%a6),%d1	|get sign of src op
30362306a36Sopenharmony_ci	moveb	FPTEMP(%a6),%d0	|get sign of dst op
30462306a36Sopenharmony_ci	eorb	%d0,%d1		|get exor of sign bits
30562306a36Sopenharmony_ci	btstl	#7,%d1		|test for sign
30662306a36Sopenharmony_ci	beqs	smod_zsn	|if clr, do not set sign big
30762306a36Sopenharmony_ci	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
30862306a36Sopenharmony_cismod_zsn:
30962306a36Sopenharmony_ci	btstl	#7,%d0		|test if + or -
31062306a36Sopenharmony_ci	beq	ld_pzero	|if pos then load +0
31162306a36Sopenharmony_ci	bra	ld_mzero	|else neg load -0
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_cismod_fpn:
31462306a36Sopenharmony_ci	moveb	ETEMP(%a6),%d1	|get sign of src op
31562306a36Sopenharmony_ci	moveb	FPTEMP(%a6),%d0	|get sign of dst op
31662306a36Sopenharmony_ci	eorb	%d0,%d1		|get exor of sign bits
31762306a36Sopenharmony_ci	btstl	#7,%d1		|test for sign
31862306a36Sopenharmony_ci	beqs	smod_fsn	|if clr, do not set sign big
31962306a36Sopenharmony_ci	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
32062306a36Sopenharmony_cismod_fsn:
32162306a36Sopenharmony_ci	tstb	DTAG(%a6)	|filter out denormal destination case
32262306a36Sopenharmony_ci	bpls	smod_nrm	|
32362306a36Sopenharmony_ci	leal	FPTEMP(%a6),%a0	|a0<- addr(FPTEMP)
32462306a36Sopenharmony_ci	bra	t_resdnrm	|force UNFL(but exact) result
32562306a36Sopenharmony_cismod_nrm:
32662306a36Sopenharmony_ci	fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
32762306a36Sopenharmony_ci	fmovex FPTEMP(%a6),%fp0	|return dest to fp0
32862306a36Sopenharmony_ci	rts
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci|
33162306a36Sopenharmony_ci|	FREM
33262306a36Sopenharmony_ci|
33362306a36Sopenharmony_cipremt:
33462306a36Sopenharmony_ci|				;$25 frem
33562306a36Sopenharmony_ci|				;dtag,stag
33662306a36Sopenharmony_ci	.long	srem		|  00,00  norm,norm = normal
33762306a36Sopenharmony_ci	.long	srem_oper	|  00,01  norm,zero = nan with operr
33862306a36Sopenharmony_ci	.long	srem_fpn	|  00,10  norm,inf  = fpn
33962306a36Sopenharmony_ci	.long	srem_snan	|  00,11  norm,nan  = nan
34062306a36Sopenharmony_ci	.long	srem_zro	|  01,00  zero,norm = +-zero
34162306a36Sopenharmony_ci	.long	srem_oper	|  01,01  zero,zero = nan with operr
34262306a36Sopenharmony_ci	.long	srem_zro	|  01,10  zero,inf  = +-zero
34362306a36Sopenharmony_ci	.long	srem_snan	|  01,11  zero,nan  = nan
34462306a36Sopenharmony_ci	.long	srem_oper	|  10,00  inf,norm  = nan with operr
34562306a36Sopenharmony_ci	.long	srem_oper	|  10,01  inf,zero  = nan with operr
34662306a36Sopenharmony_ci	.long	srem_oper	|  10,10  inf,inf   = nan with operr
34762306a36Sopenharmony_ci	.long	srem_snan	|  10,11  inf,nan   = nan
34862306a36Sopenharmony_ci	.long	srem_dnan	|  11,00  nan,norm  = nan
34962306a36Sopenharmony_ci	.long	srem_dnan	|  11,01  nan,zero  = nan
35062306a36Sopenharmony_ci	.long	srem_dnan	|  11,10  nan,inf   = nan
35162306a36Sopenharmony_ci	.long	srem_dnan	|  11,11  nan,nan   = nan
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	.global	prem
35462306a36Sopenharmony_ciprem:
35562306a36Sopenharmony_ci	clrb	FPSR_QBYTE(%a6)   |clear quotient field
35662306a36Sopenharmony_ci	bfextu	STAG(%a6){#0:#3},%d0 |stag = d0
35762306a36Sopenharmony_ci	bfextu	DTAG(%a6){#0:#3},%d1 |dtag = d1
35862306a36Sopenharmony_ci|
35962306a36Sopenharmony_ci| Alias extended denorms to norms for the jump table.
36062306a36Sopenharmony_ci|
36162306a36Sopenharmony_ci	bclr	#2,%d0
36262306a36Sopenharmony_ci	bclr	#2,%d1
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	lslb	#2,%d1
36562306a36Sopenharmony_ci	orb	%d0,%d1		|d1{3:2} = dtag, d1{1:0} = stag
36662306a36Sopenharmony_ci|				;Tag values:
36762306a36Sopenharmony_ci|				;00 = norm or denorm
36862306a36Sopenharmony_ci|				;01 = zero
36962306a36Sopenharmony_ci|				;10 = inf
37062306a36Sopenharmony_ci|				;11 = nan
37162306a36Sopenharmony_ci	lea	premt,%a1
37262306a36Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1
37362306a36Sopenharmony_ci	jmp	(%a1)
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_cisrem_snan:
37662306a36Sopenharmony_ci	bra	src_nan
37762306a36Sopenharmony_cisrem_dnan:
37862306a36Sopenharmony_ci	bra	dst_nan
37962306a36Sopenharmony_cisrem_oper:
38062306a36Sopenharmony_ci	bra	t_operr
38162306a36Sopenharmony_cisrem_zro:
38262306a36Sopenharmony_ci	moveb	ETEMP(%a6),%d1	|get sign of src op
38362306a36Sopenharmony_ci	moveb	FPTEMP(%a6),%d0	|get sign of dst op
38462306a36Sopenharmony_ci	eorb	%d0,%d1		|get exor of sign bits
38562306a36Sopenharmony_ci	btstl	#7,%d1		|test for sign
38662306a36Sopenharmony_ci	beqs	srem_zsn	|if clr, do not set sign big
38762306a36Sopenharmony_ci	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
38862306a36Sopenharmony_cisrem_zsn:
38962306a36Sopenharmony_ci	btstl	#7,%d0		|test if + or -
39062306a36Sopenharmony_ci	beq	ld_pzero	|if pos then load +0
39162306a36Sopenharmony_ci	bra	ld_mzero	|else neg load -0
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_cisrem_fpn:
39462306a36Sopenharmony_ci	moveb	ETEMP(%a6),%d1	|get sign of src op
39562306a36Sopenharmony_ci	moveb	FPTEMP(%a6),%d0	|get sign of dst op
39662306a36Sopenharmony_ci	eorb	%d0,%d1		|get exor of sign bits
39762306a36Sopenharmony_ci	btstl	#7,%d1		|test for sign
39862306a36Sopenharmony_ci	beqs	srem_fsn	|if clr, do not set sign big
39962306a36Sopenharmony_ci	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
40062306a36Sopenharmony_cisrem_fsn:
40162306a36Sopenharmony_ci	tstb	DTAG(%a6)	|filter out denormal destination case
40262306a36Sopenharmony_ci	bpls	srem_nrm	|
40362306a36Sopenharmony_ci	leal	FPTEMP(%a6),%a0	|a0<- addr(FPTEMP)
40462306a36Sopenharmony_ci	bra	t_resdnrm	|force UNFL(but exact) result
40562306a36Sopenharmony_cisrem_nrm:
40662306a36Sopenharmony_ci	fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
40762306a36Sopenharmony_ci	fmovex FPTEMP(%a6),%fp0	|return dest to fp0
40862306a36Sopenharmony_ci	rts
40962306a36Sopenharmony_ci|
41062306a36Sopenharmony_ci|	FSCALE
41162306a36Sopenharmony_ci|
41262306a36Sopenharmony_cipscalet:
41362306a36Sopenharmony_ci|				;$26 fscale
41462306a36Sopenharmony_ci|				;dtag,stag
41562306a36Sopenharmony_ci	.long	sscale		|  00,00  norm,norm = result
41662306a36Sopenharmony_ci	.long	sscale		|  00,01  norm,zero = fpn
41762306a36Sopenharmony_ci	.long	scl_opr		|  00,10  norm,inf  = nan with operr
41862306a36Sopenharmony_ci	.long	scl_snan	|  00,11  norm,nan  = nan
41962306a36Sopenharmony_ci	.long	scl_zro		|  01,00  zero,norm = +-zero
42062306a36Sopenharmony_ci	.long	scl_zro		|  01,01  zero,zero = +-zero
42162306a36Sopenharmony_ci	.long	scl_opr		|  01,10  zero,inf  = nan with operr
42262306a36Sopenharmony_ci	.long	scl_snan	|  01,11  zero,nan  = nan
42362306a36Sopenharmony_ci	.long	scl_inf		|  10,00  inf,norm  = +-inf
42462306a36Sopenharmony_ci	.long	scl_inf		|  10,01  inf,zero  = +-inf
42562306a36Sopenharmony_ci	.long	scl_opr		|  10,10  inf,inf   = nan with operr
42662306a36Sopenharmony_ci	.long	scl_snan	|  10,11  inf,nan   = nan
42762306a36Sopenharmony_ci	.long	scl_dnan	|  11,00  nan,norm  = nan
42862306a36Sopenharmony_ci	.long	scl_dnan	|  11,01  nan,zero  = nan
42962306a36Sopenharmony_ci	.long	scl_dnan	|  11,10  nan,inf   = nan
43062306a36Sopenharmony_ci	.long	scl_dnan	|  11,11  nan,nan   = nan
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	.global	pscale
43362306a36Sopenharmony_cipscale:
43462306a36Sopenharmony_ci	bfextu	STAG(%a6){#0:#3},%d0 |stag in d0
43562306a36Sopenharmony_ci	bfextu	DTAG(%a6){#0:#3},%d1 |dtag in d1
43662306a36Sopenharmony_ci	bclrl	#2,%d0		|alias  denorm into norm
43762306a36Sopenharmony_ci	bclrl	#2,%d1		|alias  denorm into norm
43862306a36Sopenharmony_ci	lslb	#2,%d1
43962306a36Sopenharmony_ci	orb	%d0,%d1		|d1{4:2} = dtag, d1{1:0} = stag
44062306a36Sopenharmony_ci|				;dtag values     stag values:
44162306a36Sopenharmony_ci|				;000 = norm      00 = norm
44262306a36Sopenharmony_ci|				;001 = zero	 01 = zero
44362306a36Sopenharmony_ci|				;010 = inf	 10 = inf
44462306a36Sopenharmony_ci|				;011 = nan	 11 = nan
44562306a36Sopenharmony_ci|				;100 = dnrm
44662306a36Sopenharmony_ci|
44762306a36Sopenharmony_ci|
44862306a36Sopenharmony_ci	leal	pscalet,%a1	|load start of jump table
44962306a36Sopenharmony_ci	movel	(%a1,%d1.w*4),%a1	|load a1 with label depending on tag
45062306a36Sopenharmony_ci	jmp	(%a1)		|go to the routine
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ciscl_opr:
45362306a36Sopenharmony_ci	bra	t_operr
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ciscl_dnan:
45662306a36Sopenharmony_ci	bra	dst_nan
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ciscl_zro:
45962306a36Sopenharmony_ci	btstb	#sign_bit,FPTEMP_EX(%a6)	|test if + or -
46062306a36Sopenharmony_ci	beq	ld_pzero		|if pos then load +0
46162306a36Sopenharmony_ci	bra	ld_mzero		|if neg then load -0
46262306a36Sopenharmony_ciscl_inf:
46362306a36Sopenharmony_ci	btstb	#sign_bit,FPTEMP_EX(%a6)	|test if + or -
46462306a36Sopenharmony_ci	beq	ld_pinf			|if pos then load +inf
46562306a36Sopenharmony_ci	bra	ld_minf			|else neg load -inf
46662306a36Sopenharmony_ciscl_snan:
46762306a36Sopenharmony_ci	bra	src_nan
46862306a36Sopenharmony_ci|
46962306a36Sopenharmony_ci|	FSINCOS
47062306a36Sopenharmony_ci|
47162306a36Sopenharmony_ci	.global	ssincosz
47262306a36Sopenharmony_cissincosz:
47362306a36Sopenharmony_ci	btstb	#sign_bit,ETEMP(%a6)	|get sign
47462306a36Sopenharmony_ci	beqs	sincosp
47562306a36Sopenharmony_ci	fmovex	MZERO,%fp0
47662306a36Sopenharmony_ci	bras	sincoscom
47762306a36Sopenharmony_cisincosp:
47862306a36Sopenharmony_ci	fmovex PZERO,%fp0
47962306a36Sopenharmony_cisincoscom:
48062306a36Sopenharmony_ci	fmovemx PONE,%fp1-%fp1	|do not allow FPSR to be affected
48162306a36Sopenharmony_ci	bra	sto_cos		|store cosine result
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	.global	ssincosi
48462306a36Sopenharmony_cissincosi:
48562306a36Sopenharmony_ci	fmovex QNAN,%fp1	|load NAN
48662306a36Sopenharmony_ci	bsr	sto_cos		|store cosine result
48762306a36Sopenharmony_ci	fmovex QNAN,%fp0	|load NAN
48862306a36Sopenharmony_ci	bra	t_operr
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	.global	ssincosnan
49162306a36Sopenharmony_cissincosnan:
49262306a36Sopenharmony_ci	movel	ETEMP_EX(%a6),FP_SCR1(%a6)
49362306a36Sopenharmony_ci	movel	ETEMP_HI(%a6),FP_SCR1+4(%a6)
49462306a36Sopenharmony_ci	movel	ETEMP_LO(%a6),FP_SCR1+8(%a6)
49562306a36Sopenharmony_ci	bsetb	#signan_bit,FP_SCR1+4(%a6)
49662306a36Sopenharmony_ci	fmovemx FP_SCR1(%a6),%fp1-%fp1
49762306a36Sopenharmony_ci	bsr	sto_cos
49862306a36Sopenharmony_ci	bra	src_nan
49962306a36Sopenharmony_ci|
50062306a36Sopenharmony_ci| This code forces default values for the zero, inf, and nan cases
50162306a36Sopenharmony_ci| in the transcendentals code.  The CC bits must be set in the
50262306a36Sopenharmony_ci| stacked FPSR to be correctly reported.
50362306a36Sopenharmony_ci|
50462306a36Sopenharmony_ci|**Returns +PI/2
50562306a36Sopenharmony_ci	.global	ld_ppi2
50662306a36Sopenharmony_cild_ppi2:
50762306a36Sopenharmony_ci	fmovex PPIBY2,%fp0		|load +pi/2
50862306a36Sopenharmony_ci	bra	t_inx2			|set inex2 exc
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci|**Returns -PI/2
51162306a36Sopenharmony_ci	.global	ld_mpi2
51262306a36Sopenharmony_cild_mpi2:
51362306a36Sopenharmony_ci	fmovex MPIBY2,%fp0		|load -pi/2
51462306a36Sopenharmony_ci	orl	#neg_mask,USER_FPSR(%a6)	|set N bit
51562306a36Sopenharmony_ci	bra	t_inx2			|set inex2 exc
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci|**Returns +inf
51862306a36Sopenharmony_ci	.global	ld_pinf
51962306a36Sopenharmony_cild_pinf:
52062306a36Sopenharmony_ci	fmovex PINF,%fp0		|load +inf
52162306a36Sopenharmony_ci	orl	#inf_mask,USER_FPSR(%a6)	|set I bit
52262306a36Sopenharmony_ci	rts
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci|**Returns -inf
52562306a36Sopenharmony_ci	.global	ld_minf
52662306a36Sopenharmony_cild_minf:
52762306a36Sopenharmony_ci	fmovex MINF,%fp0		|load -inf
52862306a36Sopenharmony_ci	orl	#neg_mask+inf_mask,USER_FPSR(%a6)	|set N and I bits
52962306a36Sopenharmony_ci	rts
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci|**Returns +1
53262306a36Sopenharmony_ci	.global	ld_pone
53362306a36Sopenharmony_cild_pone:
53462306a36Sopenharmony_ci	fmovex PONE,%fp0		|load +1
53562306a36Sopenharmony_ci	rts
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci|**Returns -1
53862306a36Sopenharmony_ci	.global	ld_mone
53962306a36Sopenharmony_cild_mone:
54062306a36Sopenharmony_ci	fmovex MONE,%fp0		|load -1
54162306a36Sopenharmony_ci	orl	#neg_mask,USER_FPSR(%a6)	|set N bit
54262306a36Sopenharmony_ci	rts
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci|**Returns +0
54562306a36Sopenharmony_ci	.global	ld_pzero
54662306a36Sopenharmony_cild_pzero:
54762306a36Sopenharmony_ci	fmovex PZERO,%fp0		|load +0
54862306a36Sopenharmony_ci	orl	#z_mask,USER_FPSR(%a6)	|set Z bit
54962306a36Sopenharmony_ci	rts
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci|**Returns -0
55262306a36Sopenharmony_ci	.global	ld_mzero
55362306a36Sopenharmony_cild_mzero:
55462306a36Sopenharmony_ci	fmovex MZERO,%fp0		|load -0
55562306a36Sopenharmony_ci	orl	#neg_mask+z_mask,USER_FPSR(%a6)	|set N and Z bits
55662306a36Sopenharmony_ci	rts
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	|end
559