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