diff options
Diffstat (limited to 'c/src/lib/libcpu/m68k/m68040/fpsp/gen_except.S')
-rw-r--r-- | c/src/lib/libcpu/m68k/m68040/fpsp/gen_except.S | 470 |
1 files changed, 0 insertions, 470 deletions
diff --git a/c/src/lib/libcpu/m68k/m68040/fpsp/gen_except.S b/c/src/lib/libcpu/m68k/m68040/fpsp/gen_except.S deleted file mode 100644 index 5139517703..0000000000 --- a/c/src/lib/libcpu/m68k/m68040/fpsp/gen_except.S +++ /dev/null @@ -1,470 +0,0 @@ -#include "fpsp-namespace.h" -// -// -// 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_error - -exc_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_except -gen_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_con -test_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_com -check_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 exit - -commonE3: - tstb UFLG_TMP(%a6) //test flag for unsup/unimp state - bnes unsE3 -uniE3: - bsetb #E3,E_BYTE(%a6) //set E3 flag - bclrb #E1,E_BYTE(%a6) //clr E1 from unimp - bra commonE - -unsE3: - tstb RES_FLG(%a6) - bnes unsE3_0 -unsE3_1: - bsetb #E3,E_BYTE(%a6) //set E3 flag -unsE3_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 frame - -commonE: - 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_exc -uns_no_exc: - tstb RES_FLG(%a6) //check if frestore is needed - bne do_clean //if clear, no frestore needed -uni_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 exit - -ofuf_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_fin -try_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 lwords - -ofuf_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_build -do_con: - cmpib #UNIMP_41_SIZE-4,1(%a7) - bnes do_restore //frame must be busy - moveql #11,%d0 //in rev, need to zero 12 lwords - -do_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 bug1384 -cont: - 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,%sp - -g_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 nada - -frame_40: - tstb 1(%sp) // check to see if idle - bne notidle -idle40: - clrl (%sp) // get rid of old fsave frame - movel %d1,USER_D1(%a6) // save d1 - movew #8,%d1 // place unimp frame instead -loop40: clrl -(%sp) - dbra %d1,loop40 - movel USER_D1(%a6),%d1 // restore d1 - movel #0x40280000,-(%sp) - frestore (%sp)+ - unlk %a5 - rts - -frame_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 instead -loop41: clrl -(%sp) - dbra %d1,loop41 - movel USER_D1(%a6),%d1 // restore d1 - movel #0x41300000,-(%sp) - frestore (%sp)+ - unlk %a5 - rts - -notidle: - bclrb #etemp15_bit,-40(%a5) - frestore (%sp)+ - unlk %a5 - rts - -nofix: - frestore (%sp)+ - unlk %a5 - rts - - |end |