Back to home page

LXR

 
 

    


0001 |
0002 |   kernel_ex.sa 3.3 12/19/90
0003 |
0004 | This file contains routines to force exception status in the
0005 | fpu for exceptional cases detected or reported within the
0006 | transcendental functions.  Typically, the t_xx routine will
0007 | set the appropriate bits in the USER_FPSR word on the stack.
0008 | The bits are tested in gen_except.sa to determine if an exceptional
0009 | situation needs to be created on return from the FPSP.
0010 |
0011 
0012 |       Copyright (C) Motorola, Inc. 1990
0013 |           All Rights Reserved
0014 |
0015 |       For details on the license for this file, please see the
0016 |       file, README, in this same directory.
0017 
0018 KERNEL_EX:    |idnt    2,1 | Motorola 040 Floating Point Software Package
0019 
0020     |section    8
0021 
0022 #include "fpsp.h"
0023 
0024 mns_inf:  .long 0xffff0000,0x00000000,0x00000000
0025 pls_inf:  .long 0x7fff0000,0x00000000,0x00000000
0026 nan:      .long 0x7fff0000,0xffffffff,0xffffffff
0027 huge:     .long 0x7ffe0000,0xffffffff,0xffffffff
0028 
0029     |xref     ovf_r_k
0030     |xref     unf_sub
0031     |xref     nrm_set
0032 
0033     .global   t_dz
0034     .global      t_dz2
0035     .global      t_operr
0036     .global      t_unfl
0037     .global      t_ovfl
0038     .global      t_ovfl2
0039     .global      t_inx2
0040     .global   t_frcinx
0041     .global   t_extdnrm
0042     .global   t_resdnrm
0043     .global   dst_nan
0044     .global   src_nan
0045 |
0046 |   DZ exception
0047 |
0048 |
0049 |   if dz trap disabled
0050 |       store properly signed inf (use sign of etemp) into fp0
0051 |       set FPSR exception status dz bit, condition code
0052 |       inf bit, and accrued dz bit
0053 |       return
0054 |       frestore the frame into the machine (done by unimp_hd)
0055 |
0056 |   else dz trap enabled
0057 |       set exception status bit & accrued bits in FPSR
0058 |       set flag to disable sto_res from corrupting fp register
0059 |       return
0060 |       frestore the frame into the machine (done by unimp_hd)
0061 |
0062 | t_dz2 is used by monadic functions such as flogn (from do_func).
0063 | t_dz is used by monadic functions such as satanh (from the
0064 | transcendental function).
0065 |
0066 t_dz2:
0067     bsetb   #neg_bit,FPSR_CC(%a6)   |set neg bit in FPSR
0068     fmovel  #0,%FPSR            |clr status bits (Z set)
0069     btstb   #dz_bit,FPCR_ENABLE(%a6)    |test FPCR for dz exc enabled
0070     bnes    dz_ena_end
0071     bras    m_inf           |flogx always returns -inf
0072 t_dz:
0073     fmovel  #0,%FPSR            |clr status bits (Z set)
0074     btstb   #dz_bit,FPCR_ENABLE(%a6)    |test FPCR for dz exc enabled
0075     bnes    dz_ena
0076 |
0077 |   dz disabled
0078 |
0079     btstb   #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos
0080     beqs    p_inf           |branch if pos sign
0081 
0082 m_inf:
0083     fmovemx mns_inf,%fp0-%fp0       |load -inf
0084     bsetb   #neg_bit,FPSR_CC(%a6)   |set neg bit in FPSR
0085     bras    set_fpsr
0086 p_inf:
0087     fmovemx pls_inf,%fp0-%fp0       |load +inf
0088 set_fpsr:
0089     orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
0090     rts
0091 |
0092 |   dz enabled
0093 |
0094 dz_ena:
0095     btstb   #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos
0096     beqs    dz_ena_end
0097     bsetb   #neg_bit,FPSR_CC(%a6)   |set neg bit in FPSR
0098 dz_ena_end:
0099     orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ
0100     st  STORE_FLG(%a6)
0101     rts
0102 |
0103 |   OPERR exception
0104 |
0105 |   if (operr trap disabled)
0106 |       set FPSR exception status operr bit, condition code
0107 |       nan bit; Store default NAN into fp0
0108 |       frestore the frame into the machine (done by unimp_hd)
0109 |
0110 |   else (operr trap enabled)
0111 |       set FPSR exception status operr bit, accrued operr bit
0112 |       set flag to disable sto_res from corrupting fp register
0113 |       frestore the frame into the machine (done by unimp_hd)
0114 |
0115 t_operr:
0116     orl #opnan_mask,USER_FPSR(%a6) |set NaN, OPERR, AIOP
0117 
0118     btstb   #operr_bit,FPCR_ENABLE(%a6) |test FPCR for operr enabled
0119     bnes    op_ena
0120 
0121     fmovemx nan,%fp0-%fp0       |load default nan
0122     rts
0123 op_ena:
0124     st  STORE_FLG(%a6)      |do not corrupt destination
0125     rts
0126 
0127 |
0128 |   t_unfl --- UNFL exception
0129 |
0130 | This entry point is used by all routines requiring unfl, inex2,
0131 | aunfl, and ainex to be set on exit.
0132 |
0133 | On entry, a0 points to the exceptional operand.  The final exceptional
0134 | operand is built in FP_SCR1 and only the sign from the original operand
0135 | is used.
0136 |
0137 t_unfl:
0138     clrl    FP_SCR1(%a6)        |set exceptional operand to zero
0139     clrl    FP_SCR1+4(%a6)
0140     clrl    FP_SCR1+8(%a6)
0141     tstb    (%a0)           |extract sign from caller's exop
0142     bpls    unfl_signok
0143     bset    #sign_bit,FP_SCR1(%a6)
0144 unfl_signok:
0145     leal    FP_SCR1(%a6),%a0
0146     orl #unfinx_mask,USER_FPSR(%a6)
0147 |                   ;set UNFL, INEX2, AUNFL, AINEX
0148 unfl_con:
0149     btstb   #unfl_bit,FPCR_ENABLE(%a6)
0150     beqs    unfl_dis
0151 
0152 unfl_ena:
0153     bfclr   STAG(%a6){#5:#3}        |clear wbtm66,wbtm1,wbtm0
0154     bsetb   #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
0155     bsetb   #sticky_bit,STICKY(%a6) |set sticky bit
0156 
0157     bclrb   #E1,E_BYTE(%a6)
0158 
0159 unfl_dis:
0160     bfextu  FPCR_MODE(%a6){#0:#2},%d0   |get round precision
0161 
0162     bclrb   #sign_bit,LOCAL_EX(%a0)
0163     sne LOCAL_SGN(%a0)      |convert to internal ext format
0164 
0165     bsr unf_sub         |returns IEEE result at a0
0166 |                   ;and sets FPSR_CC accordingly
0167 
0168     bfclr   LOCAL_SGN(%a0){#0:#8}   |convert back to IEEE ext format
0169     beqs    unfl_fin
0170 
0171     bsetb   #sign_bit,LOCAL_EX(%a0)
0172     bsetb   #sign_bit,FP_SCR1(%a6)  |set sign bit of exc operand
0173 
0174 unfl_fin:
0175     fmovemx (%a0),%fp0-%fp0     |store result in fp0
0176     rts
0177 
0178 
0179 |
0180 |   t_ovfl2 --- OVFL exception (without inex2 returned)
0181 |
0182 | This entry is used by scale to force catastrophic overflow.  The
0183 | ovfl, aovfl, and ainex bits are set, but not the inex2 bit.
0184 |
0185 t_ovfl2:
0186     orl #ovfl_inx_mask,USER_FPSR(%a6)
0187     movel   ETEMP(%a6),FP_SCR1(%a6)
0188     movel   ETEMP_HI(%a6),FP_SCR1+4(%a6)
0189     movel   ETEMP_LO(%a6),FP_SCR1+8(%a6)
0190 |
0191 | Check for single or double round precision.  If single, check if
0192 | the lower 40 bits of ETEMP are zero; if not, set inex2.  If double,
0193 | check if the lower 21 bits are zero; if not, set inex2.
0194 |
0195     moveb   FPCR_MODE(%a6),%d0
0196     andib   #0xc0,%d0
0197     beq t_work      |if extended, finish ovfl processing
0198     cmpib   #0x40,%d0       |test for single
0199     bnes    t_dbl
0200 t_sgl:
0201     tstb    ETEMP_LO(%a6)
0202     bnes    t_setinx2
0203     movel   ETEMP_HI(%a6),%d0
0204     andil   #0xff,%d0       |look at only lower 8 bits
0205     bnes    t_setinx2
0206     bra t_work
0207 t_dbl:
0208     movel   ETEMP_LO(%a6),%d0
0209     andil   #0x7ff,%d0  |look at only lower 11 bits
0210     beq t_work
0211 t_setinx2:
0212     orl #inex2_mask,USER_FPSR(%a6)
0213     bras    t_work
0214 |
0215 |   t_ovfl --- OVFL exception
0216 |
0217 |** Note: the exc operand is returned in ETEMP.
0218 |
0219 t_ovfl:
0220     orl #ovfinx_mask,USER_FPSR(%a6)
0221 t_work:
0222     btstb   #ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled
0223     beqs    ovf_dis
0224 
0225 ovf_ena:
0226     clrl    FP_SCR1(%a6)        |set exceptional operand
0227     clrl    FP_SCR1+4(%a6)
0228     clrl    FP_SCR1+8(%a6)
0229 
0230     bfclr   STAG(%a6){#5:#3}        |clear wbtm66,wbtm1,wbtm0
0231     bclrb   #wbtemp15_bit,WB_BYTE(%a6) |clear wbtemp15
0232     bsetb   #sticky_bit,STICKY(%a6) |set sticky bit
0233 
0234     bclrb   #E1,E_BYTE(%a6)
0235 |                   ;fall through to disabled case
0236 
0237 | For disabled overflow call 'ovf_r_k'.  This routine loads the
0238 | correct result based on the rounding precision, destination
0239 | format, rounding mode and sign.
0240 |
0241 ovf_dis:
0242     bsr ovf_r_k         |returns unsigned ETEMP_EX
0243 |                   ;and sets FPSR_CC accordingly.
0244     bfclr   ETEMP_SGN(%a6){#0:#8}   |fix sign
0245     beqs    ovf_pos
0246     bsetb   #sign_bit,ETEMP_EX(%a6)
0247     bsetb   #sign_bit,FP_SCR1(%a6)  |set exceptional operand sign
0248 ovf_pos:
0249     fmovemx ETEMP(%a6),%fp0-%fp0        |move the result to fp0
0250     rts
0251 
0252 
0253 |
0254 |   INEX2 exception
0255 |
0256 | The inex2 and ainex bits are set.
0257 |
0258 t_inx2:
0259     orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
0260     rts
0261 
0262 |
0263 |   Force Inex2
0264 |
0265 | This routine is called by the transcendental routines to force
0266 | the inex2 exception bits set in the FPSR.  If the underflow bit
0267 | is set, but the underflow trap was not taken, the aunfl bit in
0268 | the FPSR must be set.
0269 |
0270 t_frcinx:
0271     orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX
0272     btstb   #unfl_bit,FPSR_EXCEPT(%a6) |test for unfl bit set
0273     beqs    no_uacc1        |if clear, do not set aunfl
0274     bsetb   #aunfl_bit,FPSR_AEXCEPT(%a6)
0275 no_uacc1:
0276     rts
0277 
0278 |
0279 |   DST_NAN
0280 |
0281 | Determine if the destination nan is signalling or non-signalling,
0282 | and set the FPSR bits accordingly.  See the MC68040 User's Manual
0283 | section 3.2.2.5 NOT-A-NUMBERS.
0284 |
0285 dst_nan:
0286     btstb   #sign_bit,FPTEMP_EX(%a6) |test sign of nan
0287     beqs    dst_pos         |if clr, it was positive
0288     bsetb   #neg_bit,FPSR_CC(%a6)   |set N bit
0289 dst_pos:
0290     btstb   #signan_bit,FPTEMP_HI(%a6) |check if signalling
0291     beqs    dst_snan        |branch if signalling
0292 
0293     fmovel  %d1,%fpcr           |restore user's rmode/prec
0294     fmovex FPTEMP(%a6),%fp0     |return the non-signalling nan
0295 |
0296 | Check the source nan.  If it is signalling, snan will be reported.
0297 |
0298     moveb   STAG(%a6),%d0
0299     andib   #0xe0,%d0
0300     cmpib   #0x60,%d0
0301     bnes    no_snan
0302     btstb   #signan_bit,ETEMP_HI(%a6) |check if signalling
0303     bnes    no_snan
0304     orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
0305 no_snan:
0306     rts
0307 
0308 dst_snan:
0309     btstb   #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled
0310     beqs    dst_dis         |branch if disabled
0311 
0312     orb #nan_tag,DTAG(%a6)  |set up dtag for nan
0313     st  STORE_FLG(%a6)      |do not store a result
0314     orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
0315     rts
0316 
0317 dst_dis:
0318     bsetb   #signan_bit,FPTEMP_HI(%a6) |set SNAN bit in sop
0319     fmovel  %d1,%fpcr           |restore user's rmode/prec
0320     fmovex FPTEMP(%a6),%fp0     |load non-sign. nan
0321     orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
0322     rts
0323 
0324 |
0325 |   SRC_NAN
0326 |
0327 | Determine if the source nan is signalling or non-signalling,
0328 | and set the FPSR bits accordingly.  See the MC68040 User's Manual
0329 | section 3.2.2.5 NOT-A-NUMBERS.
0330 |
0331 src_nan:
0332     btstb   #sign_bit,ETEMP_EX(%a6) |test sign of nan
0333     beqs    src_pos         |if clr, it was positive
0334     bsetb   #neg_bit,FPSR_CC(%a6)   |set N bit
0335 src_pos:
0336     btstb   #signan_bit,ETEMP_HI(%a6) |check if signalling
0337     beqs    src_snan        |branch if signalling
0338     fmovel  %d1,%fpcr           |restore user's rmode/prec
0339     fmovex ETEMP(%a6),%fp0      |return the non-signalling nan
0340     rts
0341 
0342 src_snan:
0343     btstb   #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled
0344     beqs    src_dis         |branch if disabled
0345     bsetb   #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop
0346     orb #norm_tag,DTAG(%a6) |set up dtag for norm
0347     orb #nan_tag,STAG(%a6)  |set up stag for nan
0348     st  STORE_FLG(%a6)      |do not store a result
0349     orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
0350     rts
0351 
0352 src_dis:
0353     bsetb   #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop
0354     fmovel  %d1,%fpcr           |restore user's rmode/prec
0355     fmovex ETEMP(%a6),%fp0      |load non-sign. nan
0356     orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP
0357     rts
0358 
0359 |
0360 | For all functions that have a denormalized input and that f(x)=x,
0361 | this is the entry point
0362 |
0363 t_extdnrm:
0364     orl #unfinx_mask,USER_FPSR(%a6)
0365 |                   ;set UNFL, INEX2, AUNFL, AINEX
0366     bras    xdnrm_con
0367 |
0368 | Entry point for scale with extended denorm.  The function does
0369 | not set inex2, aunfl, or ainex.
0370 |
0371 t_resdnrm:
0372     orl #unfl_mask,USER_FPSR(%a6)
0373 
0374 xdnrm_con:
0375     btstb   #unfl_bit,FPCR_ENABLE(%a6)
0376     beqs    xdnrm_dis
0377 
0378 |
0379 | If exceptions are enabled, the additional task of setting up WBTEMP
0380 | is needed so that when the underflow exception handler is entered,
0381 | the user perceives no difference between what the 040 provides vs.
0382 | what the FPSP provides.
0383 |
0384 xdnrm_ena:
0385     movel   %a0,-(%a7)
0386 
0387     movel   LOCAL_EX(%a0),FP_SCR1(%a6)
0388     movel   LOCAL_HI(%a0),FP_SCR1+4(%a6)
0389     movel   LOCAL_LO(%a0),FP_SCR1+8(%a6)
0390 
0391     lea FP_SCR1(%a6),%a0
0392 
0393     bclrb   #sign_bit,LOCAL_EX(%a0)
0394     sne LOCAL_SGN(%a0)      |convert to internal ext format
0395     tstw    LOCAL_EX(%a0)       |check if input is denorm
0396     beqs    xdnrm_dn        |if so, skip nrm_set
0397     bsr nrm_set         |normalize the result (exponent
0398 |                   ;will be negative
0399 xdnrm_dn:
0400     bclrb   #sign_bit,LOCAL_EX(%a0) |take off false sign
0401     bfclr   LOCAL_SGN(%a0){#0:#8}   |change back to IEEE ext format
0402     beqs    xdep
0403     bsetb   #sign_bit,LOCAL_EX(%a0)
0404 xdep:
0405     bfclr   STAG(%a6){#5:#3}        |clear wbtm66,wbtm1,wbtm0
0406     bsetb   #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15
0407     bclrb   #sticky_bit,STICKY(%a6) |clear sticky bit
0408     bclrb   #E1,E_BYTE(%a6)
0409     movel   (%a7)+,%a0
0410 xdnrm_dis:
0411     bfextu  FPCR_MODE(%a6){#0:#2},%d0   |get round precision
0412     bnes    not_ext         |if not round extended, store
0413 |                   ;IEEE defaults
0414 is_ext:
0415     btstb   #sign_bit,LOCAL_EX(%a0)
0416     beqs    xdnrm_store
0417 
0418     bsetb   #neg_bit,FPSR_CC(%a6)   |set N bit in FPSR_CC
0419 
0420     bras    xdnrm_store
0421 
0422 not_ext:
0423     bclrb   #sign_bit,LOCAL_EX(%a0)
0424     sne LOCAL_SGN(%a0)      |convert to internal ext format
0425     bsr unf_sub         |returns IEEE result pointed by
0426 |                   ;a0; sets FPSR_CC accordingly
0427     bfclr   LOCAL_SGN(%a0){#0:#8}   |convert back to IEEE ext format
0428     beqs    xdnrm_store
0429     bsetb   #sign_bit,LOCAL_EX(%a0)
0430 xdnrm_store:
0431     fmovemx (%a0),%fp0-%fp0     |store result in fp0
0432     rts
0433 
0434 |
0435 | This subroutine is used for dyadic operations that use an extended
0436 | denorm within the kernel. The approach used is to capture the frame,
0437 | fix/restore.
0438 |
0439     .global t_avoid_unsupp
0440 t_avoid_unsupp:
0441     link    %a2,#-LOCAL_SIZE        |so that a2 fpsp.h negative
0442 |                   ;offsets may be used
0443     fsave   -(%a7)
0444     tstb    1(%a7)          |check if idle, exit if so
0445     beq idle_end
0446     btstb   #E1,E_BYTE(%a2)     |check for an E1 exception if
0447 |                   ;enabled, there is an unsupp
0448     beq end_avun        |else, exit
0449     btstb   #7,DTAG(%a2)        |check for denorm destination
0450     beqs    src_den         |else, must be a source denorm
0451 |
0452 | handle destination denorm
0453 |
0454     lea FPTEMP(%a2),%a0
0455     btstb   #sign_bit,LOCAL_EX(%a0)
0456     sne LOCAL_SGN(%a0)      |convert to internal ext format
0457     bclrb   #7,DTAG(%a2)        |set DTAG to norm
0458     bsr nrm_set         |normalize result, exponent
0459 |                   ;will become negative
0460     bclrb   #sign_bit,LOCAL_EX(%a0) |get rid of fake sign
0461     bfclr   LOCAL_SGN(%a0){#0:#8}   |convert back to IEEE ext format
0462     beqs    ck_src_den      |check if source is also denorm
0463     bsetb   #sign_bit,LOCAL_EX(%a0)
0464 ck_src_den:
0465     btstb   #7,STAG(%a2)
0466     beqs    end_avun
0467 src_den:
0468     lea ETEMP(%a2),%a0
0469     btstb   #sign_bit,LOCAL_EX(%a0)
0470     sne LOCAL_SGN(%a0)      |convert to internal ext format
0471     bclrb   #7,STAG(%a2)        |set STAG to norm
0472     bsr nrm_set         |normalize result, exponent
0473 |                   ;will become negative
0474     bclrb   #sign_bit,LOCAL_EX(%a0) |get rid of fake sign
0475     bfclr   LOCAL_SGN(%a0){#0:#8}   |convert back to IEEE ext format
0476     beqs    den_com
0477     bsetb   #sign_bit,LOCAL_EX(%a0)
0478 den_com:
0479     moveb   #0xfe,CU_SAVEPC(%a2)    |set continue frame
0480     clrw    NMNEXC(%a2)     |clear NMNEXC
0481     bclrb   #E1,E_BYTE(%a2)
0482 |   fmove.l %FPSR,FPSR_SHADOW(%a2)
0483 |   bset.b  #SFLAG,E_BYTE(%a2)
0484 |   bset.b  #XFLAG,T_BYTE(%a2)
0485 end_avun:
0486     frestore (%a7)+
0487     unlk    %a2
0488     rts
0489 idle_end:
0490     addl    #4,%a7
0491     unlk    %a2
0492     rts
0493     |end