URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [lib/] [libcpu/] [m68k/] [m68040/] [fpsp/] [kernel_ex.S] - Rev 1765
Compare with Previous | Blame | View Log
//// $Id: kernel_ex.S,v 1.2 2001-09-27 12:01:22 chris Exp $//// kernel_ex.sa 3.3 12/19/90//// This file contains routines to force exception status in the// fpu for exceptional cases detected or reported within the// transcendental functions. Typically, the t_xx routine will// set the appropriate bits in the USER_FPSR word on the stack.// The bits are tested in gen_except.sa to determine if an exceptional// situation needs to be created on return from the FPSP.//// 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.KERNEL_EX: //idnt 2,1 | Motorola 040 Floating Point Software Package|section 8#include "fpsp.defs"mns_inf: .long 0xffff0000,0x00000000,0x00000000pls_inf: .long 0x7fff0000,0x00000000,0x00000000nan: .long 0x7fff0000,0xffffffff,0xffffffffhuge: .long 0x7ffe0000,0xffffffff,0xffffffff|xref ovf_r_k|xref unf_sub|xref nrm_set.global t_dz.global t_dz2.global t_operr.global t_unfl.global t_ovfl.global t_ovfl2.global t_inx2.global t_frcinx.global t_extdnrm.global t_resdnrm.global dst_nan.global src_nan//// DZ exception////// if dz trap disabled// store properly signed inf (use sign of etemp) into fp0// set FPSR exception status dz bit, condition code// inf bit, and accrued dz bit// return// frestore the frame into the machine (done by unimp_hd)//// else dz trap enabled// set exception status bit & accrued bits in FPSR// set flag to disable sto_res from corrupting fp register// return// frestore the frame into the machine (done by unimp_hd)//// t_dz2 is used by monadic functions such as flogn (from do_func).// t_dz is used by monadic functions such as satanh (from the// transcendental function).//t_dz2:bsetb #neg_bit,FPSR_CC(%a6) //set neg bit in FPSRfmovel #0,%FPSR //clr status bits (Z set)btstb #dz_bit,FPCR_ENABLE(%a6) //test FPCR for dz exc enabledbnes dz_ena_endbras m_inf //flogx always returns -inft_dz:fmovel #0,%FPSR //clr status bits (Z set)btstb #dz_bit,FPCR_ENABLE(%a6) //test FPCR for dz exc enabledbnes dz_ena//// dz disabled//btstb #sign_bit,ETEMP_EX(%a6) //check sign for neg or posbeqs p_inf //branch if pos signm_inf:fmovemx mns_inf,%fp0-%fp0 //load -infbsetb #neg_bit,FPSR_CC(%a6) //set neg bit in FPSRbras set_fpsrp_inf:fmovemx pls_inf,%fp0-%fp0 //load +infset_fpsr:orl #dzinf_mask,USER_FPSR(%a6) //set I,DZ,ADZrts//// dz enabled//dz_ena:btstb #sign_bit,ETEMP_EX(%a6) //check sign for neg or posbeqs dz_ena_endbsetb #neg_bit,FPSR_CC(%a6) //set neg bit in FPSRdz_ena_end:orl #dzinf_mask,USER_FPSR(%a6) //set I,DZ,ADZst STORE_FLG(%a6)rts//// OPERR exception//// if (operr trap disabled)// set FPSR exception status operr bit, condition code// nan bit; Store default NAN into fp0// frestore the frame into the machine (done by unimp_hd)//// else (operr trap enabled)// set FPSR exception status operr bit, accrued operr bit// set flag to disable sto_res from corrupting fp register// frestore the frame into the machine (done by unimp_hd)//t_operr:orl #opnan_mask,USER_FPSR(%a6) //set NaN, OPERR, AIOPbtstb #operr_bit,FPCR_ENABLE(%a6) //test FPCR for operr enabledbnes op_enafmovemx nan,%fp0-%fp0 //load default nanrtsop_ena:st STORE_FLG(%a6) //do not corrupt destinationrts//// t_unfl --- UNFL exception//// This entry point is used by all routines requiring unfl, inex2,// aunfl, and ainex to be set on exit.//// On entry, a0 points to the exceptional operand. The final exceptional// operand is built in FP_SCR1 and only the sign from the original operand// is used.//t_unfl:clrl FP_SCR1(%a6) //set exceptional operand to zeroclrl FP_SCR1+4(%a6)clrl FP_SCR1+8(%a6)tstb (%a0) //extract sign from caller's exopbpls unfl_signokbset #sign_bit,FP_SCR1(%a6)unfl_signok:leal FP_SCR1(%a6),%a0orl #unfinx_mask,USER_FPSR(%a6)// ;set UNFL, INEX2, AUNFL, AINEXunfl_con:btstb #unfl_bit,FPCR_ENABLE(%a6)beqs unfl_disunfl_ena:bfclr STAG(%a6){#5:#3} //clear wbtm66,wbtm1,wbtm0bsetb #wbtemp15_bit,WB_BYTE(%a6) //set wbtemp15bsetb #sticky_bit,STICKY(%a6) //set sticky bitbclrb #E1,E_BYTE(%a6)unfl_dis:bfextu FPCR_MODE(%a6){#0:#2},%d0 //get round precisionbclrb #sign_bit,LOCAL_EX(%a0)sne LOCAL_SGN(%a0) //convert to internal ext formatbsr unf_sub //returns IEEE result at a0// ;and sets FPSR_CC accordinglybfclr LOCAL_SGN(%a0){#0:#8} //convert back to IEEE ext formatbeqs unfl_finbsetb #sign_bit,LOCAL_EX(%a0)bsetb #sign_bit,FP_SCR1(%a6) //set sign bit of exc operandunfl_fin:fmovemx (%a0),%fp0-%fp0 //store result in fp0rts//// t_ovfl2 --- OVFL exception (without inex2 returned)//// This entry is used by scale to force catastrophic overflow. The// ovfl, aovfl, and ainex bits are set, but not the inex2 bit.//t_ovfl2:orl #ovfl_inx_mask,USER_FPSR(%a6)movel ETEMP(%a6),FP_SCR1(%a6)movel ETEMP_HI(%a6),FP_SCR1+4(%a6)movel ETEMP_LO(%a6),FP_SCR1+8(%a6)//// Check for single or double round precision. If single, check if// the lower 40 bits of ETEMP are zero; if not, set inex2. If double,// check if the lower 21 bits are zero; if not, set inex2.//moveb FPCR_MODE(%a6),%d0andib #0xc0,%d0beq t_work //if extended, finish ovfl processingcmpib #0x40,%d0 //test for singlebnes t_dblt_sgl:tstb ETEMP_LO(%a6)bnes t_setinx2movel ETEMP_HI(%a6),%d0andil #0xff,%d0 //look at only lower 8 bitsbnes t_setinx2bra t_workt_dbl:movel ETEMP_LO(%a6),%d0andil #0x7ff,%d0 //look at only lower 11 bitsbeq t_workt_setinx2:orl #inex2_mask,USER_FPSR(%a6)bras t_work//// t_ovfl --- OVFL exception////** Note: the exc operand is returned in ETEMP.//t_ovfl:orl #ovfinx_mask,USER_FPSR(%a6)t_work:btstb #ovfl_bit,FPCR_ENABLE(%a6) //test FPCR for ovfl enabledbeqs ovf_disovf_ena:clrl FP_SCR1(%a6) //set exceptional operandclrl FP_SCR1+4(%a6)clrl FP_SCR1+8(%a6)bfclr STAG(%a6){#5:#3} //clear wbtm66,wbtm1,wbtm0bclrb #wbtemp15_bit,WB_BYTE(%a6) //clear wbtemp15bsetb #sticky_bit,STICKY(%a6) //set sticky bitbclrb #E1,E_BYTE(%a6)// ;fall through to disabled case// For disabled overflow call 'ovf_r_k'. This routine loads the// correct result based on the rounding precision, destination// format, rounding mode and sign.//ovf_dis:bsr ovf_r_k //returns unsigned ETEMP_EX// ;and sets FPSR_CC accordingly.bfclr ETEMP_SGN(%a6){#0:#8} //fix signbeqs ovf_posbsetb #sign_bit,ETEMP_EX(%a6)bsetb #sign_bit,FP_SCR1(%a6) //set exceptional operand signovf_pos:fmovemx ETEMP(%a6),%fp0-%fp0 //move the result to fp0rts//// INEX2 exception//// The inex2 and ainex bits are set.//t_inx2:orl #inx2a_mask,USER_FPSR(%a6) //set INEX2, AINEXrts//// Force Inex2//// This routine is called by the transcendental routines to force// the inex2 exception bits set in the FPSR. If the underflow bit// is set, but the underflow trap was not taken, the aunfl bit in// the FPSR must be set.//t_frcinx:orl #inx2a_mask,USER_FPSR(%a6) //set INEX2, AINEXbtstb #unfl_bit,FPSR_EXCEPT(%a6) //test for unfl bit setbeqs no_uacc1 //if clear, do not set aunflbsetb #aunfl_bit,FPSR_AEXCEPT(%a6)no_uacc1:rts//// DST_NAN//// Determine if the destination nan is signalling or non-signalling,// and set the FPSR bits accordingly. See the MC68040 User's Manual// section 3.2.2.5 NOT-A-NUMBERS.//dst_nan:btstb #sign_bit,FPTEMP_EX(%a6) //test sign of nanbeqs dst_pos //if clr, it was positivebsetb #neg_bit,FPSR_CC(%a6) //set N bitdst_pos:btstb #signan_bit,FPTEMP_HI(%a6) //check if signallingbeqs dst_snan //branch if signallingfmovel %d1,%fpcr //restore user's rmode/precfmovex FPTEMP(%a6),%fp0 //return the non-signalling nan//// Check the source nan. If it is signalling, snan will be reported.//moveb STAG(%a6),%d0andib #0xe0,%d0cmpib #0x60,%d0bnes no_snanbtstb #signan_bit,ETEMP_HI(%a6) //check if signallingbnes no_snanorl #snaniop_mask,USER_FPSR(%a6) //set NAN, SNAN, AIOPno_snan:rtsdst_snan:btstb #snan_bit,FPCR_ENABLE(%a6) //check if trap enabledbeqs dst_dis //branch if disabledorb #nan_tag,DTAG(%a6) //set up dtag for nanst STORE_FLG(%a6) //do not store a resultorl #snaniop_mask,USER_FPSR(%a6) //set NAN, SNAN, AIOPrtsdst_dis:bsetb #signan_bit,FPTEMP_HI(%a6) //set SNAN bit in sopfmovel %d1,%fpcr //restore user's rmode/precfmovex FPTEMP(%a6),%fp0 //load non-sign. nanorl #snaniop_mask,USER_FPSR(%a6) //set NAN, SNAN, AIOPrts//// SRC_NAN//// Determine if the source nan is signalling or non-signalling,// and set the FPSR bits accordingly. See the MC68040 User's Manual// section 3.2.2.5 NOT-A-NUMBERS.//src_nan:btstb #sign_bit,ETEMP_EX(%a6) //test sign of nanbeqs src_pos //if clr, it was positivebsetb #neg_bit,FPSR_CC(%a6) //set N bitsrc_pos:btstb #signan_bit,ETEMP_HI(%a6) //check if signallingbeqs src_snan //branch if signallingfmovel %d1,%fpcr //restore user's rmode/precfmovex ETEMP(%a6),%fp0 //return the non-signalling nanrtssrc_snan:btstb #snan_bit,FPCR_ENABLE(%a6) //check if trap enabledbeqs src_dis //branch if disabledbsetb #signan_bit,ETEMP_HI(%a6) //set SNAN bit in soporb #norm_tag,DTAG(%a6) //set up dtag for normorb #nan_tag,STAG(%a6) //set up stag for nanst STORE_FLG(%a6) //do not store a resultorl #snaniop_mask,USER_FPSR(%a6) //set NAN, SNAN, AIOPrtssrc_dis:bsetb #signan_bit,ETEMP_HI(%a6) //set SNAN bit in sopfmovel %d1,%fpcr //restore user's rmode/precfmovex ETEMP(%a6),%fp0 //load non-sign. nanorl #snaniop_mask,USER_FPSR(%a6) //set NAN, SNAN, AIOPrts//// For all functions that have a denormalized input and that f(x)=x,// this is the entry point//t_extdnrm:orl #unfinx_mask,USER_FPSR(%a6)// ;set UNFL, INEX2, AUNFL, AINEXbras xdnrm_con//// Entry point for scale with extended denorm. The function does// not set inex2, aunfl, or ainex.//t_resdnrm:orl #unfl_mask,USER_FPSR(%a6)xdnrm_con:btstb #unfl_bit,FPCR_ENABLE(%a6)beqs xdnrm_dis//// If exceptions are enabled, the additional task of setting up WBTEMP// is needed so that when the underflow exception handler is entered,// the user perceives no difference between what the 040 provides vs.// what the FPSP provides.//xdnrm_ena:movel %a0,-(%a7)movel LOCAL_EX(%a0),FP_SCR1(%a6)movel LOCAL_HI(%a0),FP_SCR1+4(%a6)movel LOCAL_LO(%a0),FP_SCR1+8(%a6)lea FP_SCR1(%a6),%a0bclrb #sign_bit,LOCAL_EX(%a0)sne LOCAL_SGN(%a0) //convert to internal ext formattstw LOCAL_EX(%a0) //check if input is denormbeqs xdnrm_dn //if so, skip nrm_setbsr nrm_set //normalize the result (exponent// ;will be negativexdnrm_dn:bclrb #sign_bit,LOCAL_EX(%a0) //take off false signbfclr LOCAL_SGN(%a0){#0:#8} //change back to IEEE ext formatbeqs xdepbsetb #sign_bit,LOCAL_EX(%a0)xdep:bfclr STAG(%a6){#5:#3} //clear wbtm66,wbtm1,wbtm0bsetb #wbtemp15_bit,WB_BYTE(%a6) //set wbtemp15bclrb #sticky_bit,STICKY(%a6) //clear sticky bitbclrb #E1,E_BYTE(%a6)movel (%a7)+,%a0xdnrm_dis:bfextu FPCR_MODE(%a6){#0:#2},%d0 //get round precisionbnes not_ext //if not round extended, store// ;IEEE defaultsis_ext:btstb #sign_bit,LOCAL_EX(%a0)beqs xdnrm_storebsetb #neg_bit,FPSR_CC(%a6) //set N bit in FPSR_CCbras xdnrm_storenot_ext:bclrb #sign_bit,LOCAL_EX(%a0)sne LOCAL_SGN(%a0) //convert to internal ext formatbsr unf_sub //returns IEEE result pointed by// ;a0; sets FPSR_CC accordinglybfclr LOCAL_SGN(%a0){#0:#8} //convert back to IEEE ext formatbeqs xdnrm_storebsetb #sign_bit,LOCAL_EX(%a0)xdnrm_store:fmovemx (%a0),%fp0-%fp0 //store result in fp0rts//// This subroutine is used for dyadic operations that use an extended// denorm within the kernel. The approach used is to capture the frame,// fix/restore.//.global t_avoid_unsuppt_avoid_unsupp:link %a2,#-LOCAL_SIZE //so that a2 fpsp.h negative// ;offsets may be usedfsave -(%a7)tstb 1(%a7) //check if idle, exit if sobeq idle_endbtstb #E1,E_BYTE(%a2) //check for an E1 exception if// ;enabled, there is an unsuppbeq end_avun //else, exitbtstb #7,DTAG(%a2) //check for denorm destinationbeqs src_den //else, must be a source denorm//// handle destination denorm//lea FPTEMP(%a2),%a0btstb #sign_bit,LOCAL_EX(%a0)sne LOCAL_SGN(%a0) //convert to internal ext formatbclrb #7,DTAG(%a2) //set DTAG to normbsr nrm_set //normalize result, exponent// ;will become negativebclrb #sign_bit,LOCAL_EX(%a0) //get rid of fake signbfclr LOCAL_SGN(%a0){#0:#8} //convert back to IEEE ext formatbeqs ck_src_den //check if source is also denormbsetb #sign_bit,LOCAL_EX(%a0)ck_src_den:btstb #7,STAG(%a2)beqs end_avunsrc_den:lea ETEMP(%a2),%a0btstb #sign_bit,LOCAL_EX(%a0)sne LOCAL_SGN(%a0) //convert to internal ext formatbclrb #7,STAG(%a2) //set STAG to normbsr nrm_set //normalize result, exponent// ;will become negativebclrb #sign_bit,LOCAL_EX(%a0) //get rid of fake signbfclr LOCAL_SGN(%a0){#0:#8} //convert back to IEEE ext formatbeqs den_combsetb #sign_bit,LOCAL_EX(%a0)den_com:moveb #0xfe,CU_SAVEPC(%a2) //set continue frameclrw NMNEXC(%a2) //clear NMNEXCbclrb #E1,E_BYTE(%a2)// fmove.l %FPSR,FPSR_SHADOW(%a2)// bset.b #SFLAG,E_BYTE(%a2)// bset.b #XFLAG,T_BYTE(%a2)end_avun:frestore (%a7)+unlk %a2rtsidle_end:addl #4,%a7unlk %a2rts|end
