11da177e4SLinus Torvalds| 21da177e4SLinus Torvalds| gen_except.sa 3.7 1/16/92 31da177e4SLinus Torvalds| 41da177e4SLinus Torvalds| gen_except --- FPSP routine to detect reportable exceptions 51da177e4SLinus Torvalds| 61da177e4SLinus Torvalds| This routine compares the exception enable byte of the 71da177e4SLinus Torvalds| user_fpcr on the stack with the exception status byte 81da177e4SLinus Torvalds| of the user_fpsr. 91da177e4SLinus Torvalds| 101da177e4SLinus Torvalds| Any routine which may report an exceptions must load 111da177e4SLinus Torvalds| the stack frame in memory with the exceptional operand(s). 121da177e4SLinus Torvalds| 131da177e4SLinus Torvalds| Priority for exceptions is: 141da177e4SLinus Torvalds| 151da177e4SLinus Torvalds| Highest: bsun 161da177e4SLinus Torvalds| snan 171da177e4SLinus Torvalds| operr 181da177e4SLinus Torvalds| ovfl 191da177e4SLinus Torvalds| unfl 201da177e4SLinus Torvalds| dz 211da177e4SLinus Torvalds| inex2 221da177e4SLinus Torvalds| Lowest: inex1 231da177e4SLinus Torvalds| 241da177e4SLinus Torvalds| Note: The IEEE standard specifies that inex2 is to be 251da177e4SLinus Torvalds| reported if ovfl occurs and the ovfl enable bit is not 261da177e4SLinus Torvalds| set but the inex2 enable bit is. 271da177e4SLinus Torvalds| 281da177e4SLinus Torvalds| 291da177e4SLinus Torvalds| Copyright (C) Motorola, Inc. 1990 301da177e4SLinus Torvalds| All Rights Reserved 311da177e4SLinus Torvalds| 32*e00d82d0SMatt Waddel| For details on the license for this file, please see the 33*e00d82d0SMatt Waddel| file, README, in this same directory. 341da177e4SLinus Torvalds 351da177e4SLinus TorvaldsGEN_EXCEPT: |idnt 2,1 | Motorola 040 Floating Point Software Package 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds |section 8 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds#include "fpsp.h" 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds |xref real_trace 421da177e4SLinus Torvalds |xref fpsp_done 431da177e4SLinus Torvalds |xref fpsp_fmt_error 441da177e4SLinus Torvalds 451da177e4SLinus Torvaldsexc_tbl: 461da177e4SLinus Torvalds .long bsun_exc 471da177e4SLinus Torvalds .long commonE1 481da177e4SLinus Torvalds .long commonE1 491da177e4SLinus Torvalds .long ovfl_unfl 501da177e4SLinus Torvalds .long ovfl_unfl 511da177e4SLinus Torvalds .long commonE1 521da177e4SLinus Torvalds .long commonE3 531da177e4SLinus Torvalds .long commonE3 541da177e4SLinus Torvalds .long no_match 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds .global gen_except 571da177e4SLinus Torvaldsgen_except: 581da177e4SLinus Torvalds cmpib #IDLE_SIZE-4,1(%a7) |test for idle frame 591da177e4SLinus Torvalds beq do_check |go handle idle frame 601da177e4SLinus Torvalds cmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame 611da177e4SLinus Torvalds beqs unimp_x |go handle unimp frame 621da177e4SLinus Torvalds cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame 631da177e4SLinus Torvalds beqs unimp_x |go handle unimp frame 641da177e4SLinus Torvalds cmpib #BUSY_SIZE-4,1(%a7) |if size <> $60, fmt error 651da177e4SLinus Torvalds bnel fpsp_fmt_error 661da177e4SLinus Torvalds leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 so fpsp.h 671da177e4SLinus Torvalds| ;equates will work 681da177e4SLinus Torvalds| Fix up the new busy frame with entries from the unimp frame 691da177e4SLinus Torvalds| 701da177e4SLinus Torvalds movel ETEMP_EX(%a6),ETEMP_EX(%a1) |copy etemp from unimp 711da177e4SLinus Torvalds movel ETEMP_HI(%a6),ETEMP_HI(%a1) |frame to busy frame 721da177e4SLinus Torvalds movel ETEMP_LO(%a6),ETEMP_LO(%a1) 731da177e4SLinus Torvalds movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp 741da177e4SLinus Torvalds movel CMDREG1B(%a6),%d0 |fix cmd1b to make it 751da177e4SLinus Torvalds andl #0x03c30000,%d0 |work for cmd3b 761da177e4SLinus Torvalds bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2 771da177e4SLinus Torvalds lsll #5,%d1 781da177e4SLinus Torvalds swap %d1 791da177e4SLinus Torvalds orl %d1,%d0 |put it in the right place 801da177e4SLinus Torvalds bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5 811da177e4SLinus Torvalds lsll #2,%d1 821da177e4SLinus Torvalds swap %d1 831da177e4SLinus Torvalds orl %d1,%d0 |put them in the right place 841da177e4SLinus Torvalds movel %d0,CMDREG3B(%a1) |in the busy frame 851da177e4SLinus Torvalds| 861da177e4SLinus Torvalds| Or in the FPSR from the emulation with the USER_FPSR on the stack. 871da177e4SLinus Torvalds| 881da177e4SLinus Torvalds fmovel %FPSR,%d0 891da177e4SLinus Torvalds orl %d0,USER_FPSR(%a6) 901da177e4SLinus Torvalds movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits 911da177e4SLinus Torvalds orl #sx_mask,E_BYTE(%a1) 921da177e4SLinus Torvalds bra do_clean 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds| 951da177e4SLinus Torvalds| Frame is an unimp frame possible resulting from an fmove <ea>,fp0 961da177e4SLinus Torvalds| that caused an exception 971da177e4SLinus Torvalds| 981da177e4SLinus Torvalds| a1 is modified to point into the new frame allowing fpsp equates 991da177e4SLinus Torvalds| to be valid. 1001da177e4SLinus Torvalds| 1011da177e4SLinus Torvaldsunimp_x: 1021da177e4SLinus Torvalds cmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame 1031da177e4SLinus Torvalds bnes test_rev 1041da177e4SLinus Torvalds leal UNIMP_40_SIZE+LOCAL_SIZE(%a7),%a1 1051da177e4SLinus Torvalds bras unimp_con 1061da177e4SLinus Torvaldstest_rev: 1071da177e4SLinus Torvalds cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame 1081da177e4SLinus Torvalds bnel fpsp_fmt_error |if not $28 or $30 1091da177e4SLinus Torvalds leal UNIMP_41_SIZE+LOCAL_SIZE(%a7),%a1 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvaldsunimp_con: 1121da177e4SLinus Torvalds| 1131da177e4SLinus Torvalds| Fix up the new unimp frame with entries from the old unimp frame 1141da177e4SLinus Torvalds| 1151da177e4SLinus Torvalds movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp 1161da177e4SLinus Torvalds| 1171da177e4SLinus Torvalds| Or in the FPSR from the emulation with the USER_FPSR on the stack. 1181da177e4SLinus Torvalds| 1191da177e4SLinus Torvalds fmovel %FPSR,%d0 1201da177e4SLinus Torvalds orl %d0,USER_FPSR(%a6) 1211da177e4SLinus Torvalds bra do_clean 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds| 1241da177e4SLinus Torvalds| Frame is idle, so check for exceptions reported through 1251da177e4SLinus Torvalds| USER_FPSR and set the unimp frame accordingly. 1261da177e4SLinus Torvalds| A7 must be incremented to the point before the 1271da177e4SLinus Torvalds| idle fsave vector to the unimp vector. 1281da177e4SLinus Torvalds| 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvaldsdo_check: 1311da177e4SLinus Torvalds addl #4,%a7 |point A7 back to unimp frame 1321da177e4SLinus Torvalds| 1331da177e4SLinus Torvalds| Or in the FPSR from the emulation with the USER_FPSR on the stack. 1341da177e4SLinus Torvalds| 1351da177e4SLinus Torvalds fmovel %FPSR,%d0 1361da177e4SLinus Torvalds orl %d0,USER_FPSR(%a6) 1371da177e4SLinus Torvalds| 1381da177e4SLinus Torvalds| On a busy frame, we must clear the nmnexc bits. 1391da177e4SLinus Torvalds| 1401da177e4SLinus Torvalds cmpib #BUSY_SIZE-4,1(%a7) |check frame type 1411da177e4SLinus Torvalds bnes check_fr |if busy, clr nmnexc 1421da177e4SLinus Torvalds clrw NMNEXC(%a6) |clr nmnexc & nmcexc 1431da177e4SLinus Torvalds btstb #5,CMDREG1B(%a6) |test for fmove out 1441da177e4SLinus Torvalds bnes frame_com 1451da177e4SLinus Torvalds movel USER_FPSR(%a6),FPSR_SHADOW(%a6) |set exc bits 1461da177e4SLinus Torvalds orl #sx_mask,E_BYTE(%a6) 1471da177e4SLinus Torvalds bras frame_com 1481da177e4SLinus Torvaldscheck_fr: 1491da177e4SLinus Torvalds cmpb #UNIMP_40_SIZE-4,1(%a7) 1501da177e4SLinus Torvalds beqs frame_com 1511da177e4SLinus Torvalds clrw NMNEXC(%a6) 1521da177e4SLinus Torvaldsframe_com: 1531da177e4SLinus Torvalds moveb FPCR_ENABLE(%a6),%d0 |get fpcr enable byte 1541da177e4SLinus Torvalds andb FPSR_EXCEPT(%a6),%d0 |and in the fpsr exc byte 1551da177e4SLinus Torvalds bfffo %d0{#24:#8},%d1 |test for first set bit 1561da177e4SLinus Torvalds leal exc_tbl,%a0 |load jmp table address 1571da177e4SLinus Torvalds subib #24,%d1 |normalize bit offset to 0-8 1581da177e4SLinus Torvalds movel (%a0,%d1.w*4),%a0 |load routine address based 1591da177e4SLinus Torvalds| ;based on first enabled exc 1601da177e4SLinus Torvalds jmp (%a0) |jump to routine 1611da177e4SLinus Torvalds| 1621da177e4SLinus Torvalds| Bsun is not possible in unimp or unsupp 1631da177e4SLinus Torvalds| 1641da177e4SLinus Torvaldsbsun_exc: 1651da177e4SLinus Torvalds bra do_clean 1661da177e4SLinus Torvalds| 1671da177e4SLinus Torvalds| The typical work to be done to the unimp frame to report an 1681da177e4SLinus Torvalds| exception is to set the E1/E3 byte and clr the U flag. 1691da177e4SLinus Torvalds| commonE1 does this for E1 exceptions, which are snan, 1701da177e4SLinus Torvalds| operr, and dz. commonE3 does this for E3 exceptions, which 1711da177e4SLinus Torvalds| are inex2 and inex1, and also clears the E1 exception bit 1721da177e4SLinus Torvalds| left over from the unimp exception. 1731da177e4SLinus Torvalds| 1741da177e4SLinus TorvaldscommonE1: 1751da177e4SLinus Torvalds bsetb #E1,E_BYTE(%a6) |set E1 flag 1761da177e4SLinus Torvalds bra commonE |go clean and exit 1771da177e4SLinus Torvalds 1781da177e4SLinus TorvaldscommonE3: 1791da177e4SLinus Torvalds tstb UFLG_TMP(%a6) |test flag for unsup/unimp state 1801da177e4SLinus Torvalds bnes unsE3 1811da177e4SLinus TorvaldsuniE3: 1821da177e4SLinus Torvalds bsetb #E3,E_BYTE(%a6) |set E3 flag 1831da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) |clr E1 from unimp 1841da177e4SLinus Torvalds bra commonE 1851da177e4SLinus Torvalds 1861da177e4SLinus TorvaldsunsE3: 1871da177e4SLinus Torvalds tstb RES_FLG(%a6) 1881da177e4SLinus Torvalds bnes unsE3_0 1891da177e4SLinus TorvaldsunsE3_1: 1901da177e4SLinus Torvalds bsetb #E3,E_BYTE(%a6) |set E3 flag 1911da177e4SLinus TorvaldsunsE3_0: 1921da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) |clr E1 flag 1931da177e4SLinus Torvalds movel CMDREG1B(%a6),%d0 1941da177e4SLinus Torvalds andl #0x03c30000,%d0 |work for cmd3b 1951da177e4SLinus Torvalds bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2 1961da177e4SLinus Torvalds lsll #5,%d1 1971da177e4SLinus Torvalds swap %d1 1981da177e4SLinus Torvalds orl %d1,%d0 |put it in the right place 1991da177e4SLinus Torvalds bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5 2001da177e4SLinus Torvalds lsll #2,%d1 2011da177e4SLinus Torvalds swap %d1 2021da177e4SLinus Torvalds orl %d1,%d0 |put them in the right place 2031da177e4SLinus Torvalds movel %d0,CMDREG3B(%a6) |in the busy frame 2041da177e4SLinus Torvalds 2051da177e4SLinus TorvaldscommonE: 2061da177e4SLinus Torvalds bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimp 2071da177e4SLinus Torvalds bra do_clean |go clean and exit 2081da177e4SLinus Torvalds| 2091da177e4SLinus Torvalds| No bits in the enable byte match existing exceptions. Check for 2101da177e4SLinus Torvalds| the case of the ovfl exc without the ovfl enabled, but with 2111da177e4SLinus Torvalds| inex2 enabled. 2121da177e4SLinus Torvalds| 2131da177e4SLinus Torvaldsno_match: 2141da177e4SLinus Torvalds btstb #inex2_bit,FPCR_ENABLE(%a6) |check for ovfl/inex2 case 2151da177e4SLinus Torvalds beqs no_exc |if clear, exit 2161da177e4SLinus Torvalds btstb #ovfl_bit,FPSR_EXCEPT(%a6) |now check ovfl 2171da177e4SLinus Torvalds beqs no_exc |if clear, exit 2181da177e4SLinus Torvalds bras ovfl_unfl |go to unfl_ovfl to determine if 2191da177e4SLinus Torvalds| ;it is an unsupp or unimp exc 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds| No exceptions are to be reported. If the instruction was 2221da177e4SLinus Torvalds| unimplemented, no FPU restore is necessary. If it was 2231da177e4SLinus Torvalds| unsupported, we must perform the restore. 2241da177e4SLinus Torvaldsno_exc: 2251da177e4SLinus Torvalds tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state 2261da177e4SLinus Torvalds beqs uni_no_exc 2271da177e4SLinus Torvaldsuns_no_exc: 2281da177e4SLinus Torvalds tstb RES_FLG(%a6) |check if frestore is needed 2291da177e4SLinus Torvalds bne do_clean |if clear, no frestore needed 2301da177e4SLinus Torvaldsuni_no_exc: 2311da177e4SLinus Torvalds moveml USER_DA(%a6),%d0-%d1/%a0-%a1 2321da177e4SLinus Torvalds fmovemx USER_FP0(%a6),%fp0-%fp3 2331da177e4SLinus Torvalds fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 2341da177e4SLinus Torvalds unlk %a6 2351da177e4SLinus Torvalds bra finish_up 2361da177e4SLinus Torvalds| 2371da177e4SLinus Torvalds| Unsupported Data Type Handler: 2381da177e4SLinus Torvalds| Ovfl: 2391da177e4SLinus Torvalds| An fmoveout that results in an overflow is reported this way. 2401da177e4SLinus Torvalds| Unfl: 2411da177e4SLinus Torvalds| An fmoveout that results in an underflow is reported this way. 2421da177e4SLinus Torvalds| 2431da177e4SLinus Torvalds| Unimplemented Instruction Handler: 2441da177e4SLinus Torvalds| Ovfl: 2451da177e4SLinus Torvalds| Only scosh, setox, ssinh, stwotox, and scale can set overflow in 2461da177e4SLinus Torvalds| this manner. 2471da177e4SLinus Torvalds| Unfl: 2481da177e4SLinus Torvalds| Stwotox, setox, and scale can set underflow in this manner. 2491da177e4SLinus Torvalds| Any of the other Library Routines such that f(x)=x in which 2501da177e4SLinus Torvalds| x is an extended denorm can report an underflow exception. 2511da177e4SLinus Torvalds| It is the responsibility of the exception-causing exception 2521da177e4SLinus Torvalds| to make sure that WBTEMP is correct. 2531da177e4SLinus Torvalds| 2541da177e4SLinus Torvalds| The exceptional operand is in FP_SCR1. 2551da177e4SLinus Torvalds| 2561da177e4SLinus Torvaldsovfl_unfl: 2571da177e4SLinus Torvalds tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state 2581da177e4SLinus Torvalds beqs ofuf_con 2591da177e4SLinus Torvalds| 2601da177e4SLinus Torvalds| The caller was from an unsupported data type trap. Test if the 2611da177e4SLinus Torvalds| caller set CU_ONLY. If so, the exceptional operand is expected in 2621da177e4SLinus Torvalds| FPTEMP, rather than WBTEMP. 2631da177e4SLinus Torvalds| 2641da177e4SLinus Torvalds tstb CU_ONLY(%a6) |test if inst is cu-only 2651da177e4SLinus Torvalds beq unsE3 2661da177e4SLinus Torvalds| move.w #$fe,CU_SAVEPC(%a6) 2671da177e4SLinus Torvalds clrb CU_SAVEPC(%a6) 2681da177e4SLinus Torvalds bsetb #E1,E_BYTE(%a6) |set E1 exception flag 2691da177e4SLinus Torvalds movew ETEMP_EX(%a6),FPTEMP_EX(%a6) 2701da177e4SLinus Torvalds movel ETEMP_HI(%a6),FPTEMP_HI(%a6) 2711da177e4SLinus Torvalds movel ETEMP_LO(%a6),FPTEMP_LO(%a6) 2721da177e4SLinus Torvalds bsetb #fptemp15_bit,DTAG(%a6) |set fpte15 2731da177e4SLinus Torvalds bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimp 2741da177e4SLinus Torvalds bra do_clean |go clean and exit 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvaldsofuf_con: 2771da177e4SLinus Torvalds moveb (%a7),VER_TMP(%a6) |save version number 2781da177e4SLinus Torvalds cmpib #BUSY_SIZE-4,1(%a7) |check for busy frame 2791da177e4SLinus Torvalds beqs busy_fr |if unimp, grow to busy 2801da177e4SLinus Torvalds cmpib #VER_40,(%a7) |test for orig unimp frame 2811da177e4SLinus Torvalds bnes try_41 |if not, test for rev frame 2821da177e4SLinus Torvalds moveql #13,%d0 |need to zero 14 lwords 2831da177e4SLinus Torvalds bras ofuf_fin 2841da177e4SLinus Torvaldstry_41: 2851da177e4SLinus Torvalds cmpib #VER_41,(%a7) |test for rev unimp frame 2861da177e4SLinus Torvalds bnel fpsp_fmt_error |if neither, exit with error 2871da177e4SLinus Torvalds moveql #11,%d0 |need to zero 12 lwords 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvaldsofuf_fin: 2901da177e4SLinus Torvalds clrl (%a7) 2911da177e4SLinus Torvaldsloop1: 2921da177e4SLinus Torvalds clrl -(%a7) |clear and dec a7 2931da177e4SLinus Torvalds dbra %d0,loop1 2941da177e4SLinus Torvalds moveb VER_TMP(%a6),(%a7) 2951da177e4SLinus Torvalds moveb #BUSY_SIZE-4,1(%a7) |write busy fmt word. 2961da177e4SLinus Torvaldsbusy_fr: 2971da177e4SLinus Torvalds movel FP_SCR1(%a6),WBTEMP_EX(%a6) |write 2981da177e4SLinus Torvalds movel FP_SCR1+4(%a6),WBTEMP_HI(%a6) |exceptional op to 2991da177e4SLinus Torvalds movel FP_SCR1+8(%a6),WBTEMP_LO(%a6) |wbtemp 3001da177e4SLinus Torvalds bsetb #E3,E_BYTE(%a6) |set E3 flag 3011da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) |make sure E1 is clear 3021da177e4SLinus Torvalds bclrb #UFLAG,T_BYTE(%a6) |clr U flag 3031da177e4SLinus Torvalds movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 3041da177e4SLinus Torvalds orl #sx_mask,E_BYTE(%a6) 3051da177e4SLinus Torvalds movel CMDREG1B(%a6),%d0 |fix cmd1b to make it 3061da177e4SLinus Torvalds andl #0x03c30000,%d0 |work for cmd3b 3071da177e4SLinus Torvalds bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2 3081da177e4SLinus Torvalds lsll #5,%d1 3091da177e4SLinus Torvalds swap %d1 3101da177e4SLinus Torvalds orl %d1,%d0 |put it in the right place 3111da177e4SLinus Torvalds bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5 3121da177e4SLinus Torvalds lsll #2,%d1 3131da177e4SLinus Torvalds swap %d1 3141da177e4SLinus Torvalds orl %d1,%d0 |put them in the right place 3151da177e4SLinus Torvalds movel %d0,CMDREG3B(%a6) |in the busy frame 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds| 3181da177e4SLinus Torvalds| Check if the frame to be restored is busy or unimp. 3191da177e4SLinus Torvalds|** NOTE *** Bug fix for errata (0d43b #3) 3201da177e4SLinus Torvalds| If the frame is unimp, we must create a busy frame to 3211da177e4SLinus Torvalds| fix the bug with the nmnexc bits in cases in which they 3221da177e4SLinus Torvalds| are set by a previous instruction and not cleared by 3231da177e4SLinus Torvalds| the save. The frame will be unimp only if the final 3241da177e4SLinus Torvalds| instruction in an emulation routine caused the exception 3251da177e4SLinus Torvalds| by doing an fmove <ea>,fp0. The exception operand, in 3261da177e4SLinus Torvalds| internal format, is in fptemp. 3271da177e4SLinus Torvalds| 3281da177e4SLinus Torvaldsdo_clean: 3291da177e4SLinus Torvalds cmpib #UNIMP_40_SIZE-4,1(%a7) 3301da177e4SLinus Torvalds bnes do_con 3311da177e4SLinus Torvalds moveql #13,%d0 |in orig, need to zero 14 lwords 3321da177e4SLinus Torvalds bras do_build 3331da177e4SLinus Torvaldsdo_con: 3341da177e4SLinus Torvalds cmpib #UNIMP_41_SIZE-4,1(%a7) 3351da177e4SLinus Torvalds bnes do_restore |frame must be busy 3361da177e4SLinus Torvalds moveql #11,%d0 |in rev, need to zero 12 lwords 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvaldsdo_build: 3391da177e4SLinus Torvalds moveb (%a7),VER_TMP(%a6) 3401da177e4SLinus Torvalds clrl (%a7) 3411da177e4SLinus Torvaldsloop2: 3421da177e4SLinus Torvalds clrl -(%a7) |clear and dec a7 3431da177e4SLinus Torvalds dbra %d0,loop2 3441da177e4SLinus Torvalds| 3451da177e4SLinus Torvalds| Use a1 as pointer into new frame. a6 is not correct if an unimp or 3461da177e4SLinus Torvalds| busy frame was created as the result of an exception on the final 3471da177e4SLinus Torvalds| instruction of an emulation routine. 3481da177e4SLinus Torvalds| 3491da177e4SLinus Torvalds| We need to set the nmcexc bits if the exception is E1. Otherwise, 3501da177e4SLinus Torvalds| the exc taken will be inex2. 3511da177e4SLinus Torvalds| 3521da177e4SLinus Torvalds leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 for new frame 3531da177e4SLinus Torvalds moveb VER_TMP(%a6),(%a7) |write busy fmt word 3541da177e4SLinus Torvalds moveb #BUSY_SIZE-4,1(%a7) 3551da177e4SLinus Torvalds movel FP_SCR1(%a6),WBTEMP_EX(%a1) |write 3561da177e4SLinus Torvalds movel FP_SCR1+4(%a6),WBTEMP_HI(%a1) |exceptional op to 3571da177e4SLinus Torvalds movel FP_SCR1+8(%a6),WBTEMP_LO(%a1) |wbtemp 3581da177e4SLinus Torvalds| btst.b #E1,E_BYTE(%a1) 3591da177e4SLinus Torvalds| beq.b do_restore 3601da177e4SLinus Torvalds bfextu USER_FPSR(%a6){#17:#4},%d0 |get snan/operr/ovfl/unfl bits 3611da177e4SLinus Torvalds bfins %d0,NMCEXC(%a1){#4:#4} |and insert them in nmcexc 3621da177e4SLinus Torvalds movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits 3631da177e4SLinus Torvalds orl #sx_mask,E_BYTE(%a1) 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvaldsdo_restore: 3661da177e4SLinus Torvalds moveml USER_DA(%a6),%d0-%d1/%a0-%a1 3671da177e4SLinus Torvalds fmovemx USER_FP0(%a6),%fp0-%fp3 3681da177e4SLinus Torvalds fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 3691da177e4SLinus Torvalds frestore (%a7)+ 3701da177e4SLinus Torvalds tstb RES_FLG(%a6) |RES_FLG indicates a "continuation" frame 3711da177e4SLinus Torvalds beq cont 3721da177e4SLinus Torvalds bsr bug1384 3731da177e4SLinus Torvaldscont: 3741da177e4SLinus Torvalds unlk %a6 3751da177e4SLinus Torvalds| 3761da177e4SLinus Torvalds| If trace mode enabled, then go to trace handler. This handler 3771da177e4SLinus Torvalds| cannot have any fp instructions. If there are fp inst's and an 3781da177e4SLinus Torvalds| exception has been restored into the machine then the exception 3791da177e4SLinus Torvalds| will occur upon execution of the fp inst. This is not desirable 3801da177e4SLinus Torvalds| in the kernel (supervisor mode). See MC68040 manual Section 9.3.8. 3811da177e4SLinus Torvalds| 3821da177e4SLinus Torvaldsfinish_up: 3831da177e4SLinus Torvalds btstb #7,(%a7) |test T1 in SR 3841da177e4SLinus Torvalds bnes g_trace 3851da177e4SLinus Torvalds btstb #6,(%a7) |test T0 in SR 3861da177e4SLinus Torvalds bnes g_trace 3871da177e4SLinus Torvalds bral fpsp_done 3881da177e4SLinus Torvalds| 3891da177e4SLinus Torvalds| Change integer stack to look like trace stack 3901da177e4SLinus Torvalds| The address of the instruction that caused the 3911da177e4SLinus Torvalds| exception is already in the integer stack (is 3921da177e4SLinus Torvalds| the same as the saved friar) 3931da177e4SLinus Torvalds| 3941da177e4SLinus Torvalds| If the current frame is already a 6-word stack then all 3951da177e4SLinus Torvalds| that needs to be done is to change the vector# to TRACE. 3961da177e4SLinus Torvalds| If the frame is only a 4-word stack (meaning we got here 3971da177e4SLinus Torvalds| on an Unsupported data type exception), then we need to grow 3981da177e4SLinus Torvalds| the stack an extra 2 words and get the FPIAR from the FPU. 3991da177e4SLinus Torvalds| 4001da177e4SLinus Torvaldsg_trace: 4011da177e4SLinus Torvalds bftst EXC_VEC-4(%sp){#0:#4} 4021da177e4SLinus Torvalds bne g_easy 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds subw #4,%sp | make room 4051da177e4SLinus Torvalds movel 4(%sp),(%sp) 4061da177e4SLinus Torvalds movel 8(%sp),4(%sp) 4071da177e4SLinus Torvalds subw #BUSY_SIZE,%sp 4081da177e4SLinus Torvalds fsave (%sp) 4091da177e4SLinus Torvalds fmovel %fpiar,BUSY_SIZE+EXC_EA-4(%sp) 4101da177e4SLinus Torvalds frestore (%sp) 4111da177e4SLinus Torvalds addw #BUSY_SIZE,%sp 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvaldsg_easy: 4141da177e4SLinus Torvalds movew #TRACE_VEC,EXC_VEC-4(%a7) 4151da177e4SLinus Torvalds bral real_trace 4161da177e4SLinus Torvalds| 4171da177e4SLinus Torvalds| This is a work-around for hardware bug 1384. 4181da177e4SLinus Torvalds| 4191da177e4SLinus Torvaldsbug1384: 4201da177e4SLinus Torvalds link %a5,#0 4211da177e4SLinus Torvalds fsave -(%sp) 4221da177e4SLinus Torvalds cmpib #0x41,(%sp) | check for correct frame 4231da177e4SLinus Torvalds beq frame_41 4241da177e4SLinus Torvalds bgt nofix | if more advanced mask, do nada 4251da177e4SLinus Torvalds 4261da177e4SLinus Torvaldsframe_40: 4271da177e4SLinus Torvalds tstb 1(%sp) | check to see if idle 4281da177e4SLinus Torvalds bne notidle 4291da177e4SLinus Torvaldsidle40: 4301da177e4SLinus Torvalds clrl (%sp) | get rid of old fsave frame 4311da177e4SLinus Torvalds movel %d1,USER_D1(%a6) | save d1 4321da177e4SLinus Torvalds movew #8,%d1 | place unimp frame instead 4331da177e4SLinus Torvaldsloop40: clrl -(%sp) 4341da177e4SLinus Torvalds dbra %d1,loop40 4351da177e4SLinus Torvalds movel USER_D1(%a6),%d1 | restore d1 4361da177e4SLinus Torvalds movel #0x40280000,-(%sp) 4371da177e4SLinus Torvalds frestore (%sp)+ 4381da177e4SLinus Torvalds unlk %a5 4391da177e4SLinus Torvalds rts 4401da177e4SLinus Torvalds 4411da177e4SLinus Torvaldsframe_41: 4421da177e4SLinus Torvalds tstb 1(%sp) | check to see if idle 4431da177e4SLinus Torvalds bne notidle 4441da177e4SLinus Torvaldsidle41: 4451da177e4SLinus Torvalds clrl (%sp) | get rid of old fsave frame 4461da177e4SLinus Torvalds movel %d1,USER_D1(%a6) | save d1 4471da177e4SLinus Torvalds movew #10,%d1 | place unimp frame instead 4481da177e4SLinus Torvaldsloop41: clrl -(%sp) 4491da177e4SLinus Torvalds dbra %d1,loop41 4501da177e4SLinus Torvalds movel USER_D1(%a6),%d1 | restore d1 4511da177e4SLinus Torvalds movel #0x41300000,-(%sp) 4521da177e4SLinus Torvalds frestore (%sp)+ 4531da177e4SLinus Torvalds unlk %a5 4541da177e4SLinus Torvalds rts 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvaldsnotidle: 4571da177e4SLinus Torvalds bclrb #etemp15_bit,-40(%a5) 4581da177e4SLinus Torvalds frestore (%sp)+ 4591da177e4SLinus Torvalds unlk %a5 4601da177e4SLinus Torvalds rts 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvaldsnofix: 4631da177e4SLinus Torvalds frestore (%sp)+ 4641da177e4SLinus Torvalds unlk %a5 4651da177e4SLinus Torvalds rts 4661da177e4SLinus Torvalds 4671da177e4SLinus Torvalds |end 468