1 | 1 | 2 | res_func.sa 3.9 7/29/91 2 | res_func.sa 3.9 7/29/91 3 | 3 | 4 | Normalizes denormalized numbers if necessary 4 | Normalizes denormalized numbers if necessary and updates the 5 | stack frame. The function is then restored 5 | stack frame. The function is then restored back into the 6 | machine and the 040 completes the operation. 6 | machine and the 040 completes the operation. This routine 7 | is only used by the unsupported data type/fo 7 | is only used by the unsupported data type/format handler. 8 | (Exception vector 55). 8 | (Exception vector 55). 9 | 9 | 10 | For packed move out (fmove.p fpm,<ea>) the o 10 | For packed move out (fmove.p fpm,<ea>) the operation is 11 | completed here; data is packed and moved to 11 | completed here; data is packed and moved to user memory. 12 | The stack is restored to the 040 only in the 12 | The stack is restored to the 040 only in the case of a 13 | reportable exception in the conversion. 13 | reportable exception in the conversion. 14 | 14 | 15 | 15 | 16 | Copyright (C) Motorola, Inc. 1 16 | Copyright (C) Motorola, Inc. 1990 17 | All Rights Reserved 17 | All Rights Reserved 18 | 18 | 19 | For details on the license for this fi 19 | For details on the license for this file, please see the 20 | file, README, in this same directory. 20 | file, README, in this same directory. 21 21 22 RES_FUNC: |idnt 2,1 | Motorola 040 Float 22 RES_FUNC: |idnt 2,1 | Motorola 040 Floating Point Software Package 23 23 24 |section 8 24 |section 8 25 25 26 #include "fpsp.h" 26 #include "fpsp.h" 27 27 28 sp_bnds: .short 0x3f81,0x407e 28 sp_bnds: .short 0x3f81,0x407e 29 .short 0x3f6a,0x0000 29 .short 0x3f6a,0x0000 30 dp_bnds: .short 0x3c01,0x43fe 30 dp_bnds: .short 0x3c01,0x43fe 31 .short 0x3bcd,0x0000 31 .short 0x3bcd,0x0000 32 32 33 |xref mem_write 33 |xref mem_write 34 |xref bindec 34 |xref bindec 35 |xref get_fline 35 |xref get_fline 36 |xref round 36 |xref round 37 |xref denorm 37 |xref denorm 38 |xref dest_ext 38 |xref dest_ext 39 |xref dest_dbl 39 |xref dest_dbl 40 |xref dest_sgl 40 |xref dest_sgl 41 |xref unf_sub 41 |xref unf_sub 42 |xref nrm_set 42 |xref nrm_set 43 |xref dnrm_lp 43 |xref dnrm_lp 44 |xref ovf_res 44 |xref ovf_res 45 |xref reg_dest 45 |xref reg_dest 46 |xref t_ovfl 46 |xref t_ovfl 47 |xref t_unfl 47 |xref t_unfl 48 48 49 .global res_func 49 .global res_func 50 .global p_move 50 .global p_move 51 51 52 res_func: 52 res_func: 53 clrb DNRM_FLG(%a6) 53 clrb DNRM_FLG(%a6) 54 clrb RES_FLG(%a6) 54 clrb RES_FLG(%a6) 55 clrb CU_ONLY(%a6) 55 clrb CU_ONLY(%a6) 56 tstb DY_MO_FLG(%a6) 56 tstb DY_MO_FLG(%a6) 57 beqs monadic 57 beqs monadic 58 dyadic: 58 dyadic: 59 btstb #7,DTAG(%a6) |if dop = norm 59 btstb #7,DTAG(%a6) |if dop = norm=000, zero=001, 60 | ;inf=010 or na 60 | ;inf=010 or nan=011 61 beqs monadic |then branch 61 beqs monadic |then branch 62 | ;else denorm 62 | ;else denorm 63 | HANDLE DESTINATION DENORM HERE 63 | HANDLE DESTINATION DENORM HERE 64 | ;set dtag to n 64 | ;set dtag to norm 65 | ;write the tag 65 | ;write the tag & fpte15 to the fstack 66 leal FPTEMP(%a6),%a0 66 leal FPTEMP(%a6),%a0 67 67 68 bclrb #sign_bit,LOCAL_EX(%a0) 68 bclrb #sign_bit,LOCAL_EX(%a0) 69 sne LOCAL_SGN(%a0) 69 sne LOCAL_SGN(%a0) 70 70 71 bsr nrm_set |normalize num 71 bsr nrm_set |normalize number (exp will go negative) 72 bclrb #sign_bit,LOCAL_EX(%a0) |get r 72 bclrb #sign_bit,LOCAL_EX(%a0) |get rid of false sign 73 bfclr LOCAL_SGN(%a0){#0:#8} |chang 73 bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format 74 beqs dpos 74 beqs dpos 75 bsetb #sign_bit,LOCAL_EX(%a0) 75 bsetb #sign_bit,LOCAL_EX(%a0) 76 dpos: 76 dpos: 77 bfclr DTAG(%a6){#0:#4} |set t 77 bfclr DTAG(%a6){#0:#4} |set tag to normalized, FPTE15 = 0 78 bsetb #4,DTAG(%a6) |set FPTE15 78 bsetb #4,DTAG(%a6) |set FPTE15 79 orb #0x0f,DNRM_FLG(%a6) 79 orb #0x0f,DNRM_FLG(%a6) 80 monadic: 80 monadic: 81 leal ETEMP(%a6),%a0 81 leal ETEMP(%a6),%a0 82 btstb #direction_bit,CMDREG1B(%a6) 82 btstb #direction_bit,CMDREG1B(%a6) |check direction 83 bne opclass3 83 bne opclass3 |it is a mv out 84 | 84 | 85 | At this point, only opclass 0 and 2 possible 85 | At this point, only opclass 0 and 2 possible 86 | 86 | 87 btstb #7,STAG(%a6) |if sop = norm 87 btstb #7,STAG(%a6) |if sop = norm=000, zero=001, 88 | ;inf=010 or na 88 | ;inf=010 or nan=011 89 bne mon_dnrm |else denorm 89 bne mon_dnrm |else denorm 90 tstb DY_MO_FLG(%a6) |all cases of 90 tstb DY_MO_FLG(%a6) |all cases of dyadic instructions would 91 bne normal |require norma 91 bne normal |require normalization of denorm 92 92 93 | At this point: 93 | At this point: 94 | monadic instructions: fabs = $18 f 94 | monadic instructions: fabs = $18 fneg = $1a ftst = $3a 95 | fmove = $00 f 95 | fmove = $00 fsmove = $40 fdmove = $44 96 | fsqrt = $05* f 96 | fsqrt = $05* fssqrt = $41 fdsqrt = $45 97 | (*fsqrt reenco 97 | (*fsqrt reencoded to $05) 98 | 98 | 99 movew CMDREG1B(%a6),%d0 |get c 99 movew CMDREG1B(%a6),%d0 |get command register 100 andil #0x7f,%d0 100 andil #0x7f,%d0 |strip to only command word 101 | 101 | 102 | At this point, fabs, fneg, fsmove, fdmove, f 102 | At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and 103 | fdsqrt are possible. 103 | fdsqrt are possible. 104 | For cases fabs, fneg, fsmove, and fdmove got 104 | For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize) 105 | For cases fsqrt, fssqrt, and fdsqrt goto nrm 105 | For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize) 106 | 106 | 107 btstl #0,%d0 107 btstl #0,%d0 108 bne normal |weed 108 bne normal |weed out fsqrt instructions 109 | 109 | 110 | cu_norm handles fmove in instructions with n 110 | cu_norm handles fmove in instructions with normalized inputs. 111 | The routine round is used to correctly round 111 | The routine round is used to correctly round the input for the 112 | destination precision and mode. 112 | destination precision and mode. 113 | 113 | 114 cu_norm: 114 cu_norm: 115 st CU_ONLY(%a6) |set c 115 st CU_ONLY(%a6) |set cu-only inst flag 116 movew CMDREG1B(%a6),%d0 116 movew CMDREG1B(%a6),%d0 117 andib #0x3b,%d0 |isola 117 andib #0x3b,%d0 |isolate bits to select inst 118 tstb %d0 118 tstb %d0 119 beql cu_nmove |if zero, it i 119 beql cu_nmove |if zero, it is an fmove 120 cmpib #0x18,%d0 120 cmpib #0x18,%d0 121 beql cu_nabs |if $18, it is 121 beql cu_nabs |if $18, it is fabs 122 cmpib #0x1a,%d0 122 cmpib #0x1a,%d0 123 beql cu_nneg |if $1a, it is 123 beql cu_nneg |if $1a, it is fneg 124 | 124 | 125 | Inst is ftst. Check the source operand and 125 | Inst is ftst. Check the source operand and set the cc's accordingly. 126 | No write is done, so simply rts. 126 | No write is done, so simply rts. 127 | 127 | 128 cu_ntst: 128 cu_ntst: 129 movew LOCAL_EX(%a0),%d0 129 movew LOCAL_EX(%a0),%d0 130 bclrl #15,%d0 130 bclrl #15,%d0 131 sne LOCAL_SGN(%a0) 131 sne LOCAL_SGN(%a0) 132 beqs cu_ntpo 132 beqs cu_ntpo 133 orl #neg_mask,USER_FPSR(%a6) |set 133 orl #neg_mask,USER_FPSR(%a6) |set N 134 cu_ntpo: 134 cu_ntpo: 135 cmpiw #0x7fff,%d0 |test for inf/ 135 cmpiw #0x7fff,%d0 |test for inf/nan 136 bnes cu_ntcz 136 bnes cu_ntcz 137 tstl LOCAL_HI(%a0) 137 tstl LOCAL_HI(%a0) 138 bnes cu_ntn 138 bnes cu_ntn 139 tstl LOCAL_LO(%a0) 139 tstl LOCAL_LO(%a0) 140 bnes cu_ntn 140 bnes cu_ntn 141 orl #inf_mask,USER_FPSR(%a6) 141 orl #inf_mask,USER_FPSR(%a6) 142 rts 142 rts 143 cu_ntn: 143 cu_ntn: 144 orl #nan_mask,USER_FPSR(%a6) 144 orl #nan_mask,USER_FPSR(%a6) 145 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) 145 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for 146 | 146 | ;snan handler 147 147 148 rts 148 rts 149 cu_ntcz: 149 cu_ntcz: 150 tstl LOCAL_HI(%a0) 150 tstl LOCAL_HI(%a0) 151 bnel cu_ntsx 151 bnel cu_ntsx 152 tstl LOCAL_LO(%a0) 152 tstl LOCAL_LO(%a0) 153 bnel cu_ntsx 153 bnel cu_ntsx 154 orl #z_mask,USER_FPSR(%a6) 154 orl #z_mask,USER_FPSR(%a6) 155 cu_ntsx: 155 cu_ntsx: 156 rts 156 rts 157 | 157 | 158 | Inst is fabs. Execute the absolute value fu 158 | Inst is fabs. Execute the absolute value function on the input. 159 | Branch to the fmove code. If the operand is 159 | Branch to the fmove code. If the operand is NaN, do nothing. 160 | 160 | 161 cu_nabs: 161 cu_nabs: 162 moveb STAG(%a6),%d0 162 moveb STAG(%a6),%d0 163 btstl #5,%d0 |test 163 btstl #5,%d0 |test for NaN or zero 164 bne wr_etemp |if ei 164 bne wr_etemp |if either, simply write it 165 bclrb #7,LOCAL_EX(%a0) 165 bclrb #7,LOCAL_EX(%a0) |do abs 166 bras cu_nmove |fmove 166 bras cu_nmove |fmove code will finish 167 | 167 | 168 | Inst is fneg. Execute the negate value func 168 | Inst is fneg. Execute the negate value function on the input. 169 | Fall though to the fmove code. If the opera 169 | Fall though to the fmove code. If the operand is NaN, do nothing. 170 | 170 | 171 cu_nneg: 171 cu_nneg: 172 moveb STAG(%a6),%d0 172 moveb STAG(%a6),%d0 173 btstl #5,%d0 |test 173 btstl #5,%d0 |test for NaN or zero 174 bne wr_etemp |if ei 174 bne wr_etemp |if either, simply write it 175 bchgb #7,LOCAL_EX(%a0) 175 bchgb #7,LOCAL_EX(%a0) |do neg 176 | 176 | 177 | Inst is fmove. This code also handles all r 177 | Inst is fmove. This code also handles all result writes. 178 | If bit 2 is set, round is forced to double. 178 | If bit 2 is set, round is forced to double. If it is clear, 179 | and bit 6 is set, round is forced to single. 179 | and bit 6 is set, round is forced to single. If both are clear, 180 | the round precision is found in the fpcr. I 180 | the round precision is found in the fpcr. If the rounding precision 181 | is double or single, round the result before 181 | is double or single, round the result before the write. 182 | 182 | 183 cu_nmove: 183 cu_nmove: 184 moveb STAG(%a6),%d0 184 moveb STAG(%a6),%d0 185 andib #0xe0,%d0 185 andib #0xe0,%d0 |isolate stag bits 186 bne wr_etemp |if no 186 bne wr_etemp |if not norm, simply write it 187 btstb #2,CMDREG1B+1(%a6) |check 187 btstb #2,CMDREG1B+1(%a6) |check for rd 188 bne cu_nmrd 188 bne cu_nmrd 189 btstb #6,CMDREG1B+1(%a6) |check 189 btstb #6,CMDREG1B+1(%a6) |check for rs 190 bne cu_nmrs 190 bne cu_nmrs 191 | 191 | 192 | The move or operation is not with forced pre 192 | The move or operation is not with forced precision. Test for 193 | nan or inf as the input; if so, simply write 193 | nan or inf as the input; if so, simply write it to FPn. Use the 194 | FPCR_MODE byte to get rounding on norms and 194 | FPCR_MODE byte to get rounding on norms and zeros. 195 | 195 | 196 cu_nmnr: 196 cu_nmnr: 197 bfextu FPCR_MODE(%a6){#0:#2},%d0 197 bfextu FPCR_MODE(%a6){#0:#2},%d0 198 tstb %d0 |check 198 tstb %d0 |check for extended 199 beq cu_wrexn |if so 199 beq cu_wrexn |if so, just write result 200 cmpib #1,%d0 |check 200 cmpib #1,%d0 |check for single 201 beq cu_nmrs |fall 201 beq cu_nmrs |fall through to double 202 | 202 | 203 | The move is fdmove or round precision is dou 203 | The move is fdmove or round precision is double. 204 | 204 | 205 cu_nmrd: 205 cu_nmrd: 206 movel #2,%d0 |set u 206 movel #2,%d0 |set up the size for denorm 207 movew LOCAL_EX(%a0),%d1 207 movew LOCAL_EX(%a0),%d1 |compare exponent to double threshold 208 andw #0x7fff,%d1 208 andw #0x7fff,%d1 209 cmpw #0x3c01,%d1 209 cmpw #0x3c01,%d1 210 bls cu_nunfl 210 bls cu_nunfl 211 bfextu FPCR_MODE(%a6){#2:#2},%d1 211 bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rmode 212 orl #0x00020000,%d1 |or in 212 orl #0x00020000,%d1 |or in rprec (double) 213 clrl %d0 |clear 213 clrl %d0 |clear g,r,s for round 214 bclrb #sign_bit,LOCAL_EX(%a0) |conve 214 bclrb #sign_bit,LOCAL_EX(%a0) |convert to internal format 215 sne LOCAL_SGN(%a0) 215 sne LOCAL_SGN(%a0) 216 bsrl round 216 bsrl round 217 bfclr LOCAL_SGN(%a0){#0:#8} 217 bfclr LOCAL_SGN(%a0){#0:#8} 218 beqs cu_nmrdc 218 beqs cu_nmrdc 219 bsetb #sign_bit,LOCAL_EX(%a0) 219 bsetb #sign_bit,LOCAL_EX(%a0) 220 cu_nmrdc: 220 cu_nmrdc: 221 movew LOCAL_EX(%a0),%d1 221 movew LOCAL_EX(%a0),%d1 |check for overflow 222 andw #0x7fff,%d1 222 andw #0x7fff,%d1 223 cmpw #0x43ff,%d1 223 cmpw #0x43ff,%d1 224 bge cu_novfl |take 224 bge cu_novfl |take care of overflow case 225 bra cu_wrexn 225 bra cu_wrexn 226 | 226 | 227 | The move is fsmove or round precision is sin 227 | The move is fsmove or round precision is single. 228 | 228 | 229 cu_nmrs: 229 cu_nmrs: 230 movel #1,%d0 230 movel #1,%d0 231 movew LOCAL_EX(%a0),%d1 231 movew LOCAL_EX(%a0),%d1 232 andw #0x7fff,%d1 232 andw #0x7fff,%d1 233 cmpw #0x3f81,%d1 233 cmpw #0x3f81,%d1 234 bls cu_nunfl 234 bls cu_nunfl 235 bfextu FPCR_MODE(%a6){#2:#2},%d1 235 bfextu FPCR_MODE(%a6){#2:#2},%d1 236 orl #0x00010000,%d1 236 orl #0x00010000,%d1 237 clrl %d0 237 clrl %d0 238 bclrb #sign_bit,LOCAL_EX(%a0) 238 bclrb #sign_bit,LOCAL_EX(%a0) 239 sne LOCAL_SGN(%a0) 239 sne LOCAL_SGN(%a0) 240 bsrl round 240 bsrl round 241 bfclr LOCAL_SGN(%a0){#0:#8} 241 bfclr LOCAL_SGN(%a0){#0:#8} 242 beqs cu_nmrsc 242 beqs cu_nmrsc 243 bsetb #sign_bit,LOCAL_EX(%a0) 243 bsetb #sign_bit,LOCAL_EX(%a0) 244 cu_nmrsc: 244 cu_nmrsc: 245 movew LOCAL_EX(%a0),%d1 245 movew LOCAL_EX(%a0),%d1 246 andw #0x7FFF,%d1 246 andw #0x7FFF,%d1 247 cmpw #0x407f,%d1 247 cmpw #0x407f,%d1 248 blt cu_wrexn 248 blt cu_wrexn 249 | 249 | 250 | The operand is above precision boundaries. 250 | The operand is above precision boundaries. Use t_ovfl to 251 | generate the correct value. 251 | generate the correct value. 252 | 252 | 253 cu_novfl: 253 cu_novfl: 254 bsr t_ovfl 254 bsr t_ovfl 255 bra cu_wrexn 255 bra cu_wrexn 256 | 256 | 257 | The operand is below precision boundaries. 257 | The operand is below precision boundaries. Use denorm to 258 | generate the correct value. 258 | generate the correct value. 259 | 259 | 260 cu_nunfl: 260 cu_nunfl: 261 bclrb #sign_bit,LOCAL_EX(%a0) 261 bclrb #sign_bit,LOCAL_EX(%a0) 262 sne LOCAL_SGN(%a0) 262 sne LOCAL_SGN(%a0) 263 bsr denorm 263 bsr denorm 264 bfclr LOCAL_SGN(%a0){#0:#8} |chang 264 bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format 265 beqs cu_nucont 265 beqs cu_nucont 266 bsetb #sign_bit,LOCAL_EX(%a0) 266 bsetb #sign_bit,LOCAL_EX(%a0) 267 cu_nucont: 267 cu_nucont: 268 bfextu FPCR_MODE(%a6){#2:#2},%d1 268 bfextu FPCR_MODE(%a6){#2:#2},%d1 269 btstb #2,CMDREG1B+1(%a6) |check 269 btstb #2,CMDREG1B+1(%a6) |check for rd 270 bne inst_d 270 bne inst_d 271 btstb #6,CMDREG1B+1(%a6) |check 271 btstb #6,CMDREG1B+1(%a6) |check for rs 272 bne inst_s 272 bne inst_s 273 swap %d1 273 swap %d1 274 moveb FPCR_MODE(%a6),%d1 274 moveb FPCR_MODE(%a6),%d1 275 lsrb #6,%d1 275 lsrb #6,%d1 276 swap %d1 276 swap %d1 277 bra inst_sd 277 bra inst_sd 278 inst_d: 278 inst_d: 279 orl #0x00020000,%d1 279 orl #0x00020000,%d1 280 bra inst_sd 280 bra inst_sd 281 inst_s: 281 inst_s: 282 orl #0x00010000,%d1 282 orl #0x00010000,%d1 283 inst_sd: 283 inst_sd: 284 bclrb #sign_bit,LOCAL_EX(%a0) 284 bclrb #sign_bit,LOCAL_EX(%a0) 285 sne LOCAL_SGN(%a0) 285 sne LOCAL_SGN(%a0) 286 bsrl round 286 bsrl round 287 bfclr LOCAL_SGN(%a0){#0:#8} 287 bfclr LOCAL_SGN(%a0){#0:#8} 288 beqs cu_nuflp 288 beqs cu_nuflp 289 bsetb #sign_bit,LOCAL_EX(%a0) 289 bsetb #sign_bit,LOCAL_EX(%a0) 290 cu_nuflp: 290 cu_nuflp: 291 btstb #inex2_bit,FPSR_EXCEPT(%a6) 291 btstb #inex2_bit,FPSR_EXCEPT(%a6) 292 beqs cu_nuninx 292 beqs cu_nuninx 293 orl #aunfl_mask,USER_FPSR(%a6) |if 293 orl #aunfl_mask,USER_FPSR(%a6) |if the round was inex, set AUNFL 294 cu_nuninx: 294 cu_nuninx: 295 tstl LOCAL_HI(%a0) |test 295 tstl LOCAL_HI(%a0) |test for zero 296 bnes cu_nunzro 296 bnes cu_nunzro 297 tstl LOCAL_LO(%a0) 297 tstl LOCAL_LO(%a0) 298 bnes cu_nunzro 298 bnes cu_nunzro 299 | 299 | 300 | The mantissa is zero from the denorm loop. 300 | The mantissa is zero from the denorm loop. Check sign and rmode 301 | to see if rounding should have occurred whic 301 | to see if rounding should have occurred which would leave the lsb. 302 | 302 | 303 movel USER_FPCR(%a6),%d0 303 movel USER_FPCR(%a6),%d0 304 andil #0x30,%d0 |isola 304 andil #0x30,%d0 |isolate rmode 305 cmpil #0x20,%d0 305 cmpil #0x20,%d0 306 blts cu_nzro 306 blts cu_nzro 307 bnes cu_nrp 307 bnes cu_nrp 308 cu_nrm: 308 cu_nrm: 309 tstw LOCAL_EX(%a0) |if positive, 309 tstw LOCAL_EX(%a0) |if positive, set lsb 310 bges cu_nzro 310 bges cu_nzro 311 btstb #7,FPCR_MODE(%a6) |check for d 311 btstb #7,FPCR_MODE(%a6) |check for double 312 beqs cu_nincs 312 beqs cu_nincs 313 bras cu_nincd 313 bras cu_nincd 314 cu_nrp: 314 cu_nrp: 315 tstw LOCAL_EX(%a0) |if positive, 315 tstw LOCAL_EX(%a0) |if positive, set lsb 316 blts cu_nzro 316 blts cu_nzro 317 btstb #7,FPCR_MODE(%a6) |check for d 317 btstb #7,FPCR_MODE(%a6) |check for double 318 beqs cu_nincs 318 beqs cu_nincs 319 cu_nincd: 319 cu_nincd: 320 orl #0x800,LOCAL_LO(%a0) |inc for 320 orl #0x800,LOCAL_LO(%a0) |inc for double 321 bra cu_nunzro 321 bra cu_nunzro 322 cu_nincs: 322 cu_nincs: 323 orl #0x100,LOCAL_HI(%a0) |inc for 323 orl #0x100,LOCAL_HI(%a0) |inc for single 324 bra cu_nunzro 324 bra cu_nunzro 325 cu_nzro: 325 cu_nzro: 326 orl #z_mask,USER_FPSR(%a6) 326 orl #z_mask,USER_FPSR(%a6) 327 moveb STAG(%a6),%d0 327 moveb STAG(%a6),%d0 328 andib #0xe0,%d0 328 andib #0xe0,%d0 329 cmpib #0x40,%d0 |check 329 cmpib #0x40,%d0 |check if input was tagged zero 330 beqs cu_numv 330 beqs cu_numv 331 cu_nunzro: 331 cu_nunzro: 332 orl #unfl_mask,USER_FPSR(%a6) |set 332 orl #unfl_mask,USER_FPSR(%a6) |set unfl 333 cu_numv: 333 cu_numv: 334 movel (%a0),ETEMP(%a6) 334 movel (%a0),ETEMP(%a6) 335 movel 4(%a0),ETEMP_HI(%a6) 335 movel 4(%a0),ETEMP_HI(%a6) 336 movel 8(%a0),ETEMP_LO(%a6) 336 movel 8(%a0),ETEMP_LO(%a6) 337 | 337 | 338 | Write the result to memory, setting the fpsr 338 | Write the result to memory, setting the fpsr cc bits. NaN and Inf 339 | bypass cu_wrexn. 339 | bypass cu_wrexn. 340 | 340 | 341 cu_wrexn: 341 cu_wrexn: 342 tstw LOCAL_EX(%a0) |test 342 tstw LOCAL_EX(%a0) |test for zero 343 beqs cu_wrzero 343 beqs cu_wrzero 344 cmpw #0x8000,LOCAL_EX(%a0) |test 344 cmpw #0x8000,LOCAL_EX(%a0) |test for zero 345 bnes cu_wreon 345 bnes cu_wreon 346 cu_wrzero: 346 cu_wrzero: 347 orl #z_mask,USER_FPSR(%a6) |set Z 347 orl #z_mask,USER_FPSR(%a6) |set Z bit 348 cu_wreon: 348 cu_wreon: 349 tstw LOCAL_EX(%a0) 349 tstw LOCAL_EX(%a0) 350 bpl wr_etemp 350 bpl wr_etemp 351 orl #neg_mask,USER_FPSR(%a6) 351 orl #neg_mask,USER_FPSR(%a6) 352 bra wr_etemp 352 bra wr_etemp 353 353 354 | 354 | 355 | HANDLE SOURCE DENORM HERE 355 | HANDLE SOURCE DENORM HERE 356 | 356 | 357 | ;clear denorm 357 | ;clear denorm stag to norm 358 | ;write the new 358 | ;write the new tag & ete15 to the fstack 359 mon_dnrm: 359 mon_dnrm: 360 | 360 | 361 | At this point, check for the cases in which 361 | At this point, check for the cases in which normalizing the 362 | denorm produces incorrect results. 362 | denorm produces incorrect results. 363 | 363 | 364 tstb DY_MO_FLG(%a6) |all cases of 364 tstb DY_MO_FLG(%a6) |all cases of dyadic instructions would 365 bnes nrm_src |require norma 365 bnes nrm_src |require normalization of denorm 366 366 367 | At this point: 367 | At this point: 368 | monadic instructions: fabs = $18 f 368 | monadic instructions: fabs = $18 fneg = $1a ftst = $3a 369 | fmove = $00 f 369 | fmove = $00 fsmove = $40 fdmove = $44 370 | fsqrt = $05* f 370 | fsqrt = $05* fssqrt = $41 fdsqrt = $45 371 | (*fsqrt reenco 371 | (*fsqrt reencoded to $05) 372 | 372 | 373 movew CMDREG1B(%a6),%d0 |get c 373 movew CMDREG1B(%a6),%d0 |get command register 374 andil #0x7f,%d0 374 andil #0x7f,%d0 |strip to only command word 375 | 375 | 376 | At this point, fabs, fneg, fsmove, fdmove, f 376 | At this point, fabs, fneg, fsmove, fdmove, ftst, fsqrt, fssqrt, and 377 | fdsqrt are possible. 377 | fdsqrt are possible. 378 | For cases fabs, fneg, fsmove, and fdmove got 378 | For cases fabs, fneg, fsmove, and fdmove goto spos (do not normalize) 379 | For cases fsqrt, fssqrt, and fdsqrt goto nrm 379 | For cases fsqrt, fssqrt, and fdsqrt goto nrm_src (do normalize) 380 | 380 | 381 btstl #0,%d0 381 btstl #0,%d0 382 bnes nrm_src |weed out fsqr 382 bnes nrm_src |weed out fsqrt instructions 383 st CU_ONLY(%a6) |set cu-only i 383 st CU_ONLY(%a6) |set cu-only inst flag 384 bra cu_dnrm |fmove, fabs, 384 bra cu_dnrm |fmove, fabs, fneg, ftst 385 | ;cases go to c 385 | ;cases go to cu_dnrm 386 nrm_src: 386 nrm_src: 387 bclrb #sign_bit,LOCAL_EX(%a0) 387 bclrb #sign_bit,LOCAL_EX(%a0) 388 sne LOCAL_SGN(%a0) 388 sne LOCAL_SGN(%a0) 389 bsr nrm_set |normalize num 389 bsr nrm_set |normalize number (exponent will go 390 | ; negative) 390 | ; negative) 391 bclrb #sign_bit,LOCAL_EX(%a0) |get r 391 bclrb #sign_bit,LOCAL_EX(%a0) |get rid of false sign 392 392 393 bfclr LOCAL_SGN(%a0){#0:#8} |chang 393 bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format 394 beqs spos 394 beqs spos 395 bsetb #sign_bit,LOCAL_EX(%a0) 395 bsetb #sign_bit,LOCAL_EX(%a0) 396 spos: 396 spos: 397 bfclr STAG(%a6){#0:#4} |set t 397 bfclr STAG(%a6){#0:#4} |set tag to normalized, FPTE15 = 0 398 bsetb #4,STAG(%a6) |set ETE15 398 bsetb #4,STAG(%a6) |set ETE15 399 orb #0xf0,DNRM_FLG(%a6) 399 orb #0xf0,DNRM_FLG(%a6) 400 normal: 400 normal: 401 tstb DNRM_FLG(%a6) |check if any 401 tstb DNRM_FLG(%a6) |check if any of the ops were denorms 402 bne ck_wrap |if so, check 402 bne ck_wrap |if so, check if it is a potential 403 | ;wrap-around c 403 | ;wrap-around case 404 fix_stk: 404 fix_stk: 405 moveb #0xfe,CU_SAVEPC(%a6) 405 moveb #0xfe,CU_SAVEPC(%a6) 406 bclrb #E1,E_BYTE(%a6) 406 bclrb #E1,E_BYTE(%a6) 407 407 408 clrw NMNEXC(%a6) 408 clrw NMNEXC(%a6) 409 409 410 st RES_FLG(%a6) |indicate that 410 st RES_FLG(%a6) |indicate that a restore is needed 411 rts 411 rts 412 412 413 | 413 | 414 | cu_dnrm handles all cu-only instructions (fm 414 | cu_dnrm handles all cu-only instructions (fmove, fabs, fneg, and 415 | ftst) completely in software without an fres 415 | ftst) completely in software without an frestore to the 040. 416 | 416 | 417 cu_dnrm: 417 cu_dnrm: 418 st CU_ONLY(%a6) 418 st CU_ONLY(%a6) 419 movew CMDREG1B(%a6),%d0 419 movew CMDREG1B(%a6),%d0 420 andib #0x3b,%d0 |isola 420 andib #0x3b,%d0 |isolate bits to select inst 421 tstb %d0 421 tstb %d0 422 beql cu_dmove |if zero, it i 422 beql cu_dmove |if zero, it is an fmove 423 cmpib #0x18,%d0 423 cmpib #0x18,%d0 424 beql cu_dabs |if $18, it is 424 beql cu_dabs |if $18, it is fabs 425 cmpib #0x1a,%d0 425 cmpib #0x1a,%d0 426 beql cu_dneg |if $1a, it is 426 beql cu_dneg |if $1a, it is fneg 427 | 427 | 428 | Inst is ftst. Check the source operand and 428 | Inst is ftst. Check the source operand and set the cc's accordingly. 429 | No write is done, so simply rts. 429 | No write is done, so simply rts. 430 | 430 | 431 cu_dtst: 431 cu_dtst: 432 movew LOCAL_EX(%a0),%d0 432 movew LOCAL_EX(%a0),%d0 433 bclrl #15,%d0 433 bclrl #15,%d0 434 sne LOCAL_SGN(%a0) 434 sne LOCAL_SGN(%a0) 435 beqs cu_dtpo 435 beqs cu_dtpo 436 orl #neg_mask,USER_FPSR(%a6) |set 436 orl #neg_mask,USER_FPSR(%a6) |set N 437 cu_dtpo: 437 cu_dtpo: 438 cmpiw #0x7fff,%d0 |test for inf/ 438 cmpiw #0x7fff,%d0 |test for inf/nan 439 bnes cu_dtcz 439 bnes cu_dtcz 440 tstl LOCAL_HI(%a0) 440 tstl LOCAL_HI(%a0) 441 bnes cu_dtn 441 bnes cu_dtn 442 tstl LOCAL_LO(%a0) 442 tstl LOCAL_LO(%a0) 443 bnes cu_dtn 443 bnes cu_dtn 444 orl #inf_mask,USER_FPSR(%a6) 444 orl #inf_mask,USER_FPSR(%a6) 445 rts 445 rts 446 cu_dtn: 446 cu_dtn: 447 orl #nan_mask,USER_FPSR(%a6) 447 orl #nan_mask,USER_FPSR(%a6) 448 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) 448 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for 449 | 449 | ;snan handler 450 rts 450 rts 451 cu_dtcz: 451 cu_dtcz: 452 tstl LOCAL_HI(%a0) 452 tstl LOCAL_HI(%a0) 453 bnel cu_dtsx 453 bnel cu_dtsx 454 tstl LOCAL_LO(%a0) 454 tstl LOCAL_LO(%a0) 455 bnel cu_dtsx 455 bnel cu_dtsx 456 orl #z_mask,USER_FPSR(%a6) 456 orl #z_mask,USER_FPSR(%a6) 457 cu_dtsx: 457 cu_dtsx: 458 rts 458 rts 459 | 459 | 460 | Inst is fabs. Execute the absolute value fu 460 | Inst is fabs. Execute the absolute value function on the input. 461 | Branch to the fmove code. 461 | Branch to the fmove code. 462 | 462 | 463 cu_dabs: 463 cu_dabs: 464 bclrb #7,LOCAL_EX(%a0) 464 bclrb #7,LOCAL_EX(%a0) |do abs 465 bras cu_dmove |fmove 465 bras cu_dmove |fmove code will finish 466 | 466 | 467 | Inst is fneg. Execute the negate value func 467 | Inst is fneg. Execute the negate value function on the input. 468 | Fall though to the fmove code. 468 | Fall though to the fmove code. 469 | 469 | 470 cu_dneg: 470 cu_dneg: 471 bchgb #7,LOCAL_EX(%a0) 471 bchgb #7,LOCAL_EX(%a0) |do neg 472 | 472 | 473 | Inst is fmove. This code also handles all r 473 | Inst is fmove. This code also handles all result writes. 474 | If bit 2 is set, round is forced to double. 474 | If bit 2 is set, round is forced to double. If it is clear, 475 | and bit 6 is set, round is forced to single. 475 | and bit 6 is set, round is forced to single. If both are clear, 476 | the round precision is found in the fpcr. I 476 | the round precision is found in the fpcr. If the rounding precision 477 | is double or single, the result is zero, and 477 | is double or single, the result is zero, and the mode is checked 478 | to determine if the lsb of the result should 478 | to determine if the lsb of the result should be set. 479 | 479 | 480 cu_dmove: 480 cu_dmove: 481 btstb #2,CMDREG1B+1(%a6) |check 481 btstb #2,CMDREG1B+1(%a6) |check for rd 482 bne cu_dmrd 482 bne cu_dmrd 483 btstb #6,CMDREG1B+1(%a6) |check 483 btstb #6,CMDREG1B+1(%a6) |check for rs 484 bne cu_dmrs 484 bne cu_dmrs 485 | 485 | 486 | The move or operation is not with forced pre 486 | The move or operation is not with forced precision. Use the 487 | FPCR_MODE byte to get rounding. 487 | FPCR_MODE byte to get rounding. 488 | 488 | 489 cu_dmnr: 489 cu_dmnr: 490 bfextu FPCR_MODE(%a6){#0:#2},%d0 490 bfextu FPCR_MODE(%a6){#0:#2},%d0 491 tstb %d0 |check 491 tstb %d0 |check for extended 492 beq cu_wrexd |if so 492 beq cu_wrexd |if so, just write result 493 cmpib #1,%d0 |check 493 cmpib #1,%d0 |check for single 494 beq cu_dmrs |fall 494 beq cu_dmrs |fall through to double 495 | 495 | 496 | The move is fdmove or round precision is dou 496 | The move is fdmove or round precision is double. Result is zero. 497 | Check rmode for rp or rm and set lsb accordi 497 | Check rmode for rp or rm and set lsb accordingly. 498 | 498 | 499 cu_dmrd: 499 cu_dmrd: 500 bfextu FPCR_MODE(%a6){#2:#2},%d1 500 bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rmode 501 tstw LOCAL_EX(%a0) |check 501 tstw LOCAL_EX(%a0) |check sign 502 blts cu_dmdn 502 blts cu_dmdn 503 cmpib #3,%d1 |check 503 cmpib #3,%d1 |check for rp 504 bne cu_dpd |load 504 bne cu_dpd |load double pos zero 505 bra cu_dpdr |load 505 bra cu_dpdr |load double pos zero w/lsb 506 cu_dmdn: 506 cu_dmdn: 507 cmpib #2,%d1 |check 507 cmpib #2,%d1 |check for rm 508 bne cu_dnd |load 508 bne cu_dnd |load double neg zero 509 bra cu_dndr |load 509 bra cu_dndr |load double neg zero w/lsb 510 | 510 | 511 | The move is fsmove or round precision is sin 511 | The move is fsmove or round precision is single. Result is zero. 512 | Check for rp or rm and set lsb accordingly. 512 | Check for rp or rm and set lsb accordingly. 513 | 513 | 514 cu_dmrs: 514 cu_dmrs: 515 bfextu FPCR_MODE(%a6){#2:#2},%d1 515 bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rmode 516 tstw LOCAL_EX(%a0) |check 516 tstw LOCAL_EX(%a0) |check sign 517 blts cu_dmsn 517 blts cu_dmsn 518 cmpib #3,%d1 |check 518 cmpib #3,%d1 |check for rp 519 bne cu_spd |load 519 bne cu_spd |load single pos zero 520 bra cu_spdr |load 520 bra cu_spdr |load single pos zero w/lsb 521 cu_dmsn: 521 cu_dmsn: 522 cmpib #2,%d1 |check 522 cmpib #2,%d1 |check for rm 523 bne cu_snd |load 523 bne cu_snd |load single neg zero 524 bra cu_sndr |load 524 bra cu_sndr |load single neg zero w/lsb 525 | 525 | 526 | The precision is extended, so the result in 526 | The precision is extended, so the result in etemp is correct. 527 | Simply set unfl (not inex2 or aunfl) and wri 527 | Simply set unfl (not inex2 or aunfl) and write the result to 528 | the correct fp register. 528 | the correct fp register. 529 cu_wrexd: 529 cu_wrexd: 530 orl #unfl_mask,USER_FPSR(%a6) 530 orl #unfl_mask,USER_FPSR(%a6) 531 tstw LOCAL_EX(%a0) 531 tstw LOCAL_EX(%a0) 532 beq wr_etemp 532 beq wr_etemp 533 orl #neg_mask,USER_FPSR(%a6) 533 orl #neg_mask,USER_FPSR(%a6) 534 bra wr_etemp 534 bra wr_etemp 535 | 535 | 536 | These routines write +/- zero in double form 536 | These routines write +/- zero in double format. The routines 537 | cu_dpdr and cu_dndr set the double lsb. 537 | cu_dpdr and cu_dndr set the double lsb. 538 | 538 | 539 cu_dpd: 539 cu_dpd: 540 movel #0x3c010000,LOCAL_EX(%a0) 540 movel #0x3c010000,LOCAL_EX(%a0) |force pos double zero 541 clrl LOCAL_HI(%a0) 541 clrl LOCAL_HI(%a0) 542 clrl LOCAL_LO(%a0) 542 clrl LOCAL_LO(%a0) 543 orl #z_mask,USER_FPSR(%a6) 543 orl #z_mask,USER_FPSR(%a6) 544 orl #unfinx_mask,USER_FPSR(%a6) 544 orl #unfinx_mask,USER_FPSR(%a6) 545 bra wr_etemp 545 bra wr_etemp 546 cu_dpdr: 546 cu_dpdr: 547 movel #0x3c010000,LOCAL_EX(%a0) 547 movel #0x3c010000,LOCAL_EX(%a0) |force pos double zero 548 clrl LOCAL_HI(%a0) 548 clrl LOCAL_HI(%a0) 549 movel #0x800,LOCAL_LO(%a0) |with 549 movel #0x800,LOCAL_LO(%a0) |with lsb set 550 orl #unfinx_mask,USER_FPSR(%a6) 550 orl #unfinx_mask,USER_FPSR(%a6) 551 bra wr_etemp 551 bra wr_etemp 552 cu_dnd: 552 cu_dnd: 553 movel #0xbc010000,LOCAL_EX(%a0) 553 movel #0xbc010000,LOCAL_EX(%a0) |force pos double zero 554 clrl LOCAL_HI(%a0) 554 clrl LOCAL_HI(%a0) 555 clrl LOCAL_LO(%a0) 555 clrl LOCAL_LO(%a0) 556 orl #z_mask,USER_FPSR(%a6) 556 orl #z_mask,USER_FPSR(%a6) 557 orl #neg_mask,USER_FPSR(%a6) 557 orl #neg_mask,USER_FPSR(%a6) 558 orl #unfinx_mask,USER_FPSR(%a6) 558 orl #unfinx_mask,USER_FPSR(%a6) 559 bra wr_etemp 559 bra wr_etemp 560 cu_dndr: 560 cu_dndr: 561 movel #0xbc010000,LOCAL_EX(%a0) 561 movel #0xbc010000,LOCAL_EX(%a0) |force pos double zero 562 clrl LOCAL_HI(%a0) 562 clrl LOCAL_HI(%a0) 563 movel #0x800,LOCAL_LO(%a0) |with 563 movel #0x800,LOCAL_LO(%a0) |with lsb set 564 orl #neg_mask,USER_FPSR(%a6) 564 orl #neg_mask,USER_FPSR(%a6) 565 orl #unfinx_mask,USER_FPSR(%a6) 565 orl #unfinx_mask,USER_FPSR(%a6) 566 bra wr_etemp 566 bra wr_etemp 567 | 567 | 568 | These routines write +/- zero in single form 568 | These routines write +/- zero in single format. The routines 569 | cu_dpdr and cu_dndr set the single lsb. 569 | cu_dpdr and cu_dndr set the single lsb. 570 | 570 | 571 cu_spd: 571 cu_spd: 572 movel #0x3f810000,LOCAL_EX(%a0) 572 movel #0x3f810000,LOCAL_EX(%a0) |force pos single zero 573 clrl LOCAL_HI(%a0) 573 clrl LOCAL_HI(%a0) 574 clrl LOCAL_LO(%a0) 574 clrl LOCAL_LO(%a0) 575 orl #z_mask,USER_FPSR(%a6) 575 orl #z_mask,USER_FPSR(%a6) 576 orl #unfinx_mask,USER_FPSR(%a6) 576 orl #unfinx_mask,USER_FPSR(%a6) 577 bra wr_etemp 577 bra wr_etemp 578 cu_spdr: 578 cu_spdr: 579 movel #0x3f810000,LOCAL_EX(%a0) 579 movel #0x3f810000,LOCAL_EX(%a0) |force pos single zero 580 movel #0x100,LOCAL_HI(%a0) |with 580 movel #0x100,LOCAL_HI(%a0) |with lsb set 581 clrl LOCAL_LO(%a0) 581 clrl LOCAL_LO(%a0) 582 orl #unfinx_mask,USER_FPSR(%a6) 582 orl #unfinx_mask,USER_FPSR(%a6) 583 bra wr_etemp 583 bra wr_etemp 584 cu_snd: 584 cu_snd: 585 movel #0xbf810000,LOCAL_EX(%a0) 585 movel #0xbf810000,LOCAL_EX(%a0) |force pos single zero 586 clrl LOCAL_HI(%a0) 586 clrl LOCAL_HI(%a0) 587 clrl LOCAL_LO(%a0) 587 clrl LOCAL_LO(%a0) 588 orl #z_mask,USER_FPSR(%a6) 588 orl #z_mask,USER_FPSR(%a6) 589 orl #neg_mask,USER_FPSR(%a6) 589 orl #neg_mask,USER_FPSR(%a6) 590 orl #unfinx_mask,USER_FPSR(%a6) 590 orl #unfinx_mask,USER_FPSR(%a6) 591 bra wr_etemp 591 bra wr_etemp 592 cu_sndr: 592 cu_sndr: 593 movel #0xbf810000,LOCAL_EX(%a0) 593 movel #0xbf810000,LOCAL_EX(%a0) |force pos single zero 594 movel #0x100,LOCAL_HI(%a0) |with 594 movel #0x100,LOCAL_HI(%a0) |with lsb set 595 clrl LOCAL_LO(%a0) 595 clrl LOCAL_LO(%a0) 596 orl #neg_mask,USER_FPSR(%a6) 596 orl #neg_mask,USER_FPSR(%a6) 597 orl #unfinx_mask,USER_FPSR(%a6) 597 orl #unfinx_mask,USER_FPSR(%a6) 598 bra wr_etemp 598 bra wr_etemp 599 599 600 | 600 | 601 | This code checks for 16-bit overflow conditi 601 | This code checks for 16-bit overflow conditions on dyadic 602 | operations which are not restorable into the 602 | operations which are not restorable into the floating-point 603 | unit and must be completed in software. Bas 603 | unit and must be completed in software. Basically, this 604 | condition exists with a very large norm and 604 | condition exists with a very large norm and a denorm. One 605 | of the operands must be denormalized to ente 605 | of the operands must be denormalized to enter this code. 606 | 606 | 607 | Flags used: 607 | Flags used: 608 | DY_MO_FLG contains 0 for monadic op, $ 608 | DY_MO_FLG contains 0 for monadic op, $ff for dyadic 609 | DNRM_FLG contains $00 for neither op d 609 | DNRM_FLG contains $00 for neither op denormalized 610 | $0f for the destinat 610 | $0f for the destination op denormalized 611 | $f0 for the source o 611 | $f0 for the source op denormalized 612 | $ff for both ops den 612 | $ff for both ops denormalized 613 | 613 | 614 | The wrap-around condition occurs for add, su 614 | The wrap-around condition occurs for add, sub, div, and cmp 615 | when 615 | when 616 | 616 | 617 | abs(dest_exp - src_exp) >= $8000 617 | abs(dest_exp - src_exp) >= $8000 618 | 618 | 619 | and for mul when 619 | and for mul when 620 | 620 | 621 | (dest_exp + src_exp) < $0 621 | (dest_exp + src_exp) < $0 622 | 622 | 623 | we must process the operation here if this c 623 | we must process the operation here if this case is true. 624 | 624 | 625 | The rts following the frcfpn routine is the 625 | The rts following the frcfpn routine is the exit from res_func 626 | for this condition. The restore flag (RES_F 626 | for this condition. The restore flag (RES_FLG) is left clear. 627 | No frestore is done unless an exception is t 627 | No frestore is done unless an exception is to be reported. 628 | 628 | 629 | For fadd: 629 | For fadd: 630 | if(sign_of(dest) != sign_of(src)) 630 | if(sign_of(dest) != sign_of(src)) 631 | replace exponent of src with $ 631 | replace exponent of src with $3fff (keep sign) 632 | use fpu to perform dest+new_sr 632 | use fpu to perform dest+new_src (user's rmode and X) 633 | clr sticky 633 | clr sticky 634 | else 634 | else 635 | set sticky 635 | set sticky 636 | call round with user's precision and m 636 | call round with user's precision and mode 637 | move result to fpn and wbtemp 637 | move result to fpn and wbtemp 638 | 638 | 639 | For fsub: 639 | For fsub: 640 | if(sign_of(dest) == sign_of(src)) 640 | if(sign_of(dest) == sign_of(src)) 641 | replace exponent of src with $ 641 | replace exponent of src with $3fff (keep sign) 642 | use fpu to perform dest+new_sr 642 | use fpu to perform dest+new_src (user's rmode and X) 643 | clr sticky 643 | clr sticky 644 | else 644 | else 645 | set sticky 645 | set sticky 646 | call round with user's precision and m 646 | call round with user's precision and mode 647 | move result to fpn and wbtemp 647 | move result to fpn and wbtemp 648 | 648 | 649 | For fdiv/fsgldiv: 649 | For fdiv/fsgldiv: 650 | if(both operands are denorm) 650 | if(both operands are denorm) 651 | restore_to_fpu; 651 | restore_to_fpu; 652 | if(dest is norm) 652 | if(dest is norm) 653 | force_ovf; 653 | force_ovf; 654 | else(dest is denorm) 654 | else(dest is denorm) 655 | force_unf: 655 | force_unf: 656 | 656 | 657 | For fcmp: 657 | For fcmp: 658 | if(dest is norm) 658 | if(dest is norm) 659 | N = sign_of(dest); 659 | N = sign_of(dest); 660 | else(dest is denorm) 660 | else(dest is denorm) 661 | N = sign_of(src); 661 | N = sign_of(src); 662 | 662 | 663 | For fmul: 663 | For fmul: 664 | if(both operands are denorm) 664 | if(both operands are denorm) 665 | force_unf; 665 | force_unf; 666 | if((dest_exp + src_exp) < 0) 666 | if((dest_exp + src_exp) < 0) 667 | force_unf: 667 | force_unf: 668 | else 668 | else 669 | restore_to_fpu; 669 | restore_to_fpu; 670 | 670 | 671 | local equates: 671 | local equates: 672 .set addcode,0x22 672 .set addcode,0x22 673 .set subcode,0x28 673 .set subcode,0x28 674 .set mulcode,0x23 674 .set mulcode,0x23 675 .set divcode,0x20 675 .set divcode,0x20 676 .set cmpcode,0x38 676 .set cmpcode,0x38 677 ck_wrap: 677 ck_wrap: 678 | tstb DY_MO_FLG(%a6) ;check for fsq 678 | tstb DY_MO_FLG(%a6) ;check for fsqrt 679 beq fix_stk |if zero, it i 679 beq fix_stk |if zero, it is fsqrt 680 movew CMDREG1B(%a6),%d0 680 movew CMDREG1B(%a6),%d0 681 andiw #0x3b,%d0 |strip 681 andiw #0x3b,%d0 |strip to command bits 682 cmpiw #addcode,%d0 682 cmpiw #addcode,%d0 683 beq wrap_add 683 beq wrap_add 684 cmpiw #subcode,%d0 684 cmpiw #subcode,%d0 685 beq wrap_sub 685 beq wrap_sub 686 cmpiw #mulcode,%d0 686 cmpiw #mulcode,%d0 687 beq wrap_mul 687 beq wrap_mul 688 cmpiw #cmpcode,%d0 688 cmpiw #cmpcode,%d0 689 beq wrap_cmp 689 beq wrap_cmp 690 | 690 | 691 | Inst is fdiv. 691 | Inst is fdiv. 692 | 692 | 693 wrap_div: 693 wrap_div: 694 cmpb #0xff,DNRM_FLG(%a6) |if both o 694 cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm, 695 beq fix_stk |restore to f 695 beq fix_stk |restore to fpu 696 | 696 | 697 | One of the ops is denormalized. Test for wr 697 | One of the ops is denormalized. Test for wrap condition 698 | and force the result. 698 | and force the result. 699 | 699 | 700 cmpb #0x0f,DNRM_FLG(%a6) |check for 700 cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm 701 bnes div_srcd 701 bnes div_srcd 702 div_destd: 702 div_destd: 703 bsrl ckinf_ns 703 bsrl ckinf_ns 704 bne fix_stk 704 bne fix_stk 705 bfextu ETEMP_EX(%a6){#1:#15},%d0 705 bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos) 706 bfexts FPTEMP_EX(%a6){#1:#15},%d1 706 bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg) 707 subl %d1,%d0 |subtr 707 subl %d1,%d0 |subtract dest from src 708 cmpl #0x7fff,%d0 708 cmpl #0x7fff,%d0 709 blt fix_stk |if le 709 blt fix_stk |if less, not wrap case 710 clrb WBTEMP_SGN(%a6) 710 clrb WBTEMP_SGN(%a6) 711 movew ETEMP_EX(%a6),%d0 711 movew ETEMP_EX(%a6),%d0 |find the sign of the result 712 movew FPTEMP_EX(%a6),%d1 712 movew FPTEMP_EX(%a6),%d1 713 eorw %d1,%d0 713 eorw %d1,%d0 714 andiw #0x8000,%d0 714 andiw #0x8000,%d0 715 beq force_unf 715 beq force_unf 716 st WBTEMP_SGN(%a6) 716 st WBTEMP_SGN(%a6) 717 bra force_unf 717 bra force_unf 718 718 719 ckinf_ns: 719 ckinf_ns: 720 moveb STAG(%a6),%d0 |check 720 moveb STAG(%a6),%d0 |check source tag for inf or nan 721 bra ck_in_com 721 bra ck_in_com 722 ckinf_nd: 722 ckinf_nd: 723 moveb DTAG(%a6),%d0 |check 723 moveb DTAG(%a6),%d0 |check destination tag for inf or nan 724 ck_in_com: 724 ck_in_com: 725 andib #0x60,%d0 725 andib #0x60,%d0 |isolate tag bits 726 cmpb #0x40,%d0 726 cmpb #0x40,%d0 |is it inf? 727 beq nan_or_inf |not w 727 beq nan_or_inf |not wrap case 728 cmpb #0x60,%d0 728 cmpb #0x60,%d0 |is it nan? 729 beq nan_or_inf |yes, 729 beq nan_or_inf |yes, not wrap case? 730 cmpb #0x20,%d0 730 cmpb #0x20,%d0 |is it a zero? 731 beq nan_or_inf |yes 731 beq nan_or_inf |yes 732 clrl %d0 732 clrl %d0 733 rts |then 733 rts |then ; it is either a zero of norm, 734 | ;check 734 | ;check wrap case 735 nan_or_inf: 735 nan_or_inf: 736 moveql #-1,%d0 736 moveql #-1,%d0 737 rts 737 rts 738 738 739 739 740 740 741 div_srcd: 741 div_srcd: 742 bsrl ckinf_nd 742 bsrl ckinf_nd 743 bne fix_stk 743 bne fix_stk 744 bfextu FPTEMP_EX(%a6){#1:#15},%d0 744 bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos) 745 bfexts ETEMP_EX(%a6){#1:#15},%d1 745 bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg) 746 subl %d1,%d0 |subtr 746 subl %d1,%d0 |subtract src from dest 747 cmpl #0x8000,%d0 747 cmpl #0x8000,%d0 748 blt fix_stk |if le 748 blt fix_stk |if less, not wrap case 749 clrb WBTEMP_SGN(%a6) 749 clrb WBTEMP_SGN(%a6) 750 movew ETEMP_EX(%a6),%d0 750 movew ETEMP_EX(%a6),%d0 |find the sign of the result 751 movew FPTEMP_EX(%a6),%d1 751 movew FPTEMP_EX(%a6),%d1 752 eorw %d1,%d0 752 eorw %d1,%d0 753 andiw #0x8000,%d0 753 andiw #0x8000,%d0 754 beqs force_ovf 754 beqs force_ovf 755 st WBTEMP_SGN(%a6) 755 st WBTEMP_SGN(%a6) 756 | 756 | 757 | This code handles the case of the instructio 757 | This code handles the case of the instruction resulting in 758 | an overflow condition. 758 | an overflow condition. 759 | 759 | 760 force_ovf: 760 force_ovf: 761 bclrb #E1,E_BYTE(%a6) 761 bclrb #E1,E_BYTE(%a6) 762 orl #ovfl_inx_mask,USER_FPSR(%a6) 762 orl #ovfl_inx_mask,USER_FPSR(%a6) 763 clrw NMNEXC(%a6) 763 clrw NMNEXC(%a6) 764 leal WBTEMP(%a6),%a0 |point 764 leal WBTEMP(%a6),%a0 |point a0 to memory location 765 movew CMDREG1B(%a6),%d0 765 movew CMDREG1B(%a6),%d0 766 btstl #6,%d0 |test 766 btstl #6,%d0 |test for forced precision 767 beqs frcovf_fpcr 767 beqs frcovf_fpcr 768 btstl #2,%d0 |check 768 btstl #2,%d0 |check for double 769 bnes frcovf_dbl 769 bnes frcovf_dbl 770 movel #0x1,%d0 770 movel #0x1,%d0 |inst is forced single 771 bras frcovf_rnd 771 bras frcovf_rnd 772 frcovf_dbl: 772 frcovf_dbl: 773 movel #0x2,%d0 773 movel #0x2,%d0 |inst is forced double 774 bras frcovf_rnd 774 bras frcovf_rnd 775 frcovf_fpcr: 775 frcovf_fpcr: 776 bfextu FPCR_MODE(%a6){#0:#2},%d0 776 bfextu FPCR_MODE(%a6){#0:#2},%d0 |inst not forced - use fpcr prec 777 frcovf_rnd: 777 frcovf_rnd: 778 778 779 | The 881/882 does not set inex2 for the follo 779 | The 881/882 does not set inex2 for the following case, so the 780 | line is commented out to be compatible with 780 | line is commented out to be compatible with 881/882 781 | tst.b %d0 781 | tst.b %d0 782 | beq.b frcovf_x 782 | beq.b frcovf_x 783 | or.l #inex2_mask,USER_FPSR(%a6) ;if 783 | or.l #inex2_mask,USER_FPSR(%a6) ;if prec is s or d, set inex2 784 784 785 |frcovf_x: 785 |frcovf_x: 786 bsrl ovf_res |get c 786 bsrl ovf_res |get correct result based on 787 | ;round 787 | ;round precision/mode. This 788 | ;sets 788 | ;sets FPSR_CC correctly 789 | ;retur 789 | ;returns in external format 790 bfclr WBTEMP_SGN(%a6){#0:#8} 790 bfclr WBTEMP_SGN(%a6){#0:#8} 791 beq frcfpn 791 beq frcfpn 792 bsetb #sign_bit,WBTEMP_EX(%a6) 792 bsetb #sign_bit,WBTEMP_EX(%a6) 793 bra frcfpn 793 bra frcfpn 794 | 794 | 795 | Inst is fadd. 795 | Inst is fadd. 796 | 796 | 797 wrap_add: 797 wrap_add: 798 cmpb #0xff,DNRM_FLG(%a6) |if both o 798 cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm, 799 beq fix_stk |restore to f 799 beq fix_stk |restore to fpu 800 | 800 | 801 | One of the ops is denormalized. Test for wr 801 | One of the ops is denormalized. Test for wrap condition 802 | and complete the instruction. 802 | and complete the instruction. 803 | 803 | 804 cmpb #0x0f,DNRM_FLG(%a6) |check for 804 cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm 805 bnes add_srcd 805 bnes add_srcd 806 add_destd: 806 add_destd: 807 bsrl ckinf_ns 807 bsrl ckinf_ns 808 bne fix_stk 808 bne fix_stk 809 bfextu ETEMP_EX(%a6){#1:#15},%d0 809 bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos) 810 bfexts FPTEMP_EX(%a6){#1:#15},%d1 810 bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg) 811 subl %d1,%d0 |subtr 811 subl %d1,%d0 |subtract dest from src 812 cmpl #0x8000,%d0 812 cmpl #0x8000,%d0 813 blt fix_stk |if le 813 blt fix_stk |if less, not wrap case 814 bra add_wrap 814 bra add_wrap 815 add_srcd: 815 add_srcd: 816 bsrl ckinf_nd 816 bsrl ckinf_nd 817 bne fix_stk 817 bne fix_stk 818 bfextu FPTEMP_EX(%a6){#1:#15},%d0 818 bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos) 819 bfexts ETEMP_EX(%a6){#1:#15},%d1 819 bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg) 820 subl %d1,%d0 |subtr 820 subl %d1,%d0 |subtract src from dest 821 cmpl #0x8000,%d0 821 cmpl #0x8000,%d0 822 blt fix_stk |if le 822 blt fix_stk |if less, not wrap case 823 | 823 | 824 | Check the signs of the operands. If they ar 824 | Check the signs of the operands. If they are unlike, the fpu 825 | can be used to add the norm and 1.0 with the 825 | can be used to add the norm and 1.0 with the sign of the 826 | denorm and it will correctly generate the re 826 | denorm and it will correctly generate the result in extended 827 | precision. We can then call round with no s 827 | precision. We can then call round with no sticky and the result 828 | will be correct for the user's rounding mode 828 | will be correct for the user's rounding mode and precision. If 829 | the signs are the same, we call round with t 829 | the signs are the same, we call round with the sticky bit set 830 | and the result will be correct for the user' 830 | and the result will be correct for the user's rounding mode and 831 | precision. 831 | precision. 832 | 832 | 833 add_wrap: 833 add_wrap: 834 movew ETEMP_EX(%a6),%d0 834 movew ETEMP_EX(%a6),%d0 835 movew FPTEMP_EX(%a6),%d1 835 movew FPTEMP_EX(%a6),%d1 836 eorw %d1,%d0 836 eorw %d1,%d0 837 andiw #0x8000,%d0 837 andiw #0x8000,%d0 838 beq add_same 838 beq add_same 839 | 839 | 840 | The signs are unlike. 840 | The signs are unlike. 841 | 841 | 842 cmpb #0x0f,DNRM_FLG(%a6) |is dest t 842 cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm? 843 bnes add_u_srcd 843 bnes add_u_srcd 844 movew FPTEMP_EX(%a6),%d0 844 movew FPTEMP_EX(%a6),%d0 845 andiw #0x8000,%d0 845 andiw #0x8000,%d0 846 orw #0x3fff,%d0 |force the exp 846 orw #0x3fff,%d0 |force the exponent to +/- 1 847 movew %d0,FPTEMP_EX(%a6) |in the den 847 movew %d0,FPTEMP_EX(%a6) |in the denorm 848 movel USER_FPCR(%a6),%d0 848 movel USER_FPCR(%a6),%d0 849 andil #0x30,%d0 849 andil #0x30,%d0 850 fmovel %d0,%fpcr |set u 850 fmovel %d0,%fpcr |set up users rmode and X 851 fmovex ETEMP(%a6),%fp0 851 fmovex ETEMP(%a6),%fp0 852 faddx FPTEMP(%a6),%fp0 852 faddx FPTEMP(%a6),%fp0 853 leal WBTEMP(%a6),%a0 |point a0 to w 853 leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame 854 fmovel %fpsr,%d1 854 fmovel %fpsr,%d1 855 orl %d1,USER_FPSR(%a6) |capture cc 855 orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd 856 fmovex %fp0,WBTEMP(%a6) |write 856 fmovex %fp0,WBTEMP(%a6) |write result to memory 857 lsrl #4,%d0 |put rmode in 857 lsrl #4,%d0 |put rmode in lower 2 bits 858 movel USER_FPCR(%a6),%d1 858 movel USER_FPCR(%a6),%d1 859 andil #0xc0,%d1 859 andil #0xc0,%d1 860 lsrl #6,%d1 |put precision 860 lsrl #6,%d1 |put precision in upper word 861 swap %d1 861 swap %d1 862 orl %d0,%d1 |set up for ro 862 orl %d0,%d1 |set up for round call 863 clrl %d0 |force sticky 863 clrl %d0 |force sticky to zero 864 bclrb #sign_bit,WBTEMP_EX(%a6) 864 bclrb #sign_bit,WBTEMP_EX(%a6) 865 sne WBTEMP_SGN(%a6) 865 sne WBTEMP_SGN(%a6) 866 bsrl round |round result 866 bsrl round |round result to users rmode & prec 867 bfclr WBTEMP_SGN(%a6){#0:#8} |conve 867 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format 868 beq frcfpnr 868 beq frcfpnr 869 bsetb #sign_bit,WBTEMP_EX(%a6) 869 bsetb #sign_bit,WBTEMP_EX(%a6) 870 bra frcfpnr 870 bra frcfpnr 871 add_u_srcd: 871 add_u_srcd: 872 movew ETEMP_EX(%a6),%d0 872 movew ETEMP_EX(%a6),%d0 873 andiw #0x8000,%d0 873 andiw #0x8000,%d0 874 orw #0x3fff,%d0 |force the exp 874 orw #0x3fff,%d0 |force the exponent to +/- 1 875 movew %d0,ETEMP_EX(%a6) |in the deno 875 movew %d0,ETEMP_EX(%a6) |in the denorm 876 movel USER_FPCR(%a6),%d0 876 movel USER_FPCR(%a6),%d0 877 andil #0x30,%d0 877 andil #0x30,%d0 878 fmovel %d0,%fpcr |set u 878 fmovel %d0,%fpcr |set up users rmode and X 879 fmovex ETEMP(%a6),%fp0 879 fmovex ETEMP(%a6),%fp0 880 faddx FPTEMP(%a6),%fp0 880 faddx FPTEMP(%a6),%fp0 881 fmovel %fpsr,%d1 881 fmovel %fpsr,%d1 882 orl %d1,USER_FPSR(%a6) |capture cc 882 orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd 883 leal WBTEMP(%a6),%a0 |point a0 to w 883 leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame 884 fmovex %fp0,WBTEMP(%a6) |write 884 fmovex %fp0,WBTEMP(%a6) |write result to memory 885 lsrl #4,%d0 |put rmode in 885 lsrl #4,%d0 |put rmode in lower 2 bits 886 movel USER_FPCR(%a6),%d1 886 movel USER_FPCR(%a6),%d1 887 andil #0xc0,%d1 887 andil #0xc0,%d1 888 lsrl #6,%d1 |put precision 888 lsrl #6,%d1 |put precision in upper word 889 swap %d1 889 swap %d1 890 orl %d0,%d1 |set up for ro 890 orl %d0,%d1 |set up for round call 891 clrl %d0 |force sticky 891 clrl %d0 |force sticky to zero 892 bclrb #sign_bit,WBTEMP_EX(%a6) 892 bclrb #sign_bit,WBTEMP_EX(%a6) 893 sne WBTEMP_SGN(%a6) |use internal 893 sne WBTEMP_SGN(%a6) |use internal format for round 894 bsrl round |round result 894 bsrl round |round result to users rmode & prec 895 bfclr WBTEMP_SGN(%a6){#0:#8} |conve 895 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format 896 beq frcfpnr 896 beq frcfpnr 897 bsetb #sign_bit,WBTEMP_EX(%a6) 897 bsetb #sign_bit,WBTEMP_EX(%a6) 898 bra frcfpnr 898 bra frcfpnr 899 | 899 | 900 | Signs are alike: 900 | Signs are alike: 901 | 901 | 902 add_same: 902 add_same: 903 cmpb #0x0f,DNRM_FLG(%a6) |is dest t 903 cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm? 904 bnes add_s_srcd 904 bnes add_s_srcd 905 add_s_destd: 905 add_s_destd: 906 leal ETEMP(%a6),%a0 906 leal ETEMP(%a6),%a0 907 movel USER_FPCR(%a6),%d0 907 movel USER_FPCR(%a6),%d0 908 andil #0x30,%d0 908 andil #0x30,%d0 909 lsrl #4,%d0 |put rmode in 909 lsrl #4,%d0 |put rmode in lower 2 bits 910 movel USER_FPCR(%a6),%d1 910 movel USER_FPCR(%a6),%d1 911 andil #0xc0,%d1 911 andil #0xc0,%d1 912 lsrl #6,%d1 |put precision 912 lsrl #6,%d1 |put precision in upper word 913 swap %d1 913 swap %d1 914 orl %d0,%d1 |set up for ro 914 orl %d0,%d1 |set up for round call 915 movel #0x20000000,%d0 |set sticky fo 915 movel #0x20000000,%d0 |set sticky for round 916 bclrb #sign_bit,ETEMP_EX(%a6) 916 bclrb #sign_bit,ETEMP_EX(%a6) 917 sne ETEMP_SGN(%a6) 917 sne ETEMP_SGN(%a6) 918 bsrl round |round result 918 bsrl round |round result to users rmode & prec 919 bfclr ETEMP_SGN(%a6){#0:#8} |conve 919 bfclr ETEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format 920 beqs add_s_dclr 920 beqs add_s_dclr 921 bsetb #sign_bit,ETEMP_EX(%a6) 921 bsetb #sign_bit,ETEMP_EX(%a6) 922 add_s_dclr: 922 add_s_dclr: 923 leal WBTEMP(%a6),%a0 923 leal WBTEMP(%a6),%a0 924 movel ETEMP(%a6),(%a0) |write 924 movel ETEMP(%a6),(%a0) |write result to wbtemp 925 movel ETEMP_HI(%a6),4(%a0) 925 movel ETEMP_HI(%a6),4(%a0) 926 movel ETEMP_LO(%a6),8(%a0) 926 movel ETEMP_LO(%a6),8(%a0) 927 tstw ETEMP_EX(%a6) 927 tstw ETEMP_EX(%a6) 928 bgt add_ckovf 928 bgt add_ckovf 929 orl #neg_mask,USER_FPSR(%a6) 929 orl #neg_mask,USER_FPSR(%a6) 930 bra add_ckovf 930 bra add_ckovf 931 add_s_srcd: 931 add_s_srcd: 932 leal FPTEMP(%a6),%a0 932 leal FPTEMP(%a6),%a0 933 movel USER_FPCR(%a6),%d0 933 movel USER_FPCR(%a6),%d0 934 andil #0x30,%d0 934 andil #0x30,%d0 935 lsrl #4,%d0 |put rmode in 935 lsrl #4,%d0 |put rmode in lower 2 bits 936 movel USER_FPCR(%a6),%d1 936 movel USER_FPCR(%a6),%d1 937 andil #0xc0,%d1 937 andil #0xc0,%d1 938 lsrl #6,%d1 |put precision 938 lsrl #6,%d1 |put precision in upper word 939 swap %d1 939 swap %d1 940 orl %d0,%d1 |set up for ro 940 orl %d0,%d1 |set up for round call 941 movel #0x20000000,%d0 |set sticky fo 941 movel #0x20000000,%d0 |set sticky for round 942 bclrb #sign_bit,FPTEMP_EX(%a6) 942 bclrb #sign_bit,FPTEMP_EX(%a6) 943 sne FPTEMP_SGN(%a6) 943 sne FPTEMP_SGN(%a6) 944 bsrl round |round result 944 bsrl round |round result to users rmode & prec 945 bfclr FPTEMP_SGN(%a6){#0:#8} |conve 945 bfclr FPTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format 946 beqs add_s_sclr 946 beqs add_s_sclr 947 bsetb #sign_bit,FPTEMP_EX(%a6) 947 bsetb #sign_bit,FPTEMP_EX(%a6) 948 add_s_sclr: 948 add_s_sclr: 949 leal WBTEMP(%a6),%a0 949 leal WBTEMP(%a6),%a0 950 movel FPTEMP(%a6),(%a0) |write 950 movel FPTEMP(%a6),(%a0) |write result to wbtemp 951 movel FPTEMP_HI(%a6),4(%a0) 951 movel FPTEMP_HI(%a6),4(%a0) 952 movel FPTEMP_LO(%a6),8(%a0) 952 movel FPTEMP_LO(%a6),8(%a0) 953 tstw FPTEMP_EX(%a6) 953 tstw FPTEMP_EX(%a6) 954 bgt add_ckovf 954 bgt add_ckovf 955 orl #neg_mask,USER_FPSR(%a6) 955 orl #neg_mask,USER_FPSR(%a6) 956 add_ckovf: 956 add_ckovf: 957 movew WBTEMP_EX(%a6),%d0 957 movew WBTEMP_EX(%a6),%d0 958 andiw #0x7fff,%d0 958 andiw #0x7fff,%d0 959 cmpiw #0x7fff,%d0 959 cmpiw #0x7fff,%d0 960 bne frcfpnr 960 bne frcfpnr 961 | 961 | 962 | The result has overflowed to $7fff exponent. 962 | The result has overflowed to $7fff exponent. Set I, ovfl, 963 | and aovfl, and clr the mantissa (incorrectly 963 | and aovfl, and clr the mantissa (incorrectly set by the 964 | round routine.) 964 | round routine.) 965 | 965 | 966 orl #inf_mask+ovfl_inx_mask,USER_F 966 orl #inf_mask+ovfl_inx_mask,USER_FPSR(%a6) 967 clrl 4(%a0) 967 clrl 4(%a0) 968 bra frcfpnr 968 bra frcfpnr 969 | 969 | 970 | Inst is fsub. 970 | Inst is fsub. 971 | 971 | 972 wrap_sub: 972 wrap_sub: 973 cmpb #0xff,DNRM_FLG(%a6) |if both o 973 cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm, 974 beq fix_stk |restore to f 974 beq fix_stk |restore to fpu 975 | 975 | 976 | One of the ops is denormalized. Test for wr 976 | One of the ops is denormalized. Test for wrap condition 977 | and complete the instruction. 977 | and complete the instruction. 978 | 978 | 979 cmpb #0x0f,DNRM_FLG(%a6) |check for 979 cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm 980 bnes sub_srcd 980 bnes sub_srcd 981 sub_destd: 981 sub_destd: 982 bsrl ckinf_ns 982 bsrl ckinf_ns 983 bne fix_stk 983 bne fix_stk 984 bfextu ETEMP_EX(%a6){#1:#15},%d0 984 bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos) 985 bfexts FPTEMP_EX(%a6){#1:#15},%d1 985 bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg) 986 subl %d1,%d0 |subtr 986 subl %d1,%d0 |subtract src from dest 987 cmpl #0x8000,%d0 987 cmpl #0x8000,%d0 988 blt fix_stk |if le 988 blt fix_stk |if less, not wrap case 989 bra sub_wrap 989 bra sub_wrap 990 sub_srcd: 990 sub_srcd: 991 bsrl ckinf_nd 991 bsrl ckinf_nd 992 bne fix_stk 992 bne fix_stk 993 bfextu FPTEMP_EX(%a6){#1:#15},%d0 993 bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos) 994 bfexts ETEMP_EX(%a6){#1:#15},%d1 994 bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg) 995 subl %d1,%d0 |subtr 995 subl %d1,%d0 |subtract dest from src 996 cmpl #0x8000,%d0 996 cmpl #0x8000,%d0 997 blt fix_stk |if le 997 blt fix_stk |if less, not wrap case 998 | 998 | 999 | Check the signs of the operands. If they ar 999 | Check the signs of the operands. If they are alike, the fpu 1000 | can be used to subtract from the norm 1.0 w 1000 | can be used to subtract from the norm 1.0 with the sign of the 1001 | denorm and it will correctly generate the r 1001 | denorm and it will correctly generate the result in extended 1002 | precision. We can then call round with no 1002 | precision. We can then call round with no sticky and the result 1003 | will be correct for the user's rounding mod 1003 | will be correct for the user's rounding mode and precision. If 1004 | the signs are unlike, we call round with th 1004 | the signs are unlike, we call round with the sticky bit set 1005 | and the result will be correct for the user 1005 | and the result will be correct for the user's rounding mode and 1006 | precision. 1006 | precision. 1007 | 1007 | 1008 sub_wrap: 1008 sub_wrap: 1009 movew ETEMP_EX(%a6),%d0 1009 movew ETEMP_EX(%a6),%d0 1010 movew FPTEMP_EX(%a6),%d1 1010 movew FPTEMP_EX(%a6),%d1 1011 eorw %d1,%d0 1011 eorw %d1,%d0 1012 andiw #0x8000,%d0 1012 andiw #0x8000,%d0 1013 bne sub_diff 1013 bne sub_diff 1014 | 1014 | 1015 | The signs are alike. 1015 | The signs are alike. 1016 | 1016 | 1017 cmpb #0x0f,DNRM_FLG(%a6) |is dest 1017 cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm? 1018 bnes sub_u_srcd 1018 bnes sub_u_srcd 1019 movew FPTEMP_EX(%a6),%d0 1019 movew FPTEMP_EX(%a6),%d0 1020 andiw #0x8000,%d0 1020 andiw #0x8000,%d0 1021 orw #0x3fff,%d0 |force the ex 1021 orw #0x3fff,%d0 |force the exponent to +/- 1 1022 movew %d0,FPTEMP_EX(%a6) |in the de 1022 movew %d0,FPTEMP_EX(%a6) |in the denorm 1023 movel USER_FPCR(%a6),%d0 1023 movel USER_FPCR(%a6),%d0 1024 andil #0x30,%d0 1024 andil #0x30,%d0 1025 fmovel %d0,%fpcr |set 1025 fmovel %d0,%fpcr |set up users rmode and X 1026 fmovex FPTEMP(%a6),%fp0 1026 fmovex FPTEMP(%a6),%fp0 1027 fsubx ETEMP(%a6),%fp0 1027 fsubx ETEMP(%a6),%fp0 1028 fmovel %fpsr,%d1 1028 fmovel %fpsr,%d1 1029 orl %d1,USER_FPSR(%a6) |capture c 1029 orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd 1030 leal WBTEMP(%a6),%a0 |point a0 to 1030 leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame 1031 fmovex %fp0,WBTEMP(%a6) |writ 1031 fmovex %fp0,WBTEMP(%a6) |write result to memory 1032 lsrl #4,%d0 |put rmode in 1032 lsrl #4,%d0 |put rmode in lower 2 bits 1033 movel USER_FPCR(%a6),%d1 1033 movel USER_FPCR(%a6),%d1 1034 andil #0xc0,%d1 1034 andil #0xc0,%d1 1035 lsrl #6,%d1 |put precisio 1035 lsrl #6,%d1 |put precision in upper word 1036 swap %d1 1036 swap %d1 1037 orl %d0,%d1 |set up for r 1037 orl %d0,%d1 |set up for round call 1038 clrl %d0 |force sticky 1038 clrl %d0 |force sticky to zero 1039 bclrb #sign_bit,WBTEMP_EX(%a6) 1039 bclrb #sign_bit,WBTEMP_EX(%a6) 1040 sne WBTEMP_SGN(%a6) 1040 sne WBTEMP_SGN(%a6) 1041 bsrl round |round result 1041 bsrl round |round result to users rmode & prec 1042 bfclr WBTEMP_SGN(%a6){#0:#8} |conv 1042 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format 1043 beq frcfpnr 1043 beq frcfpnr 1044 bsetb #sign_bit,WBTEMP_EX(%a6) 1044 bsetb #sign_bit,WBTEMP_EX(%a6) 1045 bra frcfpnr 1045 bra frcfpnr 1046 sub_u_srcd: 1046 sub_u_srcd: 1047 movew ETEMP_EX(%a6),%d0 1047 movew ETEMP_EX(%a6),%d0 1048 andiw #0x8000,%d0 1048 andiw #0x8000,%d0 1049 orw #0x3fff,%d0 |force the ex 1049 orw #0x3fff,%d0 |force the exponent to +/- 1 1050 movew %d0,ETEMP_EX(%a6) |in the den 1050 movew %d0,ETEMP_EX(%a6) |in the denorm 1051 movel USER_FPCR(%a6),%d0 1051 movel USER_FPCR(%a6),%d0 1052 andil #0x30,%d0 1052 andil #0x30,%d0 1053 fmovel %d0,%fpcr |set 1053 fmovel %d0,%fpcr |set up users rmode and X 1054 fmovex FPTEMP(%a6),%fp0 1054 fmovex FPTEMP(%a6),%fp0 1055 fsubx ETEMP(%a6),%fp0 1055 fsubx ETEMP(%a6),%fp0 1056 fmovel %fpsr,%d1 1056 fmovel %fpsr,%d1 1057 orl %d1,USER_FPSR(%a6) |capture c 1057 orl %d1,USER_FPSR(%a6) |capture cc's and inex from fadd 1058 leal WBTEMP(%a6),%a0 |point a0 to 1058 leal WBTEMP(%a6),%a0 |point a0 to wbtemp in frame 1059 fmovex %fp0,WBTEMP(%a6) |writ 1059 fmovex %fp0,WBTEMP(%a6) |write result to memory 1060 lsrl #4,%d0 |put rmode in 1060 lsrl #4,%d0 |put rmode in lower 2 bits 1061 movel USER_FPCR(%a6),%d1 1061 movel USER_FPCR(%a6),%d1 1062 andil #0xc0,%d1 1062 andil #0xc0,%d1 1063 lsrl #6,%d1 |put precisio 1063 lsrl #6,%d1 |put precision in upper word 1064 swap %d1 1064 swap %d1 1065 orl %d0,%d1 |set up for r 1065 orl %d0,%d1 |set up for round call 1066 clrl %d0 |force sticky 1066 clrl %d0 |force sticky to zero 1067 bclrb #sign_bit,WBTEMP_EX(%a6) 1067 bclrb #sign_bit,WBTEMP_EX(%a6) 1068 sne WBTEMP_SGN(%a6) 1068 sne WBTEMP_SGN(%a6) 1069 bsrl round |round result 1069 bsrl round |round result to users rmode & prec 1070 bfclr WBTEMP_SGN(%a6){#0:#8} |conv 1070 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format 1071 beq frcfpnr 1071 beq frcfpnr 1072 bsetb #sign_bit,WBTEMP_EX(%a6) 1072 bsetb #sign_bit,WBTEMP_EX(%a6) 1073 bra frcfpnr 1073 bra frcfpnr 1074 | 1074 | 1075 | Signs are unlike: 1075 | Signs are unlike: 1076 | 1076 | 1077 sub_diff: 1077 sub_diff: 1078 cmpb #0x0f,DNRM_FLG(%a6) |is dest 1078 cmpb #0x0f,DNRM_FLG(%a6) |is dest the denorm? 1079 bnes sub_s_srcd 1079 bnes sub_s_srcd 1080 sub_s_destd: 1080 sub_s_destd: 1081 leal ETEMP(%a6),%a0 1081 leal ETEMP(%a6),%a0 1082 movel USER_FPCR(%a6),%d0 1082 movel USER_FPCR(%a6),%d0 1083 andil #0x30,%d0 1083 andil #0x30,%d0 1084 lsrl #4,%d0 |put rmode in 1084 lsrl #4,%d0 |put rmode in lower 2 bits 1085 movel USER_FPCR(%a6),%d1 1085 movel USER_FPCR(%a6),%d1 1086 andil #0xc0,%d1 1086 andil #0xc0,%d1 1087 lsrl #6,%d1 |put precisio 1087 lsrl #6,%d1 |put precision in upper word 1088 swap %d1 1088 swap %d1 1089 orl %d0,%d1 |set up for r 1089 orl %d0,%d1 |set up for round call 1090 movel #0x20000000,%d0 |set sticky f 1090 movel #0x20000000,%d0 |set sticky for round 1091 | 1091 | 1092 | Since the dest is the denorm, the sign is t 1092 | Since the dest is the denorm, the sign is the opposite of the 1093 | norm sign. 1093 | norm sign. 1094 | 1094 | 1095 eoriw #0x8000,ETEMP_EX(%a6) |flip 1095 eoriw #0x8000,ETEMP_EX(%a6) |flip sign on result 1096 tstw ETEMP_EX(%a6) 1096 tstw ETEMP_EX(%a6) 1097 bgts sub_s_dwr 1097 bgts sub_s_dwr 1098 orl #neg_mask,USER_FPSR(%a6) 1098 orl #neg_mask,USER_FPSR(%a6) 1099 sub_s_dwr: 1099 sub_s_dwr: 1100 bclrb #sign_bit,ETEMP_EX(%a6) 1100 bclrb #sign_bit,ETEMP_EX(%a6) 1101 sne ETEMP_SGN(%a6) 1101 sne ETEMP_SGN(%a6) 1102 bsrl round |round result 1102 bsrl round |round result to users rmode & prec 1103 bfclr ETEMP_SGN(%a6){#0:#8} |conv 1103 bfclr ETEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format 1104 beqs sub_s_dclr 1104 beqs sub_s_dclr 1105 bsetb #sign_bit,ETEMP_EX(%a6) 1105 bsetb #sign_bit,ETEMP_EX(%a6) 1106 sub_s_dclr: 1106 sub_s_dclr: 1107 leal WBTEMP(%a6),%a0 1107 leal WBTEMP(%a6),%a0 1108 movel ETEMP(%a6),(%a0) |writ 1108 movel ETEMP(%a6),(%a0) |write result to wbtemp 1109 movel ETEMP_HI(%a6),4(%a0) 1109 movel ETEMP_HI(%a6),4(%a0) 1110 movel ETEMP_LO(%a6),8(%a0) 1110 movel ETEMP_LO(%a6),8(%a0) 1111 bra sub_ckovf 1111 bra sub_ckovf 1112 sub_s_srcd: 1112 sub_s_srcd: 1113 leal FPTEMP(%a6),%a0 1113 leal FPTEMP(%a6),%a0 1114 movel USER_FPCR(%a6),%d0 1114 movel USER_FPCR(%a6),%d0 1115 andil #0x30,%d0 1115 andil #0x30,%d0 1116 lsrl #4,%d0 |put rmode in 1116 lsrl #4,%d0 |put rmode in lower 2 bits 1117 movel USER_FPCR(%a6),%d1 1117 movel USER_FPCR(%a6),%d1 1118 andil #0xc0,%d1 1118 andil #0xc0,%d1 1119 lsrl #6,%d1 |put precisio 1119 lsrl #6,%d1 |put precision in upper word 1120 swap %d1 1120 swap %d1 1121 orl %d0,%d1 |set up for r 1121 orl %d0,%d1 |set up for round call 1122 movel #0x20000000,%d0 |set sticky f 1122 movel #0x20000000,%d0 |set sticky for round 1123 bclrb #sign_bit,FPTEMP_EX(%a6) 1123 bclrb #sign_bit,FPTEMP_EX(%a6) 1124 sne FPTEMP_SGN(%a6) 1124 sne FPTEMP_SGN(%a6) 1125 bsrl round |round result 1125 bsrl round |round result to users rmode & prec 1126 bfclr FPTEMP_SGN(%a6){#0:#8} |conv 1126 bfclr FPTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format 1127 beqs sub_s_sclr 1127 beqs sub_s_sclr 1128 bsetb #sign_bit,FPTEMP_EX(%a6) 1128 bsetb #sign_bit,FPTEMP_EX(%a6) 1129 sub_s_sclr: 1129 sub_s_sclr: 1130 leal WBTEMP(%a6),%a0 1130 leal WBTEMP(%a6),%a0 1131 movel FPTEMP(%a6),(%a0) |writ 1131 movel FPTEMP(%a6),(%a0) |write result to wbtemp 1132 movel FPTEMP_HI(%a6),4(%a0) 1132 movel FPTEMP_HI(%a6),4(%a0) 1133 movel FPTEMP_LO(%a6),8(%a0) 1133 movel FPTEMP_LO(%a6),8(%a0) 1134 tstw FPTEMP_EX(%a6) 1134 tstw FPTEMP_EX(%a6) 1135 bgt sub_ckovf 1135 bgt sub_ckovf 1136 orl #neg_mask,USER_FPSR(%a6) 1136 orl #neg_mask,USER_FPSR(%a6) 1137 sub_ckovf: 1137 sub_ckovf: 1138 movew WBTEMP_EX(%a6),%d0 1138 movew WBTEMP_EX(%a6),%d0 1139 andiw #0x7fff,%d0 1139 andiw #0x7fff,%d0 1140 cmpiw #0x7fff,%d0 1140 cmpiw #0x7fff,%d0 1141 bne frcfpnr 1141 bne frcfpnr 1142 | 1142 | 1143 | The result has overflowed to $7fff exponent 1143 | The result has overflowed to $7fff exponent. Set I, ovfl, 1144 | and aovfl, and clr the mantissa (incorrectl 1144 | and aovfl, and clr the mantissa (incorrectly set by the 1145 | round routine.) 1145 | round routine.) 1146 | 1146 | 1147 orl #inf_mask+ovfl_inx_mask,USER_ 1147 orl #inf_mask+ovfl_inx_mask,USER_FPSR(%a6) 1148 clrl 4(%a0) 1148 clrl 4(%a0) 1149 bra frcfpnr 1149 bra frcfpnr 1150 | 1150 | 1151 | Inst is fcmp. 1151 | Inst is fcmp. 1152 | 1152 | 1153 wrap_cmp: 1153 wrap_cmp: 1154 cmpb #0xff,DNRM_FLG(%a6) |if both 1154 cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm, 1155 beq fix_stk |restore to 1155 beq fix_stk |restore to fpu 1156 | 1156 | 1157 | One of the ops is denormalized. Test for w 1157 | One of the ops is denormalized. Test for wrap condition 1158 | and complete the instruction. 1158 | and complete the instruction. 1159 | 1159 | 1160 cmpb #0x0f,DNRM_FLG(%a6) |check fo 1160 cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm 1161 bnes cmp_srcd 1161 bnes cmp_srcd 1162 cmp_destd: 1162 cmp_destd: 1163 bsrl ckinf_ns 1163 bsrl ckinf_ns 1164 bne fix_stk 1164 bne fix_stk 1165 bfextu ETEMP_EX(%a6){#1:#15},%d0 1165 bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos) 1166 bfexts FPTEMP_EX(%a6){#1:#15},%d1 1166 bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg) 1167 subl %d1,%d0 |subt 1167 subl %d1,%d0 |subtract dest from src 1168 cmpl #0x8000,%d0 1168 cmpl #0x8000,%d0 1169 blt fix_stk |if l 1169 blt fix_stk |if less, not wrap case 1170 tstw ETEMP_EX(%a6) |set 1170 tstw ETEMP_EX(%a6) |set N to ~sign_of(src) 1171 bge cmp_setn 1171 bge cmp_setn 1172 rts 1172 rts 1173 cmp_srcd: 1173 cmp_srcd: 1174 bsrl ckinf_nd 1174 bsrl ckinf_nd 1175 bne fix_stk 1175 bne fix_stk 1176 bfextu FPTEMP_EX(%a6){#1:#15},%d0 1176 bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos) 1177 bfexts ETEMP_EX(%a6){#1:#15},%d1 1177 bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg) 1178 subl %d1,%d0 |subt 1178 subl %d1,%d0 |subtract src from dest 1179 cmpl #0x8000,%d0 1179 cmpl #0x8000,%d0 1180 blt fix_stk |if l 1180 blt fix_stk |if less, not wrap case 1181 tstw FPTEMP_EX(%a6) |set 1181 tstw FPTEMP_EX(%a6) |set N to sign_of(dest) 1182 blt cmp_setn 1182 blt cmp_setn 1183 rts 1183 rts 1184 cmp_setn: 1184 cmp_setn: 1185 orl #neg_mask,USER_FPSR(%a6) 1185 orl #neg_mask,USER_FPSR(%a6) 1186 rts 1186 rts 1187 1187 1188 | 1188 | 1189 | Inst is fmul. 1189 | Inst is fmul. 1190 | 1190 | 1191 wrap_mul: 1191 wrap_mul: 1192 cmpb #0xff,DNRM_FLG(%a6) |if both 1192 cmpb #0xff,DNRM_FLG(%a6) |if both ops denorm, 1193 beq force_unf |force an und 1193 beq force_unf |force an underflow (really!) 1194 | 1194 | 1195 | One of the ops is denormalized. Test for w 1195 | One of the ops is denormalized. Test for wrap condition 1196 | and complete the instruction. 1196 | and complete the instruction. 1197 | 1197 | 1198 cmpb #0x0f,DNRM_FLG(%a6) |check fo 1198 cmpb #0x0f,DNRM_FLG(%a6) |check for dest denorm 1199 bnes mul_srcd 1199 bnes mul_srcd 1200 mul_destd: 1200 mul_destd: 1201 bsrl ckinf_ns 1201 bsrl ckinf_ns 1202 bne fix_stk 1202 bne fix_stk 1203 bfextu ETEMP_EX(%a6){#1:#15},%d0 1203 bfextu ETEMP_EX(%a6){#1:#15},%d0 |get src exp (always pos) 1204 bfexts FPTEMP_EX(%a6){#1:#15},%d1 1204 bfexts FPTEMP_EX(%a6){#1:#15},%d1 |get dest exp (always neg) 1205 addl %d1,%d0 |subt 1205 addl %d1,%d0 |subtract dest from src 1206 bgt fix_stk 1206 bgt fix_stk 1207 bra force_unf 1207 bra force_unf 1208 mul_srcd: 1208 mul_srcd: 1209 bsrl ckinf_nd 1209 bsrl ckinf_nd 1210 bne fix_stk 1210 bne fix_stk 1211 bfextu FPTEMP_EX(%a6){#1:#15},%d0 1211 bfextu FPTEMP_EX(%a6){#1:#15},%d0 |get dest exp (always pos) 1212 bfexts ETEMP_EX(%a6){#1:#15},%d1 1212 bfexts ETEMP_EX(%a6){#1:#15},%d1 |get src exp (always neg) 1213 addl %d1,%d0 |subt 1213 addl %d1,%d0 |subtract src from dest 1214 bgt fix_stk 1214 bgt fix_stk 1215 1215 1216 | 1216 | 1217 | This code handles the case of the instructi 1217 | This code handles the case of the instruction resulting in 1218 | an underflow condition. 1218 | an underflow condition. 1219 | 1219 | 1220 force_unf: 1220 force_unf: 1221 bclrb #E1,E_BYTE(%a6) 1221 bclrb #E1,E_BYTE(%a6) 1222 orl #unfinx_mask,USER_FPSR(%a6) 1222 orl #unfinx_mask,USER_FPSR(%a6) 1223 clrw NMNEXC(%a6) 1223 clrw NMNEXC(%a6) 1224 clrb WBTEMP_SGN(%a6) 1224 clrb WBTEMP_SGN(%a6) 1225 movew ETEMP_EX(%a6),%d0 1225 movew ETEMP_EX(%a6),%d0 |find the sign of the result 1226 movew FPTEMP_EX(%a6),%d1 1226 movew FPTEMP_EX(%a6),%d1 1227 eorw %d1,%d0 1227 eorw %d1,%d0 1228 andiw #0x8000,%d0 1228 andiw #0x8000,%d0 1229 beqs frcunfcont 1229 beqs frcunfcont 1230 st WBTEMP_SGN(%a6) 1230 st WBTEMP_SGN(%a6) 1231 frcunfcont: 1231 frcunfcont: 1232 lea WBTEMP(%a6),%a0 |poin 1232 lea WBTEMP(%a6),%a0 |point a0 to memory location 1233 movew CMDREG1B(%a6),%d0 1233 movew CMDREG1B(%a6),%d0 1234 btstl #6,%d0 |test 1234 btstl #6,%d0 |test for forced precision 1235 beqs frcunf_fpcr 1235 beqs frcunf_fpcr 1236 btstl #2,%d0 |chec 1236 btstl #2,%d0 |check for double 1237 bnes frcunf_dbl 1237 bnes frcunf_dbl 1238 movel #0x1,%d0 1238 movel #0x1,%d0 |inst is forced single 1239 bras frcunf_rnd 1239 bras frcunf_rnd 1240 frcunf_dbl: 1240 frcunf_dbl: 1241 movel #0x2,%d0 1241 movel #0x2,%d0 |inst is forced double 1242 bras frcunf_rnd 1242 bras frcunf_rnd 1243 frcunf_fpcr: 1243 frcunf_fpcr: 1244 bfextu FPCR_MODE(%a6){#0:#2},%d0 1244 bfextu FPCR_MODE(%a6){#0:#2},%d0 |inst not forced - use fpcr prec 1245 frcunf_rnd: 1245 frcunf_rnd: 1246 bsrl unf_sub |get 1246 bsrl unf_sub |get correct result based on 1247 | ;roun 1247 | ;round precision/mode. This 1248 | ;sets 1248 | ;sets FPSR_CC correctly 1249 bfclr WBTEMP_SGN(%a6){#0:#8} |conv 1249 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format 1250 beqs frcfpn 1250 beqs frcfpn 1251 bsetb #sign_bit,WBTEMP_EX(%a6) 1251 bsetb #sign_bit,WBTEMP_EX(%a6) 1252 bra frcfpn 1252 bra frcfpn 1253 1253 1254 | 1254 | 1255 | Write the result to the user's fpn. All re 1255 | Write the result to the user's fpn. All results must be HUGE to be 1256 | written; otherwise the results would have o 1256 | written; otherwise the results would have overflowed or underflowed. 1257 | If the rounding precision is single or doub 1257 | If the rounding precision is single or double, the ovf_res routine 1258 | is needed to correctly supply the max value 1258 | is needed to correctly supply the max value. 1259 | 1259 | 1260 frcfpnr: 1260 frcfpnr: 1261 movew CMDREG1B(%a6),%d0 1261 movew CMDREG1B(%a6),%d0 1262 btstl #6,%d0 |test 1262 btstl #6,%d0 |test for forced precision 1263 beqs frcfpn_fpcr 1263 beqs frcfpn_fpcr 1264 btstl #2,%d0 |chec 1264 btstl #2,%d0 |check for double 1265 bnes frcfpn_dbl 1265 bnes frcfpn_dbl 1266 movel #0x1,%d0 1266 movel #0x1,%d0 |inst is forced single 1267 bras frcfpn_rnd 1267 bras frcfpn_rnd 1268 frcfpn_dbl: 1268 frcfpn_dbl: 1269 movel #0x2,%d0 1269 movel #0x2,%d0 |inst is forced double 1270 bras frcfpn_rnd 1270 bras frcfpn_rnd 1271 frcfpn_fpcr: 1271 frcfpn_fpcr: 1272 bfextu FPCR_MODE(%a6){#0:#2},%d0 1272 bfextu FPCR_MODE(%a6){#0:#2},%d0 |inst not forced - use fpcr prec 1273 tstb %d0 1273 tstb %d0 1274 beqs frcfpn |if e 1274 beqs frcfpn |if extended, write what you got 1275 frcfpn_rnd: 1275 frcfpn_rnd: 1276 bclrb #sign_bit,WBTEMP_EX(%a6) 1276 bclrb #sign_bit,WBTEMP_EX(%a6) 1277 sne WBTEMP_SGN(%a6) 1277 sne WBTEMP_SGN(%a6) 1278 bsrl ovf_res |get 1278 bsrl ovf_res |get correct result based on 1279 | ;roun 1279 | ;round precision/mode. This 1280 | ;sets 1280 | ;sets FPSR_CC correctly 1281 bfclr WBTEMP_SGN(%a6){#0:#8} |conv 1281 bfclr WBTEMP_SGN(%a6){#0:#8} |convert back to IEEE ext format 1282 beqs frcfpn_clr 1282 beqs frcfpn_clr 1283 bsetb #sign_bit,WBTEMP_EX(%a6) 1283 bsetb #sign_bit,WBTEMP_EX(%a6) 1284 frcfpn_clr: 1284 frcfpn_clr: 1285 orl #ovfinx_mask,USER_FPSR(%a6) 1285 orl #ovfinx_mask,USER_FPSR(%a6) 1286 | 1286 | 1287 | Perform the write. 1287 | Perform the write. 1288 | 1288 | 1289 frcfpn: 1289 frcfpn: 1290 bfextu CMDREG1B(%a6){#6:#3},%d0 1290 bfextu CMDREG1B(%a6){#6:#3},%d0 |extract fp destination register 1291 cmpib #3,%d0 1291 cmpib #3,%d0 1292 bles frc0123 |chec 1292 bles frc0123 |check if dest is fp0-fp3 1293 movel #7,%d1 1293 movel #7,%d1 1294 subl %d0,%d1 1294 subl %d0,%d1 1295 clrl %d0 1295 clrl %d0 1296 bsetl %d1,%d0 1296 bsetl %d1,%d0 1297 fmovemx WBTEMP(%a6),%d0 1297 fmovemx WBTEMP(%a6),%d0 1298 rts 1298 rts 1299 frc0123: 1299 frc0123: 1300 cmpib #0,%d0 1300 cmpib #0,%d0 1301 beqs frc0_dst 1301 beqs frc0_dst 1302 cmpib #1,%d0 1302 cmpib #1,%d0 1303 beqs frc1_dst 1303 beqs frc1_dst 1304 cmpib #2,%d0 1304 cmpib #2,%d0 1305 beqs frc2_dst 1305 beqs frc2_dst 1306 frc3_dst: 1306 frc3_dst: 1307 movel WBTEMP_EX(%a6),USER_FP3(%a6) 1307 movel WBTEMP_EX(%a6),USER_FP3(%a6) 1308 movel WBTEMP_HI(%a6),USER_FP3+4(%a6 1308 movel WBTEMP_HI(%a6),USER_FP3+4(%a6) 1309 movel WBTEMP_LO(%a6),USER_FP3+8(%a6 1309 movel WBTEMP_LO(%a6),USER_FP3+8(%a6) 1310 rts 1310 rts 1311 frc2_dst: 1311 frc2_dst: 1312 movel WBTEMP_EX(%a6),USER_FP2(%a6) 1312 movel WBTEMP_EX(%a6),USER_FP2(%a6) 1313 movel WBTEMP_HI(%a6),USER_FP2+4(%a6 1313 movel WBTEMP_HI(%a6),USER_FP2+4(%a6) 1314 movel WBTEMP_LO(%a6),USER_FP2+8(%a6 1314 movel WBTEMP_LO(%a6),USER_FP2+8(%a6) 1315 rts 1315 rts 1316 frc1_dst: 1316 frc1_dst: 1317 movel WBTEMP_EX(%a6),USER_FP1(%a6) 1317 movel WBTEMP_EX(%a6),USER_FP1(%a6) 1318 movel WBTEMP_HI(%a6),USER_FP1+4(%a6 1318 movel WBTEMP_HI(%a6),USER_FP1+4(%a6) 1319 movel WBTEMP_LO(%a6),USER_FP1+8(%a6 1319 movel WBTEMP_LO(%a6),USER_FP1+8(%a6) 1320 rts 1320 rts 1321 frc0_dst: 1321 frc0_dst: 1322 movel WBTEMP_EX(%a6),USER_FP0(%a6) 1322 movel WBTEMP_EX(%a6),USER_FP0(%a6) 1323 movel WBTEMP_HI(%a6),USER_FP0+4(%a6 1323 movel WBTEMP_HI(%a6),USER_FP0+4(%a6) 1324 movel WBTEMP_LO(%a6),USER_FP0+8(%a6 1324 movel WBTEMP_LO(%a6),USER_FP0+8(%a6) 1325 rts 1325 rts 1326 1326 1327 | 1327 | 1328 | Write etemp to fpn. 1328 | Write etemp to fpn. 1329 | A check is made on enabled and signalled sn 1329 | A check is made on enabled and signalled snan exceptions, 1330 | and the destination is not overwritten if t 1330 | and the destination is not overwritten if this condition exists. 1331 | This code is designed to make fmoveins of u 1331 | This code is designed to make fmoveins of unsupported data types 1332 | faster. 1332 | faster. 1333 | 1333 | 1334 wr_etemp: 1334 wr_etemp: 1335 btstb #snan_bit,FPSR_EXCEPT(%a6) 1335 btstb #snan_bit,FPSR_EXCEPT(%a6) |if snan is set, and 1336 beqs fmoveinc |enab 1336 beqs fmoveinc |enabled, force restore 1337 btstb #snan_bit,FPCR_ENABLE(%a6) |a 1337 btstb #snan_bit,FPCR_ENABLE(%a6) |and don't overwrite 1338 beqs fmoveinc |the 1338 beqs fmoveinc |the dest 1339 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) 1339 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for 1340 | 1340 | ;snan handler 1341 tstb ETEMP(%a6) |chec 1341 tstb ETEMP(%a6) |check for negative 1342 blts snan_neg 1342 blts snan_neg 1343 rts 1343 rts 1344 snan_neg: 1344 snan_neg: 1345 orl #neg_bit,USER_FPSR(%a6) |snan 1345 orl #neg_bit,USER_FPSR(%a6) |snan is negative; set N 1346 rts 1346 rts 1347 fmoveinc: 1347 fmoveinc: 1348 clrw NMNEXC(%a6) 1348 clrw NMNEXC(%a6) 1349 bclrb #E1,E_BYTE(%a6) 1349 bclrb #E1,E_BYTE(%a6) 1350 moveb STAG(%a6),%d0 |chec 1350 moveb STAG(%a6),%d0 |check if stag is inf 1351 andib #0xe0,%d0 1351 andib #0xe0,%d0 1352 cmpib #0x40,%d0 1352 cmpib #0x40,%d0 1353 bnes fminc_cnan 1353 bnes fminc_cnan 1354 orl #inf_mask,USER_FPSR(%a6) |if 1354 orl #inf_mask,USER_FPSR(%a6) |if inf, nothing yet has set I 1355 tstw LOCAL_EX(%a0) |chec 1355 tstw LOCAL_EX(%a0) |check sign 1356 bges fminc_con 1356 bges fminc_con 1357 orl #neg_mask,USER_FPSR(%a6) 1357 orl #neg_mask,USER_FPSR(%a6) 1358 bra fminc_con 1358 bra fminc_con 1359 fminc_cnan: 1359 fminc_cnan: 1360 cmpib #0x60,%d0 1360 cmpib #0x60,%d0 |check if stag is NaN 1361 bnes fminc_czero 1361 bnes fminc_czero 1362 orl #nan_mask,USER_FPSR(%a6) |if 1362 orl #nan_mask,USER_FPSR(%a6) |if nan, nothing yet has set NaN 1363 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) 1363 movel ETEMP_EX(%a6),FPTEMP_EX(%a6) |set up fptemp sign for 1364 | 1364 | ;snan handler 1365 tstw LOCAL_EX(%a0) |chec 1365 tstw LOCAL_EX(%a0) |check sign 1366 bges fminc_con 1366 bges fminc_con 1367 orl #neg_mask,USER_FPSR(%a6) 1367 orl #neg_mask,USER_FPSR(%a6) 1368 bra fminc_con 1368 bra fminc_con 1369 fminc_czero: 1369 fminc_czero: 1370 cmpib #0x20,%d0 1370 cmpib #0x20,%d0 |check if zero 1371 bnes fminc_con 1371 bnes fminc_con 1372 orl #z_mask,USER_FPSR(%a6) |if z 1372 orl #z_mask,USER_FPSR(%a6) |if zero, set Z 1373 tstw LOCAL_EX(%a0) |chec 1373 tstw LOCAL_EX(%a0) |check sign 1374 bges fminc_con 1374 bges fminc_con 1375 orl #neg_mask,USER_FPSR(%a6) 1375 orl #neg_mask,USER_FPSR(%a6) 1376 fminc_con: 1376 fminc_con: 1377 bfextu CMDREG1B(%a6){#6:#3},%d0 1377 bfextu CMDREG1B(%a6){#6:#3},%d0 |extract fp destination register 1378 cmpib #3,%d0 1378 cmpib #3,%d0 1379 bles fp0123 |chec 1379 bles fp0123 |check if dest is fp0-fp3 1380 movel #7,%d1 1380 movel #7,%d1 1381 subl %d0,%d1 1381 subl %d0,%d1 1382 clrl %d0 1382 clrl %d0 1383 bsetl %d1,%d0 1383 bsetl %d1,%d0 1384 fmovemx ETEMP(%a6),%d0 1384 fmovemx ETEMP(%a6),%d0 1385 rts 1385 rts 1386 1386 1387 fp0123: 1387 fp0123: 1388 cmpib #0,%d0 1388 cmpib #0,%d0 1389 beqs fp0_dst 1389 beqs fp0_dst 1390 cmpib #1,%d0 1390 cmpib #1,%d0 1391 beqs fp1_dst 1391 beqs fp1_dst 1392 cmpib #2,%d0 1392 cmpib #2,%d0 1393 beqs fp2_dst 1393 beqs fp2_dst 1394 fp3_dst: 1394 fp3_dst: 1395 movel ETEMP_EX(%a6),USER_FP3(%a6) 1395 movel ETEMP_EX(%a6),USER_FP3(%a6) 1396 movel ETEMP_HI(%a6),USER_FP3+4(%a6) 1396 movel ETEMP_HI(%a6),USER_FP3+4(%a6) 1397 movel ETEMP_LO(%a6),USER_FP3+8(%a6) 1397 movel ETEMP_LO(%a6),USER_FP3+8(%a6) 1398 rts 1398 rts 1399 fp2_dst: 1399 fp2_dst: 1400 movel ETEMP_EX(%a6),USER_FP2(%a6) 1400 movel ETEMP_EX(%a6),USER_FP2(%a6) 1401 movel ETEMP_HI(%a6),USER_FP2+4(%a6) 1401 movel ETEMP_HI(%a6),USER_FP2+4(%a6) 1402 movel ETEMP_LO(%a6),USER_FP2+8(%a6) 1402 movel ETEMP_LO(%a6),USER_FP2+8(%a6) 1403 rts 1403 rts 1404 fp1_dst: 1404 fp1_dst: 1405 movel ETEMP_EX(%a6),USER_FP1(%a6) 1405 movel ETEMP_EX(%a6),USER_FP1(%a6) 1406 movel ETEMP_HI(%a6),USER_FP1+4(%a6) 1406 movel ETEMP_HI(%a6),USER_FP1+4(%a6) 1407 movel ETEMP_LO(%a6),USER_FP1+8(%a6) 1407 movel ETEMP_LO(%a6),USER_FP1+8(%a6) 1408 rts 1408 rts 1409 fp0_dst: 1409 fp0_dst: 1410 movel ETEMP_EX(%a6),USER_FP0(%a6) 1410 movel ETEMP_EX(%a6),USER_FP0(%a6) 1411 movel ETEMP_HI(%a6),USER_FP0+4(%a6) 1411 movel ETEMP_HI(%a6),USER_FP0+4(%a6) 1412 movel ETEMP_LO(%a6),USER_FP0+8(%a6) 1412 movel ETEMP_LO(%a6),USER_FP0+8(%a6) 1413 rts 1413 rts 1414 1414 1415 opclass3: 1415 opclass3: 1416 st CU_ONLY(%a6) 1416 st CU_ONLY(%a6) 1417 movew CMDREG1B(%a6),%d0 |chec 1417 movew CMDREG1B(%a6),%d0 |check if packed moveout 1418 andiw #0x0c00,%d0 |isolate last 1418 andiw #0x0c00,%d0 |isolate last 2 bits of size field 1419 cmpiw #0x0c00,%d0 |if size is 0 1419 cmpiw #0x0c00,%d0 |if size is 011 or 111, it is packed 1420 beq pack_out |else it is n 1420 beq pack_out |else it is norm or denorm 1421 bra mv_out 1421 bra mv_out 1422 1422 1423 1423 1424 | 1424 | 1425 | MOVE OUT 1425 | MOVE OUT 1426 | 1426 | 1427 1427 1428 mv_tbl: 1428 mv_tbl: 1429 .long li 1429 .long li 1430 .long sgp 1430 .long sgp 1431 .long xp 1431 .long xp 1432 .long mvout_end |should never 1432 .long mvout_end |should never be taken 1433 .long wi 1433 .long wi 1434 .long dp 1434 .long dp 1435 .long bi 1435 .long bi 1436 .long mvout_end |should never 1436 .long mvout_end |should never be taken 1437 mv_out: 1437 mv_out: 1438 bfextu CMDREG1B(%a6){#3:#3},%d1 1438 bfextu CMDREG1B(%a6){#3:#3},%d1 |put source specifier in d1 1439 leal mv_tbl,%a0 1439 leal mv_tbl,%a0 1440 movel %a0@(%d1:l:4),%a0 1440 movel %a0@(%d1:l:4),%a0 1441 jmp (%a0) 1441 jmp (%a0) 1442 1442 1443 | 1443 | 1444 | This exit is for move-out to memory. The a 1444 | This exit is for move-out to memory. The aunfl bit is 1445 | set if the result is inex and unfl is signa 1445 | set if the result is inex and unfl is signalled. 1446 | 1446 | 1447 mvout_end: 1447 mvout_end: 1448 btstb #inex2_bit,FPSR_EXCEPT(%a6) 1448 btstb #inex2_bit,FPSR_EXCEPT(%a6) 1449 beqs no_aufl 1449 beqs no_aufl 1450 btstb #unfl_bit,FPSR_EXCEPT(%a6) 1450 btstb #unfl_bit,FPSR_EXCEPT(%a6) 1451 beqs no_aufl 1451 beqs no_aufl 1452 bsetb #aunfl_bit,FPSR_AEXCEPT(%a6) 1452 bsetb #aunfl_bit,FPSR_AEXCEPT(%a6) 1453 no_aufl: 1453 no_aufl: 1454 clrw NMNEXC(%a6) 1454 clrw NMNEXC(%a6) 1455 bclrb #E1,E_BYTE(%a6) 1455 bclrb #E1,E_BYTE(%a6) 1456 fmovel #0,%FPSR 1456 fmovel #0,%FPSR |clear any cc bits from res_func 1457 | 1457 | 1458 | Return ETEMP to extended format from intern 1458 | Return ETEMP to extended format from internal extended format so 1459 | that gen_except will have a correctly signe 1459 | that gen_except will have a correctly signed value for ovfl/unfl 1460 | handlers. 1460 | handlers. 1461 | 1461 | 1462 bfclr ETEMP_SGN(%a6){#0:#8} 1462 bfclr ETEMP_SGN(%a6){#0:#8} 1463 beqs mvout_con 1463 beqs mvout_con 1464 bsetb #sign_bit,ETEMP_EX(%a6) 1464 bsetb #sign_bit,ETEMP_EX(%a6) 1465 mvout_con: 1465 mvout_con: 1466 rts 1466 rts 1467 | 1467 | 1468 | This exit is for move-out to int register. 1468 | This exit is for move-out to int register. The aunfl bit is 1469 | not set in any case for this move. 1469 | not set in any case for this move. 1470 | 1470 | 1471 mvouti_end: 1471 mvouti_end: 1472 clrw NMNEXC(%a6) 1472 clrw NMNEXC(%a6) 1473 bclrb #E1,E_BYTE(%a6) 1473 bclrb #E1,E_BYTE(%a6) 1474 fmovel #0,%FPSR 1474 fmovel #0,%FPSR |clear any cc bits from res_func 1475 | 1475 | 1476 | Return ETEMP to extended format from intern 1476 | Return ETEMP to extended format from internal extended format so 1477 | that gen_except will have a correctly signe 1477 | that gen_except will have a correctly signed value for ovfl/unfl 1478 | handlers. 1478 | handlers. 1479 | 1479 | 1480 bfclr ETEMP_SGN(%a6){#0:#8} 1480 bfclr ETEMP_SGN(%a6){#0:#8} 1481 beqs mvouti_con 1481 beqs mvouti_con 1482 bsetb #sign_bit,ETEMP_EX(%a6) 1482 bsetb #sign_bit,ETEMP_EX(%a6) 1483 mvouti_con: 1483 mvouti_con: 1484 rts 1484 rts 1485 | 1485 | 1486 | li is used to handle a long integer source 1486 | li is used to handle a long integer source specifier 1487 | 1487 | 1488 1488 1489 li: 1489 li: 1490 moveql #4,%d0 |set byte cou 1490 moveql #4,%d0 |set byte count 1491 1491 1492 btstb #7,STAG(%a6) |check for ex 1492 btstb #7,STAG(%a6) |check for extended denorm 1493 bne int_dnrm |if so, branc 1493 bne int_dnrm |if so, branch 1494 1494 1495 fmovemx ETEMP(%a6),%fp0-%fp0 1495 fmovemx ETEMP(%a6),%fp0-%fp0 1496 fcmpd #0x41dfffffffc00000,%fp0 1496 fcmpd #0x41dfffffffc00000,%fp0 1497 | 41dfffffffc00000 in dbl prec = 401d0000ffff 1497 | 41dfffffffc00000 in dbl prec = 401d0000fffffffe00000000 in ext prec 1498 fbge lo_plrg 1498 fbge lo_plrg 1499 fcmpd #0xc1e0000000000000,%fp0 1499 fcmpd #0xc1e0000000000000,%fp0 1500 | c1e0000000000000 in dbl prec = c01e00008000 1500 | c1e0000000000000 in dbl prec = c01e00008000000000000000 in ext prec 1501 fble lo_nlrg 1501 fble lo_nlrg 1502 | 1502 | 1503 | at this point, the answer is between the la 1503 | at this point, the answer is between the largest pos and neg values 1504 | 1504 | 1505 movel USER_FPCR(%a6),%d1 |use 1505 movel USER_FPCR(%a6),%d1 |use user's rounding mode 1506 andil #0x30,%d1 1506 andil #0x30,%d1 1507 fmovel %d1,%fpcr 1507 fmovel %d1,%fpcr 1508 fmovel %fp0,L_SCR1(%a6) |let 1508 fmovel %fp0,L_SCR1(%a6) |let the 040 perform conversion 1509 fmovel %fpsr,%d1 1509 fmovel %fpsr,%d1 1510 orl %d1,USER_FPSR(%a6) |capt 1510 orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set 1511 bra int_wrt 1511 bra int_wrt 1512 1512 1513 1513 1514 lo_plrg: 1514 lo_plrg: 1515 movel #0x7fffffff,L_SCR1(%a6) |answ 1515 movel #0x7fffffff,L_SCR1(%a6) |answer is largest positive int 1516 fbeq int_wrt |exac 1516 fbeq int_wrt |exact answer 1517 fcmpd #0x41dfffffffe00000,%fp0 1517 fcmpd #0x41dfffffffe00000,%fp0 1518 | 41dfffffffe00000 in dbl prec = 401d0000ffff 1518 | 41dfffffffe00000 in dbl prec = 401d0000ffffffff00000000 in ext prec 1519 fbge int_operr |set 1519 fbge int_operr |set operr 1520 bra int_inx |set 1520 bra int_inx |set inexact 1521 1521 1522 lo_nlrg: 1522 lo_nlrg: 1523 movel #0x80000000,L_SCR1(%a6) 1523 movel #0x80000000,L_SCR1(%a6) 1524 fbeq int_wrt |exac 1524 fbeq int_wrt |exact answer 1525 fcmpd #0xc1e0000000100000,%fp0 1525 fcmpd #0xc1e0000000100000,%fp0 1526 | c1e0000000100000 in dbl prec = c01e00008000 1526 | c1e0000000100000 in dbl prec = c01e00008000000080000000 in ext prec 1527 fblt int_operr |set 1527 fblt int_operr |set operr 1528 bra int_inx |set 1528 bra int_inx |set inexact 1529 1529 1530 | 1530 | 1531 | wi is used to handle a word integer source 1531 | wi is used to handle a word integer source specifier 1532 | 1532 | 1533 1533 1534 wi: 1534 wi: 1535 moveql #2,%d0 |set byte cou 1535 moveql #2,%d0 |set byte count 1536 1536 1537 btstb #7,STAG(%a6) |check for ex 1537 btstb #7,STAG(%a6) |check for extended denorm 1538 bne int_dnrm |branch if so 1538 bne int_dnrm |branch if so 1539 1539 1540 fmovemx ETEMP(%a6),%fp0-%fp0 1540 fmovemx ETEMP(%a6),%fp0-%fp0 1541 fcmps #0x46fffe00,%fp0 1541 fcmps #0x46fffe00,%fp0 1542 | 46fffe00 in sgl prec = 400d0000fffe00000000 1542 | 46fffe00 in sgl prec = 400d0000fffe000000000000 in ext prec 1543 fbge wo_plrg 1543 fbge wo_plrg 1544 fcmps #0xc7000000,%fp0 1544 fcmps #0xc7000000,%fp0 1545 | c7000000 in sgl prec = c00e0000800000000000 1545 | c7000000 in sgl prec = c00e00008000000000000000 in ext prec 1546 fble wo_nlrg 1546 fble wo_nlrg 1547 1547 1548 | 1548 | 1549 | at this point, the answer is between the la 1549 | at this point, the answer is between the largest pos and neg values 1550 | 1550 | 1551 movel USER_FPCR(%a6),%d1 |use 1551 movel USER_FPCR(%a6),%d1 |use user's rounding mode 1552 andil #0x30,%d1 1552 andil #0x30,%d1 1553 fmovel %d1,%fpcr 1553 fmovel %d1,%fpcr 1554 fmovew %fp0,L_SCR1(%a6) |let 1554 fmovew %fp0,L_SCR1(%a6) |let the 040 perform conversion 1555 fmovel %fpsr,%d1 1555 fmovel %fpsr,%d1 1556 orl %d1,USER_FPSR(%a6) |capt 1556 orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set 1557 bra int_wrt 1557 bra int_wrt 1558 1558 1559 wo_plrg: 1559 wo_plrg: 1560 movew #0x7fff,L_SCR1(%a6) |answ 1560 movew #0x7fff,L_SCR1(%a6) |answer is largest positive int 1561 fbeq int_wrt |exac 1561 fbeq int_wrt |exact answer 1562 fcmps #0x46ffff00,%fp0 1562 fcmps #0x46ffff00,%fp0 1563 | 46ffff00 in sgl prec = 400d0000ffff00000000 1563 | 46ffff00 in sgl prec = 400d0000ffff000000000000 in ext prec 1564 fbge int_operr |set 1564 fbge int_operr |set operr 1565 bra int_inx |set 1565 bra int_inx |set inexact 1566 1566 1567 wo_nlrg: 1567 wo_nlrg: 1568 movew #0x8000,L_SCR1(%a6) 1568 movew #0x8000,L_SCR1(%a6) 1569 fbeq int_wrt |exac 1569 fbeq int_wrt |exact answer 1570 fcmps #0xc7000080,%fp0 1570 fcmps #0xc7000080,%fp0 1571 | c7000080 in sgl prec = c00e0000800080000000 1571 | c7000080 in sgl prec = c00e00008000800000000000 in ext prec 1572 fblt int_operr |set 1572 fblt int_operr |set operr 1573 bra int_inx |set 1573 bra int_inx |set inexact 1574 1574 1575 | 1575 | 1576 | bi is used to handle a byte integer source 1576 | bi is used to handle a byte integer source specifier 1577 | 1577 | 1578 1578 1579 bi: 1579 bi: 1580 moveql #1,%d0 |set byte cou 1580 moveql #1,%d0 |set byte count 1581 1581 1582 btstb #7,STAG(%a6) |check for ex 1582 btstb #7,STAG(%a6) |check for extended denorm 1583 bne int_dnrm |branch if so 1583 bne int_dnrm |branch if so 1584 1584 1585 fmovemx ETEMP(%a6),%fp0-%fp0 1585 fmovemx ETEMP(%a6),%fp0-%fp0 1586 fcmps #0x42fe0000,%fp0 1586 fcmps #0x42fe0000,%fp0 1587 | 42fe0000 in sgl prec = 40050000fe0000000000 1587 | 42fe0000 in sgl prec = 40050000fe00000000000000 in ext prec 1588 fbge by_plrg 1588 fbge by_plrg 1589 fcmps #0xc3000000,%fp0 1589 fcmps #0xc3000000,%fp0 1590 | c3000000 in sgl prec = c0060000800000000000 1590 | c3000000 in sgl prec = c00600008000000000000000 in ext prec 1591 fble by_nlrg 1591 fble by_nlrg 1592 1592 1593 | 1593 | 1594 | at this point, the answer is between the la 1594 | at this point, the answer is between the largest pos and neg values 1595 | 1595 | 1596 movel USER_FPCR(%a6),%d1 |use 1596 movel USER_FPCR(%a6),%d1 |use user's rounding mode 1597 andil #0x30,%d1 1597 andil #0x30,%d1 1598 fmovel %d1,%fpcr 1598 fmovel %d1,%fpcr 1599 fmoveb %fp0,L_SCR1(%a6) |let 1599 fmoveb %fp0,L_SCR1(%a6) |let the 040 perform conversion 1600 fmovel %fpsr,%d1 1600 fmovel %fpsr,%d1 1601 orl %d1,USER_FPSR(%a6) |capt 1601 orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set 1602 bra int_wrt 1602 bra int_wrt 1603 1603 1604 by_plrg: 1604 by_plrg: 1605 moveb #0x7f,L_SCR1(%a6) 1605 moveb #0x7f,L_SCR1(%a6) |answer is largest positive int 1606 fbeq int_wrt |exac 1606 fbeq int_wrt |exact answer 1607 fcmps #0x42ff0000,%fp0 1607 fcmps #0x42ff0000,%fp0 1608 | 42ff0000 in sgl prec = 40050000ff0000000000 1608 | 42ff0000 in sgl prec = 40050000ff00000000000000 in ext prec 1609 fbge int_operr |set 1609 fbge int_operr |set operr 1610 bra int_inx |set 1610 bra int_inx |set inexact 1611 1611 1612 by_nlrg: 1612 by_nlrg: 1613 moveb #0x80,L_SCR1(%a6) 1613 moveb #0x80,L_SCR1(%a6) 1614 fbeq int_wrt |exac 1614 fbeq int_wrt |exact answer 1615 fcmps #0xc3008000,%fp0 1615 fcmps #0xc3008000,%fp0 1616 | c3008000 in sgl prec = c0060000808000000000 1616 | c3008000 in sgl prec = c00600008080000000000000 in ext prec 1617 fblt int_operr |set 1617 fblt int_operr |set operr 1618 bra int_inx |set 1618 bra int_inx |set inexact 1619 1619 1620 | 1620 | 1621 | Common integer routines 1621 | Common integer routines 1622 | 1622 | 1623 | int_drnrm---account for possible nonzero re 1623 | int_drnrm---account for possible nonzero result for round up with positive 1624 | operand and round down for negative answer. 1624 | operand and round down for negative answer. In the first case (result = 1) 1625 | byte-width (store in d0) of result must be 1625 | byte-width (store in d0) of result must be honored. In the second case, 1626 | -1 in L_SCR1(a6) will cover all contingenci 1626 | -1 in L_SCR1(a6) will cover all contingencies (FMOVE.B/W/L out). 1627 1627 1628 int_dnrm: 1628 int_dnrm: 1629 movel #0,L_SCR1(%a6) | initialize 1629 movel #0,L_SCR1(%a6) | initialize result to 0 1630 bfextu FPCR_MODE(%a6){#2:#2},%d1 1630 bfextu FPCR_MODE(%a6){#2:#2},%d1 | d1 is the rounding mode 1631 cmpb #2,%d1 1631 cmpb #2,%d1 1632 bmis int_inx | if RN or RZ 1632 bmis int_inx | if RN or RZ, done 1633 bnes int_rp | if RP, cont 1633 bnes int_rp | if RP, continue below 1634 tstw ETEMP(%a6) | RM: store - 1634 tstw ETEMP(%a6) | RM: store -1 in L_SCR1 if src is negative 1635 bpls int_inx | otherwise r 1635 bpls int_inx | otherwise result is 0 1636 movel #-1,L_SCR1(%a6) 1636 movel #-1,L_SCR1(%a6) 1637 bras int_inx 1637 bras int_inx 1638 int_rp: 1638 int_rp: 1639 tstw ETEMP(%a6) | RP: store + 1639 tstw ETEMP(%a6) | RP: store +1 of proper width in L_SCR1 if 1640 | ; source is g 1640 | ; source is greater than 0 1641 bmis int_inx | otherwise, 1641 bmis int_inx | otherwise, result is 0 1642 lea L_SCR1(%a6),%a1 | a1 is addre 1642 lea L_SCR1(%a6),%a1 | a1 is address of L_SCR1 1643 addal %d0,%a1 | offset by d 1643 addal %d0,%a1 | offset by destination width -1 1644 subal #1,%a1 1644 subal #1,%a1 1645 bsetb #0,(%a1) | set 1645 bsetb #0,(%a1) | set low bit at a1 address 1646 int_inx: 1646 int_inx: 1647 oril #inx2a_mask,USER_FPSR(%a6) 1647 oril #inx2a_mask,USER_FPSR(%a6) 1648 bras int_wrt 1648 bras int_wrt 1649 int_operr: 1649 int_operr: 1650 fmovemx %fp0-%fp0,FPTEMP(%a6) |FPTE 1650 fmovemx %fp0-%fp0,FPTEMP(%a6) |FPTEMP must contain the extended 1651 | ;precision so 1651 | ;precision source that needs to be 1652 | ;converted to 1652 | ;converted to integer this is required 1653 | ;if the operr 1653 | ;if the operr exception is enabled. 1654 | ;set operr/ai 1654 | ;set operr/aiop (no inex2 on int ovfl) 1655 1655 1656 oril #opaop_mask,USER_FPSR(%a6) 1656 oril #opaop_mask,USER_FPSR(%a6) 1657 | ;fall through 1657 | ;fall through to perform int_wrt 1658 int_wrt: 1658 int_wrt: 1659 movel EXC_EA(%a6),%a1 |load destina 1659 movel EXC_EA(%a6),%a1 |load destination address 1660 tstl %a1 |check to see 1660 tstl %a1 |check to see if it is a dest register 1661 beqs wrt_dn |write data r 1661 beqs wrt_dn |write data register 1662 lea L_SCR1(%a6),%a0 |point to sup 1662 lea L_SCR1(%a6),%a0 |point to supervisor source address 1663 bsrl mem_write 1663 bsrl mem_write 1664 bra mvouti_end 1664 bra mvouti_end 1665 1665 1666 wrt_dn: 1666 wrt_dn: 1667 movel %d0,-(%sp) |d0 currently 1667 movel %d0,-(%sp) |d0 currently contains the size to write 1668 bsrl get_fline |get_fline re 1668 bsrl get_fline |get_fline returns Dn in d0 1669 andiw #0x7,%d0 |isol 1669 andiw #0x7,%d0 |isolate register 1670 movel (%sp)+,%d1 |get size 1670 movel (%sp)+,%d1 |get size 1671 cmpil #4,%d1 |most frequen 1671 cmpil #4,%d1 |most frequent case 1672 beqs sz_long 1672 beqs sz_long 1673 cmpil #2,%d1 1673 cmpil #2,%d1 1674 bnes sz_con 1674 bnes sz_con 1675 orl #8,%d0 |add 'word' s 1675 orl #8,%d0 |add 'word' size to register# 1676 bras sz_con 1676 bras sz_con 1677 sz_long: 1677 sz_long: 1678 orl #0x10,%d0 |add 1678 orl #0x10,%d0 |add 'long' size to register# 1679 sz_con: 1679 sz_con: 1680 movel %d0,%d1 |reg_dest exp 1680 movel %d0,%d1 |reg_dest expects size:reg in d1 1681 bsrl reg_dest |load proper 1681 bsrl reg_dest |load proper data register 1682 bra mvouti_end 1682 bra mvouti_end 1683 xp: 1683 xp: 1684 lea ETEMP(%a6),%a0 1684 lea ETEMP(%a6),%a0 1685 bclrb #sign_bit,LOCAL_EX(%a0) 1685 bclrb #sign_bit,LOCAL_EX(%a0) 1686 sne LOCAL_SGN(%a0) 1686 sne LOCAL_SGN(%a0) 1687 btstb #7,STAG(%a6) |check for ex 1687 btstb #7,STAG(%a6) |check for extended denorm 1688 bne xdnrm 1688 bne xdnrm 1689 clrl %d0 1689 clrl %d0 1690 bras do_fp |do normal ca 1690 bras do_fp |do normal case 1691 sgp: 1691 sgp: 1692 lea ETEMP(%a6),%a0 1692 lea ETEMP(%a6),%a0 1693 bclrb #sign_bit,LOCAL_EX(%a0) 1693 bclrb #sign_bit,LOCAL_EX(%a0) 1694 sne LOCAL_SGN(%a0) 1694 sne LOCAL_SGN(%a0) 1695 btstb #7,STAG(%a6) |check for ex 1695 btstb #7,STAG(%a6) |check for extended denorm 1696 bne sp_catas |branch if so 1696 bne sp_catas |branch if so 1697 movew LOCAL_EX(%a0),%d0 1697 movew LOCAL_EX(%a0),%d0 1698 lea sp_bnds,%a1 1698 lea sp_bnds,%a1 1699 cmpw (%a1),%d0 1699 cmpw (%a1),%d0 1700 blt sp_under 1700 blt sp_under 1701 cmpw 2(%a1),%d0 1701 cmpw 2(%a1),%d0 1702 bgt sp_over 1702 bgt sp_over 1703 movel #1,%d0 |set destinat 1703 movel #1,%d0 |set destination format to single 1704 bras do_fp |do normal ca 1704 bras do_fp |do normal case 1705 dp: 1705 dp: 1706 lea ETEMP(%a6),%a0 1706 lea ETEMP(%a6),%a0 1707 bclrb #sign_bit,LOCAL_EX(%a0) 1707 bclrb #sign_bit,LOCAL_EX(%a0) 1708 sne LOCAL_SGN(%a0) 1708 sne LOCAL_SGN(%a0) 1709 1709 1710 btstb #7,STAG(%a6) |check for ex 1710 btstb #7,STAG(%a6) |check for extended denorm 1711 bne dp_catas |branch if so 1711 bne dp_catas |branch if so 1712 1712 1713 movew LOCAL_EX(%a0),%d0 1713 movew LOCAL_EX(%a0),%d0 1714 lea dp_bnds,%a1 1714 lea dp_bnds,%a1 1715 1715 1716 cmpw (%a1),%d0 1716 cmpw (%a1),%d0 1717 blt dp_under 1717 blt dp_under 1718 cmpw 2(%a1),%d0 1718 cmpw 2(%a1),%d0 1719 bgt dp_over 1719 bgt dp_over 1720 1720 1721 movel #2,%d0 |set destinat 1721 movel #2,%d0 |set destination format to double 1722 | ;fall through 1722 | ;fall through to do_fp 1723 | 1723 | 1724 do_fp: 1724 do_fp: 1725 bfextu FPCR_MODE(%a6){#2:#2},%d1 1725 bfextu FPCR_MODE(%a6){#2:#2},%d1 |rnd mode in d1 1726 swap %d0 |rnd 1726 swap %d0 |rnd prec in upper word 1727 addl %d0,%d1 |d1 h 1727 addl %d0,%d1 |d1 has PREC/MODE info 1728 1728 1729 clrl %d0 |clea 1729 clrl %d0 |clear g,r,s 1730 1730 1731 bsrl round |roun 1731 bsrl round |round 1732 1732 1733 movel %a0,%a1 1733 movel %a0,%a1 1734 movel EXC_EA(%a6),%a0 1734 movel EXC_EA(%a6),%a0 1735 1735 1736 bfextu CMDREG1B(%a6){#3:#3},%d1 1736 bfextu CMDREG1B(%a6){#3:#3},%d1 |extract destination format 1737 | ;at t 1737 | ;at this point only the dest 1738 | ;form 1738 | ;formats sgl, dbl, ext are 1739 | ;poss 1739 | ;possible 1740 cmpb #2,%d1 1740 cmpb #2,%d1 1741 bgts ddbl |doub 1741 bgts ddbl |double=5, extended=2, single=1 1742 bnes dsgl 1742 bnes dsgl 1743 | ;fall 1743 | ;fall through to dext 1744 dext: 1744 dext: 1745 bsrl dest_ext 1745 bsrl dest_ext 1746 bra mvout_end 1746 bra mvout_end 1747 dsgl: 1747 dsgl: 1748 bsrl dest_sgl 1748 bsrl dest_sgl 1749 bra mvout_end 1749 bra mvout_end 1750 ddbl: 1750 ddbl: 1751 bsrl dest_dbl 1751 bsrl dest_dbl 1752 bra mvout_end 1752 bra mvout_end 1753 1753 1754 | 1754 | 1755 | Handle possible denorm or catastrophic unde 1755 | Handle possible denorm or catastrophic underflow cases here 1756 | 1756 | 1757 xdnrm: 1757 xdnrm: 1758 bsr set_xop |initialize W 1758 bsr set_xop |initialize WBTEMP 1759 bsetb #wbtemp15_bit,WB_BYTE(%a6) |s 1759 bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 1760 1760 1761 movel %a0,%a1 1761 movel %a0,%a1 1762 movel EXC_EA(%a6),%a0 |a0 has the d 1762 movel EXC_EA(%a6),%a0 |a0 has the destination pointer 1763 bsrl dest_ext |store to mem 1763 bsrl dest_ext |store to memory 1764 bsetb #unfl_bit,FPSR_EXCEPT(%a6) 1764 bsetb #unfl_bit,FPSR_EXCEPT(%a6) 1765 bra mvout_end 1765 bra mvout_end 1766 1766 1767 sp_under: 1767 sp_under: 1768 bsetb #etemp15_bit,STAG(%a6) 1768 bsetb #etemp15_bit,STAG(%a6) 1769 1769 1770 cmpw 4(%a1),%d0 1770 cmpw 4(%a1),%d0 1771 blts sp_catas |catastrophic 1771 blts sp_catas |catastrophic underflow case 1772 1772 1773 movel #1,%d0 |load in roun 1773 movel #1,%d0 |load in round precision 1774 movel #sgl_thresh,%d1 |load in sing 1774 movel #sgl_thresh,%d1 |load in single denorm threshold 1775 bsrl dpspdnrm |expects d1 t 1775 bsrl dpspdnrm |expects d1 to have the proper 1776 | ;denorm thres 1776 | ;denorm threshold 1777 bsrl dest_sgl |stores value 1777 bsrl dest_sgl |stores value to destination 1778 bsetb #unfl_bit,FPSR_EXCEPT(%a6) 1778 bsetb #unfl_bit,FPSR_EXCEPT(%a6) 1779 bra mvout_end |exit 1779 bra mvout_end |exit 1780 1780 1781 dp_under: 1781 dp_under: 1782 bsetb #etemp15_bit,STAG(%a6) 1782 bsetb #etemp15_bit,STAG(%a6) 1783 1783 1784 cmpw 4(%a1),%d0 1784 cmpw 4(%a1),%d0 1785 blts dp_catas |catastrophic 1785 blts dp_catas |catastrophic underflow case 1786 1786 1787 movel #dbl_thresh,%d1 |load in doub 1787 movel #dbl_thresh,%d1 |load in double precision threshold 1788 movel #2,%d0 1788 movel #2,%d0 1789 bsrl dpspdnrm |expects d1 t 1789 bsrl dpspdnrm |expects d1 to have proper 1790 | ;denorm thres 1790 | ;denorm threshold 1791 | ;expects d0 t 1791 | ;expects d0 to have round precision 1792 bsrl dest_dbl |store value 1792 bsrl dest_dbl |store value to destination 1793 bsetb #unfl_bit,FPSR_EXCEPT(%a6) 1793 bsetb #unfl_bit,FPSR_EXCEPT(%a6) 1794 bra mvout_end |exit 1794 bra mvout_end |exit 1795 1795 1796 | 1796 | 1797 | Handle catastrophic underflow cases here 1797 | Handle catastrophic underflow cases here 1798 | 1798 | 1799 sp_catas: 1799 sp_catas: 1800 | Temp fix for z bit set in unf_sub 1800 | Temp fix for z bit set in unf_sub 1801 movel USER_FPSR(%a6),-(%a7) 1801 movel USER_FPSR(%a6),-(%a7) 1802 1802 1803 movel #1,%d0 |set round pr 1803 movel #1,%d0 |set round precision to sgl 1804 1804 1805 bsrl unf_sub |a0 points to 1805 bsrl unf_sub |a0 points to result 1806 1806 1807 movel (%a7)+,USER_FPSR(%a6) 1807 movel (%a7)+,USER_FPSR(%a6) 1808 1808 1809 movel #1,%d0 1809 movel #1,%d0 1810 subw %d0,LOCAL_EX(%a0) |account fo 1810 subw %d0,LOCAL_EX(%a0) |account for difference between 1811 | ;denorm/norm 1811 | ;denorm/norm bias 1812 1812 1813 movel %a0,%a1 |a1 has the o 1813 movel %a0,%a1 |a1 has the operand input 1814 movel EXC_EA(%a6),%a0 |a0 has the d 1814 movel EXC_EA(%a6),%a0 |a0 has the destination pointer 1815 1815 1816 bsrl dest_sgl |store the re 1816 bsrl dest_sgl |store the result 1817 oril #unfinx_mask,USER_FPSR(%a6) 1817 oril #unfinx_mask,USER_FPSR(%a6) 1818 bra mvout_end 1818 bra mvout_end 1819 1819 1820 dp_catas: 1820 dp_catas: 1821 | Temp fix for z bit set in unf_sub 1821 | Temp fix for z bit set in unf_sub 1822 movel USER_FPSR(%a6),-(%a7) 1822 movel USER_FPSR(%a6),-(%a7) 1823 1823 1824 movel #2,%d0 |set round pr 1824 movel #2,%d0 |set round precision to dbl 1825 bsrl unf_sub |a0 points to 1825 bsrl unf_sub |a0 points to result 1826 1826 1827 movel (%a7)+,USER_FPSR(%a6) 1827 movel (%a7)+,USER_FPSR(%a6) 1828 1828 1829 movel #1,%d0 1829 movel #1,%d0 1830 subw %d0,LOCAL_EX(%a0) |account fo 1830 subw %d0,LOCAL_EX(%a0) |account for difference between 1831 | ;denorm/norm 1831 | ;denorm/norm bias 1832 1832 1833 movel %a0,%a1 |a1 has the o 1833 movel %a0,%a1 |a1 has the operand input 1834 movel EXC_EA(%a6),%a0 |a0 has the d 1834 movel EXC_EA(%a6),%a0 |a0 has the destination pointer 1835 1835 1836 bsrl dest_dbl |store the re 1836 bsrl dest_dbl |store the result 1837 oril #unfinx_mask,USER_FPSR(%a6) 1837 oril #unfinx_mask,USER_FPSR(%a6) 1838 bra mvout_end 1838 bra mvout_end 1839 1839 1840 | 1840 | 1841 | Handle catastrophic overflow cases here 1841 | Handle catastrophic overflow cases here 1842 | 1842 | 1843 sp_over: 1843 sp_over: 1844 | Temp fix for z bit set in unf_sub 1844 | Temp fix for z bit set in unf_sub 1845 movel USER_FPSR(%a6),-(%a7) 1845 movel USER_FPSR(%a6),-(%a7) 1846 1846 1847 movel #1,%d0 1847 movel #1,%d0 1848 leal FP_SCR1(%a6),%a0 |use 1848 leal FP_SCR1(%a6),%a0 |use FP_SCR1 for creating result 1849 movel ETEMP_EX(%a6),(%a0) 1849 movel ETEMP_EX(%a6),(%a0) 1850 movel ETEMP_HI(%a6),4(%a0) 1850 movel ETEMP_HI(%a6),4(%a0) 1851 movel ETEMP_LO(%a6),8(%a0) 1851 movel ETEMP_LO(%a6),8(%a0) 1852 bsrl ovf_res 1852 bsrl ovf_res 1853 1853 1854 movel (%a7)+,USER_FPSR(%a6) 1854 movel (%a7)+,USER_FPSR(%a6) 1855 1855 1856 movel %a0,%a1 1856 movel %a0,%a1 1857 movel EXC_EA(%a6),%a0 1857 movel EXC_EA(%a6),%a0 1858 bsrl dest_sgl 1858 bsrl dest_sgl 1859 orl #ovfinx_mask,USER_FPSR(%a6) 1859 orl #ovfinx_mask,USER_FPSR(%a6) 1860 bra mvout_end 1860 bra mvout_end 1861 1861 1862 dp_over: 1862 dp_over: 1863 | Temp fix for z bit set in ovf_res 1863 | Temp fix for z bit set in ovf_res 1864 movel USER_FPSR(%a6),-(%a7) 1864 movel USER_FPSR(%a6),-(%a7) 1865 1865 1866 movel #2,%d0 1866 movel #2,%d0 1867 leal FP_SCR1(%a6),%a0 |use 1867 leal FP_SCR1(%a6),%a0 |use FP_SCR1 for creating result 1868 movel ETEMP_EX(%a6),(%a0) 1868 movel ETEMP_EX(%a6),(%a0) 1869 movel ETEMP_HI(%a6),4(%a0) 1869 movel ETEMP_HI(%a6),4(%a0) 1870 movel ETEMP_LO(%a6),8(%a0) 1870 movel ETEMP_LO(%a6),8(%a0) 1871 bsrl ovf_res 1871 bsrl ovf_res 1872 1872 1873 movel (%a7)+,USER_FPSR(%a6) 1873 movel (%a7)+,USER_FPSR(%a6) 1874 1874 1875 movel %a0,%a1 1875 movel %a0,%a1 1876 movel EXC_EA(%a6),%a0 1876 movel EXC_EA(%a6),%a0 1877 bsrl dest_dbl 1877 bsrl dest_dbl 1878 orl #ovfinx_mask,USER_FPSR(%a6) 1878 orl #ovfinx_mask,USER_FPSR(%a6) 1879 bra mvout_end 1879 bra mvout_end 1880 1880 1881 | 1881 | 1882 | DPSPDNRM 1882 | DPSPDNRM 1883 | 1883 | 1884 | This subroutine takes an extended normalize 1884 | This subroutine takes an extended normalized number and denormalizes 1885 | it to the given round precision. This subro 1885 | it to the given round precision. This subroutine also decrements 1886 | the input operand's exponent by 1 to accoun 1886 | the input operand's exponent by 1 to account for the fact that 1887 | dest_sgl or dest_dbl expects a normalized n 1887 | dest_sgl or dest_dbl expects a normalized number's bias. 1888 | 1888 | 1889 | Input: a0 points to a normalized number in 1889 | Input: a0 points to a normalized number in internal extended format 1890 | d0 is the round precision (=1 for s 1890 | d0 is the round precision (=1 for sgl; =2 for dbl) 1891 | d1 is the single precision or doubl 1891 | d1 is the single precision or double precision 1892 | denorm threshold 1892 | denorm threshold 1893 | 1893 | 1894 | Output: (In the format for dest_sgl or dest 1894 | Output: (In the format for dest_sgl or dest_dbl) 1895 | a0 points to the destination 1895 | a0 points to the destination 1896 | a1 points to the operand 1896 | a1 points to the operand 1897 | 1897 | 1898 | Exceptions: Reports inexact 2 exception by 1898 | Exceptions: Reports inexact 2 exception by setting USER_FPSR bits 1899 | 1899 | 1900 dpspdnrm: 1900 dpspdnrm: 1901 movel %d0,-(%a7) |save round p 1901 movel %d0,-(%a7) |save round precision 1902 clrl %d0 |clear initia 1902 clrl %d0 |clear initial g,r,s 1903 bsrl dnrm_lp |careful with 1903 bsrl dnrm_lp |careful with d0, it's needed by round 1904 1904 1905 bfextu FPCR_MODE(%a6){#2:#2},%d1 |ge 1905 bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rounding mode 1906 swap %d1 1906 swap %d1 1907 movew 2(%a7),%d1 |set rounding 1907 movew 2(%a7),%d1 |set rounding precision 1908 swap %d1 |at this poin 1908 swap %d1 |at this point d1 has PREC/MODE info 1909 bsrl round |round result 1909 bsrl round |round result, sets the inex bit in 1910 | ;USER_FPSR if 1910 | ;USER_FPSR if needed 1911 1911 1912 movew #1,%d0 1912 movew #1,%d0 1913 subw %d0,LOCAL_EX(%a0) |account fo 1913 subw %d0,LOCAL_EX(%a0) |account for difference in denorm 1914 | ;vs norm bias 1914 | ;vs norm bias 1915 1915 1916 movel %a0,%a1 |a1 has the o 1916 movel %a0,%a1 |a1 has the operand input 1917 movel EXC_EA(%a6),%a0 |a0 has the d 1917 movel EXC_EA(%a6),%a0 |a0 has the destination pointer 1918 addw #4,%a7 |pop stack 1918 addw #4,%a7 |pop stack 1919 rts 1919 rts 1920 | 1920 | 1921 | SET_XOP initialized WBTEMP with the value p 1921 | SET_XOP initialized WBTEMP with the value pointed to by a0 1922 | input: a0 points to input operand in the in 1922 | input: a0 points to input operand in the internal extended format 1923 | 1923 | 1924 set_xop: 1924 set_xop: 1925 movel LOCAL_EX(%a0),WBTEMP_EX(%a6) 1925 movel LOCAL_EX(%a0),WBTEMP_EX(%a6) 1926 movel LOCAL_HI(%a0),WBTEMP_HI(%a6) 1926 movel LOCAL_HI(%a0),WBTEMP_HI(%a6) 1927 movel LOCAL_LO(%a0),WBTEMP_LO(%a6) 1927 movel LOCAL_LO(%a0),WBTEMP_LO(%a6) 1928 bfclr WBTEMP_SGN(%a6){#0:#8} 1928 bfclr WBTEMP_SGN(%a6){#0:#8} 1929 beqs sxop 1929 beqs sxop 1930 bsetb #sign_bit,WBTEMP_EX(%a6) 1930 bsetb #sign_bit,WBTEMP_EX(%a6) 1931 sxop: 1931 sxop: 1932 bfclr STAG(%a6){#5:#4} |clea 1932 bfclr STAG(%a6){#5:#4} |clear wbtm66,wbtm1,wbtm0,sbit 1933 rts 1933 rts 1934 | 1934 | 1935 | P_MOVE 1935 | P_MOVE 1936 | 1936 | 1937 p_movet: 1937 p_movet: 1938 .long p_move 1938 .long p_move 1939 .long p_movez 1939 .long p_movez 1940 .long p_movei 1940 .long p_movei 1941 .long p_moven 1941 .long p_moven 1942 .long p_move 1942 .long p_move 1943 p_regd: 1943 p_regd: 1944 .long p_dyd0 1944 .long p_dyd0 1945 .long p_dyd1 1945 .long p_dyd1 1946 .long p_dyd2 1946 .long p_dyd2 1947 .long p_dyd3 1947 .long p_dyd3 1948 .long p_dyd4 1948 .long p_dyd4 1949 .long p_dyd5 1949 .long p_dyd5 1950 .long p_dyd6 1950 .long p_dyd6 1951 .long p_dyd7 1951 .long p_dyd7 1952 1952 1953 pack_out: 1953 pack_out: 1954 leal p_movet,%a0 |load jmp tab 1954 leal p_movet,%a0 |load jmp table address 1955 movew STAG(%a6),%d0 |get source t 1955 movew STAG(%a6),%d0 |get source tag 1956 bfextu %d0{#16:#3},%d0 |isolate sour 1956 bfextu %d0{#16:#3},%d0 |isolate source bits 1957 movel (%a0,%d0.w*4),%a0 |load 1957 movel (%a0,%d0.w*4),%a0 |load a0 with routine label for tag 1958 jmp (%a0) |go to the ro 1958 jmp (%a0) |go to the routine 1959 1959 1960 p_write: 1960 p_write: 1961 movel #0x0c,%d0 |get byte cou 1961 movel #0x0c,%d0 |get byte count 1962 movel EXC_EA(%a6),%a1 |get the dest 1962 movel EXC_EA(%a6),%a1 |get the destination address 1963 bsr mem_write |write the us 1963 bsr mem_write |write the user's destination 1964 moveb #0,CU_SAVEPC(%a6) |set the cu 1964 moveb #0,CU_SAVEPC(%a6) |set the cu save pc to all 0's 1965 1965 1966 | 1966 | 1967 | Also note that the dtag must be set to norm 1967 | Also note that the dtag must be set to norm here - this is because 1968 | the 040 uses the dtag to execute the correc 1968 | the 040 uses the dtag to execute the correct microcode. 1969 | 1969 | 1970 bfclr DTAG(%a6){#0:#3} |set dtag 1970 bfclr DTAG(%a6){#0:#3} |set dtag to norm 1971 1971 1972 rts 1972 rts 1973 1973 1974 | Notes on handling of special case (zero, in 1974 | Notes on handling of special case (zero, inf, and nan) inputs: 1975 | 1. Operr is not signalled if the k-fa 1975 | 1. Operr is not signalled if the k-factor is greater than 18. 1976 | 2. Per the manual, status bits are no 1976 | 2. Per the manual, status bits are not set. 1977 | 1977 | 1978 1978 1979 p_move: 1979 p_move: 1980 movew CMDREG1B(%a6),%d0 1980 movew CMDREG1B(%a6),%d0 1981 btstl #kfact_bit,%d0 |test for dyn 1981 btstl #kfact_bit,%d0 |test for dynamic k-factor 1982 beqs statick |if clear, k- 1982 beqs statick |if clear, k-factor is static 1983 dynamick: 1983 dynamick: 1984 bfextu %d0{#25:#3},%d0 |isolate regi 1984 bfextu %d0{#25:#3},%d0 |isolate register for dynamic k-factor 1985 lea p_regd,%a0 1985 lea p_regd,%a0 1986 movel %a0@(%d0:l:4),%a0 1986 movel %a0@(%d0:l:4),%a0 1987 jmp (%a0) 1987 jmp (%a0) 1988 statick: 1988 statick: 1989 andiw #0x007f,%d0 |get k-factor 1989 andiw #0x007f,%d0 |get k-factor 1990 bfexts %d0{#25:#7},%d0 |sign extend 1990 bfexts %d0{#25:#7},%d0 |sign extend d0 for bindec 1991 leal ETEMP(%a6),%a0 |a0 will poin 1991 leal ETEMP(%a6),%a0 |a0 will point to the packed decimal 1992 bsrl bindec |perform the 1992 bsrl bindec |perform the convert; data at a6 1993 leal FP_SCR1(%a6),%a0 |load 1993 leal FP_SCR1(%a6),%a0 |load a0 with result address 1994 bral p_write 1994 bral p_write 1995 p_movez: 1995 p_movez: 1996 leal ETEMP(%a6),%a0 |a0 will poin 1996 leal ETEMP(%a6),%a0 |a0 will point to the packed decimal 1997 clrw 2(%a0) |clear lower 1997 clrw 2(%a0) |clear lower word of exp 1998 clrl 4(%a0) |load second 1998 clrl 4(%a0) |load second lword of ZERO 1999 clrl 8(%a0) |load third l 1999 clrl 8(%a0) |load third lword of ZERO 2000 bra p_write |go write res 2000 bra p_write |go write results 2001 p_movei: 2001 p_movei: 2002 fmovel #0,%FPSR |clea 2002 fmovel #0,%FPSR |clear aiop 2003 leal ETEMP(%a6),%a0 |a0 will poin 2003 leal ETEMP(%a6),%a0 |a0 will point to the packed decimal 2004 clrw 2(%a0) |clear lower 2004 clrw 2(%a0) |clear lower word of exp 2005 bra p_write |go write the 2005 bra p_write |go write the result 2006 p_moven: 2006 p_moven: 2007 leal ETEMP(%a6),%a0 |a0 will poin 2007 leal ETEMP(%a6),%a0 |a0 will point to the packed decimal 2008 clrw 2(%a0) |clear lower 2008 clrw 2(%a0) |clear lower word of exp 2009 bra p_write |go write the 2009 bra p_write |go write the result 2010 2010 2011 | 2011 | 2012 | Routines to read the dynamic k-factor from 2012 | Routines to read the dynamic k-factor from Dn. 2013 | 2013 | 2014 p_dyd0: 2014 p_dyd0: 2015 movel USER_D0(%a6),%d0 2015 movel USER_D0(%a6),%d0 2016 bras statick 2016 bras statick 2017 p_dyd1: 2017 p_dyd1: 2018 movel USER_D1(%a6),%d0 2018 movel USER_D1(%a6),%d0 2019 bras statick 2019 bras statick 2020 p_dyd2: 2020 p_dyd2: 2021 movel %d2,%d0 2021 movel %d2,%d0 2022 bras statick 2022 bras statick 2023 p_dyd3: 2023 p_dyd3: 2024 movel %d3,%d0 2024 movel %d3,%d0 2025 bras statick 2025 bras statick 2026 p_dyd4: 2026 p_dyd4: 2027 movel %d4,%d0 2027 movel %d4,%d0 2028 bras statick 2028 bras statick 2029 p_dyd5: 2029 p_dyd5: 2030 movel %d5,%d0 2030 movel %d5,%d0 2031 bras statick 2031 bras statick 2032 p_dyd6: 2032 p_dyd6: 2033 movel %d6,%d0 2033 movel %d6,%d0 2034 bra statick 2034 bra statick 2035 p_dyd7: 2035 p_dyd7: 2036 movel %d7,%d0 2036 movel %d7,%d0 2037 bra statick 2037 bra statick 2038 2038 2039 |end 2039 |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.