Back to home page

LXR

 
 

    


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

0001 #include "fpsp-namespace.h"
0002 //
0003 //
0004 //  x_unfl.sa 3.4 7/1/91
0005 //
0006 //  fpsp_unfl --- FPSP handler for underflow exception
0007 //
0008 // Trap disabled results
0009 //  For 881/2 compatibility, sw must denormalize the intermediate
0010 // result, then store the result.  Denormalization is accomplished
0011 // by taking the intermediate result (which is always normalized) and
0012 // shifting the mantissa right while incrementing the exponent until
0013 // it is equal to the denormalized exponent for the destination
0014 // format.  After denormalization, the result is rounded to the
0015 // destination format.
0016 //
0017 // Trap enabled results
0018 //  All trap disabled code applies. In addition the exceptional
0019 // operand needs to made available to the user with a bias of $6000
0020 // added to the exponent.
0021 //
0022 
0023 //      Copyright (C) Motorola, Inc. 1990
0024 //          All Rights Reserved
0025 //
0026 //  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
0027 //  The copyright notice above does not evidence any
0028 //  actual or intended publication of such source code.
0029 
0030 X_UNFL: //idnt    2,1 | Motorola 040 Floating Point Software Package
0031 
0032     |section    8
0033 
0034 #include "fpsp.defs"
0035 
0036     |xref   denorm
0037     |xref   round
0038     |xref   store
0039     |xref   g_rndpr
0040     |xref   g_opcls
0041     |xref   g_dfmtou
0042     |xref   real_unfl
0043     |xref   real_inex
0044     |xref   fpsp_done
0045     |xref   b1238_fix
0046 
0047     .global fpsp_unfl
0048 fpsp_unfl:
0049     link        %a6,#-LOCAL_SIZE
0050     fsave       -(%a7)
0051     moveml      %d0-%d1/%a0-%a1,USER_DA(%a6)
0052     fmovemx %fp0-%fp3,USER_FP0(%a6)
0053     fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
0054 
0055 //
0056     bsrl        unf_res //denormalize, round & store interm op
0057 //
0058 // If underflow exceptions are not enabled, check for inexact
0059 // exception
0060 //
0061     btstb       #unfl_bit,FPCR_ENABLE(%a6)
0062     beqs        ck_inex
0063 
0064     btstb       #E3,E_BYTE(%a6)
0065     beqs        no_e3_1
0066 //
0067 // Clear dirty bit on dest resister in the frame before branching
0068 // to b1238_fix.
0069 //
0070     bfextu      CMDREG3B(%a6){#6:#3},%d0    //get dest reg no
0071     bclrb       %d0,FPR_DIRTY_BITS(%a6) //clr dest dirty bit
0072     bsrl        b1238_fix       //test for bug1238 case
0073     movel       USER_FPSR(%a6),FPSR_SHADOW(%a6)
0074     orl     #sx_mask,E_BYTE(%a6)
0075 no_e3_1:
0076     moveml      USER_DA(%a6),%d0-%d1/%a0-%a1
0077     fmovemx USER_FP0(%a6),%fp0-%fp3
0078     fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0079     frestore    (%a7)+
0080     unlk        %a6
0081     bral        real_unfl
0082 //
0083 // It is possible to have either inex2 or inex1 exceptions with the
0084 // unfl.  If the inex enable bit is set in the FPCR, and either
0085 // inex2 or inex1 occurred, we must clean up and branch to the
0086 // real inex handler.
0087 //
0088 ck_inex:
0089     moveb       FPCR_ENABLE(%a6),%d0
0090     andb        FPSR_EXCEPT(%a6),%d0
0091     andib       #0x3,%d0
0092     beqs        unfl_done
0093 
0094 //
0095 // Inexact enabled and reported, and we must take an inexact exception
0096 //
0097 take_inex:
0098     btstb       #E3,E_BYTE(%a6)
0099     beqs        no_e3_2
0100 //
0101 // Clear dirty bit on dest resister in the frame before branching
0102 // to b1238_fix.
0103 //
0104     bfextu      CMDREG3B(%a6){#6:#3},%d0    //get dest reg no
0105     bclrb       %d0,FPR_DIRTY_BITS(%a6) //clr dest dirty bit
0106     bsrl        b1238_fix       //test for bug1238 case
0107     movel       USER_FPSR(%a6),FPSR_SHADOW(%a6)
0108     orl     #sx_mask,E_BYTE(%a6)
0109 no_e3_2:
0110     moveb       #INEX_VEC,EXC_VEC+1(%a6)
0111     moveml         USER_DA(%a6),%d0-%d1/%a0-%a1
0112     fmovemx        USER_FP0(%a6),%fp0-%fp3
0113     fmoveml        USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0114     frestore        (%a7)+
0115     unlk            %a6
0116     bral        real_inex
0117 
0118 unfl_done:
0119     bclrb       #E3,E_BYTE(%a6)
0120     beqs        e1_set      //if set then branch
0121 //
0122 // Clear dirty bit on dest resister in the frame before branching
0123 // to b1238_fix.
0124 //
0125     bfextu      CMDREG3B(%a6){#6:#3},%d0        //get dest reg no
0126     bclrb       %d0,FPR_DIRTY_BITS(%a6) //clr dest dirty bit
0127     bsrl        b1238_fix       //test for bug1238 case
0128     movel       USER_FPSR(%a6),FPSR_SHADOW(%a6)
0129     orl     #sx_mask,E_BYTE(%a6)
0130     moveml      USER_DA(%a6),%d0-%d1/%a0-%a1
0131     fmovemx USER_FP0(%a6),%fp0-%fp3
0132     fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0133     frestore    (%a7)+
0134     unlk        %a6
0135     bral        fpsp_done
0136 e1_set:
0137     moveml      USER_DA(%a6),%d0-%d1/%a0-%a1
0138     fmovemx USER_FP0(%a6),%fp0-%fp3
0139     fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0140     unlk        %a6
0141     bral        fpsp_done
0142 //
0143 //  unf_res --- underflow result calculation
0144 //
0145 unf_res:
0146     bsrl        g_rndpr     //returns RND_PREC in d0 0=ext,
0147 //                  ;1=sgl, 2=dbl
0148 //                  ;we need the RND_PREC in the
0149 //                  ;upper word for round
0150     movew       #0,-(%a7)
0151     movew       %d0,-(%a7)  //copy RND_PREC to stack
0152 //
0153 //
0154 // If the exception bit set is E3, the exceptional operand from the
0155 // fpu is in WBTEMP; else it is in FPTEMP.
0156 //
0157     btstb       #E3,E_BYTE(%a6)
0158     beqs        unf_E1
0159 unf_E3:
0160     lea     WBTEMP(%a6),%a0 //a0 now points to operand
0161 //
0162 // Test for fsgldiv and fsglmul.  If the inst was one of these, then
0163 // force the precision to extended for the denorm routine.  Use
0164 // the user's precision for the round routine.
0165 //
0166     movew       CMDREG3B(%a6),%d1   //check for fsgldiv or fsglmul
0167     andiw       #0x7f,%d1
0168     cmpiw       #0x30,%d1       //check for sgldiv
0169     beqs        unf_sgl
0170     cmpiw       #0x33,%d1       //check for sglmul
0171     bnes        unf_cont    //if not, use fpcr prec in round
0172 unf_sgl:
0173     clrl        %d0
0174     movew       #0x1,(%a7)  //override g_rndpr precision
0175 //                  ;force single
0176     bras        unf_cont
0177 unf_E1:
0178     lea     FPTEMP(%a6),%a0 //a0 now points to operand
0179 unf_cont:
0180     bclrb       #sign_bit,LOCAL_EX(%a0) //clear sign bit
0181     sne     LOCAL_SGN(%a0)      //store sign
0182 
0183     bsrl        denorm      //returns denorm, a0 points to it
0184 //
0185 // WARNING:
0186 //              ;d0 has guard,round sticky bit
0187 //              ;make sure that it is not corrupted
0188 //              ;before it reaches the round subroutine
0189 //              ;also ensure that a0 isn't corrupted
0190 
0191 //
0192 // Set up d1 for round subroutine d1 contains the PREC/MODE
0193 // information respectively on upper/lower register halves.
0194 //
0195     bfextu      FPCR_MODE(%a6){#2:#2},%d1   //get mode from FPCR
0196 //                      ;mode in lower d1
0197     addl        (%a7)+,%d1      //merge PREC/MODE
0198 //
0199 // WARNING: a0 and d0 are assumed to be intact between the denorm and
0200 // round subroutines. All code between these two subroutines
0201 // must not corrupt a0 and d0.
0202 //
0203 //
0204 // Perform Round
0205 //  Input:      a0 points to input operand
0206 //          d0{31:29} has guard, round, sticky
0207 //          d1{01:00} has rounding mode
0208 //          d1{17:16} has rounding precision
0209 //  Output:     a0 points to rounded operand
0210 //
0211 
0212     bsrl        round       //returns rounded denorm at (a0)
0213 //
0214 // Differentiate between store to memory vs. store to register
0215 //
0216 unf_store:
0217     bsrl        g_opcls     //returns opclass in d0{2:0}
0218     cmpib       #0x3,%d0
0219     bnes        not_opc011
0220 //
0221 // At this point, a store to memory is pending
0222 //
0223 opc011:
0224     bsrl        g_dfmtou
0225     tstb        %d0
0226     beqs        ext_opc011  //If extended, do not subtract
0227 //              ;If destination format is sgl/dbl,
0228     tstb        LOCAL_HI(%a0)   //If rounded result is normal,don't
0229 //                  ;subtract
0230     bmis        ext_opc011
0231     subqw       #1,LOCAL_EX(%a0)    //account for denorm bias vs.
0232 //              ;normalized bias
0233 //              ;          normalized   denormalized
0234 //              ;single       $7f           $7e
0235 //              ;double       $3ff          $3fe
0236 //
0237 ext_opc011:
0238     bsrl        store       //stores to memory
0239     bras        unf_done    //finish up
0240 
0241 //
0242 // At this point, a store to a float register is pending
0243 //
0244 not_opc011:
0245     bsrl        store   //stores to float register
0246 //              ;a0 is not corrupted on a store to a
0247 //              ;float register.
0248 //
0249 // Set the condition codes according to result
0250 //
0251     tstl        LOCAL_HI(%a0)   //check upper mantissa
0252     bnes        ck_sgn
0253     tstl        LOCAL_LO(%a0)   //check lower mantissa
0254     bnes        ck_sgn
0255     bsetb       #z_bit,FPSR_CC(%a6) //set condition codes if zero
0256 ck_sgn:
0257     btstb       #sign_bit,LOCAL_EX(%a0) //check the sign bit
0258     beqs        unf_done
0259     bsetb       #neg_bit,FPSR_CC(%a6)
0260 
0261 //
0262 // Finish.
0263 //
0264 unf_done:
0265     btstb       #inex2_bit,FPSR_EXCEPT(%a6)
0266     beqs        no_aunfl
0267     bsetb       #aunfl_bit,FPSR_AEXCEPT(%a6)
0268 no_aunfl:
0269     rts
0270 
0271     |end