162306a36Sopenharmony_ci| 262306a36Sopenharmony_ci| gen_except.sa 3.7 1/16/92 362306a36Sopenharmony_ci| 462306a36Sopenharmony_ci| gen_except --- FPSP routine to detect reportable exceptions 562306a36Sopenharmony_ci| 662306a36Sopenharmony_ci| This routine compares the exception enable byte of the 762306a36Sopenharmony_ci| user_fpcr on the stack with the exception status byte 862306a36Sopenharmony_ci| of the user_fpsr. 962306a36Sopenharmony_ci| 1062306a36Sopenharmony_ci| Any routine which may report an exceptions must load 1162306a36Sopenharmony_ci| the stack frame in memory with the exceptional operand(s). 1262306a36Sopenharmony_ci| 1362306a36Sopenharmony_ci| Priority for exceptions is: 1462306a36Sopenharmony_ci| 1562306a36Sopenharmony_ci| Highest: bsun 1662306a36Sopenharmony_ci| snan 1762306a36Sopenharmony_ci| operr 1862306a36Sopenharmony_ci| ovfl 1962306a36Sopenharmony_ci| unfl 2062306a36Sopenharmony_ci| dz 2162306a36Sopenharmony_ci| inex2 2262306a36Sopenharmony_ci| Lowest: inex1 2362306a36Sopenharmony_ci| 2462306a36Sopenharmony_ci| Note: The IEEE standard specifies that inex2 is to be 2562306a36Sopenharmony_ci| reported if ovfl occurs and the ovfl enable bit is not 2662306a36Sopenharmony_ci| set but the inex2 enable bit is. 2762306a36Sopenharmony_ci| 2862306a36Sopenharmony_ci| 2962306a36Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 3062306a36Sopenharmony_ci| All Rights Reserved 3162306a36Sopenharmony_ci| 3262306a36Sopenharmony_ci| For details on the license for this file, please see the 3362306a36Sopenharmony_ci| file, README, in this same directory. 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ciGEN_EXCEPT: |idnt 2,1 | Motorola 040 Floating Point Software Package 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci |section 8 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#include "fpsp.h" 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci |xref real_trace 4262306a36Sopenharmony_ci |xref fpsp_done 4362306a36Sopenharmony_ci |xref fpsp_fmt_error 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ciexc_tbl: 4662306a36Sopenharmony_ci .long bsun_exc 4762306a36Sopenharmony_ci .long commonE1 4862306a36Sopenharmony_ci .long commonE1 4962306a36Sopenharmony_ci .long ovfl_unfl 5062306a36Sopenharmony_ci .long ovfl_unfl 5162306a36Sopenharmony_ci .long commonE1 5262306a36Sopenharmony_ci .long commonE3 5362306a36Sopenharmony_ci .long commonE3 5462306a36Sopenharmony_ci .long no_match 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci .global gen_except 5762306a36Sopenharmony_cigen_except: 5862306a36Sopenharmony_ci cmpib #IDLE_SIZE-4,1(%a7) |test for idle frame 5962306a36Sopenharmony_ci beq do_check |go handle idle frame 6062306a36Sopenharmony_ci cmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame 6162306a36Sopenharmony_ci beqs unimp_x |go handle unimp frame 6262306a36Sopenharmony_ci cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame 6362306a36Sopenharmony_ci beqs unimp_x |go handle unimp frame 6462306a36Sopenharmony_ci cmpib #BUSY_SIZE-4,1(%a7) |if size <> $60, fmt error 6562306a36Sopenharmony_ci bnel fpsp_fmt_error 6662306a36Sopenharmony_ci leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 so fpsp.h 6762306a36Sopenharmony_ci| ;equates will work 6862306a36Sopenharmony_ci| Fix up the new busy frame with entries from the unimp frame 6962306a36Sopenharmony_ci| 7062306a36Sopenharmony_ci movel ETEMP_EX(%a6),ETEMP_EX(%a1) |copy etemp from unimp 7162306a36Sopenharmony_ci movel ETEMP_HI(%a6),ETEMP_HI(%a1) |frame to busy frame 7262306a36Sopenharmony_ci movel ETEMP_LO(%a6),ETEMP_LO(%a1) 7362306a36Sopenharmony_ci movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp 7462306a36Sopenharmony_ci movel CMDREG1B(%a6),%d0 |fix cmd1b to make it 7562306a36Sopenharmony_ci andl #0x03c30000,%d0 |work for cmd3b 7662306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2 7762306a36Sopenharmony_ci lsll #5,%d1 7862306a36Sopenharmony_ci swap %d1 7962306a36Sopenharmony_ci orl %d1,%d0 |put it in the right place 8062306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5 8162306a36Sopenharmony_ci lsll #2,%d1 8262306a36Sopenharmony_ci swap %d1 8362306a36Sopenharmony_ci orl %d1,%d0 |put them in the right place 8462306a36Sopenharmony_ci movel %d0,CMDREG3B(%a1) |in the busy frame 8562306a36Sopenharmony_ci| 8662306a36Sopenharmony_ci| Or in the FPSR from the emulation with the USER_FPSR on the stack. 8762306a36Sopenharmony_ci| 8862306a36Sopenharmony_ci fmovel %FPSR,%d0 8962306a36Sopenharmony_ci orl %d0,USER_FPSR(%a6) 9062306a36Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits 9162306a36Sopenharmony_ci orl #sx_mask,E_BYTE(%a1) 9262306a36Sopenharmony_ci bra do_clean 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci| 9562306a36Sopenharmony_ci| Frame is an unimp frame possible resulting from an fmove <ea>,fp0 9662306a36Sopenharmony_ci| that caused an exception 9762306a36Sopenharmony_ci| 9862306a36Sopenharmony_ci| a1 is modified to point into the new frame allowing fpsp equates 9962306a36Sopenharmony_ci| to be valid. 10062306a36Sopenharmony_ci| 10162306a36Sopenharmony_ciunimp_x: 10262306a36Sopenharmony_ci cmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame 10362306a36Sopenharmony_ci bnes test_rev 10462306a36Sopenharmony_ci leal UNIMP_40_SIZE+LOCAL_SIZE(%a7),%a1 10562306a36Sopenharmony_ci bras unimp_con 10662306a36Sopenharmony_citest_rev: 10762306a36Sopenharmony_ci cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame 10862306a36Sopenharmony_ci bnel fpsp_fmt_error |if not $28 or $30 10962306a36Sopenharmony_ci leal UNIMP_41_SIZE+LOCAL_SIZE(%a7),%a1 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ciunimp_con: 11262306a36Sopenharmony_ci| 11362306a36Sopenharmony_ci| Fix up the new unimp frame with entries from the old unimp frame 11462306a36Sopenharmony_ci| 11562306a36Sopenharmony_ci movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp 11662306a36Sopenharmony_ci| 11762306a36Sopenharmony_ci| Or in the FPSR from the emulation with the USER_FPSR on the stack. 11862306a36Sopenharmony_ci| 11962306a36Sopenharmony_ci fmovel %FPSR,%d0 12062306a36Sopenharmony_ci orl %d0,USER_FPSR(%a6) 12162306a36Sopenharmony_ci bra do_clean 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci| 12462306a36Sopenharmony_ci| Frame is idle, so check for exceptions reported through 12562306a36Sopenharmony_ci| USER_FPSR and set the unimp frame accordingly. 12662306a36Sopenharmony_ci| A7 must be incremented to the point before the 12762306a36Sopenharmony_ci| idle fsave vector to the unimp vector. 12862306a36Sopenharmony_ci| 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cido_check: 13162306a36Sopenharmony_ci addl #4,%a7 |point A7 back to unimp frame 13262306a36Sopenharmony_ci| 13362306a36Sopenharmony_ci| Or in the FPSR from the emulation with the USER_FPSR on the stack. 13462306a36Sopenharmony_ci| 13562306a36Sopenharmony_ci fmovel %FPSR,%d0 13662306a36Sopenharmony_ci orl %d0,USER_FPSR(%a6) 13762306a36Sopenharmony_ci| 13862306a36Sopenharmony_ci| On a busy frame, we must clear the nmnexc bits. 13962306a36Sopenharmony_ci| 14062306a36Sopenharmony_ci cmpib #BUSY_SIZE-4,1(%a7) |check frame type 14162306a36Sopenharmony_ci bnes check_fr |if busy, clr nmnexc 14262306a36Sopenharmony_ci clrw NMNEXC(%a6) |clr nmnexc & nmcexc 14362306a36Sopenharmony_ci btstb #5,CMDREG1B(%a6) |test for fmove out 14462306a36Sopenharmony_ci bnes frame_com 14562306a36Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a6) |set exc bits 14662306a36Sopenharmony_ci orl #sx_mask,E_BYTE(%a6) 14762306a36Sopenharmony_ci bras frame_com 14862306a36Sopenharmony_cicheck_fr: 14962306a36Sopenharmony_ci cmpb #UNIMP_40_SIZE-4,1(%a7) 15062306a36Sopenharmony_ci beqs frame_com 15162306a36Sopenharmony_ci clrw NMNEXC(%a6) 15262306a36Sopenharmony_ciframe_com: 15362306a36Sopenharmony_ci moveb FPCR_ENABLE(%a6),%d0 |get fpcr enable byte 15462306a36Sopenharmony_ci andb FPSR_EXCEPT(%a6),%d0 |and in the fpsr exc byte 15562306a36Sopenharmony_ci bfffo %d0{#24:#8},%d1 |test for first set bit 15662306a36Sopenharmony_ci leal exc_tbl,%a0 |load jmp table address 15762306a36Sopenharmony_ci subib #24,%d1 |normalize bit offset to 0-8 15862306a36Sopenharmony_ci movel (%a0,%d1.w*4),%a0 |load routine address based 15962306a36Sopenharmony_ci| ;based on first enabled exc 16062306a36Sopenharmony_ci jmp (%a0) |jump to routine 16162306a36Sopenharmony_ci| 16262306a36Sopenharmony_ci| Bsun is not possible in unimp or unsupp 16362306a36Sopenharmony_ci| 16462306a36Sopenharmony_cibsun_exc: 16562306a36Sopenharmony_ci bra do_clean 16662306a36Sopenharmony_ci| 16762306a36Sopenharmony_ci| The typical work to be done to the unimp frame to report an 16862306a36Sopenharmony_ci| exception is to set the E1/E3 byte and clr the U flag. 16962306a36Sopenharmony_ci| commonE1 does this for E1 exceptions, which are snan, 17062306a36Sopenharmony_ci| operr, and dz. commonE3 does this for E3 exceptions, which 17162306a36Sopenharmony_ci| are inex2 and inex1, and also clears the E1 exception bit 17262306a36Sopenharmony_ci| left over from the unimp exception. 17362306a36Sopenharmony_ci| 17462306a36Sopenharmony_cicommonE1: 17562306a36Sopenharmony_ci bsetb #E1,E_BYTE(%a6) |set E1 flag 17662306a36Sopenharmony_ci bra commonE |go clean and exit 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cicommonE3: 17962306a36Sopenharmony_ci tstb UFLG_TMP(%a6) |test flag for unsup/unimp state 18062306a36Sopenharmony_ci bnes unsE3 18162306a36Sopenharmony_ciuniE3: 18262306a36Sopenharmony_ci bsetb #E3,E_BYTE(%a6) |set E3 flag 18362306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) |clr E1 from unimp 18462306a36Sopenharmony_ci bra commonE 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ciunsE3: 18762306a36Sopenharmony_ci tstb RES_FLG(%a6) 18862306a36Sopenharmony_ci bnes unsE3_0 18962306a36Sopenharmony_ciunsE3_1: 19062306a36Sopenharmony_ci bsetb #E3,E_BYTE(%a6) |set E3 flag 19162306a36Sopenharmony_ciunsE3_0: 19262306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) |clr E1 flag 19362306a36Sopenharmony_ci movel CMDREG1B(%a6),%d0 19462306a36Sopenharmony_ci andl #0x03c30000,%d0 |work for cmd3b 19562306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2 19662306a36Sopenharmony_ci lsll #5,%d1 19762306a36Sopenharmony_ci swap %d1 19862306a36Sopenharmony_ci orl %d1,%d0 |put it in the right place 19962306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5 20062306a36Sopenharmony_ci lsll #2,%d1 20162306a36Sopenharmony_ci swap %d1 20262306a36Sopenharmony_ci orl %d1,%d0 |put them in the right place 20362306a36Sopenharmony_ci movel %d0,CMDREG3B(%a6) |in the busy frame 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cicommonE: 20662306a36Sopenharmony_ci bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimp 20762306a36Sopenharmony_ci bra do_clean |go clean and exit 20862306a36Sopenharmony_ci| 20962306a36Sopenharmony_ci| No bits in the enable byte match existing exceptions. Check for 21062306a36Sopenharmony_ci| the case of the ovfl exc without the ovfl enabled, but with 21162306a36Sopenharmony_ci| inex2 enabled. 21262306a36Sopenharmony_ci| 21362306a36Sopenharmony_cino_match: 21462306a36Sopenharmony_ci btstb #inex2_bit,FPCR_ENABLE(%a6) |check for ovfl/inex2 case 21562306a36Sopenharmony_ci beqs no_exc |if clear, exit 21662306a36Sopenharmony_ci btstb #ovfl_bit,FPSR_EXCEPT(%a6) |now check ovfl 21762306a36Sopenharmony_ci beqs no_exc |if clear, exit 21862306a36Sopenharmony_ci bras ovfl_unfl |go to unfl_ovfl to determine if 21962306a36Sopenharmony_ci| ;it is an unsupp or unimp exc 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci| No exceptions are to be reported. If the instruction was 22262306a36Sopenharmony_ci| unimplemented, no FPU restore is necessary. If it was 22362306a36Sopenharmony_ci| unsupported, we must perform the restore. 22462306a36Sopenharmony_cino_exc: 22562306a36Sopenharmony_ci tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state 22662306a36Sopenharmony_ci beqs uni_no_exc 22762306a36Sopenharmony_ciuns_no_exc: 22862306a36Sopenharmony_ci tstb RES_FLG(%a6) |check if frestore is needed 22962306a36Sopenharmony_ci bne do_clean |if clear, no frestore needed 23062306a36Sopenharmony_ciuni_no_exc: 23162306a36Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 23262306a36Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 23362306a36Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 23462306a36Sopenharmony_ci unlk %a6 23562306a36Sopenharmony_ci bra finish_up 23662306a36Sopenharmony_ci| 23762306a36Sopenharmony_ci| Unsupported Data Type Handler: 23862306a36Sopenharmony_ci| Ovfl: 23962306a36Sopenharmony_ci| An fmoveout that results in an overflow is reported this way. 24062306a36Sopenharmony_ci| Unfl: 24162306a36Sopenharmony_ci| An fmoveout that results in an underflow is reported this way. 24262306a36Sopenharmony_ci| 24362306a36Sopenharmony_ci| Unimplemented Instruction Handler: 24462306a36Sopenharmony_ci| Ovfl: 24562306a36Sopenharmony_ci| Only scosh, setox, ssinh, stwotox, and scale can set overflow in 24662306a36Sopenharmony_ci| this manner. 24762306a36Sopenharmony_ci| Unfl: 24862306a36Sopenharmony_ci| Stwotox, setox, and scale can set underflow in this manner. 24962306a36Sopenharmony_ci| Any of the other Library Routines such that f(x)=x in which 25062306a36Sopenharmony_ci| x is an extended denorm can report an underflow exception. 25162306a36Sopenharmony_ci| It is the responsibility of the exception-causing exception 25262306a36Sopenharmony_ci| to make sure that WBTEMP is correct. 25362306a36Sopenharmony_ci| 25462306a36Sopenharmony_ci| The exceptional operand is in FP_SCR1. 25562306a36Sopenharmony_ci| 25662306a36Sopenharmony_ciovfl_unfl: 25762306a36Sopenharmony_ci tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state 25862306a36Sopenharmony_ci beqs ofuf_con 25962306a36Sopenharmony_ci| 26062306a36Sopenharmony_ci| The caller was from an unsupported data type trap. Test if the 26162306a36Sopenharmony_ci| caller set CU_ONLY. If so, the exceptional operand is expected in 26262306a36Sopenharmony_ci| FPTEMP, rather than WBTEMP. 26362306a36Sopenharmony_ci| 26462306a36Sopenharmony_ci tstb CU_ONLY(%a6) |test if inst is cu-only 26562306a36Sopenharmony_ci beq unsE3 26662306a36Sopenharmony_ci| move.w #$fe,CU_SAVEPC(%a6) 26762306a36Sopenharmony_ci clrb CU_SAVEPC(%a6) 26862306a36Sopenharmony_ci bsetb #E1,E_BYTE(%a6) |set E1 exception flag 26962306a36Sopenharmony_ci movew ETEMP_EX(%a6),FPTEMP_EX(%a6) 27062306a36Sopenharmony_ci movel ETEMP_HI(%a6),FPTEMP_HI(%a6) 27162306a36Sopenharmony_ci movel ETEMP_LO(%a6),FPTEMP_LO(%a6) 27262306a36Sopenharmony_ci bsetb #fptemp15_bit,DTAG(%a6) |set fpte15 27362306a36Sopenharmony_ci bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimp 27462306a36Sopenharmony_ci bra do_clean |go clean and exit 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ciofuf_con: 27762306a36Sopenharmony_ci moveb (%a7),VER_TMP(%a6) |save version number 27862306a36Sopenharmony_ci cmpib #BUSY_SIZE-4,1(%a7) |check for busy frame 27962306a36Sopenharmony_ci beqs busy_fr |if unimp, grow to busy 28062306a36Sopenharmony_ci cmpib #VER_40,(%a7) |test for orig unimp frame 28162306a36Sopenharmony_ci bnes try_41 |if not, test for rev frame 28262306a36Sopenharmony_ci moveql #13,%d0 |need to zero 14 lwords 28362306a36Sopenharmony_ci bras ofuf_fin 28462306a36Sopenharmony_citry_41: 28562306a36Sopenharmony_ci cmpib #VER_41,(%a7) |test for rev unimp frame 28662306a36Sopenharmony_ci bnel fpsp_fmt_error |if neither, exit with error 28762306a36Sopenharmony_ci moveql #11,%d0 |need to zero 12 lwords 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ciofuf_fin: 29062306a36Sopenharmony_ci clrl (%a7) 29162306a36Sopenharmony_ciloop1: 29262306a36Sopenharmony_ci clrl -(%a7) |clear and dec a7 29362306a36Sopenharmony_ci dbra %d0,loop1 29462306a36Sopenharmony_ci moveb VER_TMP(%a6),(%a7) 29562306a36Sopenharmony_ci moveb #BUSY_SIZE-4,1(%a7) |write busy fmt word. 29662306a36Sopenharmony_cibusy_fr: 29762306a36Sopenharmony_ci movel FP_SCR1(%a6),WBTEMP_EX(%a6) |write 29862306a36Sopenharmony_ci movel FP_SCR1+4(%a6),WBTEMP_HI(%a6) |exceptional op to 29962306a36Sopenharmony_ci movel FP_SCR1+8(%a6),WBTEMP_LO(%a6) |wbtemp 30062306a36Sopenharmony_ci bsetb #E3,E_BYTE(%a6) |set E3 flag 30162306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) |make sure E1 is clear 30262306a36Sopenharmony_ci bclrb #UFLAG,T_BYTE(%a6) |clr U flag 30362306a36Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 30462306a36Sopenharmony_ci orl #sx_mask,E_BYTE(%a6) 30562306a36Sopenharmony_ci movel CMDREG1B(%a6),%d0 |fix cmd1b to make it 30662306a36Sopenharmony_ci andl #0x03c30000,%d0 |work for cmd3b 30762306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2 30862306a36Sopenharmony_ci lsll #5,%d1 30962306a36Sopenharmony_ci swap %d1 31062306a36Sopenharmony_ci orl %d1,%d0 |put it in the right place 31162306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5 31262306a36Sopenharmony_ci lsll #2,%d1 31362306a36Sopenharmony_ci swap %d1 31462306a36Sopenharmony_ci orl %d1,%d0 |put them in the right place 31562306a36Sopenharmony_ci movel %d0,CMDREG3B(%a6) |in the busy frame 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci| 31862306a36Sopenharmony_ci| Check if the frame to be restored is busy or unimp. 31962306a36Sopenharmony_ci|** NOTE *** Bug fix for errata (0d43b #3) 32062306a36Sopenharmony_ci| If the frame is unimp, we must create a busy frame to 32162306a36Sopenharmony_ci| fix the bug with the nmnexc bits in cases in which they 32262306a36Sopenharmony_ci| are set by a previous instruction and not cleared by 32362306a36Sopenharmony_ci| the save. The frame will be unimp only if the final 32462306a36Sopenharmony_ci| instruction in an emulation routine caused the exception 32562306a36Sopenharmony_ci| by doing an fmove <ea>,fp0. The exception operand, in 32662306a36Sopenharmony_ci| internal format, is in fptemp. 32762306a36Sopenharmony_ci| 32862306a36Sopenharmony_cido_clean: 32962306a36Sopenharmony_ci cmpib #UNIMP_40_SIZE-4,1(%a7) 33062306a36Sopenharmony_ci bnes do_con 33162306a36Sopenharmony_ci moveql #13,%d0 |in orig, need to zero 14 lwords 33262306a36Sopenharmony_ci bras do_build 33362306a36Sopenharmony_cido_con: 33462306a36Sopenharmony_ci cmpib #UNIMP_41_SIZE-4,1(%a7) 33562306a36Sopenharmony_ci bnes do_restore |frame must be busy 33662306a36Sopenharmony_ci moveql #11,%d0 |in rev, need to zero 12 lwords 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cido_build: 33962306a36Sopenharmony_ci moveb (%a7),VER_TMP(%a6) 34062306a36Sopenharmony_ci clrl (%a7) 34162306a36Sopenharmony_ciloop2: 34262306a36Sopenharmony_ci clrl -(%a7) |clear and dec a7 34362306a36Sopenharmony_ci dbra %d0,loop2 34462306a36Sopenharmony_ci| 34562306a36Sopenharmony_ci| Use a1 as pointer into new frame. a6 is not correct if an unimp or 34662306a36Sopenharmony_ci| busy frame was created as the result of an exception on the final 34762306a36Sopenharmony_ci| instruction of an emulation routine. 34862306a36Sopenharmony_ci| 34962306a36Sopenharmony_ci| We need to set the nmcexc bits if the exception is E1. Otherwise, 35062306a36Sopenharmony_ci| the exc taken will be inex2. 35162306a36Sopenharmony_ci| 35262306a36Sopenharmony_ci leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 for new frame 35362306a36Sopenharmony_ci moveb VER_TMP(%a6),(%a7) |write busy fmt word 35462306a36Sopenharmony_ci moveb #BUSY_SIZE-4,1(%a7) 35562306a36Sopenharmony_ci movel FP_SCR1(%a6),WBTEMP_EX(%a1) |write 35662306a36Sopenharmony_ci movel FP_SCR1+4(%a6),WBTEMP_HI(%a1) |exceptional op to 35762306a36Sopenharmony_ci movel FP_SCR1+8(%a6),WBTEMP_LO(%a1) |wbtemp 35862306a36Sopenharmony_ci| btst.b #E1,E_BYTE(%a1) 35962306a36Sopenharmony_ci| beq.b do_restore 36062306a36Sopenharmony_ci bfextu USER_FPSR(%a6){#17:#4},%d0 |get snan/operr/ovfl/unfl bits 36162306a36Sopenharmony_ci bfins %d0,NMCEXC(%a1){#4:#4} |and insert them in nmcexc 36262306a36Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits 36362306a36Sopenharmony_ci orl #sx_mask,E_BYTE(%a1) 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cido_restore: 36662306a36Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 36762306a36Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 36862306a36Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 36962306a36Sopenharmony_ci frestore (%a7)+ 37062306a36Sopenharmony_ci tstb RES_FLG(%a6) |RES_FLG indicates a "continuation" frame 37162306a36Sopenharmony_ci beq cont 37262306a36Sopenharmony_ci bsr bug1384 37362306a36Sopenharmony_cicont: 37462306a36Sopenharmony_ci unlk %a6 37562306a36Sopenharmony_ci| 37662306a36Sopenharmony_ci| If trace mode enabled, then go to trace handler. This handler 37762306a36Sopenharmony_ci| cannot have any fp instructions. If there are fp inst's and an 37862306a36Sopenharmony_ci| exception has been restored into the machine then the exception 37962306a36Sopenharmony_ci| will occur upon execution of the fp inst. This is not desirable 38062306a36Sopenharmony_ci| in the kernel (supervisor mode). See MC68040 manual Section 9.3.8. 38162306a36Sopenharmony_ci| 38262306a36Sopenharmony_cifinish_up: 38362306a36Sopenharmony_ci btstb #7,(%a7) |test T1 in SR 38462306a36Sopenharmony_ci bnes g_trace 38562306a36Sopenharmony_ci btstb #6,(%a7) |test T0 in SR 38662306a36Sopenharmony_ci bnes g_trace 38762306a36Sopenharmony_ci bral fpsp_done 38862306a36Sopenharmony_ci| 38962306a36Sopenharmony_ci| Change integer stack to look like trace stack 39062306a36Sopenharmony_ci| The address of the instruction that caused the 39162306a36Sopenharmony_ci| exception is already in the integer stack (is 39262306a36Sopenharmony_ci| the same as the saved friar) 39362306a36Sopenharmony_ci| 39462306a36Sopenharmony_ci| If the current frame is already a 6-word stack then all 39562306a36Sopenharmony_ci| that needs to be done is to change the vector# to TRACE. 39662306a36Sopenharmony_ci| If the frame is only a 4-word stack (meaning we got here 39762306a36Sopenharmony_ci| on an Unsupported data type exception), then we need to grow 39862306a36Sopenharmony_ci| the stack an extra 2 words and get the FPIAR from the FPU. 39962306a36Sopenharmony_ci| 40062306a36Sopenharmony_cig_trace: 40162306a36Sopenharmony_ci bftst EXC_VEC-4(%sp){#0:#4} 40262306a36Sopenharmony_ci bne g_easy 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci subw #4,%sp | make room 40562306a36Sopenharmony_ci movel 4(%sp),(%sp) 40662306a36Sopenharmony_ci movel 8(%sp),4(%sp) 40762306a36Sopenharmony_ci subw #BUSY_SIZE,%sp 40862306a36Sopenharmony_ci fsave (%sp) 40962306a36Sopenharmony_ci fmovel %fpiar,BUSY_SIZE+EXC_EA-4(%sp) 41062306a36Sopenharmony_ci frestore (%sp) 41162306a36Sopenharmony_ci addw #BUSY_SIZE,%sp 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_cig_easy: 41462306a36Sopenharmony_ci movew #TRACE_VEC,EXC_VEC-4(%a7) 41562306a36Sopenharmony_ci bral real_trace 41662306a36Sopenharmony_ci| 41762306a36Sopenharmony_ci| This is a work-around for hardware bug 1384. 41862306a36Sopenharmony_ci| 41962306a36Sopenharmony_cibug1384: 42062306a36Sopenharmony_ci link %a5,#0 42162306a36Sopenharmony_ci fsave -(%sp) 42262306a36Sopenharmony_ci cmpib #0x41,(%sp) | check for correct frame 42362306a36Sopenharmony_ci beq frame_41 42462306a36Sopenharmony_ci bgt nofix | if more advanced mask, do nada 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ciframe_40: 42762306a36Sopenharmony_ci tstb 1(%sp) | check to see if idle 42862306a36Sopenharmony_ci bne notidle 42962306a36Sopenharmony_ciidle40: 43062306a36Sopenharmony_ci clrl (%sp) | get rid of old fsave frame 43162306a36Sopenharmony_ci movel %d1,USER_D1(%a6) | save d1 43262306a36Sopenharmony_ci movew #8,%d1 | place unimp frame instead 43362306a36Sopenharmony_ciloop40: clrl -(%sp) 43462306a36Sopenharmony_ci dbra %d1,loop40 43562306a36Sopenharmony_ci movel USER_D1(%a6),%d1 | restore d1 43662306a36Sopenharmony_ci movel #0x40280000,-(%sp) 43762306a36Sopenharmony_ci frestore (%sp)+ 43862306a36Sopenharmony_ci unlk %a5 43962306a36Sopenharmony_ci rts 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ciframe_41: 44262306a36Sopenharmony_ci tstb 1(%sp) | check to see if idle 44362306a36Sopenharmony_ci bne notidle 44462306a36Sopenharmony_ciidle41: 44562306a36Sopenharmony_ci clrl (%sp) | get rid of old fsave frame 44662306a36Sopenharmony_ci movel %d1,USER_D1(%a6) | save d1 44762306a36Sopenharmony_ci movew #10,%d1 | place unimp frame instead 44862306a36Sopenharmony_ciloop41: clrl -(%sp) 44962306a36Sopenharmony_ci dbra %d1,loop41 45062306a36Sopenharmony_ci movel USER_D1(%a6),%d1 | restore d1 45162306a36Sopenharmony_ci movel #0x41300000,-(%sp) 45262306a36Sopenharmony_ci frestore (%sp)+ 45362306a36Sopenharmony_ci unlk %a5 45462306a36Sopenharmony_ci rts 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cinotidle: 45762306a36Sopenharmony_ci bclrb #etemp15_bit,-40(%a5) 45862306a36Sopenharmony_ci frestore (%sp)+ 45962306a36Sopenharmony_ci unlk %a5 46062306a36Sopenharmony_ci rts 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_cinofix: 46362306a36Sopenharmony_ci frestore (%sp)+ 46462306a36Sopenharmony_ci unlk %a5 46562306a36Sopenharmony_ci rts 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci |end 468