1 | 2 | x_unfl.sa 3.4 7/1/91 3 | 4 | fpsp_unfl --- FPSP handler for underflow exception 5 | 6 | Trap disabled results 7 | For 881/2 compatibility, sw must denormalize the intermediate 8 | result, then store the result. Denormalization is accomplished 9 | by taking the intermediate result (which is always normalized) and 10 | shifting the mantissa right while incrementing the exponent until 11 | it is equal to the denormalized exponent for the destination 12 | format. After denormalization, the result is rounded to the 13 | destination format. 14 | 15 | Trap enabled results 16 | All trap disabled code applies. In addition the exceptional 17 | operand needs to made available to the user with a bias of $6000 18 | added to the exponent. 19 | 20 21 | Copyright (C) Motorola, Inc. 1990 22 | All Rights Reserved 23 | 24 | THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 25 | The copyright notice above does not evidence any 26 | actual or intended publication of such source code. 27 28 X_UNFL: |idnt 2,1 | Motorola 040 Floating Point Software Package 29 30 |section 8 31 32 .include "fpsp.h" 33 34 |xref denorm 35 |xref round 36 |xref store 37 |xref g_rndpr 38 |xref g_opcls 39 |xref g_dfmtou 40 |xref real_unfl 41 |xref real_inex 42 |xref fpsp_done 43 |xref b1238_fix 44 45 .global fpsp_unfl 46 fpsp_unfl: 47 link %a6,#-LOCAL_SIZE 48 fsave -(%a7) 49 moveml %d0-%d1/%a0-%a1,USER_DA(%a6) 50 fmovemx %fp0-%fp3,USER_FP0(%a6) 51 fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6) 52 53 | 54 bsrl unf_res |denormalize, round & store interm op 55 | 56 | If underflow exceptions are not enabled, check for inexact 57 | exception 58 | 59 btstb #unfl_bit,FPCR_ENABLE(%a6) 60 beqs ck_inex 61 62 btstb #E3,E_BYTE(%a6) 63 beqs no_e3_1 64 | 65 | Clear dirty bit on dest resister in the frame before branching 66 | to b1238_fix. 67 | 68 bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no 69 bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit 70 bsrl b1238_fix |test for bug1238 case 71 movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 72 orl #sx_mask,E_BYTE(%a6) 73 no_e3_1: 74 moveml USER_DA(%a6),%d0-%d1/%a0-%a1 75 fmovemx USER_FP0(%a6),%fp0-%fp3 76 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 77 frestore (%a7)+ 78 unlk %a6 79 bral real_unfl 80 | 81 | It is possible to have either inex2 or inex1 exceptions with the 82 | unfl. If the inex enable bit is set in the FPCR, and either 83 | inex2 or inex1 occurred, we must clean up and branch to the 84 | real inex handler. 85 | 86 ck_inex: 87 moveb FPCR_ENABLE(%a6),%d0 88 andb FPSR_EXCEPT(%a6),%d0 89 andib #0x3,%d0 90 beqs unfl_done 91 92 | 93 | Inexact enabled and reported, and we must take an inexact exception 94 | 95 take_inex: 96 btstb #E3,E_BYTE(%a6) 97 beqs no_e3_2 98 | 99 | Clear dirty bit on dest resister in the frame before branching 100 | to b1238_fix. 101 | 102 bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no 103 bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit 104 bsrl b1238_fix |test for bug1238 case 105 movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 106 orl #sx_mask,E_BYTE(%a6) 107 no_e3_2: 108 moveb #INEX_VEC,EXC_VEC+1(%a6) 109 moveml USER_DA(%a6),%d0-%d1/%a0-%a1 110 fmovemx USER_FP0(%a6),%fp0-%fp3 111 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 112 frestore (%a7)+ 113 unlk %a6 114 bral real_inex 115 116 unfl_done: 117 bclrb #E3,E_BYTE(%a6) 118 beqs e1_set |if set then branch 119 | 120 | Clear dirty bit on dest resister in the frame before branching 121 | to b1238_fix. 122 | 123 bfextu CMDREG3B(%a6){#6:#3},%d0 |get dest reg no 124 bclrb %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit 125 bsrl b1238_fix |test for bug1238 case 126 movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 127 orl #sx_mask,E_BYTE(%a6) 128 moveml USER_DA(%a6),%d0-%d1/%a0-%a1 129 fmovemx USER_FP0(%a6),%fp0-%fp3 130 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 131 frestore (%a7)+ 132 unlk %a6 133 bral fpsp_done 134 e1_set: 135 moveml USER_DA(%a6),%d0-%d1/%a0-%a1 136 fmovemx USER_FP0(%a6),%fp0-%fp3 137 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 138 unlk %a6 139 bral fpsp_done 140 | 141 | unf_res --- underflow result calculation 142 | 143 unf_res: 144 bsrl g_rndpr |returns RND_PREC in d0 0=ext, 145 | ;1=sgl, 2=dbl 146 | ;we need the RND_PREC in the 147 | ;upper word for round 148 movew #0,-(%a7) 149 movew %d0,-(%a7) |copy RND_PREC to stack 150 | 151 | 152 | If the exception bit set is E3, the exceptional operand from the 153 | fpu is in WBTEMP; else it is in FPTEMP. 154 | 155 btstb #E3,E_BYTE(%a6) 156 beqs unf_E1 157 unf_E3: 158 lea WBTEMP(%a6),%a0 |a0 now points to operand 159 | 160 | Test for fsgldiv and fsglmul. If the inst was one of these, then 161 | force the precision to extended for the denorm routine. Use 162 | the user's precision for the round routine. 163 | 164 movew CMDREG3B(%a6),%d1 |check for fsgldiv or fsglmul 165 andiw #0x7f,%d1 166 cmpiw #0x30,%d1 |check for sgldiv 167 beqs unf_sgl 168 cmpiw #0x33,%d1 |check for sglmul 169 bnes unf_cont |if not, use fpcr prec in round 170 unf_sgl: 171 clrl %d0 172 movew #0x1,(%a7) |override g_rndpr precision 173 | ;force single 174 bras unf_cont 175 unf_E1: 176 lea FPTEMP(%a6),%a0 |a0 now points to operand 177 unf_cont: 178 bclrb #sign_bit,LOCAL_EX(%a0) |clear sign bit 179 sne LOCAL_SGN(%a0) |store sign 180 181 bsrl denorm |returns denorm, a0 points to it 182 | 183 | WARNING: 184 | ;d0 has guard,round sticky bit 185 | ;make sure that it is not corrupted 186 | ;before it reaches the round subroutine 187 | ;also ensure that a0 isn't corrupted 188 189 | 190 | Set up d1 for round subroutine d1 contains the PREC/MODE 191 | information respectively on upper/lower register halves. 192 | 193 bfextu FPCR_MODE(%a6){#2:#2},%d1 |get mode from FPCR 194 | ;mode in lower d1 195 addl (%a7)+,%d1 |merge PREC/MODE 196 | 197 | WARNING: a0 and d0 are assumed to be intact between the denorm and 198 | round subroutines. All code between these two subroutines 199 | must not corrupt a0 and d0. 200 | 201 | 202 | Perform Round 203 | Input: a0 points to input operand 204 | d0{31:29} has guard, round, sticky 205 | d1{01:00} has rounding mode 206 | d1{17:16} has rounding precision 207 | Output: a0 points to rounded operand 208 | 209 210 bsrl round |returns rounded denorm at (a0) 211 | 212 | Differentiate between store to memory vs. store to register 213 | 214 unf_store: 215 bsrl g_opcls |returns opclass in d0{2:0} 216 cmpib #0x3,%d0 217 bnes not_opc011 218 | 219 | At this point, a store to memory is pending 220 | 221 opc011: 222 bsrl g_dfmtou 223 tstb %d0 224 beqs ext_opc011 |If extended, do not subtract 225 | ;If destination format is sgl/dbl, 226 tstb LOCAL_HI(%a0) |If rounded result is normal,don't 227 | ;subtract 228 bmis ext_opc011 229 subqw #1,LOCAL_EX(%a0) |account for denorm bias vs. 230 | ;normalized bias 231 | ; normalized denormalized 232 | ;single $7f $7e 233 | ;double $3ff $3fe 234 | 235 ext_opc011: 236 bsrl store |stores to memory 237 bras unf_done |finish up 238 239 | 240 | At this point, a store to a float register is pending 241 | 242 not_opc011: 243 bsrl store |stores to float register 244 | ;a0 is not corrupted on a store to a 245 | ;float register. 246 | 247 | Set the condition codes according to result 248 | 249 tstl LOCAL_HI(%a0) |check upper mantissa 250 bnes ck_sgn 251 tstl LOCAL_LO(%a0) |check lower mantissa 252 bnes ck_sgn 253 bsetb #z_bit,FPSR_CC(%a6) |set condition codes if zero 254 ck_sgn: 255 btstb #sign_bit,LOCAL_EX(%a0) |check the sign bit 256 beqs unf_done 257 bsetb #neg_bit,FPSR_CC(%a6) 258 259 | 260 | Finish. 261 | 262 unf_done: 263 btstb #inex2_bit,FPSR_EXCEPT(%a6) 264 beqs no_aunfl 265 bsetb #aunfl_bit,FPSR_AEXCEPT(%a6) 266 no_aunfl: 267 rts 268 269 |end