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 19KERNEL_EX: |idnt 2,1 | Motorola 040 Floating Point Software Package 20 21 |section 8 22 23#include "fpsp.h" 24 25mns_inf: .long 0xffff0000,0x00000000,0x00000000 26pls_inf: .long 0x7fff0000,0x00000000,0x00000000 27nan: .long 0x7fff0000,0xffffffff,0xffffffff 28huge: .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| 67t_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 73t_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 83m_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 87p_inf: 88 fmovemx pls_inf,%fp0-%fp0 |load +inf 89set_fpsr: 90 orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ 91 rts 92| 93| dz enabled 94| 95dz_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 99dz_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| 116t_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 124op_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| 138t_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) 145unfl_signok: 146 leal FP_SCR1(%a6),%a0 147 orl #unfinx_mask,USER_FPSR(%a6) 148| ;set UNFL, INEX2, AUNFL, AINEX 149unfl_con: 150 btstb #unfl_bit,FPCR_ENABLE(%a6) 151 beqs unfl_dis 152 153unfl_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 160unfl_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 175unfl_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| 186t_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 201t_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 208t_dbl: 209 movel ETEMP_LO(%a6),%d0 210 andil #0x7ff,%d0 |look at only lower 11 bits 211 beq t_work 212t_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| 220t_ovfl: 221 orl #ovfinx_mask,USER_FPSR(%a6) 222t_work: 223 btstb #ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled 224 beqs ovf_dis 225 226ovf_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| 242ovf_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 249ovf_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| 259t_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| 271t_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) 276no_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| 286dst_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 290dst_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 306no_snan: 307 rts 308 309dst_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 318dst_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| 332src_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 336src_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 343src_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 353src_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| 364t_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| 372t_resdnrm: 373 orl #unfl_mask,USER_FPSR(%a6) 374 375xdnrm_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| 385xdnrm_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 400xdnrm_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) 405xdep: 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 411xdnrm_dis: 412 bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision 413 bnes not_ext |if not round extended, store 414| ;IEEE defaults 415is_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 423not_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) 431xdnrm_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 441t_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) 465ck_src_den: 466 btstb #7,STAG(%a2) 467 beqs end_avun 468src_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) 479den_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) 486end_avun: 487 frestore (%a7)+ 488 unlk %a2 489 rts 490idle_end: 491 addl #4,%a7 492 unlk %a2 493 rts 494 |end 495