123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- |
- | 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
- |
- | For details on the license for this file, please see the
- | file, README, in this same directory.
- KERNEL_EX: |idnt 2,1 | Motorola 040 Floating Point Software Package
- |section 8
- #include "fpsp.h"
- 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
|