xref: /linux/arch/m68k/fpsp040/do_func.S (revision e5451c8f8330e03ad3cfa16048b4daf961af434f)
11da177e4SLinus Torvalds|
21da177e4SLinus Torvalds|	do_func.sa 3.4 2/18/91
31da177e4SLinus Torvalds|
41da177e4SLinus Torvalds| Do_func performs the unimplemented operation.  The operation
51da177e4SLinus Torvalds| to be performed is determined from the lower 7 bits of the
61da177e4SLinus Torvalds| extension word (except in the case of fmovecr and fsincos).
71da177e4SLinus Torvalds| The opcode and tag bits form an index into a jump table in
81da177e4SLinus Torvalds| tbldo.sa.  Cases of zero, infinity and NaN are handled in
91da177e4SLinus Torvalds| do_func by forcing the default result.  Normalized and
101da177e4SLinus Torvalds| denormalized (there are no unnormalized numbers at this
111da177e4SLinus Torvalds| point) are passed onto the emulation code.
121da177e4SLinus Torvalds|
131da177e4SLinus Torvalds| CMDREG1B and STAG are extracted from the fsave frame
141da177e4SLinus Torvalds| and combined to form the table index.  The function called
151da177e4SLinus Torvalds| will start with a0 pointing to the ETEMP operand.  Dyadic
161da177e4SLinus Torvalds| functions can find FPTEMP at -12(a0).
171da177e4SLinus Torvalds|
181da177e4SLinus Torvalds| Called functions return their result in fp0.  Sincos returns
191da177e4SLinus Torvalds| sin(x) in fp0 and cos(x) in fp1.
201da177e4SLinus Torvalds|
211da177e4SLinus Torvalds
221da177e4SLinus Torvalds|		Copyright (C) Motorola, Inc. 1990
231da177e4SLinus Torvalds|			All Rights Reserved
241da177e4SLinus Torvalds|
25*e00d82d0SMatt Waddel|       For details on the license for this file, please see the
26*e00d82d0SMatt Waddel|       file, README, in this same directory.
271da177e4SLinus Torvalds
281da177e4SLinus TorvaldsDO_FUNC:	|idnt    2,1 | Motorola 040 Floating Point Software Package
291da177e4SLinus Torvalds
301da177e4SLinus Torvalds	|section	8
311da177e4SLinus Torvalds
321da177e4SLinus Torvalds#include "fpsp.h"
331da177e4SLinus Torvalds
341da177e4SLinus Torvalds	|xref	t_dz2
351da177e4SLinus Torvalds	|xref	t_operr
361da177e4SLinus Torvalds	|xref	t_inx2
371da177e4SLinus Torvalds	|xref	t_resdnrm
381da177e4SLinus Torvalds	|xref	dst_nan
391da177e4SLinus Torvalds	|xref	src_nan
401da177e4SLinus Torvalds	|xref	nrm_set
411da177e4SLinus Torvalds	|xref	sto_cos
421da177e4SLinus Torvalds
431da177e4SLinus Torvalds	|xref	tblpre
441da177e4SLinus Torvalds	|xref	slognp1,slogn,slog10,slog2
451da177e4SLinus Torvalds	|xref	slognd,slog10d,slog2d
461da177e4SLinus Torvalds	|xref	smod,srem
471da177e4SLinus Torvalds	|xref	sscale
481da177e4SLinus Torvalds	|xref	smovcr
491da177e4SLinus Torvalds
501da177e4SLinus TorvaldsPONE:	.long	0x3fff0000,0x80000000,0x00000000	|+1
511da177e4SLinus TorvaldsMONE:	.long	0xbfff0000,0x80000000,0x00000000	|-1
521da177e4SLinus TorvaldsPZERO:	.long	0x00000000,0x00000000,0x00000000	|+0
531da177e4SLinus TorvaldsMZERO:	.long	0x80000000,0x00000000,0x00000000	|-0
541da177e4SLinus TorvaldsPINF:	.long	0x7fff0000,0x00000000,0x00000000	|+inf
551da177e4SLinus TorvaldsMINF:	.long	0xffff0000,0x00000000,0x00000000	|-inf
561da177e4SLinus TorvaldsQNAN:	.long	0x7fff0000,0xffffffff,0xffffffff	|non-signaling nan
571da177e4SLinus TorvaldsPPIBY2:  .long	0x3FFF0000,0xC90FDAA2,0x2168C235	|+PI/2
581da177e4SLinus TorvaldsMPIBY2:  .long	0xbFFF0000,0xC90FDAA2,0x2168C235	|-PI/2
591da177e4SLinus Torvalds
601da177e4SLinus Torvalds	.global	do_func
611da177e4SLinus Torvaldsdo_func:
621da177e4SLinus Torvalds	clrb	CU_ONLY(%a6)
631da177e4SLinus Torvalds|
641da177e4SLinus Torvalds| Check for fmovecr.  It does not follow the format of fp gen
651da177e4SLinus Torvalds| unimplemented instructions.  The test is on the upper 6 bits;
661da177e4SLinus Torvalds| if they are $17, the inst is fmovecr.  Call entry smovcr
671da177e4SLinus Torvalds| directly.
681da177e4SLinus Torvalds|
691da177e4SLinus Torvalds	bfextu	CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
701da177e4SLinus Torvalds	cmpil	#0x17,%d0		|if op class and size fields are $17,
711da177e4SLinus Torvalds|				;it is FMOVECR; if not, continue
721da177e4SLinus Torvalds	bnes	not_fmovecr
731da177e4SLinus Torvalds	jmp	smovcr		|fmovecr; jmp directly to emulation
741da177e4SLinus Torvalds
751da177e4SLinus Torvaldsnot_fmovecr:
761da177e4SLinus Torvalds	movew	CMDREG1B(%a6),%d0
771da177e4SLinus Torvalds	andl	#0x7F,%d0
781da177e4SLinus Torvalds	cmpil	#0x38,%d0		|if the extension is >= $38,
791da177e4SLinus Torvalds	bge	serror		|it is illegal
801da177e4SLinus Torvalds	bfextu	STAG(%a6){#0:#3},%d1
811da177e4SLinus Torvalds	lsll	#3,%d0		|make room for STAG
821da177e4SLinus Torvalds	addl	%d1,%d0		|combine for final index into table
831da177e4SLinus Torvalds	leal	tblpre,%a1	|start of monster jump table
841da177e4SLinus Torvalds	movel	(%a1,%d0.w*4),%a1	|real target address
851da177e4SLinus Torvalds	leal	ETEMP(%a6),%a0	|a0 is pointer to src op
861da177e4SLinus Torvalds	movel	USER_FPCR(%a6),%d1
871da177e4SLinus Torvalds	andl	#0xFF,%d1		| discard all but rounding mode/prec
881da177e4SLinus Torvalds	fmovel	#0,%fpcr
891da177e4SLinus Torvalds	jmp	(%a1)
901da177e4SLinus Torvalds|
911da177e4SLinus Torvalds|	ERROR
921da177e4SLinus Torvalds|
931da177e4SLinus Torvalds	.global	serror
941da177e4SLinus Torvaldsserror:
951da177e4SLinus Torvalds	st	STORE_FLG(%a6)
961da177e4SLinus Torvalds	rts
971da177e4SLinus Torvalds|
981da177e4SLinus Torvalds| These routines load forced values into fp0.  They are called
991da177e4SLinus Torvalds| by index into tbldo.
1001da177e4SLinus Torvalds|
1011da177e4SLinus Torvalds| Load a signed zero to fp0 and set inex2/ainex
1021da177e4SLinus Torvalds|
1031da177e4SLinus Torvalds	.global	snzrinx
1041da177e4SLinus Torvaldssnzrinx:
1051da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)	|get sign of source operand
1061da177e4SLinus Torvalds	bnes	ld_mzinx	|if negative, branch
1071da177e4SLinus Torvalds	bsr	ld_pzero	|bsr so we can return and set inx
1081da177e4SLinus Torvalds	bra	t_inx2		|now, set the inx for the next inst
1091da177e4SLinus Torvaldsld_mzinx:
1101da177e4SLinus Torvalds	bsr	ld_mzero	|if neg, load neg zero, return here
1111da177e4SLinus Torvalds	bra	t_inx2		|now, set the inx for the next inst
1121da177e4SLinus Torvalds|
1131da177e4SLinus Torvalds| Load a signed zero to fp0; do not set inex2/ainex
1141da177e4SLinus Torvalds|
1151da177e4SLinus Torvalds	.global	szero
1161da177e4SLinus Torvaldsszero:
1171da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0) |get sign of source operand
1181da177e4SLinus Torvalds	bne	ld_mzero	|if neg, load neg zero
1191da177e4SLinus Torvalds	bra	ld_pzero	|load positive zero
1201da177e4SLinus Torvalds|
1211da177e4SLinus Torvalds| Load a signed infinity to fp0; do not set inex2/ainex
1221da177e4SLinus Torvalds|
1231da177e4SLinus Torvalds	.global	sinf
1241da177e4SLinus Torvaldssinf:
1251da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)	|get sign of source operand
1261da177e4SLinus Torvalds	bne	ld_minf			|if negative branch
1271da177e4SLinus Torvalds	bra	ld_pinf
1281da177e4SLinus Torvalds|
1291da177e4SLinus Torvalds| Load a signed one to fp0; do not set inex2/ainex
1301da177e4SLinus Torvalds|
1311da177e4SLinus Torvalds	.global	sone
1321da177e4SLinus Torvaldssone:
1331da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
1341da177e4SLinus Torvalds	bne	ld_mone
1351da177e4SLinus Torvalds	bra	ld_pone
1361da177e4SLinus Torvalds|
1371da177e4SLinus Torvalds| Load a signed pi/2 to fp0; do not set inex2/ainex
1381da177e4SLinus Torvalds|
1391da177e4SLinus Torvalds	.global	spi_2
1401da177e4SLinus Torvaldsspi_2:
1411da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
1421da177e4SLinus Torvalds	bne	ld_mpi2
1431da177e4SLinus Torvalds	bra	ld_ppi2
1441da177e4SLinus Torvalds|
1451da177e4SLinus Torvalds| Load either a +0 or +inf for plus/minus operand
1461da177e4SLinus Torvalds|
1471da177e4SLinus Torvalds	.global	szr_inf
1481da177e4SLinus Torvaldsszr_inf:
1491da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
1501da177e4SLinus Torvalds	bne	ld_pzero
1511da177e4SLinus Torvalds	bra	ld_pinf
1521da177e4SLinus Torvalds|
1531da177e4SLinus Torvalds| Result is either an operr or +inf for plus/minus operand
1541da177e4SLinus Torvalds| [Used by slogn, slognp1, slog10, and slog2]
1551da177e4SLinus Torvalds|
1561da177e4SLinus Torvalds	.global	sopr_inf
1571da177e4SLinus Torvaldssopr_inf:
1581da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
1591da177e4SLinus Torvalds	bne	t_operr
1601da177e4SLinus Torvalds	bra	ld_pinf
1611da177e4SLinus Torvalds|
1621da177e4SLinus Torvalds|	FLOGNP1
1631da177e4SLinus Torvalds|
1641da177e4SLinus Torvalds	.global	sslognp1
1651da177e4SLinus Torvaldssslognp1:
1661da177e4SLinus Torvalds	fmovemx (%a0),%fp0-%fp0
1671da177e4SLinus Torvalds	fcmpb	#-1,%fp0
1681da177e4SLinus Torvalds	fbgt	slognp1
1691da177e4SLinus Torvalds	fbeq	t_dz2		|if = -1, divide by zero exception
1701da177e4SLinus Torvalds	fmovel	#0,%FPSR		|clr N flag
1711da177e4SLinus Torvalds	bra	t_operr		|take care of operands < -1
1721da177e4SLinus Torvalds|
1731da177e4SLinus Torvalds|	FETOXM1
1741da177e4SLinus Torvalds|
1751da177e4SLinus Torvalds	.global	setoxm1i
1761da177e4SLinus Torvaldssetoxm1i:
1771da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
1781da177e4SLinus Torvalds	bne	ld_mone
1791da177e4SLinus Torvalds	bra	ld_pinf
1801da177e4SLinus Torvalds|
1811da177e4SLinus Torvalds|	FLOGN
1821da177e4SLinus Torvalds|
1831da177e4SLinus Torvalds| Test for 1.0 as an input argument, returning +zero.  Also check
1841da177e4SLinus Torvalds| the sign and return operr if negative.
1851da177e4SLinus Torvalds|
1861da177e4SLinus Torvalds	.global	sslogn
1871da177e4SLinus Torvaldssslogn:
1881da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)
1891da177e4SLinus Torvalds	bne	t_operr		|take care of operands < 0
1901da177e4SLinus Torvalds	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
1911da177e4SLinus Torvalds	bne	slogn
1921da177e4SLinus Torvalds	cmpil	#0x80000000,LOCAL_HI(%a0)
1931da177e4SLinus Torvalds	bne	slogn
1941da177e4SLinus Torvalds	tstl	LOCAL_LO(%a0)
1951da177e4SLinus Torvalds	bne	slogn
1961da177e4SLinus Torvalds	fmovex	PZERO,%fp0
1971da177e4SLinus Torvalds	rts
1981da177e4SLinus Torvalds
1991da177e4SLinus Torvalds	.global	sslognd
2001da177e4SLinus Torvaldssslognd:
2011da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)
2021da177e4SLinus Torvalds	beq	slognd
2031da177e4SLinus Torvalds	bra	t_operr		|take care of operands < 0
2041da177e4SLinus Torvalds
2051da177e4SLinus Torvalds|
2061da177e4SLinus Torvalds|	FLOG10
2071da177e4SLinus Torvalds|
2081da177e4SLinus Torvalds	.global	sslog10
2091da177e4SLinus Torvaldssslog10:
2101da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)
2111da177e4SLinus Torvalds	bne	t_operr		|take care of operands < 0
2121da177e4SLinus Torvalds	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
2131da177e4SLinus Torvalds	bne	slog10
2141da177e4SLinus Torvalds	cmpil	#0x80000000,LOCAL_HI(%a0)
2151da177e4SLinus Torvalds	bne	slog10
2161da177e4SLinus Torvalds	tstl	LOCAL_LO(%a0)
2171da177e4SLinus Torvalds	bne	slog10
2181da177e4SLinus Torvalds	fmovex	PZERO,%fp0
2191da177e4SLinus Torvalds	rts
2201da177e4SLinus Torvalds
2211da177e4SLinus Torvalds	.global	sslog10d
2221da177e4SLinus Torvaldssslog10d:
2231da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)
2241da177e4SLinus Torvalds	beq	slog10d
2251da177e4SLinus Torvalds	bra	t_operr		|take care of operands < 0
2261da177e4SLinus Torvalds
2271da177e4SLinus Torvalds|
2281da177e4SLinus Torvalds|	FLOG2
2291da177e4SLinus Torvalds|
2301da177e4SLinus Torvalds	.global	sslog2
2311da177e4SLinus Torvaldssslog2:
2321da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)
2331da177e4SLinus Torvalds	bne	t_operr		|take care of operands < 0
2341da177e4SLinus Torvalds	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
2351da177e4SLinus Torvalds	bne	slog2
2361da177e4SLinus Torvalds	cmpil	#0x80000000,LOCAL_HI(%a0)
2371da177e4SLinus Torvalds	bne	slog2
2381da177e4SLinus Torvalds	tstl	LOCAL_LO(%a0)
2391da177e4SLinus Torvalds	bne	slog2
2401da177e4SLinus Torvalds	fmovex	PZERO,%fp0
2411da177e4SLinus Torvalds	rts
2421da177e4SLinus Torvalds
2431da177e4SLinus Torvalds	.global	sslog2d
2441da177e4SLinus Torvaldssslog2d:
2451da177e4SLinus Torvalds	btstb	#sign_bit,LOCAL_EX(%a0)
2461da177e4SLinus Torvalds	beq	slog2d
2471da177e4SLinus Torvalds	bra	t_operr		|take care of operands < 0
2481da177e4SLinus Torvalds
2491da177e4SLinus Torvalds|
2501da177e4SLinus Torvalds|	FMOD
2511da177e4SLinus Torvalds|
2521da177e4SLinus Torvaldspmodt:
2531da177e4SLinus Torvalds|				;$21 fmod
2541da177e4SLinus Torvalds|				;dtag,stag
2551da177e4SLinus Torvalds	.long	smod		|  00,00  norm,norm = normal
2561da177e4SLinus Torvalds	.long	smod_oper	|  00,01  norm,zero = nan with operr
2571da177e4SLinus Torvalds	.long	smod_fpn	|  00,10  norm,inf  = fpn
2581da177e4SLinus Torvalds	.long	smod_snan	|  00,11  norm,nan  = nan
2591da177e4SLinus Torvalds	.long	smod_zro	|  01,00  zero,norm = +-zero
2601da177e4SLinus Torvalds	.long	smod_oper	|  01,01  zero,zero = nan with operr
2611da177e4SLinus Torvalds	.long	smod_zro	|  01,10  zero,inf  = +-zero
2621da177e4SLinus Torvalds	.long	smod_snan	|  01,11  zero,nan  = nan
2631da177e4SLinus Torvalds	.long	smod_oper	|  10,00  inf,norm  = nan with operr
2641da177e4SLinus Torvalds	.long	smod_oper	|  10,01  inf,zero  = nan with operr
2651da177e4SLinus Torvalds	.long	smod_oper	|  10,10  inf,inf   = nan with operr
2661da177e4SLinus Torvalds	.long	smod_snan	|  10,11  inf,nan   = nan
2671da177e4SLinus Torvalds	.long	smod_dnan	|  11,00  nan,norm  = nan
2681da177e4SLinus Torvalds	.long	smod_dnan	|  11,01  nan,zero  = nan
2691da177e4SLinus Torvalds	.long	smod_dnan	|  11,10  nan,inf   = nan
2701da177e4SLinus Torvalds	.long	smod_dnan	|  11,11  nan,nan   = nan
2711da177e4SLinus Torvalds
2721da177e4SLinus Torvalds	.global	pmod
2731da177e4SLinus Torvaldspmod:
2741da177e4SLinus Torvalds	clrb	FPSR_QBYTE(%a6) | clear quotient field
2751da177e4SLinus Torvalds	bfextu	STAG(%a6){#0:#3},%d0 |stag = d0
2761da177e4SLinus Torvalds	bfextu	DTAG(%a6){#0:#3},%d1 |dtag = d1
2771da177e4SLinus Torvalds
2781da177e4SLinus Torvalds|
2791da177e4SLinus Torvalds| Alias extended denorms to norms for the jump table.
2801da177e4SLinus Torvalds|
2811da177e4SLinus Torvalds	bclrl	#2,%d0
2821da177e4SLinus Torvalds	bclrl	#2,%d1
2831da177e4SLinus Torvalds
2841da177e4SLinus Torvalds	lslb	#2,%d1
2851da177e4SLinus Torvalds	orb	%d0,%d1		|d1{3:2} = dtag, d1{1:0} = stag
2861da177e4SLinus Torvalds|				;Tag values:
2871da177e4SLinus Torvalds|				;00 = norm or denorm
2881da177e4SLinus Torvalds|				;01 = zero
2891da177e4SLinus Torvalds|				;10 = inf
2901da177e4SLinus Torvalds|				;11 = nan
2911da177e4SLinus Torvalds	lea	pmodt,%a1
2921da177e4SLinus Torvalds	movel	(%a1,%d1.w*4),%a1
2931da177e4SLinus Torvalds	jmp	(%a1)
2941da177e4SLinus Torvalds
2951da177e4SLinus Torvaldssmod_snan:
2961da177e4SLinus Torvalds	bra	src_nan
2971da177e4SLinus Torvaldssmod_dnan:
2981da177e4SLinus Torvalds	bra	dst_nan
2991da177e4SLinus Torvaldssmod_oper:
3001da177e4SLinus Torvalds	bra	t_operr
3011da177e4SLinus Torvaldssmod_zro:
3021da177e4SLinus Torvalds	moveb	ETEMP(%a6),%d1	|get sign of src op
3031da177e4SLinus Torvalds	moveb	FPTEMP(%a6),%d0	|get sign of dst op
3041da177e4SLinus Torvalds	eorb	%d0,%d1		|get exor of sign bits
3051da177e4SLinus Torvalds	btstl	#7,%d1		|test for sign
3061da177e4SLinus Torvalds	beqs	smod_zsn	|if clr, do not set sign big
3071da177e4SLinus Torvalds	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
3081da177e4SLinus Torvaldssmod_zsn:
3091da177e4SLinus Torvalds	btstl	#7,%d0		|test if + or -
3101da177e4SLinus Torvalds	beq	ld_pzero	|if pos then load +0
3111da177e4SLinus Torvalds	bra	ld_mzero	|else neg load -0
3121da177e4SLinus Torvalds
3131da177e4SLinus Torvaldssmod_fpn:
3141da177e4SLinus Torvalds	moveb	ETEMP(%a6),%d1	|get sign of src op
3151da177e4SLinus Torvalds	moveb	FPTEMP(%a6),%d0	|get sign of dst op
3161da177e4SLinus Torvalds	eorb	%d0,%d1		|get exor of sign bits
3171da177e4SLinus Torvalds	btstl	#7,%d1		|test for sign
3181da177e4SLinus Torvalds	beqs	smod_fsn	|if clr, do not set sign big
3191da177e4SLinus Torvalds	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
3201da177e4SLinus Torvaldssmod_fsn:
3211da177e4SLinus Torvalds	tstb	DTAG(%a6)	|filter out denormal destination case
3221da177e4SLinus Torvalds	bpls	smod_nrm	|
3231da177e4SLinus Torvalds	leal	FPTEMP(%a6),%a0	|a0<- addr(FPTEMP)
3241da177e4SLinus Torvalds	bra	t_resdnrm	|force UNFL(but exact) result
3251da177e4SLinus Torvaldssmod_nrm:
3261da177e4SLinus Torvalds	fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
3271da177e4SLinus Torvalds	fmovex FPTEMP(%a6),%fp0	|return dest to fp0
3281da177e4SLinus Torvalds	rts
3291da177e4SLinus Torvalds
3301da177e4SLinus Torvalds|
3311da177e4SLinus Torvalds|	FREM
3321da177e4SLinus Torvalds|
3331da177e4SLinus Torvaldspremt:
3341da177e4SLinus Torvalds|				;$25 frem
3351da177e4SLinus Torvalds|				;dtag,stag
3361da177e4SLinus Torvalds	.long	srem		|  00,00  norm,norm = normal
3371da177e4SLinus Torvalds	.long	srem_oper	|  00,01  norm,zero = nan with operr
3381da177e4SLinus Torvalds	.long	srem_fpn	|  00,10  norm,inf  = fpn
3391da177e4SLinus Torvalds	.long	srem_snan	|  00,11  norm,nan  = nan
3401da177e4SLinus Torvalds	.long	srem_zro	|  01,00  zero,norm = +-zero
3411da177e4SLinus Torvalds	.long	srem_oper	|  01,01  zero,zero = nan with operr
3421da177e4SLinus Torvalds	.long	srem_zro	|  01,10  zero,inf  = +-zero
3431da177e4SLinus Torvalds	.long	srem_snan	|  01,11  zero,nan  = nan
3441da177e4SLinus Torvalds	.long	srem_oper	|  10,00  inf,norm  = nan with operr
3451da177e4SLinus Torvalds	.long	srem_oper	|  10,01  inf,zero  = nan with operr
3461da177e4SLinus Torvalds	.long	srem_oper	|  10,10  inf,inf   = nan with operr
3471da177e4SLinus Torvalds	.long	srem_snan	|  10,11  inf,nan   = nan
3481da177e4SLinus Torvalds	.long	srem_dnan	|  11,00  nan,norm  = nan
3491da177e4SLinus Torvalds	.long	srem_dnan	|  11,01  nan,zero  = nan
3501da177e4SLinus Torvalds	.long	srem_dnan	|  11,10  nan,inf   = nan
3511da177e4SLinus Torvalds	.long	srem_dnan	|  11,11  nan,nan   = nan
3521da177e4SLinus Torvalds
3531da177e4SLinus Torvalds	.global	prem
3541da177e4SLinus Torvaldsprem:
3551da177e4SLinus Torvalds	clrb	FPSR_QBYTE(%a6)   |clear quotient field
3561da177e4SLinus Torvalds	bfextu	STAG(%a6){#0:#3},%d0 |stag = d0
3571da177e4SLinus Torvalds	bfextu	DTAG(%a6){#0:#3},%d1 |dtag = d1
3581da177e4SLinus Torvalds|
3591da177e4SLinus Torvalds| Alias extended denorms to norms for the jump table.
3601da177e4SLinus Torvalds|
3611da177e4SLinus Torvalds	bclr	#2,%d0
3621da177e4SLinus Torvalds	bclr	#2,%d1
3631da177e4SLinus Torvalds
3641da177e4SLinus Torvalds	lslb	#2,%d1
3651da177e4SLinus Torvalds	orb	%d0,%d1		|d1{3:2} = dtag, d1{1:0} = stag
3661da177e4SLinus Torvalds|				;Tag values:
3671da177e4SLinus Torvalds|				;00 = norm or denorm
3681da177e4SLinus Torvalds|				;01 = zero
3691da177e4SLinus Torvalds|				;10 = inf
3701da177e4SLinus Torvalds|				;11 = nan
3711da177e4SLinus Torvalds	lea	premt,%a1
3721da177e4SLinus Torvalds	movel	(%a1,%d1.w*4),%a1
3731da177e4SLinus Torvalds	jmp	(%a1)
3741da177e4SLinus Torvalds
3751da177e4SLinus Torvaldssrem_snan:
3761da177e4SLinus Torvalds	bra	src_nan
3771da177e4SLinus Torvaldssrem_dnan:
3781da177e4SLinus Torvalds	bra	dst_nan
3791da177e4SLinus Torvaldssrem_oper:
3801da177e4SLinus Torvalds	bra	t_operr
3811da177e4SLinus Torvaldssrem_zro:
3821da177e4SLinus Torvalds	moveb	ETEMP(%a6),%d1	|get sign of src op
3831da177e4SLinus Torvalds	moveb	FPTEMP(%a6),%d0	|get sign of dst op
3841da177e4SLinus Torvalds	eorb	%d0,%d1		|get exor of sign bits
3851da177e4SLinus Torvalds	btstl	#7,%d1		|test for sign
3861da177e4SLinus Torvalds	beqs	srem_zsn	|if clr, do not set sign big
3871da177e4SLinus Torvalds	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
3881da177e4SLinus Torvaldssrem_zsn:
3891da177e4SLinus Torvalds	btstl	#7,%d0		|test if + or -
3901da177e4SLinus Torvalds	beq	ld_pzero	|if pos then load +0
3911da177e4SLinus Torvalds	bra	ld_mzero	|else neg load -0
3921da177e4SLinus Torvalds
3931da177e4SLinus Torvaldssrem_fpn:
3941da177e4SLinus Torvalds	moveb	ETEMP(%a6),%d1	|get sign of src op
3951da177e4SLinus Torvalds	moveb	FPTEMP(%a6),%d0	|get sign of dst op
3961da177e4SLinus Torvalds	eorb	%d0,%d1		|get exor of sign bits
3971da177e4SLinus Torvalds	btstl	#7,%d1		|test for sign
3981da177e4SLinus Torvalds	beqs	srem_fsn	|if clr, do not set sign big
3991da177e4SLinus Torvalds	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
4001da177e4SLinus Torvaldssrem_fsn:
4011da177e4SLinus Torvalds	tstb	DTAG(%a6)	|filter out denormal destination case
4021da177e4SLinus Torvalds	bpls	srem_nrm	|
4031da177e4SLinus Torvalds	leal	FPTEMP(%a6),%a0	|a0<- addr(FPTEMP)
4041da177e4SLinus Torvalds	bra	t_resdnrm	|force UNFL(but exact) result
4051da177e4SLinus Torvaldssrem_nrm:
4061da177e4SLinus Torvalds	fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
4071da177e4SLinus Torvalds	fmovex FPTEMP(%a6),%fp0	|return dest to fp0
4081da177e4SLinus Torvalds	rts
4091da177e4SLinus Torvalds|
4101da177e4SLinus Torvalds|	FSCALE
4111da177e4SLinus Torvalds|
4121da177e4SLinus Torvaldspscalet:
4131da177e4SLinus Torvalds|				;$26 fscale
4141da177e4SLinus Torvalds|				;dtag,stag
4151da177e4SLinus Torvalds	.long	sscale		|  00,00  norm,norm = result
4161da177e4SLinus Torvalds	.long	sscale		|  00,01  norm,zero = fpn
4171da177e4SLinus Torvalds	.long	scl_opr		|  00,10  norm,inf  = nan with operr
4181da177e4SLinus Torvalds	.long	scl_snan	|  00,11  norm,nan  = nan
4191da177e4SLinus Torvalds	.long	scl_zro		|  01,00  zero,norm = +-zero
4201da177e4SLinus Torvalds	.long	scl_zro		|  01,01  zero,zero = +-zero
4211da177e4SLinus Torvalds	.long	scl_opr		|  01,10  zero,inf  = nan with operr
4221da177e4SLinus Torvalds	.long	scl_snan	|  01,11  zero,nan  = nan
4231da177e4SLinus Torvalds	.long	scl_inf		|  10,00  inf,norm  = +-inf
4241da177e4SLinus Torvalds	.long	scl_inf		|  10,01  inf,zero  = +-inf
4251da177e4SLinus Torvalds	.long	scl_opr		|  10,10  inf,inf   = nan with operr
4261da177e4SLinus Torvalds	.long	scl_snan	|  10,11  inf,nan   = nan
4271da177e4SLinus Torvalds	.long	scl_dnan	|  11,00  nan,norm  = nan
4281da177e4SLinus Torvalds	.long	scl_dnan	|  11,01  nan,zero  = nan
4291da177e4SLinus Torvalds	.long	scl_dnan	|  11,10  nan,inf   = nan
4301da177e4SLinus Torvalds	.long	scl_dnan	|  11,11  nan,nan   = nan
4311da177e4SLinus Torvalds
4321da177e4SLinus Torvalds	.global	pscale
4331da177e4SLinus Torvaldspscale:
4341da177e4SLinus Torvalds	bfextu	STAG(%a6){#0:#3},%d0 |stag in d0
4351da177e4SLinus Torvalds	bfextu	DTAG(%a6){#0:#3},%d1 |dtag in d1
4361da177e4SLinus Torvalds	bclrl	#2,%d0		|alias  denorm into norm
4371da177e4SLinus Torvalds	bclrl	#2,%d1		|alias  denorm into norm
4381da177e4SLinus Torvalds	lslb	#2,%d1
4391da177e4SLinus Torvalds	orb	%d0,%d1		|d1{4:2} = dtag, d1{1:0} = stag
4401da177e4SLinus Torvalds|				;dtag values     stag values:
4411da177e4SLinus Torvalds|				;000 = norm      00 = norm
4421da177e4SLinus Torvalds|				;001 = zero	 01 = zero
4431da177e4SLinus Torvalds|				;010 = inf	 10 = inf
4441da177e4SLinus Torvalds|				;011 = nan	 11 = nan
4451da177e4SLinus Torvalds|				;100 = dnrm
4461da177e4SLinus Torvalds|
4471da177e4SLinus Torvalds|
4481da177e4SLinus Torvalds	leal	pscalet,%a1	|load start of jump table
4491da177e4SLinus Torvalds	movel	(%a1,%d1.w*4),%a1	|load a1 with label depending on tag
4501da177e4SLinus Torvalds	jmp	(%a1)		|go to the routine
4511da177e4SLinus Torvalds
4521da177e4SLinus Torvaldsscl_opr:
4531da177e4SLinus Torvalds	bra	t_operr
4541da177e4SLinus Torvalds
4551da177e4SLinus Torvaldsscl_dnan:
4561da177e4SLinus Torvalds	bra	dst_nan
4571da177e4SLinus Torvalds
4581da177e4SLinus Torvaldsscl_zro:
4591da177e4SLinus Torvalds	btstb	#sign_bit,FPTEMP_EX(%a6)	|test if + or -
4601da177e4SLinus Torvalds	beq	ld_pzero		|if pos then load +0
4611da177e4SLinus Torvalds	bra	ld_mzero		|if neg then load -0
4621da177e4SLinus Torvaldsscl_inf:
4631da177e4SLinus Torvalds	btstb	#sign_bit,FPTEMP_EX(%a6)	|test if + or -
4641da177e4SLinus Torvalds	beq	ld_pinf			|if pos then load +inf
4651da177e4SLinus Torvalds	bra	ld_minf			|else neg load -inf
4661da177e4SLinus Torvaldsscl_snan:
4671da177e4SLinus Torvalds	bra	src_nan
4681da177e4SLinus Torvalds|
4691da177e4SLinus Torvalds|	FSINCOS
4701da177e4SLinus Torvalds|
4711da177e4SLinus Torvalds	.global	ssincosz
4721da177e4SLinus Torvaldsssincosz:
4731da177e4SLinus Torvalds	btstb	#sign_bit,ETEMP(%a6)	|get sign
4741da177e4SLinus Torvalds	beqs	sincosp
4751da177e4SLinus Torvalds	fmovex	MZERO,%fp0
4761da177e4SLinus Torvalds	bras	sincoscom
4771da177e4SLinus Torvaldssincosp:
4781da177e4SLinus Torvalds	fmovex PZERO,%fp0
4791da177e4SLinus Torvaldssincoscom:
4801da177e4SLinus Torvalds	fmovemx PONE,%fp1-%fp1	|do not allow FPSR to be affected
4811da177e4SLinus Torvalds	bra	sto_cos		|store cosine result
4821da177e4SLinus Torvalds
4831da177e4SLinus Torvalds	.global	ssincosi
4841da177e4SLinus Torvaldsssincosi:
4851da177e4SLinus Torvalds	fmovex QNAN,%fp1	|load NAN
4861da177e4SLinus Torvalds	bsr	sto_cos		|store cosine result
4871da177e4SLinus Torvalds	fmovex QNAN,%fp0	|load NAN
4881da177e4SLinus Torvalds	bra	t_operr
4891da177e4SLinus Torvalds
4901da177e4SLinus Torvalds	.global	ssincosnan
4911da177e4SLinus Torvaldsssincosnan:
4921da177e4SLinus Torvalds	movel	ETEMP_EX(%a6),FP_SCR1(%a6)
4931da177e4SLinus Torvalds	movel	ETEMP_HI(%a6),FP_SCR1+4(%a6)
4941da177e4SLinus Torvalds	movel	ETEMP_LO(%a6),FP_SCR1+8(%a6)
4951da177e4SLinus Torvalds	bsetb	#signan_bit,FP_SCR1+4(%a6)
4961da177e4SLinus Torvalds	fmovemx FP_SCR1(%a6),%fp1-%fp1
4971da177e4SLinus Torvalds	bsr	sto_cos
4981da177e4SLinus Torvalds	bra	src_nan
4991da177e4SLinus Torvalds|
5001da177e4SLinus Torvalds| This code forces default values for the zero, inf, and nan cases
5011da177e4SLinus Torvalds| in the transcendentals code.  The CC bits must be set in the
5021da177e4SLinus Torvalds| stacked FPSR to be correctly reported.
5031da177e4SLinus Torvalds|
5041da177e4SLinus Torvalds|**Returns +PI/2
5051da177e4SLinus Torvalds	.global	ld_ppi2
5061da177e4SLinus Torvaldsld_ppi2:
5071da177e4SLinus Torvalds	fmovex PPIBY2,%fp0		|load +pi/2
5081da177e4SLinus Torvalds	bra	t_inx2			|set inex2 exc
5091da177e4SLinus Torvalds
5101da177e4SLinus Torvalds|**Returns -PI/2
5111da177e4SLinus Torvalds	.global	ld_mpi2
5121da177e4SLinus Torvaldsld_mpi2:
5131da177e4SLinus Torvalds	fmovex MPIBY2,%fp0		|load -pi/2
5141da177e4SLinus Torvalds	orl	#neg_mask,USER_FPSR(%a6)	|set N bit
5151da177e4SLinus Torvalds	bra	t_inx2			|set inex2 exc
5161da177e4SLinus Torvalds
5171da177e4SLinus Torvalds|**Returns +inf
5181da177e4SLinus Torvalds	.global	ld_pinf
5191da177e4SLinus Torvaldsld_pinf:
5201da177e4SLinus Torvalds	fmovex PINF,%fp0		|load +inf
5211da177e4SLinus Torvalds	orl	#inf_mask,USER_FPSR(%a6)	|set I bit
5221da177e4SLinus Torvalds	rts
5231da177e4SLinus Torvalds
5241da177e4SLinus Torvalds|**Returns -inf
5251da177e4SLinus Torvalds	.global	ld_minf
5261da177e4SLinus Torvaldsld_minf:
5271da177e4SLinus Torvalds	fmovex MINF,%fp0		|load -inf
5281da177e4SLinus Torvalds	orl	#neg_mask+inf_mask,USER_FPSR(%a6)	|set N and I bits
5291da177e4SLinus Torvalds	rts
5301da177e4SLinus Torvalds
5311da177e4SLinus Torvalds|**Returns +1
5321da177e4SLinus Torvalds	.global	ld_pone
5331da177e4SLinus Torvaldsld_pone:
5341da177e4SLinus Torvalds	fmovex PONE,%fp0		|load +1
5351da177e4SLinus Torvalds	rts
5361da177e4SLinus Torvalds
5371da177e4SLinus Torvalds|**Returns -1
5381da177e4SLinus Torvalds	.global	ld_mone
5391da177e4SLinus Torvaldsld_mone:
5401da177e4SLinus Torvalds	fmovex MONE,%fp0		|load -1
5411da177e4SLinus Torvalds	orl	#neg_mask,USER_FPSR(%a6)	|set N bit
5421da177e4SLinus Torvalds	rts
5431da177e4SLinus Torvalds
5441da177e4SLinus Torvalds|**Returns +0
5451da177e4SLinus Torvalds	.global	ld_pzero
5461da177e4SLinus Torvaldsld_pzero:
5471da177e4SLinus Torvalds	fmovex PZERO,%fp0		|load +0
5481da177e4SLinus Torvalds	orl	#z_mask,USER_FPSR(%a6)	|set Z bit
5491da177e4SLinus Torvalds	rts
5501da177e4SLinus Torvalds
5511da177e4SLinus Torvalds|**Returns -0
5521da177e4SLinus Torvalds	.global	ld_mzero
5531da177e4SLinus Torvaldsld_mzero:
5541da177e4SLinus Torvalds	fmovex MZERO,%fp0		|load -0
5551da177e4SLinus Torvalds	orl	#neg_mask+z_mask,USER_FPSR(%a6)	|set N and Z bits
5561da177e4SLinus Torvalds	rts
5571da177e4SLinus Torvalds
5581da177e4SLinus Torvalds	|end
559