📄 pfpsp.s
字号:
# was exact, then a branch to _real_inex() is made. btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set? beq.w fu_out_done # nofu_out_ovflchk: btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled? beq.w fu_out_done # no bra.w fu_inex # yes## The fp move out that took the "Unimplemented Data Type" exception was# being traced. Since the stack frames are similar, get the "current" PC# from FPIAR and put it in the trace stack frame then jump to _real_trace().## UNSUPP FRAME TRACE FRAME# ***************** *****************# * EA * * Current *# * * * PC *# ***************** *****************# * 0x3 * 0x0dc * * 0x2 * 0x024 *# ***************** *****************# * Next * * Next *# * PC * * PC *# ***************** *****************# * SR * * SR *# ***************** *****************#fu_out_trace: mov.w &0x2024,0x6(%sp) fmov.l %fpiar,0x8(%sp) bra.l _real_trace# an exception occurred and that exception was enabled.fu_out_exc: subi.l &24,%d0 # fix offset to be 0-8# we don't mess with the existing fsave frame. just re-insert it and# jump to the "_real_{}()" handler... mov.w (tbl_fu_out.b,%pc,%d0.w*2),%d0 jmp (tbl_fu_out.b,%pc,%d0.w*1) swbeg &0x8tbl_fu_out: short tbl_fu_out - tbl_fu_out # BSUN can't happen short tbl_fu_out - tbl_fu_out # SNAN can't happen short fu_operr - tbl_fu_out # OPERR short fu_ovfl - tbl_fu_out # OVFL short fu_unfl - tbl_fu_out # UNFL short tbl_fu_out - tbl_fu_out # DZ can't happen short fu_inex - tbl_fu_out # INEX2 short tbl_fu_out - tbl_fu_out # INEX1 won't make it here# for snan,operr,ovfl,unfl, src op is still in FP_SRC so just# frestore it.fu_snan: 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 mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd8 mov.w &0xe006,2+FP_SRC(%a6) frestore FP_SRC(%a6) unlk %a6 bra.l _real_snanfu_operr: 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 mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0 mov.w &0xe004,2+FP_SRC(%a6) frestore FP_SRC(%a6) unlk %a6 bra.l _real_operrfu_ovfl: fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack 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 mov.w &0x30d4,EXC_VOFF(%a6) # vector offset = 0xd4 mov.w &0xe005,2+FP_SRC(%a6) frestore FP_SRC(%a6) # restore EXOP unlk %a6 bra.l _real_ovfl# underflow can happen for extended precision. extended precision opclass# three instruction exceptions don't update the stack pointer. so, if the# exception occurred from user mode, then simply update a7 and exit normally.# if the exception occurred from supervisor mode, check iffu_unfl: mov.l EXC_A6(%a6),(%a6) # restore a6 btst &0x5,EXC_SR(%a6) bne.w fu_unfl_s mov.l EXC_A7(%a6),%a0 # restore a7 whether we need mov.l %a0,%usp # to or not...fu_unfl_cont: fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack 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 mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc mov.w &0xe003,2+FP_SRC(%a6) frestore FP_SRC(%a6) # restore EXOP unlk %a6 bra.l _real_unflfu_unfl_s: cmpi.b SPCOND_FLG(%a6),&mda7_flg # was the <ea> mode -(sp)? bne.b fu_unfl_cont# the extended precision result is still in fp0. but, we need to save it# somewhere on the stack until we can copy it to its final resting place# (where the exc frame is currently). make sure it's not at the top of the# frame or it will get overwritten when the exc stack frame is shifted "down". fmovm.x &0x80,FP_SRC(%a6) # put answer on stack fmovm.x &0x40,FP_DST(%a6) # put EXOP on stack 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 mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc mov.w &0xe003,2+FP_DST(%a6) frestore FP_DST(%a6) # restore EXOP mov.l (%a6),%a6 # restore frame pointer mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp) mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp) mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)# now, copy the result to the proper place on the stack mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp) mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp) mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp) add.l &LOCAL_SIZE-0x8,%sp bra.l _real_unfl# fmove in and out enter here.fu_inex: fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack 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 mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4 mov.w &0xe001,2+FP_SRC(%a6) frestore FP_SRC(%a6) # restore EXOP unlk %a6 bra.l _real_inex##################################################################################################################################################fu_in_pack:# I'm not sure at this point what FPSR bits are valid for this instruction.# so, since the emulation routines re-create them anyways, zero exception field andi.l &0x0ff00ff,USER_FPSR(%a6) # zero exception field fmov.l &0x0,%fpcr # zero current control regs fmov.l &0x0,%fpsr bsr.l get_packed # fetch packed src operand lea FP_SRC(%a6),%a0 # pass ptr to src bsr.l set_tag_x # set src optype tag mov.b %d0,STAG(%a6) # save src optype tag bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg# bit five of the fp extension word separates the monadic and dyadic operations# at this point btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic? beq.b fu_extract_p # monadic cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst? beq.b fu_extract_p # yes, so it's monadic, too 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 fu_op2_done_p # no bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZEROfu_op2_done_p: mov.b %d0,DTAG(%a6) # save dst optype tagfu_extract_p: clr.l %d0 mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension lea FP_SRC(%a6),%a0 lea FP_DST(%a6),%a1 mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr jsr (tbl_unsupp.l,%pc,%d1.l*1)## Exceptions in order of precedence:# BSUN : none# SNAN : all dyadic ops# OPERR : fsqrt(-NORM)# OVFL : all except ftst,fcmp# UNFL : all except ftst,fcmp# DZ : fdiv# INEX2 : all except ftst,fcmp# INEX1 : all## we determine the highest priority exception(if any) set by the# emulation routine that has also been enabled by the user. mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled bne.w fu_in_ena_p # some are enabledfu_in_cont_p:# fcmp and ftst do not store any result. mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension andi.b &0x38,%d0 # extract bits 3-5 cmpi.b %d0,&0x38 # is instr fcmp or ftst? beq.b fu_in_exit_p # yes bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg bsr.l store_fpreg # store the resultfu_in_exit_p: btst &0x5,EXC_SR(%a6) # user or supervisor? bne.w fu_in_exit_s_p # supervisor mov.l EXC_A7(%a6),%a0 # update user a7 mov.l %a0,%uspfu_in_exit_cont_p: 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 # unravel stack frame btst &0x7,(%sp) # is trace on? bne.w fu_trace_p # yes bra.l _fpsp_done # exit to os# the exception occurred in supervisor mode. check to see if the# addressing mode was (a7)+. if so, we'll need to shift the# stack frame "up".fu_in_exit_s_p: btst &mia7_bit,SPCOND_FLG(%a6) # was ea mode (a7)+ beq.b fu_in_exit_cont_p # no 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 # unravel stack frame# shift the stack frame "up". we don't really care about the <ea> field. mov.l 0x4(%sp),0x10(%sp) mov.l 0x0(%sp),0xc(%sp) add.l &0xc,%sp btst &0x7,(%sp) # is trace on? bne.w fu_trace_p # yes bra.l _fpsp_done # exit to osfu_in_ena_p: and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled & set bfffo %d0{&24:&8},%d0 # find highest priority exception bne.b fu_in_exc_p # at least one was set## No exceptions occurred that were also enabled. Now:## if (OVFL && ovfl_disabled && inexact_enabled) {# branch to _real_inex() (even if the result was exact!);# } else {# save the result in the proper fp reg (unless the op is fcmp or ftst);# return;# }# btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set? beq.w fu_in_cont_p # nofu_in_ovflchk_p: btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled? beq.w fu_in_cont_p # no bra.w fu_in_exc_ovfl_p # do _real_inex() now## An exception occurred and that exception was enabled:## shift enabled exception field into lo byte of d0;# if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||# ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {# /*# * this is the case where we must call _real_inex() now or else# * there will be no other way to pass it the exceptional operand# */# call _real_inex();# } else {# restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;# }#fu_in_exc_p: subi.l &24,%d0 # fix offset to be 0-8 cmpi.b %d0,&0x6 # is exception INEX? (6 or 7) blt.b fu_in_exc_exit_p # no# the enabled exception was inexact btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur? bne.w fu_in_exc_unfl_p # yes btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur? bne.w fu_in_exc_ovfl_p # yes# here, we insert the correct fsave status value into the fsave frame for the# corresponding exception. the operand in the fsave frame should be the original# src operand.# as a reminder for future predicted pain and agony, we are passing in fsave the# "non-skewed" operand for cases of sgl and dbl src INFs,NANs, and DENORMs.# this is INCORRECT for enabled SNAN which would give to the user the skewed SNAN!!!fu_in_exc_exit_p: btst &0x5,EXC_SR(%a6) # user or supervisor? bne.w fu_in_exc_exit_s_p # supervisor mov.l EXC_A7(%a6),%a0 # update user a7 mov.l %a0,%uspfu_in_exc_exit_cont_p: mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6) 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) # restore src op unlk %a6 btst &0x7,(%sp) # is trace enabled? bne.w fu_trace_p # yes bra.l _fpsp_donetbl_except_p: short 0xe000,0xe006,0xe004,0xe005 short 0xe003,0xe002,0xe001,0xe001fu_in_exc_ovfl_p: mov.w &0x3,%d0 bra.w fu_in_exc_exit_pfu_in_exc_unfl_p: mov.w &0x4,%d0 bra.w fu_in_exc_exit_pfu_in_exc_exit_s_p: btst &mia7_bit,SPCOND_FLG(%a6) beq.b fu_in_exc_exit_cont_p mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6) 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -