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