patch-1.3.94 linux/arch/m68k/fpsp040/do_func.S

Next file: linux/arch/m68k/fpsp040/fpsp.h
Previous file: linux/arch/m68k/fpsp040/decbin.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.93/linux/arch/m68k/fpsp040/do_func.S linux/arch/m68k/fpsp040/do_func.S
@@ -0,0 +1,559 @@
+|
+|	do_func.sa 3.4 2/18/91
+|
+| Do_func performs the unimplemented operation.  The operation
+| to be performed is determined from the lower 7 bits of the
+| extension word (except in the case of fmovecr and fsincos).
+| The opcode and tag bits form an index into a jump table in 
+| tbldo.sa.  Cases of zero, infinity and NaN are handled in 
+| do_func by forcing the default result.  Normalized and
+| denormalized (there are no unnormalized numbers at this
+| point) are passed onto the emulation code.  
+|
+| CMDREG1B and STAG are extracted from the fsave frame
+| and combined to form the table index.  The function called
+| will start with a0 pointing to the ETEMP operand.  Dyadic
+| functions can find FPTEMP at -12(a0).
+|
+| Called functions return their result in fp0.  Sincos returns
+| sin(x) in fp0 and cos(x) in fp1.
+|
+
+|		Copyright (C) Motorola, Inc. 1990
+|			All Rights Reserved
+|
+|	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
+|	The copyright notice above does not evidence any  
+|	actual or intended publication of such source code.
+
+DO_FUNC:	|idnt    2,1 | Motorola 040 Floating Point Software Package
+
+	|section	8
+
+	.include "fpsp.h"
+
+	|xref	t_dz2
+	|xref	t_operr
+	|xref	t_inx2
+	|xref 	t_resdnrm
+	|xref	dst_nan
+	|xref	src_nan
+	|xref	nrm_set
+	|xref	sto_cos
+
+	|xref	tblpre
+	|xref	slognp1,slogn,slog10,slog2
+	|xref	slognd,slog10d,slog2d
+	|xref	smod,srem
+	|xref	sscale
+	|xref	smovcr
+
+PONE:	.long	0x3fff0000,0x80000000,0x00000000	|+1
+MONE:	.long	0xbfff0000,0x80000000,0x00000000	|-1
+PZERO:	.long	0x00000000,0x00000000,0x00000000	|+0
+MZERO:	.long	0x80000000,0x00000000,0x00000000	|-0
+PINF:	.long	0x7fff0000,0x00000000,0x00000000	|+inf
+MINF:	.long	0xffff0000,0x00000000,0x00000000	|-inf
+QNAN:	.long	0x7fff0000,0xffffffff,0xffffffff	|non-signaling nan
+PPIBY2:  .long	0x3FFF0000,0xC90FDAA2,0x2168C235	|+PI/2
+MPIBY2:  .long	0xbFFF0000,0xC90FDAA2,0x2168C235	|-PI/2
+
+	.global	do_func
+do_func:
+	clrb	CU_ONLY(%a6)
+|
+| Check for fmovecr.  It does not follow the format of fp gen
+| unimplemented instructions.  The test is on the upper 6 bits;
+| if they are $17, the inst is fmovecr.  Call entry smovcr
+| directly.
+|
+	bfextu	CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
+	cmpil	#0x17,%d0		|if op class and size fields are $17, 
+|				;it is FMOVECR; if not, continue
+	bnes	not_fmovecr
+	jmp	smovcr		|fmovecr; jmp directly to emulation
+
+not_fmovecr:
+	movew	CMDREG1B(%a6),%d0
+	andl	#0x7F,%d0
+	cmpil	#0x38,%d0		|if the extension is >= $38, 
+	bges	serror		|it is illegal
+	bfextu	STAG(%a6){#0:#3},%d1
+	lsll	#3,%d0		|make room for STAG
+	addl	%d1,%d0		|combine for final index into table
+	leal	tblpre,%a1	|start of monster jump table
+	movel	(%a1,%d0.w*4),%a1	|real target address
+	leal	ETEMP(%a6),%a0	|a0 is pointer to src op
+	movel	USER_FPCR(%a6),%d1
+	andl	#0xFF,%d1		| discard all but rounding mode/prec
+	fmovel	#0,%fpcr
+	jmp	(%a1)
+|
+|	ERROR
+|
+	.global	serror
+serror:
+	st	STORE_FLG(%a6)
+	rts
+|
+| These routines load forced values into fp0.  They are called
+| by index into tbldo.
+|
+| Load a signed zero to fp0 and set inex2/ainex
+|
+	.global	snzrinx
+snzrinx:
+	btstb	#sign_bit,LOCAL_EX(%a0)	|get sign of source operand
+	bnes	ld_mzinx	|if negative, branch
+	bsr	ld_pzero	|bsr so we can return and set inx
+	bra	t_inx2		|now, set the inx for the next inst
+ld_mzinx:
+	bsr	ld_mzero	|if neg, load neg zero, return here
+	bra	t_inx2		|now, set the inx for the next inst
+|
+| Load a signed zero to fp0; do not set inex2/ainex 
+|
+	.global	szero
+szero:
+	btstb	#sign_bit,LOCAL_EX(%a0) |get sign of source operand
+	bne	ld_mzero	|if neg, load neg zero
+	bra	ld_pzero	|load positive zero
+|
+| Load a signed infinity to fp0; do not set inex2/ainex 
+|
+	.global	sinf
+sinf:
+	btstb	#sign_bit,LOCAL_EX(%a0)	|get sign of source operand
+	bne	ld_minf			|if negative branch
+	bra	ld_pinf
+|
+| Load a signed one to fp0; do not set inex2/ainex 
+|
+	.global	sone
+sone:
+	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
+	bne	ld_mone
+	bra	ld_pone
+|
+| Load a signed pi/2 to fp0; do not set inex2/ainex 
+|
+	.global	spi_2
+spi_2:
+	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
+	bne	ld_mpi2
+	bra	ld_ppi2
+|
+| Load either a +0 or +inf for plus/minus operand
+|
+	.global	szr_inf
+szr_inf:
+	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
+	bne	ld_pzero
+	bra	ld_pinf
+|
+| Result is either an operr or +inf for plus/minus operand
+| [Used by slogn, slognp1, slog10, and slog2]
+|
+	.global	sopr_inf
+sopr_inf:
+	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
+	bne	t_operr
+	bra	ld_pinf
+|
+|	FLOGNP1 
+|
+	.global	sslognp1
+sslognp1:
+	fmovemx (%a0),%fp0-%fp0
+	fcmpb	#-1,%fp0
+	fbgt	slognp1		
+	fbeq	t_dz2		|if = -1, divide by zero exception
+	fmovel	#0,%FPSR		|clr N flag
+	bra	t_operr		|take care of operands < -1
+|
+|	FETOXM1
+|
+	.global	setoxm1i
+setoxm1i:
+	btstb	#sign_bit,LOCAL_EX(%a0)	|check sign of source
+	bne	ld_mone
+	bra	ld_pinf
+|
+|	FLOGN
+|
+| Test for 1.0 as an input argument, returning +zero.  Also check
+| the sign and return operr if negative.
+|
+	.global	sslogn
+sslogn:
+	btstb	#sign_bit,LOCAL_EX(%a0) 
+	bne	t_operr		|take care of operands < 0
+	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
+	bne	slogn
+	cmpil	#0x80000000,LOCAL_HI(%a0)
+	bne	slogn
+	tstl	LOCAL_LO(%a0)
+	bne	slogn
+	fmovex	PZERO,%fp0
+	rts
+
+	.global	sslognd
+sslognd:
+	btstb	#sign_bit,LOCAL_EX(%a0) 
+	beq	slognd
+	bra	t_operr		|take care of operands < 0
+
+|
+|	FLOG10
+|
+	.global	sslog10
+sslog10:
+	btstb	#sign_bit,LOCAL_EX(%a0)
+	bne	t_operr		|take care of operands < 0
+	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
+	bne	slog10
+	cmpil	#0x80000000,LOCAL_HI(%a0)
+	bne	slog10
+	tstl	LOCAL_LO(%a0)
+	bne	slog10
+	fmovex	PZERO,%fp0
+	rts
+
+	.global	sslog10d
+sslog10d:
+	btstb	#sign_bit,LOCAL_EX(%a0) 
+	beq	slog10d
+	bra	t_operr		|take care of operands < 0
+
+|
+|	FLOG2
+|
+	.global	sslog2
+sslog2:
+	btstb	#sign_bit,LOCAL_EX(%a0)
+	bne	t_operr		|take care of operands < 0
+	cmpiw	#0x3fff,LOCAL_EX(%a0) |test for 1.0 input
+	bne	slog2
+	cmpil	#0x80000000,LOCAL_HI(%a0)
+	bne	slog2
+	tstl	LOCAL_LO(%a0)
+	bne	slog2
+	fmovex	PZERO,%fp0
+	rts
+
+	.global	sslog2d
+sslog2d:
+	btstb	#sign_bit,LOCAL_EX(%a0) 
+	beq	slog2d
+	bra	t_operr		|take care of operands < 0
+
+|
+|	FMOD
+|
+pmodt:
+|				;$21 fmod
+|				;dtag,stag
+	.long	smod		|  00,00  norm,norm = normal
+	.long	smod_oper	|  00,01  norm,zero = nan with operr
+	.long	smod_fpn	|  00,10  norm,inf  = fpn
+	.long	smod_snan	|  00,11  norm,nan  = nan
+	.long	smod_zro	|  01,00  zero,norm = +-zero
+	.long	smod_oper	|  01,01  zero,zero = nan with operr
+	.long	smod_zro	|  01,10  zero,inf  = +-zero
+	.long	smod_snan	|  01,11  zero,nan  = nan
+	.long	smod_oper	|  10,00  inf,norm  = nan with operr
+	.long	smod_oper	|  10,01  inf,zero  = nan with operr
+	.long	smod_oper	|  10,10  inf,inf   = nan with operr
+	.long	smod_snan	|  10,11  inf,nan   = nan
+	.long	smod_dnan	|  11,00  nan,norm  = nan
+	.long	smod_dnan	|  11,01  nan,zero  = nan
+	.long	smod_dnan	|  11,10  nan,inf   = nan
+	.long	smod_dnan	|  11,11  nan,nan   = nan
+
+	.global	pmod
+pmod:
+	clrb	FPSR_QBYTE(%a6) | clear quotient field
+	bfextu	STAG(%a6){#0:#3},%d0 |stag = d0
+	bfextu	DTAG(%a6){#0:#3},%d1 |dtag = d1
+
+|
+| Alias extended denorms to norms for the jump table.
+|
+	bclrl	#2,%d0
+	bclrl	#2,%d1
+
+	lslb	#2,%d1
+	orb	%d0,%d1		|d1{3:2} = dtag, d1{1:0} = stag
+|				;Tag values:
+|				;00 = norm or denorm
+|				;01 = zero
+|				;10 = inf
+|				;11 = nan
+	lea	pmodt,%a1
+	movel	(%a1,%d1.w*4),%a1
+	jmp	(%a1)
+
+smod_snan:
+	bra	src_nan
+smod_dnan:
+	bra	dst_nan
+smod_oper:
+	bra	t_operr
+smod_zro:
+	moveb	ETEMP(%a6),%d1	|get sign of src op
+	moveb	FPTEMP(%a6),%d0	|get sign of dst op
+	eorb	%d0,%d1		|get exor of sign bits
+	btstl	#7,%d1		|test for sign
+	beqs	smod_zsn	|if clr, do not set sign big
+	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
+smod_zsn:
+	btstl	#7,%d0		|test if + or -
+	beq	ld_pzero	|if pos then load +0
+	bra	ld_mzero	|else neg load -0
+	
+smod_fpn:
+	moveb	ETEMP(%a6),%d1	|get sign of src op
+	moveb	FPTEMP(%a6),%d0	|get sign of dst op
+	eorb	%d0,%d1		|get exor of sign bits
+	btstl	#7,%d1		|test for sign
+	beqs	smod_fsn	|if clr, do not set sign big
+	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
+smod_fsn:
+	tstb	DTAG(%a6)	|filter out denormal destination case
+	bpls	smod_nrm	|
+	leal	FPTEMP(%a6),%a0	|a0<- addr(FPTEMP)
+	bra	t_resdnrm	|force UNFL(but exact) result
+smod_nrm:
+	fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
+	fmovex FPTEMP(%a6),%fp0	|return dest to fp0
+	rts
+		
+|
+|	FREM
+|
+premt:
+|				;$25 frem
+|				;dtag,stag
+	.long	srem		|  00,00  norm,norm = normal
+	.long	srem_oper	|  00,01  norm,zero = nan with operr
+	.long	srem_fpn	|  00,10  norm,inf  = fpn
+	.long	srem_snan	|  00,11  norm,nan  = nan
+	.long	srem_zro	|  01,00  zero,norm = +-zero
+	.long	srem_oper	|  01,01  zero,zero = nan with operr
+	.long	srem_zro	|  01,10  zero,inf  = +-zero
+	.long	srem_snan	|  01,11  zero,nan  = nan
+	.long	srem_oper	|  10,00  inf,norm  = nan with operr
+	.long	srem_oper	|  10,01  inf,zero  = nan with operr
+	.long	srem_oper	|  10,10  inf,inf   = nan with operr
+	.long	srem_snan	|  10,11  inf,nan   = nan
+	.long	srem_dnan	|  11,00  nan,norm  = nan
+	.long	srem_dnan	|  11,01  nan,zero  = nan
+	.long	srem_dnan	|  11,10  nan,inf   = nan
+	.long	srem_dnan	|  11,11  nan,nan   = nan
+
+	.global	prem
+prem:
+	clrb	FPSR_QBYTE(%a6)   |clear quotient field
+	bfextu	STAG(%a6){#0:#3},%d0 |stag = d0
+	bfextu	DTAG(%a6){#0:#3},%d1 |dtag = d1
+|
+| Alias extended denorms to norms for the jump table.
+|
+	bclr	#2,%d0
+	bclr	#2,%d1
+
+	lslb	#2,%d1
+	orb	%d0,%d1		|d1{3:2} = dtag, d1{1:0} = stag
+|				;Tag values:
+|				;00 = norm or denorm
+|				;01 = zero
+|				;10 = inf
+|				;11 = nan
+	lea	premt,%a1
+	movel	(%a1,%d1.w*4),%a1
+	jmp	(%a1)
+	
+srem_snan:
+	bra	src_nan
+srem_dnan:
+	bra	dst_nan
+srem_oper:
+	bra	t_operr
+srem_zro:
+	moveb	ETEMP(%a6),%d1	|get sign of src op
+	moveb	FPTEMP(%a6),%d0	|get sign of dst op
+	eorb	%d0,%d1		|get exor of sign bits
+	btstl	#7,%d1		|test for sign
+	beqs	srem_zsn	|if clr, do not set sign big
+	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
+srem_zsn:
+	btstl	#7,%d0		|test if + or -
+	beq	ld_pzero	|if pos then load +0
+	bra	ld_mzero	|else neg load -0
+	
+srem_fpn:
+	moveb	ETEMP(%a6),%d1	|get sign of src op
+	moveb	FPTEMP(%a6),%d0	|get sign of dst op
+	eorb	%d0,%d1		|get exor of sign bits
+	btstl	#7,%d1		|test for sign
+	beqs	srem_fsn	|if clr, do not set sign big
+	bsetb	#q_sn_bit,FPSR_QBYTE(%a6) |set q-byte sign bit
+srem_fsn:
+	tstb	DTAG(%a6)	|filter out denormal destination case
+	bpls	srem_nrm	|
+	leal	FPTEMP(%a6),%a0	|a0<- addr(FPTEMP)
+	bra	t_resdnrm	|force UNFL(but exact) result
+srem_nrm:
+	fmovel USER_FPCR(%a6),%fpcr |use user's rmode and precision
+	fmovex FPTEMP(%a6),%fp0	|return dest to fp0
+	rts
+|
+|	FSCALE
+|
+pscalet:
+|				;$26 fscale
+|				;dtag,stag
+	.long	sscale		|  00,00  norm,norm = result
+	.long	sscale		|  00,01  norm,zero = fpn
+	.long	scl_opr		|  00,10  norm,inf  = nan with operr
+	.long	scl_snan	|  00,11  norm,nan  = nan
+	.long	scl_zro		|  01,00  zero,norm = +-zero
+	.long	scl_zro		|  01,01  zero,zero = +-zero
+	.long	scl_opr		|  01,10  zero,inf  = nan with operr
+	.long	scl_snan	|  01,11  zero,nan  = nan
+	.long	scl_inf		|  10,00  inf,norm  = +-inf
+	.long	scl_inf		|  10,01  inf,zero  = +-inf
+	.long	scl_opr		|  10,10  inf,inf   = nan with operr
+ 	.long	scl_snan	|  10,11  inf,nan   = nan
+ 	.long	scl_dnan	|  11,00  nan,norm  = nan
+ 	.long	scl_dnan	|  11,01  nan,zero  = nan
+ 	.long	scl_dnan	|  11,10  nan,inf   = nan
+	.long	scl_dnan	|  11,11  nan,nan   = nan
+
+	.global	pscale
+pscale:
+	bfextu	STAG(%a6){#0:#3},%d0 |stag in d0
+	bfextu	DTAG(%a6){#0:#3},%d1 |dtag in d1
+	bclrl	#2,%d0		|alias  denorm into norm
+	bclrl	#2,%d1		|alias  denorm into norm
+	lslb	#2,%d1
+	orb	%d0,%d1		|d1{4:2} = dtag, d1{1:0} = stag
+|				;dtag values     stag values:
+|				;000 = norm      00 = norm
+|				;001 = zero	 01 = zero
+|				;010 = inf	 10 = inf
+|				;011 = nan	 11 = nan
+|				;100 = dnrm
+|
+|
+	leal	pscalet,%a1	|load start of jump table
+	movel	(%a1,%d1.w*4),%a1	|load a1 with label depending on tag
+	jmp	(%a1)		|go to the routine
+
+scl_opr:
+	bra	t_operr
+
+scl_dnan:
+	bra	dst_nan
+
+scl_zro:
+	btstb	#sign_bit,FPTEMP_EX(%a6)	|test if + or -
+	beq	ld_pzero		|if pos then load +0
+	bra	ld_mzero		|if neg then load -0
+scl_inf:
+	btstb	#sign_bit,FPTEMP_EX(%a6)	|test if + or -
+	beq	ld_pinf			|if pos then load +inf
+	bra	ld_minf			|else neg load -inf
+scl_snan:
+	bra	src_nan
+|
+|	FSINCOS
+|
+	.global	ssincosz
+ssincosz:
+	btstb	#sign_bit,ETEMP(%a6)	|get sign
+	beqs	sincosp
+	fmovex	MZERO,%fp0
+	bras	sincoscom
+sincosp:
+	fmovex PZERO,%fp0
+sincoscom:
+  	fmovemx PONE,%fp1-%fp1	|do not allow FPSR to be affected
+	bra	sto_cos		|store cosine result
+
+	.global	ssincosi
+ssincosi:
+	fmovex QNAN,%fp1	|load NAN
+	bsr	sto_cos		|store cosine result
+	fmovex QNAN,%fp0	|load NAN
+	bra	t_operr
+
+	.global	ssincosnan
+ssincosnan:
+	movel	ETEMP_EX(%a6),FP_SCR1(%a6)
+	movel	ETEMP_HI(%a6),FP_SCR1+4(%a6)
+	movel	ETEMP_LO(%a6),FP_SCR1+8(%a6)
+	bsetb	#signan_bit,FP_SCR1+4(%a6)
+	fmovemx FP_SCR1(%a6),%fp1-%fp1
+	bsr	sto_cos
+	bra	src_nan
+|
+| This code forces default values for the zero, inf, and nan cases 
+| in the transcendentals code.  The CC bits must be set in the
+| stacked FPSR to be correctly reported.
+|
+|**Returns +PI/2
+	.global	ld_ppi2
+ld_ppi2:
+	fmovex PPIBY2,%fp0		|load +pi/2
+	bra	t_inx2			|set inex2 exc
+
+|**Returns -PI/2
+	.global	ld_mpi2
+ld_mpi2:
+	fmovex MPIBY2,%fp0		|load -pi/2
+	orl	#neg_mask,USER_FPSR(%a6)	|set N bit
+	bra	t_inx2			|set inex2 exc
+
+|**Returns +inf
+	.global	ld_pinf
+ld_pinf:
+	fmovex PINF,%fp0		|load +inf
+	orl	#inf_mask,USER_FPSR(%a6)	|set I bit
+	rts
+
+|**Returns -inf
+	.global	ld_minf
+ld_minf:
+	fmovex MINF,%fp0		|load -inf
+	orl	#neg_mask+inf_mask,USER_FPSR(%a6)	|set N and I bits
+	rts
+
+|**Returns +1
+	.global	ld_pone
+ld_pone:
+	fmovex PONE,%fp0		|load +1
+	rts
+
+|**Returns -1
+	.global	ld_mone
+ld_mone:
+	fmovex MONE,%fp0		|load -1
+	orl	#neg_mask,USER_FPSR(%a6)	|set N bit
+	rts
+
+|**Returns +0
+	.global	ld_pzero
+ld_pzero:
+	fmovex PZERO,%fp0		|load +0
+	orl	#z_mask,USER_FPSR(%a6)	|set Z bit
+	rts
+
+|**Returns -0
+	.global	ld_mzero
+ld_mzero:
+	fmovex MZERO,%fp0		|load -0
+	orl	#neg_mask+z_mask,USER_FPSR(%a6)	|set N and Z bits
+	rts
+
+	|end

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this