📄 pfpsp.s
字号:
beq.l _fpsp_done # no fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024 bra.l _real_trace########################################################################## XDEF **************************************************************** ## _fpsp_unfl(): 060FPSP entry point for FP Underflow exception. ## ## This handler should be the first code executed upon taking the ## FP Underflow exception in an operating system. ## ## XREF **************************************************************** ## _imem_read_long() - read instruction longword ## fix_skewed_ops() - adjust src operand in fsave frame ## set_tag_x() - determine optype of src/dst operands ## store_fpreg() - store opclass 0 or 2 result to FP regfile ## unnorm_fix() - change UNNORM operands to NORM or ZERO ## load_fpn2() - load dst operand from FP regfile ## fout() - emulate an opclass 3 instruction ## tbl_unsupp - add of table of emulation routines for opclass 0,2 ## _fpsp_done() - "callout" for 060FPSP exit (all work done!) ## _real_ovfl() - "callout" for Overflow exception enabled code ## _real_inex() - "callout" for Inexact exception enabled code ## _real_trace() - "callout" for Trace exception code ## ## INPUT *************************************************************** ## - The system stack contains the FP Unfl exception stack frame ## - The fsave frame contains the source operand ## ## OUTPUT ************************************************************** ## Underflow Exception enabled: ## - The system stack is unchanged ## - The fsave frame contains the adjusted src op for opclass 0,2 ## Underflow Exception disabled: ## - The system stack is unchanged ## - The "exception present" flag in the fsave frame is cleared ## ## ALGORITHM *********************************************************** ## On the 060, if an FP underflow is present as the result of any ## instruction, the 060 will take an underflow exception whether the ## exception is enabled or disabled in the FPCR. For the disabled case, ## This handler emulates the instruction to determine what the correct ## default result should be for the operation. This default result is ## then stored in either the FP regfile, data regfile, or memory. ## Finally, the handler exits through the "callout" _fpsp_done() ## denoting that no exceptional conditions exist within the machine. ## If the exception is enabled, then this handler must create the ## exceptional operand and plave it in the fsave state frame, and store ## the default result (only if the instruction is opclass 3). For ## exceptions enabled, this handler must exit through the "callout" ## _real_unfl() so that the operating system enabled overflow handler ## can handle this case. ## Two other conditions exist. First, if underflow was disabled ## but the inexact exception was enabled and the result was inexact, ## this handler must exit through the "callout" _real_inex(). ## was inexact. ## Also, in the case of an opclass three instruction where ## underflow was disabled and the trace exception was enabled, this ## handler must exit through the "callout" _real_trace(). ## ########################################################################## global _fpsp_unfl_fpsp_unfl:#$# sub.l &24,%sp # make room for src/dst link.w %a6,&-LOCAL_SIZE # init stack frame fsave FP_SRC(%a6) # grab the "busy" frame movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack# the FPIAR holds the "current PC" of the faulting instruction mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr bsr.l _imem_read_long # fetch the instruction words mov.l %d0,EXC_OPWORD(%a6)############################################################################## btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out? bne.w funfl_out lea FP_SRC(%a6),%a0 # pass: ptr to src op bsr.l fix_skewed_ops # fix src op lea FP_SRC(%a6),%a0 # pass: ptr to src op bsr.l set_tag_x # tag the operand type mov.b %d0,STAG(%a6) # maybe NORM,DENORM# bit five of the fp ext word separates the monadic and dyadic operations# that can pass through fpsp_unfl(). remember that fcmp, and ftst# will never take this exception. btst &0x5,1+EXC_CMDREG(%a6) # is op monadic or dyadic? beq.b funfl_extract # monadic# now, what's left that's not dyadic is fsincos. we can distinguish it# from all dyadics by the '0110xxx pattern btst &0x4,1+EXC_CMDREG(%a6) # is op an fsincos? bne.b funfl_extract # yes bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg bsr.l load_fpn2 # load dst into FP_DST lea FP_DST(%a6),%a0 # pass: ptr to dst op bsr.l set_tag_x # tag the operand type cmpi.b %d0,&UNNORM # is operand an UNNORM? bne.b funfl_op2_done # no bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZEROfunfl_op2_done: mov.b %d0,DTAG(%a6) # save dst optype tagfunfl_extract:#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6) clr.l %d0 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode mov.b 1+EXC_CMDREG(%a6),%d1 andi.w &0x007f,%d1 # extract extension andi.l &0x00ff01ff,USER_FPSR(%a6) fmov.l &0x0,%fpcr # zero current control regs fmov.l &0x0,%fpsr lea FP_SRC(%a6),%a0 lea FP_DST(%a6),%a1# maybe we can make these entry points ONLY the OVFL entry points of each routine. mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr jsr (tbl_unsupp.l,%pc,%d1.l*1) bfextu EXC_CMDREG(%a6){&6:&3},%d0 bsr.l store_fpreg# The `060 FPU multiplier hardware is such that if the result of a# multiply operation is the smallest possible normalized number# (0x00000000_80000000_00000000), then the machine will take an# underflow exception. Since this is incorrect, we need to check# if our emulation, after re-doing the operation, decided that# no underflow was called for. We do these checks only in# funfl_{unfl,inex}_on() because w/ both exceptions disabled, this# special case will simply exit gracefully with the correct result.# the exceptional possibilities we have left ourselves with are ONLY overflow# and inexact. and, the inexact is such that overflow occurred and was disabled# but inexact was enabled. btst &unfl_bit,FPCR_ENABLE(%a6) bne.b funfl_unfl_onfunfl_chkinex: btst &inex2_bit,FPCR_ENABLE(%a6) bne.b funfl_inex_onfunfl_exit: fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 unlk %a6#$# add.l &24,%sp bra.l _fpsp_done# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP# in fp1 (don't forget to save fp0). what to do now?# well, we simply have to get to go to _real_unfl()!funfl_unfl_on:# The `060 FPU multiplier hardware is such that if the result of a# multiply operation is the smallest possible normalized number# (0x00000000_80000000_00000000), then the machine will take an# underflow exception. Since this is incorrect, we check here to see# if our emulation, after re-doing the operation, decided that# no underflow was called for. btst &unfl_bit,FPSR_EXCEPT(%a6) beq.w funfl_chkinexfunfl_unfl_on2: fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack mov.w &0xe003,2+FP_SRC(%a6) # save exc status fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s! unlk %a6 bra.l _real_unfl# undeflow occurred but is disabled. meanwhile, inexact is enabled. therefore,# we must jump to real_inex().funfl_inex_on:# The `060 FPU multiplier hardware is such that if the result of a# multiply operation is the smallest possible normalized number# (0x00000000_80000000_00000000), then the machine will take an# underflow exception.# But, whether bogus or not, if inexact is enabled AND it occurred,# then we have to branch to real_inex. btst &inex2_bit,FPSR_EXCEPT(%a6) beq.w funfl_exitfunfl_inex_on2: fmovm.x &0x40,FP_SRC(%a6) # save EXOP to stack mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4 mov.w &0xe001,2+FP_SRC(%a6) # save exc status fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 frestore FP_SRC(%a6) # do this after fmovm,other f<op>s! unlk %a6 bra.l _real_inex#######################################################################funfl_out:#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)# the src operand is definitely a NORM(!), so tag it as such mov.b &NORM,STAG(%a6) # set src optype tag clr.l %d0 mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field fmov.l &0x0,%fpcr # zero current control regs fmov.l &0x0,%fpsr lea FP_SRC(%a6),%a0 # pass ptr to src operand bsr.l fout btst &unfl_bit,FPCR_ENABLE(%a6) bne.w funfl_unfl_on2 btst &inex2_bit,FPCR_ENABLE(%a6) bne.w funfl_inex_on2 fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1 unlk %a6#$# add.l &24,%sp btst &0x7,(%sp) # is trace on? beq.l _fpsp_done # no fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024 bra.l _real_trace########################################################################## XDEF **************************************************************** ## _fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented ## Data Type" exception. ## ## This handler should be the first code executed upon taking the ## FP Unimplemented Data Type exception in an operating system. ## ## XREF **************************************************************** ## _imem_read_{word,long}() - read instruction word/longword ## fix_skewed_ops() - adjust src operand in fsave frame ## set_tag_x() - determine optype of src/dst operands ## store_fpreg() - store opclass 0 or 2 result to FP regfile ## unnorm_fix() - change UNNORM operands to NORM or ZERO ## load_fpn2() - load dst operand from FP regfile ## load_fpn1() - load src operand from FP regfile ## fout() - emulate an opclass 3 instruction ## tbl_unsupp - add of table of emulation routines for opclass 0,2 ## _real_inex() - "callout" to operating system inexact handler ## _fpsp_done() - "callout" for exit; work all done ## _real_trace() - "callout" for Trace enabled exception ## funimp_skew() - adjust fsave src ops to "incorrect" value ## _real_snan() - "callout" for SNAN exception ## _real_operr() - "callout" for OPERR exception ## _real_ovfl() - "callout" for OVFL exception ## _real_unfl() - "callout" for UNFL exception ## get_packed() - fetch packed operand from memory ## ## INPUT *************************************************************** ## - The system stack contains the "Unimp Data Type" stk frame ## - The fsave frame contains the ssrc op (for UNNORM/DENORM) ## ## OUTPUT ************************************************************** ## If Inexact exception (opclass 3): ## - The system stack is changed to an Inexact exception stk frame ## If SNAN exception (opclass 3): ## - The system stack is changed to an SNAN exception stk frame ## If OPERR exception (opclass 3): ## - The system stack is changed to an OPERR exception stk frame ## If OVFL exception (opclass 3): ## - The system stack is changed to an OVFL exception stk frame ## If UNFL exception (opclass 3): ## - The system stack is changed to an UNFL exception stack frame ## If Trace exception enabled: ## - The system stack is changed to a Trace exception stack frame ## Else: (normal case) ## - Correct result has been stored as appropriate ## ## ALGORITHM *********************************************************** ## Two main instruction types can enter here: (1) DENORM or UNNORM ## unimplemented data types. These can be either opclass 0,2 or 3 ## instructions, and (2) PACKED unimplemented data format instructions ## also of opclasses 0,2, or 3. ## For UNNORM/DENORM opclass 0 and 2, the handler fetches the src ## operand from the fsave state frame and the dst operand (if dyadic) ## from the FP register file. The instruction is then emulated by ## choosing an emulation routine from a table of routines indexed by ## instruction type. Once the instruction has been emulated and result ## saved, then we check to see if any enabled exceptions resulted from ## instruction emulation. If none, then we exit through the "callout" ## _fpsp_done(). If there is an enabled FP exception, then we insert ## this exception into the FPU in the fsave state frame and then exit ## through _fpsp_done(). ## PACKED opclass 0 and 2 is similar in how the instruction is ## emulated and exceptions handled. The differences occur in how the ## handler loads the packed op (by calling get_packed() routine) and ## by the fact that a Trace exception could be pending for PACKED ops. ## If a Trace exception is pending, then the current exception stack ## frame is changed to a Trace exception stack frame and an exit is ## made through _real_trace(). ## For UNNORM/DENORM opclass 3, the actual move out to memory is ## performed by calling the routine fout(). If no exception should occur ## as the result of emulation, then an exit either occurs through ## _fpsp_done() or through _real_trace() if a Trace exception is pending ## (a Trace stack frame must be created here, too). If an FP exception ## should occur, then we must create an exception stack frame of that ## type and jump to either _real_snan(), _real_operr(), _real_inex(), ## _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3 ## emulation is performed in a similar manner. ## ############################################################################ (1) DENORM and UNNORM (unimplemented) data types:## post-instruction# *****************# * EA *# pre-instruction * *# ***************** *****************# * 0x0 * 0x0dc * * 0x3 * 0x0dc *# ***************** *****************# * Next * * Next *# * PC * * PC *# ***************** *****************# * SR * * SR *# ***************** *****************## (2) PACKED format (unsupported) opclasses two and three:# *****************# * EA *# * *# *****************# * 0x2 * 0x0dc *# *****************# * Next *# * PC *# *****************# * SR *# *****************# global _fpsp_unsupp_fpsp_unsupp: link.w %a6,&-LOCAL_SIZE # init stack frame fsave FP_SRC(%a6) # save fp state movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1 fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack btst &0x5,EXC_SR(%a6) # user or supervisor mode? bne.b fu_sfu_u:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -