Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:48

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