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

📄 res_func.s

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 S
📖 第 1 页 / 共 4 页
字号:
	bra	cu_dndr			//load double neg zero w/lsb//// The move is fsmove or round precision is single.  Result is zero.// Check for rp or rm and set lsb accordingly.//cu_dmrs:	bfextu	FPCR_MODE(%a6){#2:#2},%d1	//get rmode	tstw	LOCAL_EX(%a0)		//check sign	blts	cu_dmsn	cmpib	#3,%d1			//check for rp	bne	cu_spd			//load single pos zero	bra	cu_spdr			//load single pos zero w/lsbcu_dmsn:	cmpib	#2,%d1			//check for rm	bne	cu_snd			//load single neg zero	bra	cu_sndr			//load single neg zero w/lsb//// The precision is extended, so the result in etemp is correct.// Simply set unfl (not inex2 or aunfl) and write the result to // the correct fp register.cu_wrexd:	orl	#unfl_mask,USER_FPSR(%a6)	tstw	LOCAL_EX(%a0)	beq	wr_etemp	orl	#neg_mask,USER_FPSR(%a6)	bra	wr_etemp//// These routines write +/- zero in double format.  The routines// cu_dpdr and cu_dndr set the double lsb.//cu_dpd:	movel	#0x3c010000,LOCAL_EX(%a0)	//force pos double zero	clrl	LOCAL_HI(%a0)	clrl	LOCAL_LO(%a0)	orl	#z_mask,USER_FPSR(%a6)	orl	#unfinx_mask,USER_FPSR(%a6)	bra	wr_etempcu_dpdr:	movel	#0x3c010000,LOCAL_EX(%a0)	//force pos double zero	clrl	LOCAL_HI(%a0)	movel	#0x800,LOCAL_LO(%a0)	//with lsb set	orl	#unfinx_mask,USER_FPSR(%a6)	bra	wr_etempcu_dnd:	movel	#0xbc010000,LOCAL_EX(%a0)	//force pos double zero	clrl	LOCAL_HI(%a0)	clrl	LOCAL_LO(%a0)	orl	#z_mask,USER_FPSR(%a6)	orl	#neg_mask,USER_FPSR(%a6)	orl	#unfinx_mask,USER_FPSR(%a6)	bra	wr_etempcu_dndr:	movel	#0xbc010000,LOCAL_EX(%a0)	//force pos double zero	clrl	LOCAL_HI(%a0)	movel	#0x800,LOCAL_LO(%a0)	//with lsb set	orl	#neg_mask,USER_FPSR(%a6)	orl	#unfinx_mask,USER_FPSR(%a6)	bra	wr_etemp//// These routines write +/- zero in single format.  The routines// cu_dpdr and cu_dndr set the single lsb.//cu_spd:	movel	#0x3f810000,LOCAL_EX(%a0)	//force pos single zero	clrl	LOCAL_HI(%a0)	clrl	LOCAL_LO(%a0)	orl	#z_mask,USER_FPSR(%a6)	orl	#unfinx_mask,USER_FPSR(%a6)	bra	wr_etempcu_spdr:	movel	#0x3f810000,LOCAL_EX(%a0)	//force pos single zero	movel	#0x100,LOCAL_HI(%a0)	//with lsb set	clrl	LOCAL_LO(%a0)	orl	#unfinx_mask,USER_FPSR(%a6)	bra	wr_etempcu_snd:	movel	#0xbf810000,LOCAL_EX(%a0)	//force pos single zero	clrl	LOCAL_HI(%a0)	clrl	LOCAL_LO(%a0)	orl	#z_mask,USER_FPSR(%a6)	orl	#neg_mask,USER_FPSR(%a6)	orl	#unfinx_mask,USER_FPSR(%a6)	bra	wr_etempcu_sndr:	movel	#0xbf810000,LOCAL_EX(%a0)	//force pos single zero	movel	#0x100,LOCAL_HI(%a0)	//with lsb set	clrl	LOCAL_LO(%a0)	orl	#neg_mask,USER_FPSR(%a6)	orl	#unfinx_mask,USER_FPSR(%a6)	bra	wr_etemp	//// This code checks for 16-bit overflow conditions on dyadic// operations which are not restorable into the floating-point// unit and must be completed in software.  Basically, this// condition exists with a very large norm and a denorm.  One// of the operands must be denormalized to enter this code.//// Flags used://	DY_MO_FLG contains 0 for monadic op, $ff for dyadic//	DNRM_FLG contains $00 for neither op denormalized//	                  $0f for the destination op denormalized//	                  $f0 for the source op denormalized//	                  $ff for both ops denormalized//// The wrap-around condition occurs for add, sub, div, and cmp// when ////	abs(dest_exp - src_exp) >= $8000//// and for mul when////	(dest_exp + src_exp) < $0//// we must process the operation here if this case is true.//// The rts following the frcfpn routine is the exit from res_func// for this condition.  The restore flag (RES_FLG) is left clear.// No frestore is done unless an exception is to be reported.//// For fadd: //	if(sign_of(dest) != sign_of(src))//		replace exponent of src with $3fff (keep sign)//		use fpu to perform dest+new_src (user's rmode and X)//		clr sticky//	else//		set sticky//	call round with user's precision and mode//	move result to fpn and wbtemp//// For fsub://	if(sign_of(dest) == sign_of(src))//		replace exponent of src with $3fff (keep sign)//		use fpu to perform dest+new_src (user's rmode and X)//		clr sticky//	else//		set sticky//	call round with user's precision and mode//	move result to fpn and wbtemp//// For fdiv/fsgldiv://	if(both operands are denorm)//		restore_to_fpu;//	if(dest is norm)//		force_ovf;//	else(dest is denorm)//		force_unf://// For fcmp://	if(dest is norm)//		N = sign_of(dest);//	else(dest is denorm)//		N = sign_of(src);//// For fmul://	if(both operands are denorm)//		force_unf;//	if((dest_exp + src_exp) < 0)//		force_unf://	else//		restore_to_fpu;//// local equates:	.set	addcode,0x22	.set	subcode,0x28	.set	mulcode,0x23	.set	divcode,0x20	.set	cmpcode,0x38ck_wrap:	| tstb	DY_MO_FLG(%a6)	;check for fsqrt	beq	fix_stk		//if zero, it is fsqrt	movew	CMDREG1B(%a6),%d0	andiw	#0x3b,%d0		//strip to command bits	cmpiw	#addcode,%d0	beq	wrap_add	cmpiw	#subcode,%d0	beq	wrap_sub	cmpiw	#mulcode,%d0	beq	wrap_mul	cmpiw	#cmpcode,%d0	beq	wrap_cmp//// Inst is fdiv.  //wrap_div:	cmpb	#0xff,DNRM_FLG(%a6) //if both ops denorm, 	beq	fix_stk		 //restore to fpu//// One of the ops is denormalized.  Test for wrap condition// and force the result.//	cmpb	#0x0f,DNRM_FLG(%a6) //check for dest denorm	bnes	div_srcddiv_destd:	bsrl	ckinf_ns	bne	fix_stk	bfextu	ETEMP_EX(%a6){#1:#15},%d0	//get src exp (always pos)	bfexts	FPTEMP_EX(%a6){#1:#15},%d1	//get dest exp (always neg)	subl	%d1,%d0			//subtract dest from src	cmpl	#0x7fff,%d0	blt	fix_stk			//if less, not wrap case	clrb	WBTEMP_SGN(%a6)	movew	ETEMP_EX(%a6),%d0		//find the sign of the result	movew	FPTEMP_EX(%a6),%d1	eorw	%d1,%d0	andiw	#0x8000,%d0	beq	force_unf	st	WBTEMP_SGN(%a6)	bra	force_unfckinf_ns:	moveb	STAG(%a6),%d0		//check source tag for inf or nan	bra	ck_in_comckinf_nd:	moveb	DTAG(%a6),%d0		//check destination tag for inf or nanck_in_com:		andib	#0x60,%d0			//isolate tag bits	cmpb	#0x40,%d0			//is it inf?	beq	nan_or_inf		//not wrap case	cmpb	#0x60,%d0			//is it nan?	beq	nan_or_inf		//yes, not wrap case?	cmpb	#0x20,%d0			//is it a zero?	beq	nan_or_inf		//yes	clrl	%d0	rts				//then ; it is either a zero of norm,//					;check wrap casenan_or_inf:	moveql	#-1,%d0	rtsdiv_srcd:	bsrl	ckinf_nd	bne	fix_stk	bfextu	FPTEMP_EX(%a6){#1:#15},%d0	//get dest exp (always pos)	bfexts	ETEMP_EX(%a6){#1:#15},%d1	//get src exp (always neg)	subl	%d1,%d0			//subtract src from dest	cmpl	#0x8000,%d0	blt	fix_stk			//if less, not wrap case	clrb	WBTEMP_SGN(%a6)	movew	ETEMP_EX(%a6),%d0		//find the sign of the result	movew	FPTEMP_EX(%a6),%d1	eorw	%d1,%d0	andiw	#0x8000,%d0	beqs	force_ovf	st	WBTEMP_SGN(%a6)//// This code handles the case of the instruction resulting in // an overflow condition.//force_ovf:	bclrb	#E1,E_BYTE(%a6)	orl	#ovfl_inx_mask,USER_FPSR(%a6)	clrw	NMNEXC(%a6)	leal	WBTEMP(%a6),%a0		//point a0 to memory location	movew	CMDREG1B(%a6),%d0	btstl	#6,%d0			//test for forced precision	beqs	frcovf_fpcr	btstl	#2,%d0			//check for double	bnes	frcovf_dbl	movel	#0x1,%d0			//inst is forced single	bras	frcovf_rndfrcovf_dbl:	movel	#0x2,%d0			//inst is forced double	bras	frcovf_rndfrcovf_fpcr:	bfextu	FPCR_MODE(%a6){#0:#2},%d0	//inst not forced - use fpcr precfrcovf_rnd:// The 881/882 does not set inex2 for the following case, so the // line is commented out to be compatible with 881/882//	tst.b	%d0//	beq.b	frcovf_x//	or.l	#inex2_mask,USER_FPSR(%a6) ;if prec is s or d, set inex2//frcovf_x:	bsrl	ovf_res			//get correct result based on//					;round precision/mode.  This //					;sets FPSR_CC correctly//					;returns in external format	bfclr	WBTEMP_SGN(%a6){#0:#8}	beq	frcfpn	bsetb	#sign_bit,WBTEMP_EX(%a6)	bra	frcfpn//// Inst is fadd.//wrap_add:	cmpb	#0xff,DNRM_FLG(%a6) //if both ops denorm, 	beq	fix_stk		 //restore to fpu//// One of the ops is denormalized.  Test for wrap condition// and complete the instruction.//	cmpb	#0x0f,DNRM_FLG(%a6) //check for dest denorm	bnes	add_srcdadd_destd:	bsrl	ckinf_ns	bne	fix_stk	bfextu	ETEMP_EX(%a6){#1:#15},%d0	//get src exp (always pos)	bfexts	FPTEMP_EX(%a6){#1:#15},%d1	//get dest exp (always neg)	subl	%d1,%d0			//subtract dest from src	cmpl	#0x8000,%d0	blt	fix_stk			//if less, not wrap case	bra	add_wrapadd_srcd:	bsrl	ckinf_nd	bne	fix_stk	bfextu	FPTEMP_EX(%a6){#1:#15},%d0	//get dest exp (always pos)	bfexts	ETEMP_EX(%a6){#1:#15},%d1	//get src exp (always neg)	subl	%d1,%d0			//subtract src from dest	cmpl	#0x8000,%d0	blt	fix_stk			//if less, not wrap case//// Check the signs of the operands.  If they are unlike, the fpu// can be used to add the norm and 1.0 with the sign of the// denorm and it will correctly generate the result in extended// precision.  We can then call round with no sticky and the result// will be correct for the user's rounding mode and precision.  If// the signs are the same, we call round with the sticky bit set// and the result will be correct for the user's rounding mode and// precision.//add_wrap:	movew	ETEMP_EX(%a6),%d0	movew	FPTEMP_EX(%a6),%d1	eorw	%d1,%d0	andiw	#0x8000,%d0	beq	add_same//// The signs are unlike.//	cmpb	#0x0f,DNRM_FLG(%a6) //is dest the denorm?	bnes	add_u_srcd	movew	FPTEMP_EX(%a6),%d0	andiw	#0x8000,%d0	orw	#0x3fff,%d0	//force the exponent to +/- 1	movew	%d0,FPTEMP_EX(%a6) //in the denorm	movel	USER_FPCR(%a6),%d0	andil	#0x30,%d0	fmovel	%d0,%fpcr		//set up users rmode and X	fmovex	ETEMP(%a6),%fp0	faddx	FPTEMP(%a6),%fp0	leal	WBTEMP(%a6),%a0	//point a0 to wbtemp in frame	fmovel	%fpsr,%d1	orl	%d1,USER_FPSR(%a6) //capture cc's and inex from fadd	fmovex	%fp0,WBTEMP(%a6)	//write result to memory	lsrl	#4,%d0		//put rmode in lower 2 bits	movel	USER_FPCR(%a6),%d1	andil	#0xc0,%d1	lsrl	#6,%d1		//put precision in upper word	swap	%d1	orl	%d0,%d1		//set up for round call	clrl	%d0		//force sticky to zero	bclrb	#sign_bit,WBTEMP_EX(%a6)	sne	WBTEMP_SGN(%a6)	bsrl	round		//round result to users rmode & prec	bfclr	WBTEMP_SGN(%a6){#0:#8}	//convert back to IEEE ext format	beq	frcfpnr	bsetb	#sign_bit,WBTEMP_EX(%a6)	bra	frcfpnradd_u_srcd:	movew	ETEMP_EX(%a6),%d0	andiw	#0x8000,%d0	orw	#0x3fff,%d0	//force the exponent to +/- 1	movew	%d0,ETEMP_EX(%a6) //in the denorm	movel	USER_FPCR(%a6),%d0	andil	#0x30,%d0	fmovel	%d0,%fpcr		//set up users rmode and X	fmovex	ETEMP(%a6),%fp0	faddx	FPTEMP(%a6),%fp0	fmovel	%fpsr,%d1	orl	%d1,USER_FPSR(%a6) //capture cc's and inex from fadd	leal	WBTEMP(%a6),%a0	//point a0 to wbtemp in frame	fmovex	%fp0,WBTEMP(%a6)	//write result to memory	lsrl	#4,%d0		//put rmode in lower 2 bits	movel	USER_FPCR(%a6),%d1	andil	#0xc0,%d1	lsrl	#6,%d1		//put precision in upper word	swap	%d1	orl	%d0,%d1		//set up for round call	clrl	%d0		//force sticky to zero	bclrb	#sign_bit,WBTEMP_EX(%a6)	sne	WBTEMP_SGN(%a6)	//use internal format for round	bsrl	round		//round result to users rmode & prec	bfclr	WBTEMP_SGN(%a6){#0:#8}	//convert back to IEEE ext format	beq	frcfpnr	bsetb	#sign_bit,WBTEMP_EX(%a6)	bra	frcfpnr//// Signs are alike://add_same:	cmpb	#0x0f,DNRM_FLG(%a6) //is dest the denorm?	bnes	add_s_srcdadd_s_destd:	leal	ETEMP(%a6),%a0	movel	USER_FPCR(%a6),%d0	andil	#0x30,%d0	lsrl	#4,%d0		//put rmode in lower 2 bits	movel	USER_FPCR(%a6),%d1	andil	#0xc0,%d1	lsrl	#6,%d1		//put precision in upper word	swap	%d1	orl	%d0,%d1		//set up for round call	movel	#0x20000000,%d0	//set sticky for round	bclrb	#sign_bit,ETEMP_EX(%a6)	sne	ETEMP_SGN(%a6)	bsrl	round		//round result to users rmode & prec	bfclr	ETEMP_SGN(%a6){#0:#8}	//convert back to IEEE ext format	beqs	add_s_dclr	bsetb	#sign_bit,ETEMP_EX(%a6)add_s_dclr:	leal	WBTEMP(%a6),%a0	movel	ETEMP(%a6),(%a0)	//write result to wbtemp	movel	ETEMP_HI(%a6),4(%a0)	movel	ETEMP_LO(%a6),8(%a0)	tstw	ETEMP_EX(%a6)	bgt	add_ckovf	orl	#neg_mask,USER_FPSR(%a6)	bra	add_ckovfadd_s_srcd:	leal	FPTEMP(%a6),%a0	movel	USER_FPCR(%a6),%d0	andil	#0x30,%d0	lsrl	#4,%d0		//put rmode in lower 2 bits	movel	USER_FPCR(%a6),%d1	andil	#0xc0,%d1	lsrl	#6,%d1		//put precision in upper word	swap	%d1	orl	%d0,%d1		//set up for round call	movel	#0x20000000,%d0	//set sticky for round	bclrb	#sign_bit,FPTEMP_EX(%a6)	sne	FPTEMP_SGN(%a6)	bsrl	round		//round result to users rmode & prec	bfclr	FPTEMP_SGN(%a6){#0:#8}	//convert back to IEEE ext format	beqs	add_s_sclr	bsetb	#sign_bit,FPTEMP_EX(%a6)add_s_sclr:	leal	WBTEMP(%a6),%a0	movel	FPTEMP(%a6),(%a0)	//write result to wbtemp	movel	FPTEMP_HI(%a6),4(%a0)	movel	FPTEMP_LO(%a6),8(%a0)	tstw	FPTEMP_EX(%a6)	bgt	add_ckovf	orl	#neg_mask,USER_FPSR(%a6)add_ckovf:	movew	WBTEMP_EX(%a6),%d0	andiw	#0x7fff,%d0	cmpiw	#0x7fff,%d0	bne	frcfpnr//// The result has overflowed to $7fff exponent.  Set I, ovfl,// and aovfl, and clr the mantissa (incorrectly set by the// round routine.)//	orl	#inf_mask+ovfl_inx_mask,USER_FPSR(%a6)		clrl	4(%a0)	bra	frcfpnr//// Inst is fsub.//wrap_sub:	cmpb	#0xff,DNRM_FLG(%a6) //if both ops denorm, 	beq	fix_stk		 //restore to fpu//// One of the ops is denormalized.  Test for wrap condition// and complete the instruction.//	cmpb	#0x0f,DNRM_FLG(%a6) //check for dest denorm	bnes	sub_srcdsub_destd:	bsrl	ckinf_ns	bne	fix_stk	bfextu	ETEMP_EX(%a6){#1:#15},%d0	//get src exp (always pos)	bfexts	FPTEMP_EX(%a6){#1:#15},%d1	//get dest exp (always neg)	subl	%d1,%d0			//subtract src from dest	cmpl	#0x8000,%d0	blt	fix_stk			//if less, not wrap case	bra	sub_wrapsub_srcd:	bsrl	ckinf_nd	bne	fix_stk	bfextu	FPTEMP_EX(%a6){#1:#15},%d0	//get dest exp (always pos)	bfexts	ETEMP_EX(%a6){#1:#15},%d1	//get src exp (always neg)	subl	%d1,%d0			//subtract dest from src	cmpl	#0x8000,%d0	blt	fix_stk			//if less, not wrap case//// Check the signs of the operands.  If they are alike, the fpu// can be used to subtract from the norm 1.0 with the sign of the// denorm and it will correctly generate the result in extended// precision.  We can then call round with no sticky and the result// will be correct for the user's rounding mode and precision.  If// the signs are unlike, we call round with the sticky bit set// and the result will be correct for the user's rounding mode and// precision.//sub_wrap:	movew	ETEMP_EX(%a6),%d0	movew	FPTEMP_EX(%a6),%d1	eorw	%d1,%d0	andiw	#0x8000,%d0	bne	sub_diff//// The signs are alike.//	cmpb	#0x0f,DNRM_FLG(%a6) //is dest the denorm?	bnes	sub_u_srcd	movew	FPTEMP_EX(%a6),%d0

⌨️ 快捷键说明

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