⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 res_func.s

📁 自己根据lkd和情境分析
💻 S
📖 第 1 页 / 共 4 页
字号:
||	res_func.sa 3.9 7/29/91|| Normalizes denormalized numbers if necessary and updates the| stack frame.  The function is then restored back into the| machine and the 040 completes the operation.  This routine| is only used by the unsupported data type/format handler.| (Exception vector 55).|| For packed move out (fmove.p fpm,<ea>) the operation is| completed here; data is packed and moved to user memory. | The stack is restored to the 040 only in the case of a| reportable exception in the conversion.|||		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.RES_FUNC:    |idnt    2,1 | Motorola 040 Floating Point Software Package	|section	8	.include "fpsp.h"sp_bnds:	.short	0x3f81,0x407e		.short	0x3f6a,0x0000dp_bnds:	.short	0x3c01,0x43fe		.short	0x3bcd,0x0000	|xref	mem_write	|xref	bindec	|xref	get_fline	|xref	round	|xref	denorm	|xref	dest_ext	|xref	dest_dbl	|xref	dest_sgl	|xref	unf_sub	|xref	nrm_set	|xref	dnrm_lp	|xref	ovf_res	|xref	reg_dest	|xref	t_ovfl	|xref	t_unfl	.global	res_func	.global 	p_moveres_func:	clrb	DNRM_FLG(%a6)	clrb	RES_FLG(%a6)	clrb	CU_ONLY(%a6)	tstb	DY_MO_FLG(%a6)	beqs	monadicdyadic:	btstb	#7,DTAG(%a6)	|if dop = norm=000, zero=001,|				;inf=010 or nan=011	beqs	monadic		|then branch|				;else denorm| HANDLE DESTINATION DENORM HERE|				;set dtag to norm|				;write the tag & fpte15 to the fstack	leal	FPTEMP(%a6),%a0	bclrb	#sign_bit,LOCAL_EX(%a0)	sne	LOCAL_SGN(%a0)	bsr	nrm_set		|normalize number (exp will go negative)	bclrb	#sign_bit,LOCAL_EX(%a0) |get rid of false sign	bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format	beqs	dpos	bsetb	#sign_bit,LOCAL_EX(%a0)dpos:	bfclr	DTAG(%a6){#0:#4}	|set tag to normalized, FPTE15 = 0	bsetb	#4,DTAG(%a6)	|set FPTE15	orb	#0x0f,DNRM_FLG(%a6)monadic:	leal	ETEMP(%a6),%a0	btstb	#direction_bit,CMDREG1B(%a6)	|check direction	bne	opclass3			|it is a mv out|| At this point, only opclass 0 and 2 possible|	btstb	#7,STAG(%a6)	|if sop = norm=000, zero=001,|				;inf=010 or nan=011	bne	mon_dnrm	|else denorm	tstb	DY_MO_FLG(%a6)	|all cases of dyadic instructions would	bne	normal		|require normalization of denorm| At this point:|	monadic instructions:	fabs  = $18  fneg   = $1a  ftst   = $3a|				fmove = $00  fsmove = $40  fdmove = $44|				fsqrt = $05* fssqrt = $41  fdsqrt = $45|				(*fsqrt reencoded to $05)|	movew	CMDREG1B(%a6),%d0	|get command register	andil	#0x7f,%d0			|strip to only command word|| At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and | fdsqrt are possible.| For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize)| For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize)|	btstl	#0,%d0	bne	normal			|weed out fsqrt instructions|| cu_norm handles fmove in instructions with normalized inputs.| The routine round is used to correctly round the input for the| destination precision and mode.|cu_norm:	st	CU_ONLY(%a6)		|set cu-only inst flag	movew	CMDREG1B(%a6),%d0	andib	#0x3b,%d0		|isolate bits to select inst	tstb	%d0	beql	cu_nmove	|if zero, it is an fmove	cmpib	#0x18,%d0	beql	cu_nabs		|if $18, it is fabs	cmpib	#0x1a,%d0	beql	cu_nneg		|if $1a, it is fneg|| Inst is ftst.  Check the source operand and set the cc's accordingly.| No write is done, so simply rts.|cu_ntst:	movew	LOCAL_EX(%a0),%d0	bclrl	#15,%d0	sne	LOCAL_SGN(%a0)	beqs	cu_ntpo	orl	#neg_mask,USER_FPSR(%a6) |set Ncu_ntpo:	cmpiw	#0x7fff,%d0	|test for inf/nan	bnes	cu_ntcz	tstl	LOCAL_HI(%a0)	bnes	cu_ntn	tstl	LOCAL_LO(%a0)	bnes	cu_ntn	orl	#inf_mask,USER_FPSR(%a6)	rtscu_ntn:	orl	#nan_mask,USER_FPSR(%a6)	movel	ETEMP_EX(%a6),FPTEMP_EX(%a6)	|set up fptemp sign for |						;snan handler	rtscu_ntcz:	tstl	LOCAL_HI(%a0)	bnel	cu_ntsx	tstl	LOCAL_LO(%a0)	bnel	cu_ntsx	orl	#z_mask,USER_FPSR(%a6)cu_ntsx:	rts|| Inst is fabs.  Execute the absolute value function on the input.| Branch to the fmove code.  If the operand is NaN, do nothing.|cu_nabs:	moveb	STAG(%a6),%d0	btstl	#5,%d0			|test for NaN or zero	bne	wr_etemp		|if either, simply write it	bclrb	#7,LOCAL_EX(%a0)		|do abs	bras	cu_nmove		|fmove code will finish|| Inst is fneg.  Execute the negate value function on the input.| Fall though to the fmove code.  If the operand is NaN, do nothing.|cu_nneg:	moveb	STAG(%a6),%d0	btstl	#5,%d0			|test for NaN or zero	bne	wr_etemp		|if either, simply write it	bchgb	#7,LOCAL_EX(%a0)		|do neg|| Inst is fmove.  This code also handles all result writes.| If bit 2 is set, round is forced to double.  If it is clear,| and bit 6 is set, round is forced to single.  If both are clear,| the round precision is found in the fpcr.  If the rounding precision| is double or single, round the result before the write.|cu_nmove:	moveb	STAG(%a6),%d0	andib	#0xe0,%d0			|isolate stag bits	bne	wr_etemp		|if not norm, simply write it	btstb	#2,CMDREG1B+1(%a6)	|check for rd	bne	cu_nmrd	btstb	#6,CMDREG1B+1(%a6)	|check for rs	bne	cu_nmrs|| The move or operation is not with forced precision.  Test for| nan or inf as the input; if so, simply write it to FPn.  Use the| FPCR_MODE byte to get rounding on norms and zeros.|cu_nmnr:	bfextu	FPCR_MODE(%a6){#0:#2},%d0	tstb	%d0			|check for extended	beq	cu_wrexn		|if so, just write result	cmpib	#1,%d0			|check for single	beq	cu_nmrs			|fall through to double|| The move is fdmove or round precision is double.|cu_nmrd:	movel	#2,%d0			|set up the size for denorm	movew	LOCAL_EX(%a0),%d1		|compare exponent to double threshold	andw	#0x7fff,%d1		cmpw	#0x3c01,%d1	bls	cu_nunfl	bfextu	FPCR_MODE(%a6){#2:#2},%d1	|get rmode	orl	#0x00020000,%d1		|or in rprec (double)	clrl	%d0			|clear g,r,s for round	bclrb	#sign_bit,LOCAL_EX(%a0)	|convert to internal format	sne	LOCAL_SGN(%a0)	bsrl	round	bfclr	LOCAL_SGN(%a0){#0:#8}	beqs	cu_nmrdc	bsetb	#sign_bit,LOCAL_EX(%a0)cu_nmrdc:	movew	LOCAL_EX(%a0),%d1		|check for overflow	andw	#0x7fff,%d1	cmpw	#0x43ff,%d1	bge	cu_novfl		|take care of overflow case	bra	cu_wrexn|| The move is fsmove or round precision is single.|cu_nmrs:	movel	#1,%d0	movew	LOCAL_EX(%a0),%d1	andw	#0x7fff,%d1	cmpw	#0x3f81,%d1	bls	cu_nunfl	bfextu	FPCR_MODE(%a6){#2:#2},%d1	orl	#0x00010000,%d1	clrl	%d0	bclrb	#sign_bit,LOCAL_EX(%a0)	sne	LOCAL_SGN(%a0)	bsrl	round	bfclr	LOCAL_SGN(%a0){#0:#8}	beqs	cu_nmrsc	bsetb	#sign_bit,LOCAL_EX(%a0)cu_nmrsc:	movew	LOCAL_EX(%a0),%d1	andw	#0x7FFF,%d1	cmpw	#0x407f,%d1	blt	cu_wrexn|| The operand is above precision boundaries.  Use t_ovfl to| generate the correct value.|cu_novfl:	bsr	t_ovfl	bra	cu_wrexn|| The operand is below precision boundaries.  Use denorm to| generate the correct value.|cu_nunfl:	bclrb	#sign_bit,LOCAL_EX(%a0)	sne	LOCAL_SGN(%a0)	bsr	denorm	bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format	beqs	cu_nucont	bsetb	#sign_bit,LOCAL_EX(%a0)cu_nucont:	bfextu	FPCR_MODE(%a6){#2:#2},%d1	btstb	#2,CMDREG1B+1(%a6)	|check for rd	bne	inst_d	btstb	#6,CMDREG1B+1(%a6)	|check for rs	bne	inst_s	swap	%d1	moveb	FPCR_MODE(%a6),%d1	lsrb	#6,%d1	swap	%d1	bra	inst_sdinst_d:	orl	#0x00020000,%d1	bra	inst_sdinst_s:	orl	#0x00010000,%d1inst_sd:	bclrb	#sign_bit,LOCAL_EX(%a0)	sne	LOCAL_SGN(%a0)	bsrl	round	bfclr	LOCAL_SGN(%a0){#0:#8}	beqs	cu_nuflp	bsetb	#sign_bit,LOCAL_EX(%a0)cu_nuflp:	btstb	#inex2_bit,FPSR_EXCEPT(%a6)	beqs	cu_nuninx	orl	#aunfl_mask,USER_FPSR(%a6) |if the round was inex, set AUNFLcu_nuninx:	tstl	LOCAL_HI(%a0)		|test for zero	bnes	cu_nunzro	tstl	LOCAL_LO(%a0)	bnes	cu_nunzro|| The mantissa is zero from the denorm loop.  Check sign and rmode| to see if rounding should have occurred which would leave the lsb.|	movel	USER_FPCR(%a6),%d0	andil	#0x30,%d0		|isolate rmode	cmpil	#0x20,%d0	blts	cu_nzro	bnes	cu_nrpcu_nrm:	tstw	LOCAL_EX(%a0)	|if positive, set lsb	bges	cu_nzro	btstb	#7,FPCR_MODE(%a6) |check for double	beqs	cu_nincs	bras	cu_nincdcu_nrp:	tstw	LOCAL_EX(%a0)	|if positive, set lsb	blts	cu_nzro	btstb	#7,FPCR_MODE(%a6) |check for double	beqs	cu_nincscu_nincd:	orl	#0x800,LOCAL_LO(%a0) |inc for double	bra	cu_nunzrocu_nincs:	orl	#0x100,LOCAL_HI(%a0) |inc for single	bra	cu_nunzrocu_nzro:	orl	#z_mask,USER_FPSR(%a6)	moveb	STAG(%a6),%d0	andib	#0xe0,%d0	cmpib	#0x40,%d0		|check if input was tagged zero	beqs	cu_numvcu_nunzro:	orl	#unfl_mask,USER_FPSR(%a6) |set unflcu_numv:	movel	(%a0),ETEMP(%a6)	movel	4(%a0),ETEMP_HI(%a6)	movel	8(%a0),ETEMP_LO(%a6)|| Write the result to memory, setting the fpsr cc bits.  NaN and Inf| bypass cu_wrexn.|cu_wrexn:	tstw	LOCAL_EX(%a0)		|test for zero	beqs	cu_wrzero	cmpw	#0x8000,LOCAL_EX(%a0)	|test for zero	bnes	cu_wreoncu_wrzero:	orl	#z_mask,USER_FPSR(%a6)	|set Z bitcu_wreon:	tstw	LOCAL_EX(%a0)	bpl	wr_etemp	orl	#neg_mask,USER_FPSR(%a6)	bra	wr_etemp|| HANDLE SOURCE DENORM HERE||				;clear denorm stag to norm|				;write the new tag & ete15 to the fstackmon_dnrm:|| At this point, check for the cases in which normalizing the | denorm produces incorrect results.|	tstb	DY_MO_FLG(%a6)	|all cases of dyadic instructions would	bnes	nrm_src		|require normalization of denorm| At this point:|	monadic instructions:	fabs  = $18  fneg   = $1a  ftst   = $3a|				fmove = $00  fsmove = $40  fdmove = $44|				fsqrt = $05* fssqrt = $41  fdsqrt = $45|				(*fsqrt reencoded to $05)|	movew	CMDREG1B(%a6),%d0	|get command register	andil	#0x7f,%d0			|strip to only command word|| At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and | fdsqrt are possible.| For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize)| For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize)|	btstl	#0,%d0	bnes	nrm_src		|weed out fsqrt instructions	st	CU_ONLY(%a6)	|set cu-only inst flag	bra	cu_dnrm		|fmove, fabs, fneg, ftst |				;cases go to cu_dnrmnrm_src:	bclrb	#sign_bit,LOCAL_EX(%a0)	sne	LOCAL_SGN(%a0)	bsr	nrm_set		|normalize number (exponent will go |				; negative)	bclrb	#sign_bit,LOCAL_EX(%a0) |get rid of false sign	bfclr	LOCAL_SGN(%a0){#0:#8}	|change back to IEEE ext format	beqs	spos	bsetb	#sign_bit,LOCAL_EX(%a0)spos:	bfclr	STAG(%a6){#0:#4}	|set tag to normalized, FPTE15 = 0	bsetb	#4,STAG(%a6)	|set ETE15	orb	#0xf0,DNRM_FLG(%a6)normal:	tstb	DNRM_FLG(%a6)	|check if any of the ops were denorms	bne	ck_wrap		|if so, check if it is a potential|				;wrap-around casefix_stk:	moveb	#0xfe,CU_SAVEPC(%a6)	bclrb	#E1,E_BYTE(%a6)	clrw	NMNEXC(%a6)	st	RES_FLG(%a6)	|indicate that a restore is needed	rts|| cu_dnrm handles all cu-only instructions (fmove, fabs, fneg, and| ftst) completely in software without an frestore to the 040. |cu_dnrm:	st	CU_ONLY(%a6)	movew	CMDREG1B(%a6),%d0	andib	#0x3b,%d0		|isolate bits to select inst	tstb	%d0	beql	cu_dmove	|if zero, it is an fmove	cmpib	#0x18,%d0	beql	cu_dabs		|if $18, it is fabs	cmpib	#0x1a,%d0	beql	cu_dneg		|if $1a, it is fneg|| Inst is ftst.  Check the source operand and set the cc's accordingly.| No write is done, so simply rts.|cu_dtst:	movew	LOCAL_EX(%a0),%d0	bclrl	#15,%d0	sne	LOCAL_SGN(%a0)	beqs	cu_dtpo	orl	#neg_mask,USER_FPSR(%a6) |set Ncu_dtpo:	cmpiw	#0x7fff,%d0	|test for inf/nan	bnes	cu_dtcz	tstl	LOCAL_HI(%a0)	bnes	cu_dtn	tstl	LOCAL_LO(%a0)	bnes	cu_dtn	orl	#inf_mask,USER_FPSR(%a6)	rtscu_dtn:	orl	#nan_mask,USER_FPSR(%a6)	movel	ETEMP_EX(%a6),FPTEMP_EX(%a6)	|set up fptemp sign for |						;snan handler	rtscu_dtcz:	tstl	LOCAL_HI(%a0)	bnel	cu_dtsx	tstl	LOCAL_LO(%a0)	bnel	cu_dtsx	orl	#z_mask,USER_FPSR(%a6)cu_dtsx:	rts|| Inst is fabs.  Execute the absolute value function on the input.| Branch to the fmove code.|cu_dabs:	bclrb	#7,LOCAL_EX(%a0)		|do abs	bras	cu_dmove		|fmove code will finish|| Inst is fneg.  Execute the negate value function on the input.| Fall though to the fmove code.|cu_dneg:	bchgb	#7,LOCAL_EX(%a0)		|do neg|| Inst is fmove.  This code also handles all result writes.| If bit 2 is set, round is forced to double.  If it is clear,| and bit 6 is set, round is forced to single.  If both are clear,| the round precision is found in the fpcr.  If the rounding precision| is double or single, the result is zero, and the mode is checked| to determine if the lsb of the result should be set.|cu_dmove:	btstb	#2,CMDREG1B+1(%a6)	|check for rd	bne	cu_dmrd	btstb	#6,CMDREG1B+1(%a6)	|check for rs	bne	cu_dmrs|| The move or operation is not with forced precision.  Use the| FPCR_MODE byte to get rounding.|cu_dmnr:	bfextu	FPCR_MODE(%a6){#0:#2},%d0	tstb	%d0			|check for extended	beq	cu_wrexd		|if so, just write result	cmpib	#1,%d0			|check for single	beq	cu_dmrs			|fall through to double|| The move is fdmove or round precision is double.  Result is zero.| Check rmode for rp or rm and set lsb accordingly.|cu_dmrd:	bfextu	FPCR_MODE(%a6){#2:#2},%d1	|get rmode	tstw	LOCAL_EX(%a0)		|check sign	blts	cu_dmdn	cmpib	#3,%d1			|check for rp	bne	cu_dpd			|load double pos zero	bra	cu_dpdr			|load double pos zero w/lsbcu_dmdn:	cmpib	#2,%d1			|check for rm	bne	cu_dnd			|load double neg zero	bra	cu_dndr			|load double neg zero w/lsb|

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -