diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 1998-12-14 23:15:38 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 1998-12-14 23:15:38 +0000 |
commit | 01629105c2817a59a4f1f05039593f211cf5ddaa (patch) | |
tree | 76f6bb8f9ca6ddbd015e3b81964a8dacffaf5cf9 /c/src/lib/libcpu/m68k/m68040/fpsp/kernel_ex.S | |
parent | Patch from Ralf Corsepius <corsepiu@faw.uni-ulm.de> to rename all (diff) | |
download | rtems-01629105c2817a59a4f1f05039593f211cf5ddaa.tar.bz2 |
Patch from Ralf Corsepius <corsepiu@faw.uni-ulm.de> to rename all
.s files to .S in conformance with GNU conventions. This is a
minor step along the way to supporting automake.
Diffstat (limited to 'c/src/lib/libcpu/m68k/m68040/fpsp/kernel_ex.S')
-rw-r--r-- | c/src/lib/libcpu/m68k/m68040/fpsp/kernel_ex.S | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/m68k/m68040/fpsp/kernel_ex.S b/c/src/lib/libcpu/m68k/m68040/fpsp/kernel_ex.S new file mode 100644 index 0000000000..c4fd6812af --- /dev/null +++ b/c/src/lib/libcpu/m68k/m68040/fpsp/kernel_ex.S @@ -0,0 +1,496 @@ +// +// $Id$ +// +// 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,0x00000000 +pls_inf: .long 0x7fff0000,0x00000000,0x00000000 +nan: .long 0x7fff0000,0xffffffff,0xffffffff +huge: .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 FPSR + fmovel #0,%FPSR //clr status bits (Z set) + btstb #dz_bit,FPCR_ENABLE(%a6) //test FPCR for dz exc enabled + bnes dz_ena_end + bras m_inf //flogx always returns -inf +t_dz: + fmovel #0,%FPSR //clr status bits (Z set) + btstb #dz_bit,FPCR_ENABLE(%a6) //test FPCR for dz exc enabled + bnes dz_ena +// +// dz disabled +// + btstb #sign_bit,ETEMP_EX(%a6) //check sign for neg or pos + beqs p_inf //branch if pos sign + +m_inf: + fmovemx mns_inf,%fp0-%fp0 //load -inf + bsetb #neg_bit,FPSR_CC(%a6) //set neg bit in FPSR + bras set_fpsr +p_inf: + fmovemx pls_inf,%fp0-%fp0 //load +inf +set_fpsr: + orl #dzinf_mask,USER_FPSR(%a6) //set I,DZ,ADZ + rts +// +// dz enabled +// +dz_ena: + btstb #sign_bit,ETEMP_EX(%a6) //check sign for neg or pos + beqs dz_ena_end + bsetb #neg_bit,FPSR_CC(%a6) //set neg bit in FPSR +dz_ena_end: + orl #dzinf_mask,USER_FPSR(%a6) //set I,DZ,ADZ + st 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, AIOP + + btstb #operr_bit,FPCR_ENABLE(%a6) //test FPCR for operr enabled + bnes op_ena + + fmovemx nan,%fp0-%fp0 //load default nan + rts +op_ena: + st STORE_FLG(%a6) //do not corrupt destination + rts + +// +// 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 zero + clrl FP_SCR1+4(%a6) + clrl FP_SCR1+8(%a6) + tstb (%a0) //extract sign from caller's exop + bpls unfl_signok + bset #sign_bit,FP_SCR1(%a6) +unfl_signok: + leal FP_SCR1(%a6),%a0 + orl #unfinx_mask,USER_FPSR(%a6) +// ;set UNFL, INEX2, AUNFL, AINEX +unfl_con: + btstb #unfl_bit,FPCR_ENABLE(%a6) + beqs unfl_dis + +unfl_ena: + bfclr STAG(%a6){#5:#3} //clear wbtm66,wbtm1,wbtm0 + bsetb #wbtemp15_bit,WB_BYTE(%a6) //set wbtemp15 + bsetb #sticky_bit,STICKY(%a6) //set sticky bit + + bclrb #E1,E_BYTE(%a6) + +unfl_dis: + bfextu FPCR_MODE(%a6){#0:#2},%d0 //get round precision + + bclrb #sign_bit,LOCAL_EX(%a0) + sne LOCAL_SGN(%a0) //convert to internal ext format + + bsr unf_sub //returns IEEE result at a0 +// ;and sets FPSR_CC accordingly + + bfclr LOCAL_SGN(%a0){#0:#8} //convert back to IEEE ext format + beqs unfl_fin + + bsetb #sign_bit,LOCAL_EX(%a0) + bsetb #sign_bit,FP_SCR1(%a6) //set sign bit of exc operand + +unfl_fin: + fmovemx (%a0),%fp0-%fp0 //store result in fp0 + rts + + +// +// 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),%d0 + andib #0xc0,%d0 + beq t_work //if extended, finish ovfl processing + cmpib #0x40,%d0 //test for single + bnes t_dbl +t_sgl: + tstb ETEMP_LO(%a6) + bnes t_setinx2 + movel ETEMP_HI(%a6),%d0 + andil #0xff,%d0 //look at only lower 8 bits + bnes t_setinx2 + bra t_work +t_dbl: + movel ETEMP_LO(%a6),%d0 + andil #0x7ff,%d0 //look at only lower 11 bits + beq t_work +t_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 enabled + beqs ovf_dis + +ovf_ena: + clrl FP_SCR1(%a6) //set exceptional operand + clrl FP_SCR1+4(%a6) + clrl FP_SCR1+8(%a6) + + bfclr STAG(%a6){#5:#3} //clear wbtm66,wbtm1,wbtm0 + bclrb #wbtemp15_bit,WB_BYTE(%a6) //clear wbtemp15 + bsetb #sticky_bit,STICKY(%a6) //set sticky bit + + bclrb #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 sign + beqs ovf_pos + bsetb #sign_bit,ETEMP_EX(%a6) + bsetb #sign_bit,FP_SCR1(%a6) //set exceptional operand sign +ovf_pos: + fmovemx ETEMP(%a6),%fp0-%fp0 //move the result to fp0 + rts + + +// +// INEX2 exception +// +// The inex2 and ainex bits are set. +// +t_inx2: + orl #inx2a_mask,USER_FPSR(%a6) //set INEX2, AINEX + rts + +// +// 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, AINEX + btstb #unfl_bit,FPSR_EXCEPT(%a6) //test for unfl bit set + beqs no_uacc1 //if clear, do not set aunfl + bsetb #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 nan + beqs dst_pos //if clr, it was positive + bsetb #neg_bit,FPSR_CC(%a6) //set N bit +dst_pos: + btstb #signan_bit,FPTEMP_HI(%a6) //check if signalling + beqs dst_snan //branch if signalling + + fmovel %d1,%fpcr //restore user's rmode/prec + fmovex FPTEMP(%a6),%fp0 //return the non-signalling nan +// +// Check the source nan. If it is signalling, snan will be reported. +// + moveb STAG(%a6),%d0 + andib #0xe0,%d0 + cmpib #0x60,%d0 + bnes no_snan + btstb #signan_bit,ETEMP_HI(%a6) //check if signalling + bnes no_snan + orl #snaniop_mask,USER_FPSR(%a6) //set NAN, SNAN, AIOP +no_snan: + rts + +dst_snan: + btstb #snan_bit,FPCR_ENABLE(%a6) //check if trap enabled + beqs dst_dis //branch if disabled + + orb #nan_tag,DTAG(%a6) //set up dtag for nan + st STORE_FLG(%a6) //do not store a result + orl #snaniop_mask,USER_FPSR(%a6) //set NAN, SNAN, AIOP + rts + +dst_dis: + bsetb #signan_bit,FPTEMP_HI(%a6) //set SNAN bit in sop + fmovel %d1,%fpcr //restore user's rmode/prec + fmovex FPTEMP(%a6),%fp0 //load non-sign. nan + orl #snaniop_mask,USER_FPSR(%a6) //set NAN, SNAN, AIOP + rts + +// +// 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 nan + beqs src_pos //if clr, it was positive + bsetb #neg_bit,FPSR_CC(%a6) //set N bit +src_pos: + btstb #signan_bit,ETEMP_HI(%a6) //check if signalling + beqs src_snan //branch if signalling + fmovel %d1,%fpcr //restore user's rmode/prec + fmovex ETEMP(%a6),%fp0 //return the non-signalling nan + rts + +src_snan: + btstb #snan_bit,FPCR_ENABLE(%a6) //check if trap enabled + beqs src_dis //branch if disabled + bsetb #signan_bit,ETEMP_HI(%a6) //set SNAN bit in sop + orb #norm_tag,DTAG(%a6) //set up dtag for norm + orb #nan_tag,STAG(%a6) //set up stag for nan + st STORE_FLG(%a6) //do not store a result + orl #snaniop_mask,USER_FPSR(%a6) //set NAN, SNAN, AIOP + rts + +src_dis: + bsetb #signan_bit,ETEMP_HI(%a6) //set SNAN bit in sop + fmovel %d1,%fpcr //restore user's rmode/prec + fmovex ETEMP(%a6),%fp0 //load non-sign. nan + orl #snaniop_mask,USER_FPSR(%a6) //set NAN, SNAN, AIOP + rts + +// +// 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, AINEX + bras 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),%a0 + + bclrb #sign_bit,LOCAL_EX(%a0) + sne LOCAL_SGN(%a0) //convert to internal ext format + tstw LOCAL_EX(%a0) //check if input is denorm + beqs xdnrm_dn //if so, skip nrm_set + bsr nrm_set //normalize the result (exponent +// ;will be negative +xdnrm_dn: + bclrb #sign_bit,LOCAL_EX(%a0) //take off false sign + bfclr LOCAL_SGN(%a0){#0:#8} //change back to IEEE ext format + beqs xdep + bsetb #sign_bit,LOCAL_EX(%a0) +xdep: + bfclr STAG(%a6){#5:#3} //clear wbtm66,wbtm1,wbtm0 + bsetb #wbtemp15_bit,WB_BYTE(%a6) //set wbtemp15 + bclrb #sticky_bit,STICKY(%a6) //clear sticky bit + bclrb #E1,E_BYTE(%a6) + movel (%a7)+,%a0 +xdnrm_dis: + bfextu FPCR_MODE(%a6){#0:#2},%d0 //get round precision + bnes not_ext //if not round extended, store +// ;IEEE defaults +is_ext: + btstb #sign_bit,LOCAL_EX(%a0) + beqs xdnrm_store + + bsetb #neg_bit,FPSR_CC(%a6) //set N bit in FPSR_CC + + bras xdnrm_store + +not_ext: + bclrb #sign_bit,LOCAL_EX(%a0) + sne LOCAL_SGN(%a0) //convert to internal ext format + bsr unf_sub //returns IEEE result pointed by +// ;a0; sets FPSR_CC accordingly + bfclr LOCAL_SGN(%a0){#0:#8} //convert back to IEEE ext format + beqs xdnrm_store + bsetb #sign_bit,LOCAL_EX(%a0) +xdnrm_store: + fmovemx (%a0),%fp0-%fp0 //store result in fp0 + rts + +// +// 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_unsupp +t_avoid_unsupp: + link %a2,#-LOCAL_SIZE //so that a2 fpsp.h negative +// ;offsets may be used + fsave -(%a7) + tstb 1(%a7) //check if idle, exit if so + beq idle_end + btstb #E1,E_BYTE(%a2) //check for an E1 exception if +// ;enabled, there is an unsupp + beq end_avun //else, exit + btstb #7,DTAG(%a2) //check for denorm destination + beqs src_den //else, must be a source denorm +// +// handle destination denorm +// + lea FPTEMP(%a2),%a0 + btstb #sign_bit,LOCAL_EX(%a0) + sne LOCAL_SGN(%a0) //convert to internal ext format + bclrb #7,DTAG(%a2) //set DTAG to norm + bsr nrm_set //normalize result, exponent +// ;will become negative + bclrb #sign_bit,LOCAL_EX(%a0) //get rid of fake sign + bfclr LOCAL_SGN(%a0){#0:#8} //convert back to IEEE ext format + beqs ck_src_den //check if source is also denorm + bsetb #sign_bit,LOCAL_EX(%a0) +ck_src_den: + btstb #7,STAG(%a2) + beqs end_avun +src_den: + lea ETEMP(%a2),%a0 + btstb #sign_bit,LOCAL_EX(%a0) + sne LOCAL_SGN(%a0) //convert to internal ext format + bclrb #7,STAG(%a2) //set STAG to norm + bsr nrm_set //normalize result, exponent +// ;will become negative + bclrb #sign_bit,LOCAL_EX(%a0) //get rid of fake sign + bfclr LOCAL_SGN(%a0){#0:#8} //convert back to IEEE ext format + beqs den_com + bsetb #sign_bit,LOCAL_EX(%a0) +den_com: + moveb #0xfe,CU_SAVEPC(%a2) //set continue frame + clrw NMNEXC(%a2) //clear NMNEXC + bclrb #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 %a2 + rts +idle_end: + addl #4,%a7 + unlk %a2 + rts + |end |