URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [fpsp040/] [gen_except.S] - Rev 1765
Compare with Previous | Blame | View Log
|| 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.h"|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 framebeq do_check |go handle idle framecmpib #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp framebeqs unimp_x |go handle unimp framecmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp framebeqs unimp_x |go handle unimp framecmpib #BUSY_SIZE-4,1(%a7) |if size <> $60, fmt errorbnel fpsp_fmt_errorleal 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 unimpmovel ETEMP_HI(%a6),ETEMP_HI(%a1) |frame to busy framemovel ETEMP_LO(%a6),ETEMP_LO(%a1)movel CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimpmovel CMDREG1B(%a6),%d0 |fix cmd1b to make itandl #0x03c30000,%d0 |work for cmd3bbfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2lsll #5,%d1swap %d1orl %d1,%d0 |put it in the right placebfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5lsll #2,%d1swap %d1orl %d1,%d0 |put them in the right placemovel %d0,CMDREG3B(%a1) |in the busy frame|| Or in the FPSR from the emulation with the USER_FPSR on the stack.|fmovel %FPSR,%d0orl %d0,USER_FPSR(%a6)movel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bitsorl #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 framebnes test_revleal UNIMP_40_SIZE+LOCAL_SIZE(%a7),%a1bras unimp_contest_rev:cmpib #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp framebnel fpsp_fmt_error |if not $28 or $30leal UNIMP_41_SIZE+LOCAL_SIZE(%a7),%a1unimp_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,%d0orl %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,%d0orl %d0,USER_FPSR(%a6)|| On a busy frame, we must clear the nmnexc bits.|cmpib #BUSY_SIZE-4,1(%a7) |check frame typebnes check_fr |if busy, clr nmnexcclrw NMNEXC(%a6) |clr nmnexc & nmcexcbtstb #5,CMDREG1B(%a6) |test for fmove outbnes frame_commovel USER_FPSR(%a6),FPSR_SHADOW(%a6) |set exc bitsorl #sx_mask,E_BYTE(%a6)bras frame_comcheck_fr:cmpb #UNIMP_40_SIZE-4,1(%a7)beqs frame_comclrw NMNEXC(%a6)frame_com:moveb FPCR_ENABLE(%a6),%d0 |get fpcr enable byteandb FPSR_EXCEPT(%a6),%d0 |and in the fpsr exc bytebfffo %d0{#24:#8},%d1 |test for first set bitleal exc_tbl,%a0 |load jmp table addresssubib #24,%d1 |normalize bit offset to 0-8movel (%a0,%d1.w*4),%a0 |load routine address based| ;based on first enabled excjmp (%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 flagbra commonE |go clean and exitcommonE3:tstb UFLG_TMP(%a6) |test flag for unsup/unimp statebnes unsE3uniE3:bsetb #E3,E_BYTE(%a6) |set E3 flagbclrb #E1,E_BYTE(%a6) |clr E1 from unimpbra commonEunsE3:tstb RES_FLG(%a6)bnes unsE3_0unsE3_1:bsetb #E3,E_BYTE(%a6) |set E3 flagunsE3_0:bclrb #E1,E_BYTE(%a6) |clr E1 flagmovel CMDREG1B(%a6),%d0andl #0x03c30000,%d0 |work for cmd3bbfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2lsll #5,%d1swap %d1orl %d1,%d0 |put it in the right placebfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5lsll #2,%d1swap %d1orl %d1,%d0 |put them in the right placemovel %d0,CMDREG3B(%a6) |in the busy framecommonE:bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimpbra 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 casebeqs no_exc |if clear, exitbtstb #ovfl_bit,FPSR_EXCEPT(%a6) |now check ovflbeqs no_exc |if clear, exitbras 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 statebeqs uni_no_excuns_no_exc:tstb RES_FLG(%a6) |check if frestore is neededbne do_clean |if clear, no frestore neededuni_no_exc:moveml USER_DA(%a6),%d0-%d1/%a0-%a1fmovemx USER_FP0(%a6),%fp0-%fp3fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiarunlk %a6bra 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 statebeqs 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-onlybeq unsE3| move.w #$fe,CU_SAVEPC(%a6)clrb CU_SAVEPC(%a6)bsetb #E1,E_BYTE(%a6) |set E1 exception flagmovew 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 fpte15bclrb #UFLAG,T_BYTE(%a6) |clr U flag from unimpbra do_clean |go clean and exitofuf_con:moveb (%a7),VER_TMP(%a6) |save version numbercmpib #BUSY_SIZE-4,1(%a7) |check for busy framebeqs busy_fr |if unimp, grow to busycmpib #VER_40,(%a7) |test for orig unimp framebnes try_41 |if not, test for rev framemoveql #13,%d0 |need to zero 14 lwordsbras ofuf_fintry_41:cmpib #VER_41,(%a7) |test for rev unimp framebnel fpsp_fmt_error |if neither, exit with errormoveql #11,%d0 |need to zero 12 lwordsofuf_fin:clrl (%a7)loop1:clrl -(%a7) |clear and dec a7dbra %d0,loop1moveb VER_TMP(%a6),(%a7)moveb #BUSY_SIZE-4,1(%a7) |write busy fmt word.busy_fr:movel FP_SCR1(%a6),WBTEMP_EX(%a6) |writemovel FP_SCR1+4(%a6),WBTEMP_HI(%a6) |exceptional op tomovel FP_SCR1+8(%a6),WBTEMP_LO(%a6) |wbtempbsetb #E3,E_BYTE(%a6) |set E3 flagbclrb #E1,E_BYTE(%a6) |make sure E1 is clearbclrb #UFLAG,T_BYTE(%a6) |clr U flagmovel USER_FPSR(%a6),FPSR_SHADOW(%a6)orl #sx_mask,E_BYTE(%a6)movel CMDREG1B(%a6),%d0 |fix cmd1b to make itandl #0x03c30000,%d0 |work for cmd3bbfextu CMDREG1B(%a6){#13:#1},%d1 |extract bit 2lsll #5,%d1swap %d1orl %d1,%d0 |put it in the right placebfextu CMDREG1B(%a6){#10:#3},%d1 |extract bit 3,4,5lsll #2,%d1swap %d1orl %d1,%d0 |put them in the right placemovel %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_conmoveql #13,%d0 |in orig, need to zero 14 lwordsbras do_builddo_con:cmpib #UNIMP_41_SIZE-4,1(%a7)bnes do_restore |frame must be busymoveql #11,%d0 |in rev, need to zero 12 lwordsdo_build:moveb (%a7),VER_TMP(%a6)clrl (%a7)loop2:clrl -(%a7) |clear and dec a7dbra %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 framemoveb VER_TMP(%a6),(%a7) |write busy fmt wordmoveb #BUSY_SIZE-4,1(%a7)movel FP_SCR1(%a6),WBTEMP_EX(%a1) |writemovel FP_SCR1+4(%a6),WBTEMP_HI(%a1) |exceptional op tomovel FP_SCR1+8(%a6),WBTEMP_LO(%a1) |wbtemp| btst.b #E1,E_BYTE(%a1)| beq.b do_restorebfextu USER_FPSR(%a6){#17:#4},%d0 |get snan/operr/ovfl/unfl bitsbfins %d0,NMCEXC(%a1){#4:#4} |and insert them in nmcexcmovel USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bitsorl #sx_mask,E_BYTE(%a1)do_restore:moveml USER_DA(%a6),%d0-%d1/%a0-%a1fmovemx USER_FP0(%a6),%fp0-%fp3fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiarfrestore (%a7)+tstb RES_FLG(%a6) |RES_FLG indicates a "continuation" framebeq contbsr 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 SRbnes g_tracebtstb #6,(%a7) |test T0 in SRbnes g_tracebral 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_easysubw #4,%sp | make roommovel 4(%sp),(%sp)movel 8(%sp),4(%sp)subw #BUSY_SIZE,%spfsave (%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,#0fsave -(%sp)cmpib #0x41,(%sp) | check for correct framebeq frame_41bgt nofix | if more advanced mask, do nadaframe_40:tstb 1(%sp) | check to see if idlebne notidleidle40:clrl (%sp) | get rid of old fsave framemovel %d1,USER_D1(%a6) | save d1movew #8,%d1 | place unimp frame insteadloop40: clrl -(%sp)dbra %d1,loop40movel USER_D1(%a6),%d1 | restore d1movel #0x40280000,-(%sp)frestore (%sp)+unlk %a5rtsframe_41:tstb 1(%sp) | check to see if idlebne notidleidle41:clrl (%sp) | get rid of old fsave framemovel %d1,USER_D1(%a6) | save d1movew #10,%d1 | place unimp frame insteadloop41: clrl -(%sp)dbra %d1,loop41movel USER_D1(%a6),%d1 | restore d1movel #0x41300000,-(%sp)frestore (%sp)+unlk %a5rtsnotidle:bclrb #etemp15_bit,-40(%a5)frestore (%sp)+unlk %a5rtsnofix:frestore (%sp)+unlk %a5rts|end
