18c2ecf20Sopenharmony_ci| 28c2ecf20Sopenharmony_ci| gen_except.sa 3.7 1/16/92 38c2ecf20Sopenharmony_ci| 48c2ecf20Sopenharmony_ci| gen_except --- FPSP routine to detect reportable exceptions 58c2ecf20Sopenharmony_ci| 68c2ecf20Sopenharmony_ci| This routine compares the exception enable byte of the 78c2ecf20Sopenharmony_ci| user_fpcr on the stack with the exception status byte 88c2ecf20Sopenharmony_ci| of the user_fpsr. 98c2ecf20Sopenharmony_ci| 108c2ecf20Sopenharmony_ci| Any routine which may report an exceptions must load 118c2ecf20Sopenharmony_ci| the stack frame in memory with the exceptional operand(s). 128c2ecf20Sopenharmony_ci| 138c2ecf20Sopenharmony_ci| Priority for exceptions is: 148c2ecf20Sopenharmony_ci| 158c2ecf20Sopenharmony_ci| Highest: bsun 168c2ecf20Sopenharmony_ci| snan 178c2ecf20Sopenharmony_ci| operr 188c2ecf20Sopenharmony_ci| ovfl 198c2ecf20Sopenharmony_ci| unfl 208c2ecf20Sopenharmony_ci| dz 218c2ecf20Sopenharmony_ci| inex2 228c2ecf20Sopenharmony_ci| Lowest: inex1 238c2ecf20Sopenharmony_ci| 248c2ecf20Sopenharmony_ci| Note: The IEEE standard specifies that inex2 is to be 258c2ecf20Sopenharmony_ci| reported if ovfl occurs and the ovfl enable bit is not 268c2ecf20Sopenharmony_ci| set but the inex2 enable bit is. 278c2ecf20Sopenharmony_ci| 288c2ecf20Sopenharmony_ci| 298c2ecf20Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 308c2ecf20Sopenharmony_ci| All Rights Reserved 318c2ecf20Sopenharmony_ci| 328c2ecf20Sopenharmony_ci| For details on the license for this file, please see the 338c2ecf20Sopenharmony_ci| file, README, in this same directory. 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ciGEN_EXCEPT: |idnt 2,1 | Motorola 040 Floating Point Software Package 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci |section 8 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#include "fpsp.h" 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci |xref real_trace 428c2ecf20Sopenharmony_ci |xref fpsp_done 438c2ecf20Sopenharmony_ci |xref fpsp_fmt_error 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ciexc_tbl: 468c2ecf20Sopenharmony_ci .long bsun_exc 478c2ecf20Sopenharmony_ci .long commonE1 488c2ecf20Sopenharmony_ci .long commonE1 498c2ecf20Sopenharmony_ci .long ovfl_unfl 508c2ecf20Sopenharmony_ci .long ovfl_unfl 518c2ecf20Sopenharmony_ci .long commonE1 528c2ecf20Sopenharmony_ci .long commonE3 538c2ecf20Sopenharmony_ci .long commonE3 548c2ecf20Sopenharmony_ci .long no_match 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci .global gen_except 578c2ecf20Sopenharmony_cigen_except: 588c2ecf20Sopenharmony_ci cmpib #IDLE_SIZE-4,1(%a7) |test for idle frame 598c2ecf20Sopenharmony_ci beq do_check |go handle idle frame 608c2ecf20Sopenharmony_ci cmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame 618c2ecf20Sopenharmony_ci beqs unimp_x |go handle unimp frame 628c2ecf20Sopenharmony_ci cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame 638c2ecf20Sopenharmony_ci beqs unimp_x |go handle unimp frame 648c2ecf20Sopenharmony_ci cmpib #BUSY_SIZE-4,1(%a7) |if size <> $60, fmt error 658c2ecf20Sopenharmony_ci bnel fpsp_fmt_error 668c2ecf20Sopenharmony_ci leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 so fpsp.h 678c2ecf20Sopenharmony_ci| ;equates will work 688c2ecf20Sopenharmony_ci| Fix up the new busy frame with entries from the unimp frame 698c2ecf20Sopenharmony_ci| 708c2ecf20Sopenharmony_ci movel ETEMP_EX(%a6),ETEMP_EX(%a1) |copy etemp from unimp 718c2ecf20Sopenharmony_ci movel ETEMP_HI(%a6),ETEMP_HI(%a1) |frame to busy frame 728c2ecf20Sopenharmony_ci movel ETEMP_LO(%a6),ETEMP_LO(%a1) 738c2ecf20Sopenharmony_ci movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp 748c2ecf20Sopenharmony_ci movel CMDREG1B(%a6),%d0 |fix cmd1b to make it 758c2ecf20Sopenharmony_ci andl #0x03c30000,%d0 |work for cmd3b 768c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2 778c2ecf20Sopenharmony_ci lsll #5,%d1 788c2ecf20Sopenharmony_ci swap %d1 798c2ecf20Sopenharmony_ci orl %d1,%d0 |put it in the right place 808c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5 818c2ecf20Sopenharmony_ci lsll #2,%d1 828c2ecf20Sopenharmony_ci swap %d1 838c2ecf20Sopenharmony_ci orl %d1,%d0 |put them in the right place 848c2ecf20Sopenharmony_ci movel %d0,CMDREG3B(%a1) |in the busy frame 858c2ecf20Sopenharmony_ci| 868c2ecf20Sopenharmony_ci| Or in the FPSR from the emulation with the USER_FPSR on the stack. 878c2ecf20Sopenharmony_ci| 888c2ecf20Sopenharmony_ci fmovel %FPSR,%d0 898c2ecf20Sopenharmony_ci orl %d0,USER_FPSR(%a6) 908c2ecf20Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits 918c2ecf20Sopenharmony_ci orl #sx_mask,E_BYTE(%a1) 928c2ecf20Sopenharmony_ci bra do_clean 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci| 958c2ecf20Sopenharmony_ci| Frame is an unimp frame possible resulting from an fmove <ea>,fp0 968c2ecf20Sopenharmony_ci| that caused an exception 978c2ecf20Sopenharmony_ci| 988c2ecf20Sopenharmony_ci| a1 is modified to point into the new frame allowing fpsp equates 998c2ecf20Sopenharmony_ci| to be valid. 1008c2ecf20Sopenharmony_ci| 1018c2ecf20Sopenharmony_ciunimp_x: 1028c2ecf20Sopenharmony_ci cmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame 1038c2ecf20Sopenharmony_ci bnes test_rev 1048c2ecf20Sopenharmony_ci leal UNIMP_40_SIZE+LOCAL_SIZE(%a7),%a1 1058c2ecf20Sopenharmony_ci bras unimp_con 1068c2ecf20Sopenharmony_citest_rev: 1078c2ecf20Sopenharmony_ci cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame 1088c2ecf20Sopenharmony_ci bnel fpsp_fmt_error |if not $28 or $30 1098c2ecf20Sopenharmony_ci leal UNIMP_41_SIZE+LOCAL_SIZE(%a7),%a1 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ciunimp_con: 1128c2ecf20Sopenharmony_ci| 1138c2ecf20Sopenharmony_ci| Fix up the new unimp frame with entries from the old unimp frame 1148c2ecf20Sopenharmony_ci| 1158c2ecf20Sopenharmony_ci movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp 1168c2ecf20Sopenharmony_ci| 1178c2ecf20Sopenharmony_ci| Or in the FPSR from the emulation with the USER_FPSR on the stack. 1188c2ecf20Sopenharmony_ci| 1198c2ecf20Sopenharmony_ci fmovel %FPSR,%d0 1208c2ecf20Sopenharmony_ci orl %d0,USER_FPSR(%a6) 1218c2ecf20Sopenharmony_ci bra do_clean 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci| 1248c2ecf20Sopenharmony_ci| Frame is idle, so check for exceptions reported through 1258c2ecf20Sopenharmony_ci| USER_FPSR and set the unimp frame accordingly. 1268c2ecf20Sopenharmony_ci| A7 must be incremented to the point before the 1278c2ecf20Sopenharmony_ci| idle fsave vector to the unimp vector. 1288c2ecf20Sopenharmony_ci| 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cido_check: 1318c2ecf20Sopenharmony_ci addl #4,%a7 |point A7 back to unimp frame 1328c2ecf20Sopenharmony_ci| 1338c2ecf20Sopenharmony_ci| Or in the FPSR from the emulation with the USER_FPSR on the stack. 1348c2ecf20Sopenharmony_ci| 1358c2ecf20Sopenharmony_ci fmovel %FPSR,%d0 1368c2ecf20Sopenharmony_ci orl %d0,USER_FPSR(%a6) 1378c2ecf20Sopenharmony_ci| 1388c2ecf20Sopenharmony_ci| On a busy frame, we must clear the nmnexc bits. 1398c2ecf20Sopenharmony_ci| 1408c2ecf20Sopenharmony_ci cmpib #BUSY_SIZE-4,1(%a7) |check frame type 1418c2ecf20Sopenharmony_ci bnes check_fr |if busy, clr nmnexc 1428c2ecf20Sopenharmony_ci clrw NMNEXC(%a6) |clr nmnexc & nmcexc 1438c2ecf20Sopenharmony_ci btstb #5,CMDREG1B(%a6) |test for fmove out 1448c2ecf20Sopenharmony_ci bnes frame_com 1458c2ecf20Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a6) |set exc bits 1468c2ecf20Sopenharmony_ci orl #sx_mask,E_BYTE(%a6) 1478c2ecf20Sopenharmony_ci bras frame_com 1488c2ecf20Sopenharmony_cicheck_fr: 1498c2ecf20Sopenharmony_ci cmpb #UNIMP_40_SIZE-4,1(%a7) 1508c2ecf20Sopenharmony_ci beqs frame_com 1518c2ecf20Sopenharmony_ci clrw NMNEXC(%a6) 1528c2ecf20Sopenharmony_ciframe_com: 1538c2ecf20Sopenharmony_ci moveb FPCR_ENABLE(%a6),%d0 |get fpcr enable byte 1548c2ecf20Sopenharmony_ci andb FPSR_EXCEPT(%a6),%d0 |and in the fpsr exc byte 1558c2ecf20Sopenharmony_ci bfffo %d0{#24:#8},%d1 |test for first set bit 1568c2ecf20Sopenharmony_ci leal exc_tbl,%a0 |load jmp table address 1578c2ecf20Sopenharmony_ci subib #24,%d1 |normalize bit offset to 0-8 1588c2ecf20Sopenharmony_ci movel (%a0,%d1.w*4),%a0 |load routine address based 1598c2ecf20Sopenharmony_ci| ;based on first enabled exc 1608c2ecf20Sopenharmony_ci jmp (%a0) |jump to routine 1618c2ecf20Sopenharmony_ci| 1628c2ecf20Sopenharmony_ci| Bsun is not possible in unimp or unsupp 1638c2ecf20Sopenharmony_ci| 1648c2ecf20Sopenharmony_cibsun_exc: 1658c2ecf20Sopenharmony_ci bra do_clean 1668c2ecf20Sopenharmony_ci| 1678c2ecf20Sopenharmony_ci| The typical work to be done to the unimp frame to report an 1688c2ecf20Sopenharmony_ci| exception is to set the E1/E3 byte and clr the U flag. 1698c2ecf20Sopenharmony_ci| commonE1 does this for E1 exceptions, which are snan, 1708c2ecf20Sopenharmony_ci| operr, and dz. commonE3 does this for E3 exceptions, which 1718c2ecf20Sopenharmony_ci| are inex2 and inex1, and also clears the E1 exception bit 1728c2ecf20Sopenharmony_ci| left over from the unimp exception. 1738c2ecf20Sopenharmony_ci| 1748c2ecf20Sopenharmony_cicommonE1: 1758c2ecf20Sopenharmony_ci bsetb #E1,E_BYTE(%a6) |set E1 flag 1768c2ecf20Sopenharmony_ci bra commonE |go clean and exit 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cicommonE3: 1798c2ecf20Sopenharmony_ci tstb UFLG_TMP(%a6) |test flag for unsup/unimp state 1808c2ecf20Sopenharmony_ci bnes unsE3 1818c2ecf20Sopenharmony_ciuniE3: 1828c2ecf20Sopenharmony_ci bsetb #E3,E_BYTE(%a6) |set E3 flag 1838c2ecf20Sopenharmony_ci bclrb #E1,E_BYTE(%a6) |clr E1 from unimp 1848c2ecf20Sopenharmony_ci bra commonE 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ciunsE3: 1878c2ecf20Sopenharmony_ci tstb RES_FLG(%a6) 1888c2ecf20Sopenharmony_ci bnes unsE3_0 1898c2ecf20Sopenharmony_ciunsE3_1: 1908c2ecf20Sopenharmony_ci bsetb #E3,E_BYTE(%a6) |set E3 flag 1918c2ecf20Sopenharmony_ciunsE3_0: 1928c2ecf20Sopenharmony_ci bclrb #E1,E_BYTE(%a6) |clr E1 flag 1938c2ecf20Sopenharmony_ci movel CMDREG1B(%a6),%d0 1948c2ecf20Sopenharmony_ci andl #0x03c30000,%d0 |work for cmd3b 1958c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2 1968c2ecf20Sopenharmony_ci lsll #5,%d1 1978c2ecf20Sopenharmony_ci swap %d1 1988c2ecf20Sopenharmony_ci orl %d1,%d0 |put it in the right place 1998c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5 2008c2ecf20Sopenharmony_ci lsll #2,%d1 2018c2ecf20Sopenharmony_ci swap %d1 2028c2ecf20Sopenharmony_ci orl %d1,%d0 |put them in the right place 2038c2ecf20Sopenharmony_ci movel %d0,CMDREG3B(%a6) |in the busy frame 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cicommonE: 2068c2ecf20Sopenharmony_ci bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimp 2078c2ecf20Sopenharmony_ci bra do_clean |go clean and exit 2088c2ecf20Sopenharmony_ci| 2098c2ecf20Sopenharmony_ci| No bits in the enable byte match existing exceptions. Check for 2108c2ecf20Sopenharmony_ci| the case of the ovfl exc without the ovfl enabled, but with 2118c2ecf20Sopenharmony_ci| inex2 enabled. 2128c2ecf20Sopenharmony_ci| 2138c2ecf20Sopenharmony_cino_match: 2148c2ecf20Sopenharmony_ci btstb #inex2_bit,FPCR_ENABLE(%a6) |check for ovfl/inex2 case 2158c2ecf20Sopenharmony_ci beqs no_exc |if clear, exit 2168c2ecf20Sopenharmony_ci btstb #ovfl_bit,FPSR_EXCEPT(%a6) |now check ovfl 2178c2ecf20Sopenharmony_ci beqs no_exc |if clear, exit 2188c2ecf20Sopenharmony_ci bras ovfl_unfl |go to unfl_ovfl to determine if 2198c2ecf20Sopenharmony_ci| ;it is an unsupp or unimp exc 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci| No exceptions are to be reported. If the instruction was 2228c2ecf20Sopenharmony_ci| unimplemented, no FPU restore is necessary. If it was 2238c2ecf20Sopenharmony_ci| unsupported, we must perform the restore. 2248c2ecf20Sopenharmony_cino_exc: 2258c2ecf20Sopenharmony_ci tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state 2268c2ecf20Sopenharmony_ci beqs uni_no_exc 2278c2ecf20Sopenharmony_ciuns_no_exc: 2288c2ecf20Sopenharmony_ci tstb RES_FLG(%a6) |check if frestore is needed 2298c2ecf20Sopenharmony_ci bne do_clean |if clear, no frestore needed 2308c2ecf20Sopenharmony_ciuni_no_exc: 2318c2ecf20Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 2328c2ecf20Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 2338c2ecf20Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 2348c2ecf20Sopenharmony_ci unlk %a6 2358c2ecf20Sopenharmony_ci bra finish_up 2368c2ecf20Sopenharmony_ci| 2378c2ecf20Sopenharmony_ci| Unsupported Data Type Handler: 2388c2ecf20Sopenharmony_ci| Ovfl: 2398c2ecf20Sopenharmony_ci| An fmoveout that results in an overflow is reported this way. 2408c2ecf20Sopenharmony_ci| Unfl: 2418c2ecf20Sopenharmony_ci| An fmoveout that results in an underflow is reported this way. 2428c2ecf20Sopenharmony_ci| 2438c2ecf20Sopenharmony_ci| Unimplemented Instruction Handler: 2448c2ecf20Sopenharmony_ci| Ovfl: 2458c2ecf20Sopenharmony_ci| Only scosh, setox, ssinh, stwotox, and scale can set overflow in 2468c2ecf20Sopenharmony_ci| this manner. 2478c2ecf20Sopenharmony_ci| Unfl: 2488c2ecf20Sopenharmony_ci| Stwotox, setox, and scale can set underflow in this manner. 2498c2ecf20Sopenharmony_ci| Any of the other Library Routines such that f(x)=x in which 2508c2ecf20Sopenharmony_ci| x is an extended denorm can report an underflow exception. 2518c2ecf20Sopenharmony_ci| It is the responsibility of the exception-causing exception 2528c2ecf20Sopenharmony_ci| to make sure that WBTEMP is correct. 2538c2ecf20Sopenharmony_ci| 2548c2ecf20Sopenharmony_ci| The exceptional operand is in FP_SCR1. 2558c2ecf20Sopenharmony_ci| 2568c2ecf20Sopenharmony_ciovfl_unfl: 2578c2ecf20Sopenharmony_ci tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state 2588c2ecf20Sopenharmony_ci beqs ofuf_con 2598c2ecf20Sopenharmony_ci| 2608c2ecf20Sopenharmony_ci| The caller was from an unsupported data type trap. Test if the 2618c2ecf20Sopenharmony_ci| caller set CU_ONLY. If so, the exceptional operand is expected in 2628c2ecf20Sopenharmony_ci| FPTEMP, rather than WBTEMP. 2638c2ecf20Sopenharmony_ci| 2648c2ecf20Sopenharmony_ci tstb CU_ONLY(%a6) |test if inst is cu-only 2658c2ecf20Sopenharmony_ci beq unsE3 2668c2ecf20Sopenharmony_ci| move.w #$fe,CU_SAVEPC(%a6) 2678c2ecf20Sopenharmony_ci clrb CU_SAVEPC(%a6) 2688c2ecf20Sopenharmony_ci bsetb #E1,E_BYTE(%a6) |set E1 exception flag 2698c2ecf20Sopenharmony_ci movew ETEMP_EX(%a6),FPTEMP_EX(%a6) 2708c2ecf20Sopenharmony_ci movel ETEMP_HI(%a6),FPTEMP_HI(%a6) 2718c2ecf20Sopenharmony_ci movel ETEMP_LO(%a6),FPTEMP_LO(%a6) 2728c2ecf20Sopenharmony_ci bsetb #fptemp15_bit,DTAG(%a6) |set fpte15 2738c2ecf20Sopenharmony_ci bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimp 2748c2ecf20Sopenharmony_ci bra do_clean |go clean and exit 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ciofuf_con: 2778c2ecf20Sopenharmony_ci moveb (%a7),VER_TMP(%a6) |save version number 2788c2ecf20Sopenharmony_ci cmpib #BUSY_SIZE-4,1(%a7) |check for busy frame 2798c2ecf20Sopenharmony_ci beqs busy_fr |if unimp, grow to busy 2808c2ecf20Sopenharmony_ci cmpib #VER_40,(%a7) |test for orig unimp frame 2818c2ecf20Sopenharmony_ci bnes try_41 |if not, test for rev frame 2828c2ecf20Sopenharmony_ci moveql #13,%d0 |need to zero 14 lwords 2838c2ecf20Sopenharmony_ci bras ofuf_fin 2848c2ecf20Sopenharmony_citry_41: 2858c2ecf20Sopenharmony_ci cmpib #VER_41,(%a7) |test for rev unimp frame 2868c2ecf20Sopenharmony_ci bnel fpsp_fmt_error |if neither, exit with error 2878c2ecf20Sopenharmony_ci moveql #11,%d0 |need to zero 12 lwords 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ciofuf_fin: 2908c2ecf20Sopenharmony_ci clrl (%a7) 2918c2ecf20Sopenharmony_ciloop1: 2928c2ecf20Sopenharmony_ci clrl -(%a7) |clear and dec a7 2938c2ecf20Sopenharmony_ci dbra %d0,loop1 2948c2ecf20Sopenharmony_ci moveb VER_TMP(%a6),(%a7) 2958c2ecf20Sopenharmony_ci moveb #BUSY_SIZE-4,1(%a7) |write busy fmt word. 2968c2ecf20Sopenharmony_cibusy_fr: 2978c2ecf20Sopenharmony_ci movel FP_SCR1(%a6),WBTEMP_EX(%a6) |write 2988c2ecf20Sopenharmony_ci movel FP_SCR1+4(%a6),WBTEMP_HI(%a6) |exceptional op to 2998c2ecf20Sopenharmony_ci movel FP_SCR1+8(%a6),WBTEMP_LO(%a6) |wbtemp 3008c2ecf20Sopenharmony_ci bsetb #E3,E_BYTE(%a6) |set E3 flag 3018c2ecf20Sopenharmony_ci bclrb #E1,E_BYTE(%a6) |make sure E1 is clear 3028c2ecf20Sopenharmony_ci bclrb #UFLAG,T_BYTE(%a6) |clr U flag 3038c2ecf20Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 3048c2ecf20Sopenharmony_ci orl #sx_mask,E_BYTE(%a6) 3058c2ecf20Sopenharmony_ci movel CMDREG1B(%a6),%d0 |fix cmd1b to make it 3068c2ecf20Sopenharmony_ci andl #0x03c30000,%d0 |work for cmd3b 3078c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2 3088c2ecf20Sopenharmony_ci lsll #5,%d1 3098c2ecf20Sopenharmony_ci swap %d1 3108c2ecf20Sopenharmony_ci orl %d1,%d0 |put it in the right place 3118c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5 3128c2ecf20Sopenharmony_ci lsll #2,%d1 3138c2ecf20Sopenharmony_ci swap %d1 3148c2ecf20Sopenharmony_ci orl %d1,%d0 |put them in the right place 3158c2ecf20Sopenharmony_ci movel %d0,CMDREG3B(%a6) |in the busy frame 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci| 3188c2ecf20Sopenharmony_ci| Check if the frame to be restored is busy or unimp. 3198c2ecf20Sopenharmony_ci|** NOTE *** Bug fix for errata (0d43b #3) 3208c2ecf20Sopenharmony_ci| If the frame is unimp, we must create a busy frame to 3218c2ecf20Sopenharmony_ci| fix the bug with the nmnexc bits in cases in which they 3228c2ecf20Sopenharmony_ci| are set by a previous instruction and not cleared by 3238c2ecf20Sopenharmony_ci| the save. The frame will be unimp only if the final 3248c2ecf20Sopenharmony_ci| instruction in an emulation routine caused the exception 3258c2ecf20Sopenharmony_ci| by doing an fmove <ea>,fp0. The exception operand, in 3268c2ecf20Sopenharmony_ci| internal format, is in fptemp. 3278c2ecf20Sopenharmony_ci| 3288c2ecf20Sopenharmony_cido_clean: 3298c2ecf20Sopenharmony_ci cmpib #UNIMP_40_SIZE-4,1(%a7) 3308c2ecf20Sopenharmony_ci bnes do_con 3318c2ecf20Sopenharmony_ci moveql #13,%d0 |in orig, need to zero 14 lwords 3328c2ecf20Sopenharmony_ci bras do_build 3338c2ecf20Sopenharmony_cido_con: 3348c2ecf20Sopenharmony_ci cmpib #UNIMP_41_SIZE-4,1(%a7) 3358c2ecf20Sopenharmony_ci bnes do_restore |frame must be busy 3368c2ecf20Sopenharmony_ci moveql #11,%d0 |in rev, need to zero 12 lwords 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cido_build: 3398c2ecf20Sopenharmony_ci moveb (%a7),VER_TMP(%a6) 3408c2ecf20Sopenharmony_ci clrl (%a7) 3418c2ecf20Sopenharmony_ciloop2: 3428c2ecf20Sopenharmony_ci clrl -(%a7) |clear and dec a7 3438c2ecf20Sopenharmony_ci dbra %d0,loop2 3448c2ecf20Sopenharmony_ci| 3458c2ecf20Sopenharmony_ci| Use a1 as pointer into new frame. a6 is not correct if an unimp or 3468c2ecf20Sopenharmony_ci| busy frame was created as the result of an exception on the final 3478c2ecf20Sopenharmony_ci| instruction of an emulation routine. 3488c2ecf20Sopenharmony_ci| 3498c2ecf20Sopenharmony_ci| We need to set the nmcexc bits if the exception is E1. Otherwise, 3508c2ecf20Sopenharmony_ci| the exc taken will be inex2. 3518c2ecf20Sopenharmony_ci| 3528c2ecf20Sopenharmony_ci leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 for new frame 3538c2ecf20Sopenharmony_ci moveb VER_TMP(%a6),(%a7) |write busy fmt word 3548c2ecf20Sopenharmony_ci moveb #BUSY_SIZE-4,1(%a7) 3558c2ecf20Sopenharmony_ci movel FP_SCR1(%a6),WBTEMP_EX(%a1) |write 3568c2ecf20Sopenharmony_ci movel FP_SCR1+4(%a6),WBTEMP_HI(%a1) |exceptional op to 3578c2ecf20Sopenharmony_ci movel FP_SCR1+8(%a6),WBTEMP_LO(%a1) |wbtemp 3588c2ecf20Sopenharmony_ci| btst.b #E1,E_BYTE(%a1) 3598c2ecf20Sopenharmony_ci| beq.b do_restore 3608c2ecf20Sopenharmony_ci bfextu USER_FPSR(%a6){#17:#4},%d0 |get snan/operr/ovfl/unfl bits 3618c2ecf20Sopenharmony_ci bfins %d0,NMCEXC(%a1){#4:#4} |and insert them in nmcexc 3628c2ecf20Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits 3638c2ecf20Sopenharmony_ci orl #sx_mask,E_BYTE(%a1) 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_cido_restore: 3668c2ecf20Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 3678c2ecf20Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 3688c2ecf20Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 3698c2ecf20Sopenharmony_ci frestore (%a7)+ 3708c2ecf20Sopenharmony_ci tstb RES_FLG(%a6) |RES_FLG indicates a "continuation" frame 3718c2ecf20Sopenharmony_ci beq cont 3728c2ecf20Sopenharmony_ci bsr bug1384 3738c2ecf20Sopenharmony_cicont: 3748c2ecf20Sopenharmony_ci unlk %a6 3758c2ecf20Sopenharmony_ci| 3768c2ecf20Sopenharmony_ci| If trace mode enabled, then go to trace handler. This handler 3778c2ecf20Sopenharmony_ci| cannot have any fp instructions. If there are fp inst's and an 3788c2ecf20Sopenharmony_ci| exception has been restored into the machine then the exception 3798c2ecf20Sopenharmony_ci| will occur upon execution of the fp inst. This is not desirable 3808c2ecf20Sopenharmony_ci| in the kernel (supervisor mode). See MC68040 manual Section 9.3.8. 3818c2ecf20Sopenharmony_ci| 3828c2ecf20Sopenharmony_cifinish_up: 3838c2ecf20Sopenharmony_ci btstb #7,(%a7) |test T1 in SR 3848c2ecf20Sopenharmony_ci bnes g_trace 3858c2ecf20Sopenharmony_ci btstb #6,(%a7) |test T0 in SR 3868c2ecf20Sopenharmony_ci bnes g_trace 3878c2ecf20Sopenharmony_ci bral fpsp_done 3888c2ecf20Sopenharmony_ci| 3898c2ecf20Sopenharmony_ci| Change integer stack to look like trace stack 3908c2ecf20Sopenharmony_ci| The address of the instruction that caused the 3918c2ecf20Sopenharmony_ci| exception is already in the integer stack (is 3928c2ecf20Sopenharmony_ci| the same as the saved friar) 3938c2ecf20Sopenharmony_ci| 3948c2ecf20Sopenharmony_ci| If the current frame is already a 6-word stack then all 3958c2ecf20Sopenharmony_ci| that needs to be done is to change the vector# to TRACE. 3968c2ecf20Sopenharmony_ci| If the frame is only a 4-word stack (meaning we got here 3978c2ecf20Sopenharmony_ci| on an Unsupported data type exception), then we need to grow 3988c2ecf20Sopenharmony_ci| the stack an extra 2 words and get the FPIAR from the FPU. 3998c2ecf20Sopenharmony_ci| 4008c2ecf20Sopenharmony_cig_trace: 4018c2ecf20Sopenharmony_ci bftst EXC_VEC-4(%sp){#0:#4} 4028c2ecf20Sopenharmony_ci bne g_easy 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci subw #4,%sp | make room 4058c2ecf20Sopenharmony_ci movel 4(%sp),(%sp) 4068c2ecf20Sopenharmony_ci movel 8(%sp),4(%sp) 4078c2ecf20Sopenharmony_ci subw #BUSY_SIZE,%sp 4088c2ecf20Sopenharmony_ci fsave (%sp) 4098c2ecf20Sopenharmony_ci fmovel %fpiar,BUSY_SIZE+EXC_EA-4(%sp) 4108c2ecf20Sopenharmony_ci frestore (%sp) 4118c2ecf20Sopenharmony_ci addw #BUSY_SIZE,%sp 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cig_easy: 4148c2ecf20Sopenharmony_ci movew #TRACE_VEC,EXC_VEC-4(%a7) 4158c2ecf20Sopenharmony_ci bral real_trace 4168c2ecf20Sopenharmony_ci| 4178c2ecf20Sopenharmony_ci| This is a work-around for hardware bug 1384. 4188c2ecf20Sopenharmony_ci| 4198c2ecf20Sopenharmony_cibug1384: 4208c2ecf20Sopenharmony_ci link %a5,#0 4218c2ecf20Sopenharmony_ci fsave -(%sp) 4228c2ecf20Sopenharmony_ci cmpib #0x41,(%sp) | check for correct frame 4238c2ecf20Sopenharmony_ci beq frame_41 4248c2ecf20Sopenharmony_ci bgt nofix | if more advanced mask, do nada 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ciframe_40: 4278c2ecf20Sopenharmony_ci tstb 1(%sp) | check to see if idle 4288c2ecf20Sopenharmony_ci bne notidle 4298c2ecf20Sopenharmony_ciidle40: 4308c2ecf20Sopenharmony_ci clrl (%sp) | get rid of old fsave frame 4318c2ecf20Sopenharmony_ci movel %d1,USER_D1(%a6) | save d1 4328c2ecf20Sopenharmony_ci movew #8,%d1 | place unimp frame instead 4338c2ecf20Sopenharmony_ciloop40: clrl -(%sp) 4348c2ecf20Sopenharmony_ci dbra %d1,loop40 4358c2ecf20Sopenharmony_ci movel USER_D1(%a6),%d1 | restore d1 4368c2ecf20Sopenharmony_ci movel #0x40280000,-(%sp) 4378c2ecf20Sopenharmony_ci frestore (%sp)+ 4388c2ecf20Sopenharmony_ci unlk %a5 4398c2ecf20Sopenharmony_ci rts 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ciframe_41: 4428c2ecf20Sopenharmony_ci tstb 1(%sp) | check to see if idle 4438c2ecf20Sopenharmony_ci bne notidle 4448c2ecf20Sopenharmony_ciidle41: 4458c2ecf20Sopenharmony_ci clrl (%sp) | get rid of old fsave frame 4468c2ecf20Sopenharmony_ci movel %d1,USER_D1(%a6) | save d1 4478c2ecf20Sopenharmony_ci movew #10,%d1 | place unimp frame instead 4488c2ecf20Sopenharmony_ciloop41: clrl -(%sp) 4498c2ecf20Sopenharmony_ci dbra %d1,loop41 4508c2ecf20Sopenharmony_ci movel USER_D1(%a6),%d1 | restore d1 4518c2ecf20Sopenharmony_ci movel #0x41300000,-(%sp) 4528c2ecf20Sopenharmony_ci frestore (%sp)+ 4538c2ecf20Sopenharmony_ci unlk %a5 4548c2ecf20Sopenharmony_ci rts 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_cinotidle: 4578c2ecf20Sopenharmony_ci bclrb #etemp15_bit,-40(%a5) 4588c2ecf20Sopenharmony_ci frestore (%sp)+ 4598c2ecf20Sopenharmony_ci unlk %a5 4608c2ecf20Sopenharmony_ci rts 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_cinofix: 4638c2ecf20Sopenharmony_ci frestore (%sp)+ 4648c2ecf20Sopenharmony_ci unlk %a5 4658c2ecf20Sopenharmony_ci rts 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci |end 468