📄 gen_except.s
字号:
//// $Id: gen_except.S,v 1.1 1998/12/14 23:15:21 joel Exp $//// gen_except.sa 3.7 1/16/92//// gen_except --- FPSP routine to detect reportable exceptions// // This routine compares the exception enable byte of the// user_fpcr on the stack with the exception status byte// of the user_fpsr. //// Any routine which may report an exceptions must load// the stack frame in memory with the exceptional operand(s).//// Priority for exceptions is://// Highest: bsun// snan// operr// ovfl// unfl// dz// inex2// Lowest: inex1//// Note: The IEEE standard specifies that inex2 is to be// reported if ovfl occurs and the ovfl enable bit is not// set but the inex2 enable bit is. ////// Copyright (C) Motorola, Inc. 1990// All Rights Reserved//// THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA // The copyright notice above does not evidence any // actual or intended publication of such source code.GEN_EXCEPT: //idnt 2,1 | Motorola 040 Floating Point Software Package |section 8#include "fpsp.defs" |xref real_trace |xref fpsp_done |xref fpsp_fmt_errorexc_tbl: .long bsun_exc .long commonE1 .long commonE1 .long ovfl_unfl .long ovfl_unfl .long commonE1 .long commonE3 .long commonE3 .long no_match .global gen_exceptgen_except: cmpib #IDLE_SIZE-4,1(%a7) //test for idle frame beq do_check //go handle idle frame cmpib #UNIMP_40_SIZE-4,1(%a7) //test for orig unimp frame beqs unimp_x //go handle unimp frame cmpib #UNIMP_41_SIZE-4,1(%a7) //test for rev unimp frame beqs unimp_x //go handle unimp frame cmpib #BUSY_SIZE-4,1(%a7) //if size <> $60, fmt error bnel fpsp_fmt_error leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 //init a1 so fpsp.h// ;equates will work// Fix up the new busy frame with entries from the unimp frame// movel ETEMP_EX(%a6),ETEMP_EX(%a1) //copy etemp from unimp movel ETEMP_HI(%a6),ETEMP_HI(%a1) //frame to busy frame movel ETEMP_LO(%a6),ETEMP_LO(%a1) movel CMDREG1B(%a6),CMDREG1B(%a1) //set inst in frame to unimp movel CMDREG1B(%a6),%d0 //fix cmd1b to make it andl #0x03c30000,%d0 //work for cmd3b bfextu CMDREG1B(%a6){#13:#1},%d1 //extract bit 2 lsll #5,%d1 swap %d1 orl %d1,%d0 //put it in the right place bfextu CMDREG1B(%a6){#10:#3},%d1 //extract bit 3,4,5 lsll #2,%d1 swap %d1 orl %d1,%d0 //put them in the right place movel %d0,CMDREG3B(%a1) //in the busy frame//// Or in the FPSR from the emulation with the USER_FPSR on the stack.// fmovel %FPSR,%d0 orl %d0,USER_FPSR(%a6) movel USER_FPSR(%a6),FPSR_SHADOW(%a1) //set exc bits orl #sx_mask,E_BYTE(%a1) bra do_clean//// Frame is an unimp frame possible resulting from an fmove <ea>,fp0// that caused an exception//// a1 is modified to point into the new frame allowing fpsp equates// to be valid.//unimp_x: cmpib #UNIMP_40_SIZE-4,1(%a7) //test for orig unimp frame bnes test_rev leal UNIMP_40_SIZE+LOCAL_SIZE(%a7),%a1 bras unimp_contest_rev: cmpib #UNIMP_41_SIZE-4,1(%a7) //test for rev unimp frame bnel fpsp_fmt_error //if not $28 or $30 leal UNIMP_41_SIZE+LOCAL_SIZE(%a7),%a1 unimp_con://// Fix up the new unimp frame with entries from the old unimp frame// movel CMDREG1B(%a6),CMDREG1B(%a1) //set inst in frame to unimp//// Or in the FPSR from the emulation with the USER_FPSR on the stack.// fmovel %FPSR,%d0 orl %d0,USER_FPSR(%a6) bra do_clean//// Frame is idle, so check for exceptions reported through// USER_FPSR and set the unimp frame accordingly. // A7 must be incremented to the point before the// idle fsave vector to the unimp vector.// do_check: addl #4,%a7 //point A7 back to unimp frame//// Or in the FPSR from the emulation with the USER_FPSR on the stack.// fmovel %FPSR,%d0 orl %d0,USER_FPSR(%a6)//// On a busy frame, we must clear the nmnexc bits.// cmpib #BUSY_SIZE-4,1(%a7) //check frame type bnes check_fr //if busy, clr nmnexc clrw NMNEXC(%a6) //clr nmnexc & nmcexc btstb #5,CMDREG1B(%a6) //test for fmove out bnes frame_com movel USER_FPSR(%a6),FPSR_SHADOW(%a6) //set exc bits orl #sx_mask,E_BYTE(%a6) bras frame_comcheck_fr: cmpb #UNIMP_40_SIZE-4,1(%a7) beqs frame_com clrw NMNEXC(%a6)frame_com: moveb FPCR_ENABLE(%a6),%d0 //get fpcr enable byte andb FPSR_EXCEPT(%a6),%d0 //and in the fpsr exc byte bfffo %d0{#24:#8},%d1 //test for first set bit leal exc_tbl,%a0 //load jmp table address subib #24,%d1 //normalize bit offset to 0-8 movel (%a0,%d1.w*4),%a0 //load routine address based// ;based on first enabled exc jmp (%a0) //jump to routine//// Bsun is not possible in unimp or unsupp//bsun_exc: bra do_clean//// The typical work to be done to the unimp frame to report an // exception is to set the E1/E3 byte and clr the U flag.// commonE1 does this for E1 exceptions, which are snan, // operr, and dz. commonE3 does this for E3 exceptions, which // are inex2 and inex1, and also clears the E1 exception bit// left over from the unimp exception.//commonE1: bsetb #E1,E_BYTE(%a6) //set E1 flag bra commonE //go clean and exitcommonE3: tstb UFLG_TMP(%a6) //test flag for unsup/unimp state bnes unsE3uniE3: bsetb #E3,E_BYTE(%a6) //set E3 flag bclrb #E1,E_BYTE(%a6) //clr E1 from unimp bra commonEunsE3: tstb RES_FLG(%a6) bnes unsE3_0 unsE3_1: bsetb #E3,E_BYTE(%a6) //set E3 flagunsE3_0: bclrb #E1,E_BYTE(%a6) //clr E1 flag movel CMDREG1B(%a6),%d0 andl #0x03c30000,%d0 //work for cmd3b bfextu CMDREG1B(%a6){#13:#1},%d1 //extract bit 2 lsll #5,%d1 swap %d1 orl %d1,%d0 //put it in the right place bfextu CMDREG1B(%a6){#10:#3},%d1 //extract bit 3,4,5 lsll #2,%d1 swap %d1 orl %d1,%d0 //put them in the right place movel %d0,CMDREG3B(%a6) //in the busy framecommonE: bclrb #UFLAG,T_BYTE(%a6) //clr U flag from unimp bra do_clean //go clean and exit//// No bits in the enable byte match existing exceptions. Check for// the case of the ovfl exc without the ovfl enabled, but with// inex2 enabled.//no_match: btstb #inex2_bit,FPCR_ENABLE(%a6) //check for ovfl/inex2 case beqs no_exc //if clear, exit btstb #ovfl_bit,FPSR_EXCEPT(%a6) //now check ovfl beqs no_exc //if clear, exit bras ovfl_unfl //go to unfl_ovfl to determine if// ;it is an unsupp or unimp exc // No exceptions are to be reported. If the instruction was // unimplemented, no FPU restore is necessary. If it was// unsupported, we must perform the restore.no_exc: tstb UFLG_TMP(%a6) //test flag for unsupp/unimp state beqs uni_no_excuns_no_exc: tstb RES_FLG(%a6) //check if frestore is needed bne do_clean //if clear, no frestore neededuni_no_exc: moveml USER_DA(%a6),%d0-%d1/%a0-%a1 fmovemx USER_FP0(%a6),%fp0-%fp3 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar unlk %a6 bra finish_up//// Unsupported Data Type Handler:// Ovfl:// An fmoveout that results in an overflow is reported this way.// Unfl:// An fmoveout that results in an underflow is reported this way.//// Unimplemented Instruction Handler:// Ovfl:// Only scosh, setox, ssinh, stwotox, and scale can set overflow in // this manner.// Unfl:// Stwotox, setox, and scale can set underflow in this manner.// Any of the other Library Routines such that f(x)=x in which// x is an extended denorm can report an underflow exception. // It is the responsibility of the exception-causing exception // to make sure that WBTEMP is correct.//// The exceptional operand is in FP_SCR1.//ovfl_unfl: tstb UFLG_TMP(%a6) //test flag for unsupp/unimp state beqs ofuf_con//// The caller was from an unsupported data type trap. Test if the// caller set CU_ONLY. If so, the exceptional operand is expected in// FPTEMP, rather than WBTEMP.// tstb CU_ONLY(%a6) //test if inst is cu-only beq unsE3// move.w #$fe,CU_SAVEPC(%a6) clrb CU_SAVEPC(%a6) bsetb #E1,E_BYTE(%a6) //set E1 exception flag movew ETEMP_EX(%a6),FPTEMP_EX(%a6) movel ETEMP_HI(%a6),FPTEMP_HI(%a6) movel ETEMP_LO(%a6),FPTEMP_LO(%a6) bsetb #fptemp15_bit,DTAG(%a6) //set fpte15 bclrb #UFLAG,T_BYTE(%a6) //clr U flag from unimp bra do_clean //go clean and exitofuf_con: moveb (%a7),VER_TMP(%a6) //save version number cmpib #BUSY_SIZE-4,1(%a7) //check for busy frame beqs busy_fr //if unimp, grow to busy cmpib #VER_40,(%a7) //test for orig unimp frame bnes try_41 //if not, test for rev frame moveql #13,%d0 //need to zero 14 lwords bras ofuf_fintry_41: cmpib #VER_41,(%a7) //test for rev unimp frame bnel fpsp_fmt_error //if neither, exit with error moveql #11,%d0 //need to zero 12 lwordsofuf_fin: clrl (%a7)loop1: clrl -(%a7) //clear and dec a7 dbra %d0,loop1 moveb VER_TMP(%a6),(%a7) moveb #BUSY_SIZE-4,1(%a7) //write busy fmt word.busy_fr: movel FP_SCR1(%a6),WBTEMP_EX(%a6) //write movel FP_SCR1+4(%a6),WBTEMP_HI(%a6) //exceptional op to movel FP_SCR1+8(%a6),WBTEMP_LO(%a6) //wbtemp bsetb #E3,E_BYTE(%a6) //set E3 flag bclrb #E1,E_BYTE(%a6) //make sure E1 is clear bclrb #UFLAG,T_BYTE(%a6) //clr U flag movel USER_FPSR(%a6),FPSR_SHADOW(%a6) orl #sx_mask,E_BYTE(%a6) movel CMDREG1B(%a6),%d0 //fix cmd1b to make it andl #0x03c30000,%d0 //work for cmd3b bfextu CMDREG1B(%a6){#13:#1},%d1 //extract bit 2 lsll #5,%d1 swap %d1 orl %d1,%d0 //put it in the right place bfextu CMDREG1B(%a6){#10:#3},%d1 //extract bit 3,4,5 lsll #2,%d1 swap %d1 orl %d1,%d0 //put them in the right place movel %d0,CMDREG3B(%a6) //in the busy frame//// Check if the frame to be restored is busy or unimp.//** NOTE *** Bug fix for errata (0d43b #3)// If the frame is unimp, we must create a busy frame to // fix the bug with the nmnexc bits in cases in which they// are set by a previous instruction and not cleared by// the save. The frame will be unimp only if the final // instruction in an emulation routine caused the exception// by doing an fmove <ea>,fp0. The exception operand, in// internal format, is in fptemp.//do_clean: cmpib #UNIMP_40_SIZE-4,1(%a7) bnes do_con moveql #13,%d0 //in orig, need to zero 14 lwords bras do_builddo_con: cmpib #UNIMP_41_SIZE-4,1(%a7) bnes do_restore //frame must be busy moveql #11,%d0 //in rev, need to zero 12 lwordsdo_build: moveb (%a7),VER_TMP(%a6) clrl (%a7)loop2: clrl -(%a7) //clear and dec a7 dbra %d0,loop2//// Use a1 as pointer into new frame. a6 is not correct if an unimp or// busy frame was created as the result of an exception on the final// instruction of an emulation routine.//// We need to set the nmcexc bits if the exception is E1. Otherwise,// the exc taken will be inex2.// leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 //init a1 for new frame moveb VER_TMP(%a6),(%a7) //write busy fmt word moveb #BUSY_SIZE-4,1(%a7) movel FP_SCR1(%a6),WBTEMP_EX(%a1) //write movel FP_SCR1+4(%a6),WBTEMP_HI(%a1) //exceptional op to movel FP_SCR1+8(%a6),WBTEMP_LO(%a1) //wbtemp// btst.b #E1,E_BYTE(%a1)// beq.b do_restore bfextu USER_FPSR(%a6){#17:#4},%d0 //get snan/operr/ovfl/unfl bits bfins %d0,NMCEXC(%a1){#4:#4} //and insert them in nmcexc movel USER_FPSR(%a6),FPSR_SHADOW(%a1) //set exc bits orl #sx_mask,E_BYTE(%a1) do_restore: moveml USER_DA(%a6),%d0-%d1/%a0-%a1 fmovemx USER_FP0(%a6),%fp0-%fp3 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar frestore (%a7)+ tstb RES_FLG(%a6) //RES_FLG indicates a "continuation" frame beq cont bsr bug1384cont: unlk %a6//// If trace mode enabled, then go to trace handler. This handler // cannot have any fp instructions. If there are fp inst's and an // exception has been restored into the machine then the exception // will occur upon execution of the fp inst. This is not desirable // in the kernel (supervisor mode). See MC68040 manual Section 9.3.8.//finish_up: btstb #7,(%a7) //test T1 in SR bnes g_trace btstb #6,(%a7) //test T0 in SR bnes g_trace bral fpsp_done//// Change integer stack to look like trace stack// The address of the instruction that caused the// exception is already in the integer stack (is// the same as the saved friar)//// If the current frame is already a 6-word stack then all// that needs to be done is to change the vector# to TRACE.// If the frame is only a 4-word stack (meaning we got here// on an Unsupported data type exception), then we need to grow// the stack an extra 2 words and get the FPIAR from the FPU.//g_trace: bftst EXC_VEC-4(%sp){#0:#4} bne g_easy subw #4,%sp // make room movel 4(%sp),(%sp) movel 8(%sp),4(%sp) subw #BUSY_SIZE,%sp fsave (%sp) fmovel %fpiar,BUSY_SIZE+EXC_EA-4(%sp) frestore (%sp) addw #BUSY_SIZE,%spg_easy: movew #TRACE_VEC,EXC_VEC-4(%a7) bral real_trace//// This is a work-around for hardware bug 1384.//bug1384: link %a5,#0 fsave -(%sp) cmpib #0x41,(%sp) // check for correct frame beq frame_41 bgt nofix // if more advanced mask, do nadaframe_40: tstb 1(%sp) // check to see if idle bne notidleidle40: clrl (%sp) // get rid of old fsave frame movel %d1,USER_D1(%a6) // save d1 movew #8,%d1 // place unimp frame insteadloop40: clrl -(%sp) dbra %d1,loop40 movel USER_D1(%a6),%d1 // restore d1 movel #0x40280000,-(%sp) frestore (%sp)+ unlk %a5 rtsframe_41: tstb 1(%sp) // check to see if idle bne notidle idle41: clrl (%sp) // get rid of old fsave frame movel %d1,USER_D1(%a6) // save d1 movew #10,%d1 // place unimp frame insteadloop41: clrl -(%sp) dbra %d1,loop41 movel USER_D1(%a6),%d1 // restore d1 movel #0x41300000,-(%sp) frestore (%sp)+ unlk %a5 rtsnotidle: bclrb #etemp15_bit,-40(%a5) frestore (%sp)+ unlk %a5 rtsnofix: frestore (%sp)+ unlk %a5 rts |end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -