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