1 | 2 | kernel_ex.sa 3.3 12/19/90 3 | 4 | This file contains routines to force exception status in the 5 | fpu for exceptional cases detected or reported within the 6 | transcendental functions. Typically, the t_xx routine will 7 | set the appropriate bits in the USER_FPSR word on the stack. 8 | The bits are tested in gen_except.sa to determine if an exceptional 9 | situation needs to be created on return from the FPSP. 10 | 11 12 | Copyright (C) Motorola, Inc. 1990 13 | All Rights Reserved 14 | 15 | THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 16 | The copyright notice above does not evidence any 17 | actual or intended publication of such source code. 18 19 KERNEL_EX: |idnt 2,1 | Motorola 040 Floating Point Software Package 20 21 |section 8 22 23 .include "fpsp.h" 24 25 mns_inf: .long 0xffff0000,0x00000000,0x00000000 26 pls_inf: .long 0x7fff0000,0x00000000,0x00000000 27 nan: .long 0x7fff0000,0xffffffff,0xffffffff 28 huge: .long 0x7ffe0000,0xffffffff,0xffffffff 29 30 |xref ovf_r_k 31 |xref unf_sub 32 |xref nrm_set 33 34 .global t_dz 35 .global t_dz2 36 .global t_operr 37 .global t_unfl 38 .global t_ovfl 39 .global t_ovfl2 40 .global t_inx2 41 .global t_frcinx 42 .global t_extdnrm 43 .global t_resdnrm 44 .global dst_nan 45 .global src_nan 46 | 47 | DZ exception 48 | 49 | 50 | if dz trap disabled 51 | store properly signed inf (use sign of etemp) into fp0 52 | set FPSR exception status dz bit, condition code 53 | inf bit, and accrued dz bit 54 | return 55 | frestore the frame into the machine (done by unimp_hd) 56 | 57 | else dz trap enabled 58 | set exception status bit & accrued bits in FPSR 59 | set flag to disable sto_res from corrupting fp register 60 | return 61 | frestore the frame into the machine (done by unimp_hd) 62 | 63 | t_dz2 is used by monadic functions such as flogn (from do_func). 64 | t_dz is used by monadic functions such as satanh (from the 65 | transcendental function). 66 | 67 t_dz2: 68 bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 69 fmovel #0,%FPSR |clr status bits (Z set) 70 btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled 71 bnes dz_ena_end 72 bras m_inf |flogx always returns -inf 73 t_dz: 74 fmovel #0,%FPSR |clr status bits (Z set) 75 btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled 76 bnes dz_ena 77 | 78 | dz disabled 79 | 80 btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos 81 beqs p_inf |branch if pos sign 82 83 m_inf: 84 fmovemx mns_inf,%fp0-%fp0 |load -inf 85 bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 86 bras set_fpsr 87 p_inf: 88 fmovemx pls_inf,%fp0-%fp0 |load +inf 89 set_fpsr: 90 orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ 91 rts 92 | 93 | dz enabled 94 | 95 dz_ena: 96 btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos 97 beqs dz_ena_end 98 bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 99 dz_ena_end: 100 orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ 101 st STORE_FLG(%a6) 102 rts 103 | 104 | OPERR exception 105 | 106 | if (operr trap disabled) 107 | set FPSR exception status operr bit, condition code 108 | nan bit; Store default NAN into fp0 109 | frestore the frame into the machine (done by unimp_hd) 110 | 111 | else (operr trap enabled) 112 | set FPSR exception status operr bit, accrued operr bit 113 | set flag to disable sto_res from corrupting fp register 114 | frestore the frame into the machine (done by unimp_hd) 115 | 116 t_operr: 117 orl #opnan_mask,USER_FPSR(%a6) |set NaN, OPERR, AIOP 118 119 btstb #operr_bit,FPCR_ENABLE(%a6) |test FPCR for operr enabled 120 bnes op_ena 121 122 fmovemx nan,%fp0-%fp0 |load default nan 123 rts 124 op_ena: 125 st STORE_FLG(%a6) |do not corrupt destination 126 rts 127 128 | 129 | t_unfl --- UNFL exception 130 | 131 | This entry point is used by all routines requiring unfl, inex2, 132 | aunfl, and ainex to be set on exit. 133 | 134 | On entry, a0 points to the exceptional operand. The final exceptional 135 | operand is built in FP_SCR1 and only the sign from the original operand 136 | is used. 137 | 138 t_unfl: 139 clrl FP_SCR1(%a6) |set exceptional operand to zero 140 clrl FP_SCR1+4(%a6) 141 clrl FP_SCR1+8(%a6) 142 tstb (%a0) |extract sign from caller's exop 143 bpls unfl_signok 144 bset #sign_bit,FP_SCR1(%a6) 145 unfl_signok: 146 leal FP_SCR1(%a6),%a0 147 orl #unfinx_mask,USER_FPSR(%a6) 148 | ;set UNFL, INEX2, AUNFL, AINEX 149 unfl_con: 150 btstb #unfl_bit,FPCR_ENABLE(%a6) 151 beqs unfl_dis 152 153 unfl_ena: 154 bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 155 bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 156 bsetb #sticky_bit,STICKY(%a6) |set sticky bit 157 158 bclrb #E1,E_BYTE(%a6) 159 160 unfl_dis: 161 bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision 162 163 bclrb #sign_bit,LOCAL_EX(%a0) 164 sne LOCAL_SGN(%a0) |convert to internal ext format 165 166 bsr unf_sub |returns IEEE result at a0 167 | ;and sets FPSR_CC accordingly 168 169 bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 170 beqs unfl_fin 171 172 bsetb #sign_bit,LOCAL_EX(%a0) 173 bsetb #sign_bit,FP_SCR1(%a6) |set sign bit of exc operand 174 175 unfl_fin: 176 fmovemx (%a0),%fp0-%fp0 |store result in fp0 177 rts 178 179 180 | 181 | t_ovfl2 --- OVFL exception (without inex2 returned) 182 | 183 | This entry is used by scale to force catastrophic overflow. The 184 | ovfl, aovfl, and ainex bits are set, but not the inex2 bit. 185 | 186 t_ovfl2: 187 orl #ovfl_inx_mask,USER_FPSR(%a6) 188 movel ETEMP(%a6),FP_SCR1(%a6) 189 movel ETEMP_HI(%a6),FP_SCR1+4(%a6) 190 movel ETEMP_LO(%a6),FP_SCR1+8(%a6) 191 | 192 | Check for single or double round precision. If single, check if 193 | the lower 40 bits of ETEMP are zero; if not, set inex2. If double, 194 | check if the lower 21 bits are zero; if not, set inex2. 195 | 196 moveb FPCR_MODE(%a6),%d0 197 andib #0xc0,%d0 198 beq t_work |if extended, finish ovfl processing 199 cmpib #0x40,%d0 |test for single 200 bnes t_dbl 201 t_sgl: 202 tstb ETEMP_LO(%a6) 203 bnes t_setinx2 204 movel ETEMP_HI(%a6),%d0 205 andil #0xff,%d0 |look at only lower 8 bits 206 bnes t_setinx2 207 bra t_work 208 t_dbl: 209 movel ETEMP_LO(%a6),%d0 210 andil #0x7ff,%d0 |look at only lower 11 bits 211 beq t_work 212 t_setinx2: 213 orl #inex2_mask,USER_FPSR(%a6) 214 bras t_work 215 | 216 | t_ovfl --- OVFL exception 217 | 218 |** Note: the exc operand is returned in ETEMP. 219 | 220 t_ovfl: 221 orl #ovfinx_mask,USER_FPSR(%a6) 222 t_work: 223 btstb #ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled 224 beqs ovf_dis 225 226 ovf_ena: 227 clrl FP_SCR1(%a6) |set exceptional operand 228 clrl FP_SCR1+4(%a6) 229 clrl FP_SCR1+8(%a6) 230 231 bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 232 bclrb #wbtemp15_bit,WB_BYTE(%a6) |clear wbtemp15 233 bsetb #sticky_bit,STICKY(%a6) |set sticky bit 234 235 bclrb #E1,E_BYTE(%a6) 236 | ;fall through to disabled case 237 238 | For disabled overflow call 'ovf_r_k'. This routine loads the 239 | correct result based on the rounding precision, destination 240 | format, rounding mode and sign. 241 | 242 ovf_dis: 243 bsr ovf_r_k |returns unsigned ETEMP_EX 244 | ;and sets FPSR_CC accordingly. 245 bfclr ETEMP_SGN(%a6){#0:#8} |fix sign 246 beqs ovf_pos 247 bsetb #sign_bit,ETEMP_EX(%a6) 248 bsetb #sign_bit,FP_SCR1(%a6) |set exceptional operand sign 249 ovf_pos: 250 fmovemx ETEMP(%a6),%fp0-%fp0 |move the result to fp0 251 rts 252 253 254 | 255 | INEX2 exception 256 | 257 | The inex2 and ainex bits are set. 258 | 259 t_inx2: 260 orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX 261 rts 262 263 | 264 | Force Inex2 265 | 266 | This routine is called by the transcendental routines to force 267 | the inex2 exception bits set in the FPSR. If the underflow bit 268 | is set, but the underflow trap was not taken, the aunfl bit in 269 | the FPSR must be set. 270 | 271 t_frcinx: 272 orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX 273 btstb #unfl_bit,FPSR_EXCEPT(%a6) |test for unfl bit set 274 beqs no_uacc1 |if clear, do not set aunfl 275 bsetb #aunfl_bit,FPSR_AEXCEPT(%a6) 276 no_uacc1: 277 rts 278 279 | 280 | DST_NAN 281 | 282 | Determine if the destination nan is signalling or non-signalling, 283 | and set the FPSR bits accordingly. See the MC68040 User's Manual 284 | section 3.2.2.5 NOT-A-NUMBERS. 285 | 286 dst_nan: 287 btstb #sign_bit,FPTEMP_EX(%a6) |test sign of nan 288 beqs dst_pos |if clr, it was positive 289 bsetb #neg_bit,FPSR_CC(%a6) |set N bit 290 dst_pos: 291 btstb #signan_bit,FPTEMP_HI(%a6) |check if signalling 292 beqs dst_snan |branch if signalling 293 294 fmovel %d1,%fpcr |restore user's rmode/prec 295 fmovex FPTEMP(%a6),%fp0 |return the non-signalling nan 296 | 297 | Check the source nan. If it is signalling, snan will be reported. 298 | 299 moveb STAG(%a6),%d0 300 andib #0xe0,%d0 301 cmpib #0x60,%d0 302 bnes no_snan 303 btstb #signan_bit,ETEMP_HI(%a6) |check if signalling 304 bnes no_snan 305 orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 306 no_snan: 307 rts 308 309 dst_snan: 310 btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled 311 beqs dst_dis |branch if disabled 312 313 orb #nan_tag,DTAG(%a6) |set up dtag for nan 314 st STORE_FLG(%a6) |do not store a result 315 orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 316 rts 317 318 dst_dis: 319 bsetb #signan_bit,FPTEMP_HI(%a6) |set SNAN bit in sop 320 fmovel %d1,%fpcr |restore user's rmode/prec 321 fmovex FPTEMP(%a6),%fp0 |load non-sign. nan 322 orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 323 rts 324 325 | 326 | SRC_NAN 327 | 328 | Determine if the source nan is signalling or non-signalling, 329 | and set the FPSR bits accordingly. See the MC68040 User's Manual 330 | section 3.2.2.5 NOT-A-NUMBERS. 331 | 332 src_nan: 333 btstb #sign_bit,ETEMP_EX(%a6) |test sign of nan 334 beqs src_pos |if clr, it was positive 335 bsetb #neg_bit,FPSR_CC(%a6) |set N bit 336 src_pos: 337 btstb #signan_bit,ETEMP_HI(%a6) |check if signalling 338 beqs src_snan |branch if signalling 339 fmovel %d1,%fpcr |restore user's rmode/prec 340 fmovex ETEMP(%a6),%fp0 |return the non-signalling nan 341 rts 342 343 src_snan: 344 btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled 345 beqs src_dis |branch if disabled 346 bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop 347 orb #norm_tag,DTAG(%a6) |set up dtag for norm 348 orb #nan_tag,STAG(%a6) |set up stag for nan 349 st STORE_FLG(%a6) |do not store a result 350 orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 351 rts 352 353 src_dis: 354 bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop 355 fmovel %d1,%fpcr |restore user's rmode/prec 356 fmovex ETEMP(%a6),%fp0 |load non-sign. nan 357 orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 358 rts 359 360 | 361 | For all functions that have a denormalized input and that f(x)=x, 362 | this is the entry point 363 | 364 t_extdnrm: 365 orl #unfinx_mask,USER_FPSR(%a6) 366 | ;set UNFL, INEX2, AUNFL, AINEX 367 bras xdnrm_con 368 | 369 | Entry point for scale with extended denorm. The function does 370 | not set inex2, aunfl, or ainex. 371 | 372 t_resdnrm: 373 orl #unfl_mask,USER_FPSR(%a6) 374 375 xdnrm_con: 376 btstb #unfl_bit,FPCR_ENABLE(%a6) 377 beqs xdnrm_dis 378 379 | 380 | If exceptions are enabled, the additional task of setting up WBTEMP 381 | is needed so that when the underflow exception handler is entered, 382 | the user perceives no difference between what the 040 provides vs. 383 | what the FPSP provides. 384 | 385 xdnrm_ena: 386 movel %a0,-(%a7) 387 388 movel LOCAL_EX(%a0),FP_SCR1(%a6) 389 movel LOCAL_HI(%a0),FP_SCR1+4(%a6) 390 movel LOCAL_LO(%a0),FP_SCR1+8(%a6) 391 392 lea FP_SCR1(%a6),%a0 393 394 bclrb #sign_bit,LOCAL_EX(%a0) 395 sne LOCAL_SGN(%a0) |convert to internal ext format 396 tstw LOCAL_EX(%a0) |check if input is denorm 397 beqs xdnrm_dn |if so, skip nrm_set 398 bsr nrm_set |normalize the result (exponent 399 | ;will be negative 400 xdnrm_dn: 401 bclrb #sign_bit,LOCAL_EX(%a0) |take off false sign 402 bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format 403 beqs xdep 404 bsetb #sign_bit,LOCAL_EX(%a0) 405 xdep: 406 bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 407 bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 408 bclrb #sticky_bit,STICKY(%a6) |clear sticky bit 409 bclrb #E1,E_BYTE(%a6) 410 movel (%a7)+,%a0 411 xdnrm_dis: 412 bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision 413 bnes not_ext |if not round extended, store 414 | ;IEEE defaults 415 is_ext: 416 btstb #sign_bit,LOCAL_EX(%a0) 417 beqs xdnrm_store 418 419 bsetb #neg_bit,FPSR_CC(%a6) |set N bit in FPSR_CC 420 421 bras xdnrm_store 422 423 not_ext: 424 bclrb #sign_bit,LOCAL_EX(%a0) 425 sne LOCAL_SGN(%a0) |convert to internal ext format 426 bsr unf_sub |returns IEEE result pointed by 427 | ;a0; sets FPSR_CC accordingly 428 bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 429 beqs xdnrm_store 430 bsetb #sign_bit,LOCAL_EX(%a0) 431 xdnrm_store: 432 fmovemx (%a0),%fp0-%fp0 |store result in fp0 433 rts 434 435 | 436 | This subroutine is used for dyadic operations that use an extended 437 | denorm within the kernel. The approach used is to capture the frame, 438 | fix/restore. 439 | 440 .global t_avoid_unsupp 441 t_avoid_unsupp: 442 link %a2,#-LOCAL_SIZE |so that a2 fpsp.h negative 443 | ;offsets may be used 444 fsave -(%a7) 445 tstb 1(%a7) |check if idle, exit if so 446 beq idle_end 447 btstb #E1,E_BYTE(%a2) |check for an E1 exception if 448 | ;enabled, there is an unsupp 449 beq end_avun |else, exit 450 btstb #7,DTAG(%a2) |check for denorm destination 451 beqs src_den |else, must be a source denorm 452 | 453 | handle destination denorm 454 | 455 lea FPTEMP(%a2),%a0 456 btstb #sign_bit,LOCAL_EX(%a0) 457 sne LOCAL_SGN(%a0) |convert to internal ext format 458 bclrb #7,DTAG(%a2) |set DTAG to norm 459 bsr nrm_set |normalize result, exponent 460 | ;will become negative 461 bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign 462 bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 463 beqs ck_src_den |check if source is also denorm 464 bsetb #sign_bit,LOCAL_EX(%a0) 465 ck_src_den: 466 btstb #7,STAG(%a2) 467 beqs end_avun 468 src_den: 469 lea ETEMP(%a2),%a0 470 btstb #sign_bit,LOCAL_EX(%a0) 471 sne LOCAL_SGN(%a0) |convert to internal ext format 472 bclrb #7,STAG(%a2) |set STAG to norm 473 bsr nrm_set |normalize result, exponent 474 | ;will become negative 475 bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign 476 bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 477 beqs den_com 478 bsetb #sign_bit,LOCAL_EX(%a0) 479 den_com: 480 moveb #0xfe,CU_SAVEPC(%a2) |set continue frame 481 clrw NMNEXC(%a2) |clear NMNEXC 482 bclrb #E1,E_BYTE(%a2) 483 | fmove.l %FPSR,FPSR_SHADOW(%a2) 484 | bset.b #SFLAG,E_BYTE(%a2) 485 | bset.b #XFLAG,T_BYTE(%a2) 486 end_avun: 487 frestore (%a7)+ 488 unlk %a2 489 rts 490 idle_end: 491 addl #4,%a7 492 unlk %a2 493 rts 494 |end