Annotation of sys/arch/m68k/fpsp/gen_except.sa, Revision 1.1
1.1 ! nbrk 1: * $OpenBSD: gen_except.sa,v 1.2 1996/05/29 21:05:29 niklas Exp $
! 2: * $NetBSD: gen_except.sa,v 1.3 1994/10/26 07:49:07 cgd Exp $
! 3:
! 4: * MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
! 5: * M68000 Hi-Performance Microprocessor Division
! 6: * M68040 Software Package
! 7: *
! 8: * M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
! 9: * All rights reserved.
! 10: *
! 11: * THE SOFTWARE is provided on an "AS IS" basis and without warranty.
! 12: * To the maximum extent permitted by applicable law,
! 13: * MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
! 14: * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
! 15: * PARTICULAR PURPOSE and any warranty against infringement with
! 16: * regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
! 17: * and any accompanying written materials.
! 18: *
! 19: * To the maximum extent permitted by applicable law,
! 20: * IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
! 21: * (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
! 22: * PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
! 23: * OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
! 24: * SOFTWARE. Motorola assumes no responsibility for the maintenance
! 25: * and support of the SOFTWARE.
! 26: *
! 27: * You are hereby granted a copyright license to use, modify, and
! 28: * distribute the SOFTWARE so long as this entire notice is retained
! 29: * without alteration in any modified and/or redistributed versions,
! 30: * and that such modified versions are clearly identified as such.
! 31: * No licenses are granted by implication, estoppel or otherwise
! 32: * under any patents or trademarks of Motorola, Inc.
! 33:
! 34: *
! 35: * gen_except.sa 3.7 1/16/92
! 36: *
! 37: * gen_except --- FPSP routine to detect reportable exceptions
! 38: *
! 39: * This routine compares the exception enable byte of the
! 40: * user_fpcr on the stack with the exception status byte
! 41: * of the user_fpsr.
! 42: *
! 43: * Any routine which may report an exceptions must load
! 44: * the stack frame in memory with the exceptional operand(s).
! 45: *
! 46: * Priority for exceptions is:
! 47: *
! 48: * Highest: bsun
! 49: * snan
! 50: * operr
! 51: * ovfl
! 52: * unfl
! 53: * dz
! 54: * inex2
! 55: * Lowest: inex1
! 56: *
! 57: * Note: The IEEE standard specifies that inex2 is to be
! 58: * reported if ovfl occurs and the ovfl enable bit is not
! 59: * set but the inex2 enable bit is.
! 60: *
! 61:
! 62: GEN_EXCEPT IDNT 2,1 Motorola 040 Floating Point Software Package
! 63:
! 64: section 8
! 65:
! 66: include fpsp.h
! 67:
! 68: xref real_trace
! 69: xref fpsp_done
! 70: xref fpsp_fmt_error
! 71:
! 72: exc_tbl:
! 73: dc.l bsun_exc
! 74: dc.l commonE1
! 75: dc.l commonE1
! 76: dc.l ovfl_unfl
! 77: dc.l ovfl_unfl
! 78: dc.l commonE1
! 79: dc.l commonE3
! 80: dc.l commonE3
! 81: dc.l no_match
! 82:
! 83: xdef gen_except
! 84: gen_except:
! 85: cmpi.b #IDLE_SIZE-4,1(a7) ;test for idle frame
! 86: beq.w do_check ;go handle idle frame
! 87: cmpi.b #UNIMP_40_SIZE-4,1(a7) ;test for orig unimp frame
! 88: beq.b unimp_x ;go handle unimp frame
! 89: cmpi.b #UNIMP_41_SIZE-4,1(a7) ;test for rev unimp frame
! 90: beq.b unimp_x ;go handle unimp frame
! 91: cmpi.b #BUSY_SIZE-4,1(a7) ;if size <> $60, fmt error
! 92: bne.l fpsp_fmt_error
! 93: lea.l BUSY_SIZE+LOCAL_SIZE(a7),a1 ;init a1 so fpsp.h
! 94: * ;equates will work
! 95: * Fix up the new busy frame with entries from the unimp frame
! 96: *
! 97: move.l ETEMP_EX(a6),ETEMP_EX(a1) ;copy etemp from unimp
! 98: move.l ETEMP_HI(a6),ETEMP_HI(a1) ;frame to busy frame
! 99: move.l ETEMP_LO(a6),ETEMP_LO(a1)
! 100: move.l CMDREG1B(a6),CMDREG1B(a1) ;set inst in frame to unimp
! 101: move.l CMDREG1B(a6),d0 ;fix cmd1b to make it
! 102: and.l #$03c30000,d0 ;work for cmd3b
! 103: bfextu CMDREG1B(a6){13:1},d1 ;extract bit 2
! 104: lsl.l #5,d1
! 105: swap d1
! 106: or.l d1,d0 ;put it in the right place
! 107: bfextu CMDREG1B(a6){10:3},d1 ;extract bit 3,4,5
! 108: lsl.l #2,d1
! 109: swap d1
! 110: or.l d1,d0 ;put them in the right place
! 111: move.l d0,CMDREG3B(a1) ;in the busy frame
! 112: *
! 113: * Or in the FPSR from the emulation with the USER_FPSR on the stack.
! 114: *
! 115: fmove.l FPSR,d0
! 116: or.l d0,USER_FPSR(a6)
! 117: move.l USER_FPSR(a6),FPSR_SHADOW(a1) ;set exc bits
! 118: or.l #sx_mask,E_BYTE(a1)
! 119: bra do_clean
! 120:
! 121: *
! 122: * Frame is an unimp frame possible resulting from an fmove <ea>,fp0
! 123: * that caused an exception
! 124: *
! 125: * a1 is modified to point into the new frame allowing fpsp equates
! 126: * to be valid.
! 127: *
! 128: unimp_x:
! 129: cmpi.b #UNIMP_40_SIZE-4,1(a7) ;test for orig unimp frame
! 130: bne.b test_rev
! 131: lea.l UNIMP_40_SIZE+LOCAL_SIZE(a7),a1
! 132: bra.b unimp_con
! 133: test_rev:
! 134: cmpi.b #UNIMP_41_SIZE-4,1(a7) ;test for rev unimp frame
! 135: bne.l fpsp_fmt_error ;if not $28 or $30
! 136: lea.l UNIMP_41_SIZE+LOCAL_SIZE(a7),a1
! 137:
! 138: unimp_con:
! 139: *
! 140: * Fix up the new unimp frame with entries from the old unimp frame
! 141: *
! 142: move.l CMDREG1B(a6),CMDREG1B(a1) ;set inst in frame to unimp
! 143: *
! 144: * Or in the FPSR from the emulation with the USER_FPSR on the stack.
! 145: *
! 146: fmove.l FPSR,d0
! 147: or.l d0,USER_FPSR(a6)
! 148: bra do_clean
! 149:
! 150: *
! 151: * Frame is idle, so check for exceptions reported through
! 152: * USER_FPSR and set the unimp frame accordingly.
! 153: * A7 must be incremented to the point before the
! 154: * idle fsave vector to the unimp vector.
! 155: *
! 156:
! 157: do_check:
! 158: add.l #4,A7 ;point A7 back to unimp frame
! 159: *
! 160: * Or in the FPSR from the emulation with the USER_FPSR on the stack.
! 161: *
! 162: fmove.l FPSR,d0
! 163: or.l d0,USER_FPSR(a6)
! 164: *
! 165: * On a busy frame, we must clear the nmnexc bits.
! 166: *
! 167: cmpi.b #BUSY_SIZE-4,1(a7) ;check frame type
! 168: bne.b check_fr ;if busy, clr nmnexc
! 169: clr.w NMNEXC(a6) ;clr nmnexc & nmcexc
! 170: btst.b #5,CMDREG1B(a6) ;test for fmove out
! 171: bne.b frame_com
! 172: move.l USER_FPSR(a6),FPSR_SHADOW(a6) ;set exc bits
! 173: or.l #sx_mask,E_BYTE(a6)
! 174: bra.b frame_com
! 175: check_fr:
! 176: cmp.b #UNIMP_40_SIZE-4,1(a7)
! 177: beq.b frame_com
! 178: clr.w NMNEXC(a6)
! 179: frame_com:
! 180: move.b FPCR_ENABLE(a6),d0 ;get fpcr enable byte
! 181: and.b FPSR_EXCEPT(a6),d0 ;and in the fpsr exc byte
! 182: bfffo d0{24:8},d1 ;test for first set bit
! 183: lea.l exc_tbl,a0 ;load jmp table address
! 184: subi.b #24,d1 ;normalize bit offset to 0-8
! 185: move.l (a0,d1.w*4),a0 ;load routine address based
! 186: * ;based on first enabled exc
! 187: jmp (a0) ;jump to routine
! 188: *
! 189: * Bsun is not possible in unimp or unsupp
! 190: *
! 191: bsun_exc:
! 192: bra do_clean
! 193: *
! 194: * The typical work to be done to the unimp frame to report an
! 195: * exception is to set the E1/E3 byte and clr the U flag.
! 196: * commonE1 does this for E1 exceptions, which are snan,
! 197: * operr, and dz. commonE3 does this for E3 exceptions, which
! 198: * are inex2 and inex1, and also clears the E1 exception bit
! 199: * left over from the unimp exception.
! 200: *
! 201: commonE1:
! 202: bset.b #E1,E_BYTE(a6) ;set E1 flag
! 203: bra.w commonE ;go clean and exit
! 204:
! 205: commonE3:
! 206: tst.b UFLG_TMP(a6) ;test flag for unsup/unimp state
! 207: bne.b unsE3
! 208: uniE3:
! 209: bset.b #E3,E_BYTE(a6) ;set E3 flag
! 210: bclr.b #E1,E_BYTE(a6) ;clr E1 from unimp
! 211: bra.w commonE
! 212:
! 213: unsE3:
! 214: tst.b RES_FLG(a6)
! 215: bne.b unsE3_0
! 216: unsE3_1:
! 217: bset.b #E3,E_BYTE(a6) ;set E3 flag
! 218: unsE3_0:
! 219: bclr.b #E1,E_BYTE(a6) ;clr E1 flag
! 220: move.l CMDREG1B(a6),d0
! 221: and.l #$03c30000,d0 ;work for cmd3b
! 222: bfextu CMDREG1B(a6){13:1},d1 ;extract bit 2
! 223: lsl.l #5,d1
! 224: swap d1
! 225: or.l d1,d0 ;put it in the right place
! 226: bfextu CMDREG1B(a6){10:3},d1 ;extract bit 3,4,5
! 227: lsl.l #2,d1
! 228: swap d1
! 229: or.l d1,d0 ;put them in the right place
! 230: move.l d0,CMDREG3B(a6) ;in the busy frame
! 231:
! 232: commonE:
! 233: bclr.b #UFLAG,T_BYTE(a6) ;clr U flag from unimp
! 234: bra.w do_clean ;go clean and exit
! 235: *
! 236: * No bits in the enable byte match existing exceptions. Check for
! 237: * the case of the ovfl exc without the ovfl enabled, but with
! 238: * inex2 enabled.
! 239: *
! 240: no_match:
! 241: btst.b #inex2_bit,FPCR_ENABLE(a6) ;check for ovfl/inex2 case
! 242: beq.b no_exc ;if clear, exit
! 243: btst.b #ovfl_bit,FPSR_EXCEPT(a6) ;now check ovfl
! 244: beq.b no_exc ;if clear, exit
! 245: bra.b ovfl_unfl ;go to unfl_ovfl to determine if
! 246: * ;it is an unsupp or unimp exc
! 247:
! 248: * No exceptions are to be reported. If the instruction was
! 249: * unimplemented, no FPU restore is necessary. If it was
! 250: * unsupported, we must perform the restore.
! 251: no_exc:
! 252: tst.b UFLG_TMP(a6) ;test flag for unsupp/unimp state
! 253: beq.b uni_no_exc
! 254: uns_no_exc:
! 255: tst.b RES_FLG(a6) ;check if frestore is needed
! 256: bne.w do_clean ;if clear, no frestore needed
! 257: uni_no_exc:
! 258: movem.l USER_DA(a6),d0-d1/a0-a1
! 259: fmovem.x USER_FP0(a6),fp0-fp3
! 260: fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
! 261: unlk a6
! 262: bra finish_up
! 263: *
! 264: * Unsupported Data Type Handler:
! 265: * Ovfl:
! 266: * An fmoveout that results in an overflow is reported this way.
! 267: * Unfl:
! 268: * An fmoveout that results in an underflow is reported this way.
! 269: *
! 270: * Unimplemented Instruction Handler:
! 271: * Ovfl:
! 272: * Only scosh, setox, ssinh, stwotox, and scale can set overflow in
! 273: * this manner.
! 274: * Unfl:
! 275: * Stwotox, setox, and scale can set underflow in this manner.
! 276: * Any of the other Library Routines such that f(x)=x in which
! 277: * x is an extended denorm can report an underflow exception.
! 278: * It is the responsibility of the exception-causing exception
! 279: * to make sure that WBTEMP is correct.
! 280: *
! 281: * The exceptional operand is in FP_SCR1.
! 282: *
! 283: ovfl_unfl:
! 284: tst.b UFLG_TMP(a6) ;test flag for unsupp/unimp state
! 285: beq.b ofuf_con
! 286: *
! 287: * The caller was from an unsupported data type trap. Test if the
! 288: * caller set CU_ONLY. If so, the exceptional operand is expected in
! 289: * FPTEMP, rather than WBTEMP.
! 290: *
! 291: tst.b CU_ONLY(a6) ;test if inst is cu-only
! 292: beq.w unsE3
! 293: * move.w #$fe,CU_SAVEPC(a6)
! 294: clr.b CU_SAVEPC(a6)
! 295: bset.b #E1,E_BYTE(a6) ;set E1 exception flag
! 296: move.w ETEMP_EX(a6),FPTEMP_EX(a6)
! 297: move.l ETEMP_HI(a6),FPTEMP_HI(a6)
! 298: move.l ETEMP_LO(a6),FPTEMP_LO(a6)
! 299: bset.b #fptemp15_bit,DTAG(a6) ;set fpte15
! 300: bclr.b #UFLAG,T_BYTE(a6) ;clr U flag from unimp
! 301: bra.w do_clean ;go clean and exit
! 302:
! 303: ofuf_con:
! 304: move.b (a7),VER_TMP(a6) ;save version number
! 305: cmpi.b #BUSY_SIZE-4,1(a7) ;check for busy frame
! 306: beq.b busy_fr ;if unimp, grow to busy
! 307: cmpi.b #VER_40,(a7) ;test for orig unimp frame
! 308: bne.b try_41 ;if not, test for rev frame
! 309: moveq.l #13,d0 ;need to zero 14 lwords
! 310: bra.b ofuf_fin
! 311: try_41:
! 312: cmpi.b #VER_41,(a7) ;test for rev unimp frame
! 313: bne.l fpsp_fmt_error ;if neither, exit with error
! 314: moveq.l #11,d0 ;need to zero 12 lwords
! 315:
! 316: ofuf_fin:
! 317: clr.l (a7)
! 318: loop1:
! 319: clr.l -(a7) ;clear and dec a7
! 320: dbra.w d0,loop1
! 321: move.b VER_TMP(a6),(a7)
! 322: move.b #BUSY_SIZE-4,1(a7) ;write busy fmt word.
! 323: busy_fr:
! 324: move.l FP_SCR1(a6),WBTEMP_EX(a6) ;write
! 325: move.l FP_SCR1+4(a6),WBTEMP_HI(a6) ;execptional op to
! 326: move.l FP_SCR1+8(a6),WBTEMP_LO(a6) ;wbtemp
! 327: bset.b #E3,E_BYTE(a6) ;set E3 flag
! 328: bclr.b #E1,E_BYTE(a6) ;make sure E1 is clear
! 329: bclr.b #UFLAG,T_BYTE(a6) ;clr U flag
! 330: move.l USER_FPSR(a6),FPSR_SHADOW(a6)
! 331: or.l #sx_mask,E_BYTE(a6)
! 332: move.l CMDREG1B(a6),d0 ;fix cmd1b to make it
! 333: and.l #$03c30000,d0 ;work for cmd3b
! 334: bfextu CMDREG1B(a6){13:1},d1 ;extract bit 2
! 335: lsl.l #5,d1
! 336: swap d1
! 337: or.l d1,d0 ;put it in the right place
! 338: bfextu CMDREG1B(a6){10:3},d1 ;extract bit 3,4,5
! 339: lsl.l #2,d1
! 340: swap d1
! 341: or.l d1,d0 ;put them in the right place
! 342: move.l d0,CMDREG3B(a6) ;in the busy frame
! 343:
! 344: *
! 345: * Check if the frame to be restored is busy or unimp.
! 346: *** NOTE *** Bug fix for errata (0d43b #3)
! 347: * If the frame is unimp, we must create a busy frame to
! 348: * fix the bug with the nmnexc bits in cases in which they
! 349: * are set by a previous instruction and not cleared by
! 350: * the save. The frame will be unimp only if the final
! 351: * instruction in an emulation routine caused the exception
! 352: * by doing an fmove <ea>,fp0. The exception operand, in
! 353: * internal format, is in fptemp.
! 354: *
! 355: do_clean:
! 356: cmpi.b #UNIMP_40_SIZE-4,1(a7)
! 357: bne.b do_con
! 358: moveq.l #13,d0 ;in orig, need to zero 14 lwords
! 359: bra.b do_build
! 360: do_con:
! 361: cmpi.b #UNIMP_41_SIZE-4,1(a7)
! 362: bne.b do_restore ;frame must be busy
! 363: moveq.l #11,d0 ;in rev, need to zero 12 lwords
! 364:
! 365: do_build:
! 366: move.b (a7),VER_TMP(a6)
! 367: clr.l (a7)
! 368: loop2:
! 369: clr.l -(a7) ;clear and dec a7
! 370: dbra.w d0,loop2
! 371: *
! 372: * Use a1 as pointer into new frame. a6 is not correct if an unimp or
! 373: * busy frame was created as the result of an exception on the final
! 374: * instruction of an emulation routine.
! 375: *
! 376: * We need to set the nmcexc bits if the exception is E1. Otherwise,
! 377: * the exc taken will be inex2.
! 378: *
! 379: lea.l BUSY_SIZE+LOCAL_SIZE(a7),a1 ;init a1 for new frame
! 380: move.b VER_TMP(a6),(a7) ;write busy fmt word
! 381: move.b #BUSY_SIZE-4,1(a7)
! 382: move.l FP_SCR1(a6),WBTEMP_EX(a1) ;write
! 383: move.l FP_SCR1+4(a6),WBTEMP_HI(a1) ;exceptional op to
! 384: move.l FP_SCR1+8(a6),WBTEMP_LO(a1) ;wbtemp
! 385: * btst.b #E1,E_BYTE(a1)
! 386: * beq.b do_restore
! 387: bfextu USER_FPSR(a6){17:4},d0 ;get snan/operr/ovfl/unfl bits
! 388: bfins d0,NMCEXC(a1){4:4} ;and insert them in nmcexc
! 389: move.l USER_FPSR(a6),FPSR_SHADOW(a1) ;set exc bits
! 390: or.l #sx_mask,E_BYTE(a1)
! 391:
! 392: do_restore:
! 393: movem.l USER_DA(a6),d0-d1/a0-a1
! 394: fmovem.x USER_FP0(a6),fp0-fp3
! 395: fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
! 396: frestore (a7)+
! 397: tst.b RES_FLG(a6) ;RES_FLG indicates a "continuation" frame
! 398: beq cont
! 399: bsr bug1384
! 400: cont:
! 401: unlk a6
! 402: *
! 403: * If trace mode enabled, then go to trace handler. This handler
! 404: * cannot have any fp instructions. If there are fp inst's and an
! 405: * exception has been restored into the machine then the exception
! 406: * will occur upon execution of the fp inst. This is not desirable
! 407: * in the kernel (supervisor mode). See MC68040 manual Section 9.3.8.
! 408: *
! 409: finish_up:
! 410: btst.b #7,(a7) ;test T1 in SR
! 411: bne.b g_trace
! 412: btst.b #6,(a7) ;test T0 in SR
! 413: bne.b g_trace
! 414: bra.l fpsp_done
! 415: *
! 416: * Change integer stack to look like trace stack
! 417: * The address of the instruction that caused the
! 418: * exception is already in the integer stack (is
! 419: * the same as the saved friar)
! 420: *
! 421: * If the current frame is already a 6-word stack then all
! 422: * that needs to be done is to change the vector# to TRACE.
! 423: * If the frame is only a 4-word stack (meaning we got here
! 424: * on an Unsupported data type exception), then we need to grow
! 425: * the stack an extra 2 words and get the FPIAR from the FPU.
! 426: *
! 427: g_trace:
! 428: bftst EXC_VEC-4(sp){0:4}
! 429: bne g_easy
! 430:
! 431: subq.l #4,sp make room
! 432: move.l 4(sp),(sp)
! 433: move.l 8(sp),4(sp)
! 434: sub.l #BUSY_SIZE,sp
! 435: fsave (sp)
! 436: fmove.l fpiar,BUSY_SIZE+EXC_EA-4(sp)
! 437: frestore (sp)
! 438: add.l #BUSY_SIZE,sp
! 439:
! 440: g_easy:
! 441: move.w #TRACE_VEC,EXC_VEC-4(a7)
! 442: bra.l real_trace
! 443: *
! 444: * This is a work-around for hardware bug 1384.
! 445: *
! 446: bug1384:
! 447: link a5,#0
! 448: fsave -(sp)
! 449: cmpi.b #$41,(sp) ; check for correct frame
! 450: beq frame_41
! 451: bgt nofix ; if more advanced mask, do nada
! 452:
! 453: frame_40:
! 454: tst.b 1(sp) ; check to see if idle
! 455: bne notidle
! 456: idle40:
! 457: clr.l (sp) ; get rid of old fsave frame
! 458: move.l d1,USER_D1(a6) ; save d1
! 459: move.w #8,d1 ; place unimp frame instead
! 460: loop40: clr.l -(sp)
! 461: dbra d1,loop40
! 462: move.l USER_D1(a6),d1 ; restore d1
! 463: move.l #$40280000,-(sp)
! 464: frestore (sp)+
! 465: unlk a5
! 466: rts
! 467:
! 468: frame_41:
! 469: tst.b 1(sp) ; check to see if idle
! 470: bne notidle
! 471: idle41:
! 472: clr.l (sp) ; get rid of old fsave frame
! 473: move.l d1,USER_D1(a6) ; save d1
! 474: move.w #10,d1 ; place unimp frame instead
! 475: loop41: clr.l -(sp)
! 476: dbra d1,loop41
! 477: move.l USER_D1(a6),d1 ; restore d1
! 478: move.l #$41300000,-(sp)
! 479: frestore (sp)+
! 480: unlk a5
! 481: rts
! 482:
! 483: notidle:
! 484: bclr.b #etemp15_bit,-40(a5)
! 485: frestore (sp)+
! 486: unlk a5
! 487: rts
! 488:
! 489: nofix:
! 490: frestore (sp)+
! 491: unlk a5
! 492: rts
! 493:
! 494: end
CVSweb