📄 res_func.s
字号:
wi: moveql #2,%d0 |set byte count btstb #7,STAG(%a6) |check for extended denorm bne int_dnrm |branch if so fmovemx ETEMP(%a6),%fp0-%fp0 fcmps #0x46fffe00,%fp0| 46fffe00 in sgl prec = 400d0000fffe000000000000 in ext prec fbge wo_plrg fcmps #0xc7000000,%fp0| c7000000 in sgl prec = c00e00008000000000000000 in ext prec fble wo_nlrg|| at this point, the answer is between the largest pos and neg values| movel USER_FPCR(%a6),%d1 |use user's rounding mode andil #0x30,%d1 fmovel %d1,%fpcr fmovew %fp0,L_SCR1(%a6) |let the 040 perform conversion fmovel %fpsr,%d1 orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set bra int_wrtwo_plrg: movew #0x7fff,L_SCR1(%a6) |answer is largest positive int fbeq int_wrt |exact answer fcmps #0x46ffff00,%fp0| 46ffff00 in sgl prec = 400d0000ffff000000000000 in ext prec fbge int_operr |set operr bra int_inx |set inexactwo_nlrg: movew #0x8000,L_SCR1(%a6) fbeq int_wrt |exact answer fcmps #0xc7000080,%fp0| c7000080 in sgl prec = c00e00008000800000000000 in ext prec fblt int_operr |set operr bra int_inx |set inexact|| bi is used to handle a byte integer source specifier|bi: moveql #1,%d0 |set byte count btstb #7,STAG(%a6) |check for extended denorm bne int_dnrm |branch if so fmovemx ETEMP(%a6),%fp0-%fp0 fcmps #0x42fe0000,%fp0| 42fe0000 in sgl prec = 40050000fe00000000000000 in ext prec fbge by_plrg fcmps #0xc3000000,%fp0| c3000000 in sgl prec = c00600008000000000000000 in ext prec fble by_nlrg|| at this point, the answer is between the largest pos and neg values| movel USER_FPCR(%a6),%d1 |use user's rounding mode andil #0x30,%d1 fmovel %d1,%fpcr fmoveb %fp0,L_SCR1(%a6) |let the 040 perform conversion fmovel %fpsr,%d1 orl %d1,USER_FPSR(%a6) |capture inex2/ainex if set bra int_wrtby_plrg: moveb #0x7f,L_SCR1(%a6) |answer is largest positive int fbeq int_wrt |exact answer fcmps #0x42ff0000,%fp0| 42ff0000 in sgl prec = 40050000ff00000000000000 in ext prec fbge int_operr |set operr bra int_inx |set inexactby_nlrg: moveb #0x80,L_SCR1(%a6) fbeq int_wrt |exact answer fcmps #0xc3008000,%fp0| c3008000 in sgl prec = c00600008080000000000000 in ext prec fblt int_operr |set operr bra int_inx |set inexact|| Common integer routines|| int_drnrm---account for possible nonzero result for round up with positive| operand and round down for negative answer. In the first case (result = 1)| byte-width (store in d0) of result must be honored. In the second case,| -1 in L_SCR1(a6) will cover all contingencies (FMOVE.B/W/L out).int_dnrm: movel #0,L_SCR1(%a6) | initialize result to 0 bfextu FPCR_MODE(%a6){#2:#2},%d1 | d1 is the rounding mode cmpb #2,%d1 bmis int_inx | if RN or RZ, done bnes int_rp | if RP, continue below tstw ETEMP(%a6) | RM: store -1 in L_SCR1 if src is negative bpls int_inx | otherwise result is 0 movel #-1,L_SCR1(%a6) bras int_inxint_rp: tstw ETEMP(%a6) | RP: store +1 of proper width in L_SCR1 if| ; source is greater than 0 bmis int_inx | otherwise, result is 0 lea L_SCR1(%a6),%a1 | a1 is address of L_SCR1 addal %d0,%a1 | offset by destination width -1 subal #1,%a1 bsetb #0,(%a1) | set low bit at a1 addressint_inx: oril #inx2a_mask,USER_FPSR(%a6) bras int_wrtint_operr: fmovemx %fp0-%fp0,FPTEMP(%a6) |FPTEMP must contain the extended| ;precision source that needs to be| ;converted to integer this is required| ;if the operr exception is enabled.| ;set operr/aiop (no inex2 on int ovfl) oril #opaop_mask,USER_FPSR(%a6)| ;fall through to perform int_wrtint_wrt: movel EXC_EA(%a6),%a1 |load destination address tstl %a1 |check to see if it is a dest register beqs wrt_dn |write data register lea L_SCR1(%a6),%a0 |point to supervisor source address bsrl mem_write bra mvouti_endwrt_dn: movel %d0,-(%sp) |d0 currently contains the size to write bsrl get_fline |get_fline returns Dn in d0 andiw #0x7,%d0 |isolate register movel (%sp)+,%d1 |get size cmpil #4,%d1 |most frequent case beqs sz_long cmpil #2,%d1 bnes sz_con orl #8,%d0 |add 'word' size to register# bras sz_consz_long: orl #0x10,%d0 |add 'long' size to register#sz_con: movel %d0,%d1 |reg_dest expects size:reg in d1 bsrl reg_dest |load proper data register bra mvouti_endxp: lea ETEMP(%a6),%a0 bclrb #sign_bit,LOCAL_EX(%a0) sne LOCAL_SGN(%a0) btstb #7,STAG(%a6) |check for extended denorm bne xdnrm clrl %d0 bras do_fp |do normal casesgp: lea ETEMP(%a6),%a0 bclrb #sign_bit,LOCAL_EX(%a0) sne LOCAL_SGN(%a0) btstb #7,STAG(%a6) |check for extended denorm bne sp_catas |branch if so movew LOCAL_EX(%a0),%d0 lea sp_bnds,%a1 cmpw (%a1),%d0 blt sp_under cmpw 2(%a1),%d0 bgt sp_over movel #1,%d0 |set destination format to single bras do_fp |do normal casedp: lea ETEMP(%a6),%a0 bclrb #sign_bit,LOCAL_EX(%a0) sne LOCAL_SGN(%a0) btstb #7,STAG(%a6) |check for extended denorm bne dp_catas |branch if so movew LOCAL_EX(%a0),%d0 lea dp_bnds,%a1 cmpw (%a1),%d0 blt dp_under cmpw 2(%a1),%d0 bgt dp_over movel #2,%d0 |set destination format to double| ;fall through to do_fp|do_fp: bfextu FPCR_MODE(%a6){#2:#2},%d1 |rnd mode in d1 swap %d0 |rnd prec in upper word addl %d0,%d1 |d1 has PREC/MODE info clrl %d0 |clear g,r,s bsrl round |round movel %a0,%a1 movel EXC_EA(%a6),%a0 bfextu CMDREG1B(%a6){#3:#3},%d1 |extract destination format| ;at this point only the dest| ;formats sgl, dbl, ext are| ;possible cmpb #2,%d1 bgts ddbl |double=5, extended=2, single=1 bnes dsgl| ;fall through to dextdext: bsrl dest_ext bra mvout_enddsgl: bsrl dest_sgl bra mvout_endddbl: bsrl dest_dbl bra mvout_end|| Handle possible denorm or catastrophic underflow cases here|xdnrm: bsr set_xop |initialize WBTEMP bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 movel %a0,%a1 movel EXC_EA(%a6),%a0 |a0 has the destination pointer bsrl dest_ext |store to memory bsetb #unfl_bit,FPSR_EXCEPT(%a6) bra mvout_endsp_under: bsetb #etemp15_bit,STAG(%a6) cmpw 4(%a1),%d0 blts sp_catas |catastrophic underflow case movel #1,%d0 |load in round precision movel #sgl_thresh,%d1 |load in single denorm threshold bsrl dpspdnrm |expects d1 to have the proper| ;denorm threshold bsrl dest_sgl |stores value to destination bsetb #unfl_bit,FPSR_EXCEPT(%a6) bra mvout_end |exitdp_under: bsetb #etemp15_bit,STAG(%a6) cmpw 4(%a1),%d0 blts dp_catas |catastrophic underflow case movel #dbl_thresh,%d1 |load in double precision threshold movel #2,%d0 bsrl dpspdnrm |expects d1 to have proper| ;denorm threshold| ;expects d0 to have round precision bsrl dest_dbl |store value to destination bsetb #unfl_bit,FPSR_EXCEPT(%a6) bra mvout_end |exit|| Handle catastrophic underflow cases here|sp_catas:| Temp fix for z bit set in unf_sub movel USER_FPSR(%a6),-(%a7) movel #1,%d0 |set round precision to sgl bsrl unf_sub |a0 points to result movel (%a7)+,USER_FPSR(%a6) movel #1,%d0 subw %d0,LOCAL_EX(%a0) |account for difference between| ;denorm/norm bias movel %a0,%a1 |a1 has the operand input movel EXC_EA(%a6),%a0 |a0 has the destination pointer bsrl dest_sgl |store the result oril #unfinx_mask,USER_FPSR(%a6) bra mvout_enddp_catas:| Temp fix for z bit set in unf_sub movel USER_FPSR(%a6),-(%a7) movel #2,%d0 |set round precision to dbl bsrl unf_sub |a0 points to result movel (%a7)+,USER_FPSR(%a6) movel #1,%d0 subw %d0,LOCAL_EX(%a0) |account for difference between| ;denorm/norm bias movel %a0,%a1 |a1 has the operand input movel EXC_EA(%a6),%a0 |a0 has the destination pointer bsrl dest_dbl |store the result oril #unfinx_mask,USER_FPSR(%a6) bra mvout_end|| Handle catastrophic overflow cases here|sp_over:| Temp fix for z bit set in unf_sub movel USER_FPSR(%a6),-(%a7) movel #1,%d0 leal FP_SCR1(%a6),%a0 |use FP_SCR1 for creating result movel ETEMP_EX(%a6),(%a0) movel ETEMP_HI(%a6),4(%a0) movel ETEMP_LO(%a6),8(%a0) bsrl ovf_res movel (%a7)+,USER_FPSR(%a6) movel %a0,%a1 movel EXC_EA(%a6),%a0 bsrl dest_sgl orl #ovfinx_mask,USER_FPSR(%a6) bra mvout_enddp_over:| Temp fix for z bit set in ovf_res movel USER_FPSR(%a6),-(%a7) movel #2,%d0 leal FP_SCR1(%a6),%a0 |use FP_SCR1 for creating result movel ETEMP_EX(%a6),(%a0) movel ETEMP_HI(%a6),4(%a0) movel ETEMP_LO(%a6),8(%a0) bsrl ovf_res movel (%a7)+,USER_FPSR(%a6) movel %a0,%a1 movel EXC_EA(%a6),%a0 bsrl dest_dbl orl #ovfinx_mask,USER_FPSR(%a6) bra mvout_end|| DPSPDNRM|| This subroutine takes an extended normalized number and denormalizes| it to the given round precision. This subroutine also decrements| the input operand's exponent by 1 to account for the fact that| dest_sgl or dest_dbl expects a normalized number's bias.|| Input: a0 points to a normalized number in internal extended format| d0 is the round precision (=1 for sgl; =2 for dbl)| d1 is the single precision or double precision| denorm threshold|| Output: (In the format for dest_sgl or dest_dbl)| a0 points to the destination| a1 points to the operand|| Exceptions: Reports inexact 2 exception by setting USER_FPSR bits|dpspdnrm: movel %d0,-(%a7) |save round precision clrl %d0 |clear initial g,r,s bsrl dnrm_lp |careful with d0, it's needed by round bfextu FPCR_MODE(%a6){#2:#2},%d1 |get rounding mode swap %d1 movew 2(%a7),%d1 |set rounding precision swap %d1 |at this point d1 has PREC/MODE info bsrl round |round result, sets the inex bit in| ;USER_FPSR if needed movew #1,%d0 subw %d0,LOCAL_EX(%a0) |account for difference in denorm| ;vs norm bias movel %a0,%a1 |a1 has the operand input movel EXC_EA(%a6),%a0 |a0 has the destination pointer addw #4,%a7 |pop stack rts|| SET_XOP initialized WBTEMP with the value pointed to by a0| input: a0 points to input operand in the internal extended format|set_xop: movel LOCAL_EX(%a0),WBTEMP_EX(%a6) movel LOCAL_HI(%a0),WBTEMP_HI(%a6) movel LOCAL_LO(%a0),WBTEMP_LO(%a6) bfclr WBTEMP_SGN(%a6){#0:#8} beqs sxop bsetb #sign_bit,WBTEMP_EX(%a6)sxop: bfclr STAG(%a6){#5:#4} |clear wbtm66,wbtm1,wbtm0,sbit rts|| P_MOVE|p_movet: .long p_move .long p_movez .long p_movei .long p_moven .long p_movep_regd: .long p_dyd0 .long p_dyd1 .long p_dyd2 .long p_dyd3 .long p_dyd4 .long p_dyd5 .long p_dyd6 .long p_dyd7pack_out: leal p_movet,%a0 |load jmp table address movew STAG(%a6),%d0 |get source tag bfextu %d0{#16:#3},%d0 |isolate source bits movel (%a0,%d0.w*4),%a0 |load a0 with routine label for tag jmp (%a0) |go to the routinep_write: movel #0x0c,%d0 |get byte count movel EXC_EA(%a6),%a1 |get the destination address bsr mem_write |write the user's destination moveb #0,CU_SAVEPC(%a6) |set the cu save pc to all 0's|| Also note that the dtag must be set to norm here - this is because| the 040 uses the dtag to execute the correct microcode.| bfclr DTAG(%a6){#0:#3} |set dtag to norm rts| Notes on handling of special case (zero, inf, and nan) inputs:| 1. Operr is not signalled if the k-factor is greater than 18.| 2. Per the manual, status bits are not set.|p_move: movew CMDREG1B(%a6),%d0 btstl #kfact_bit,%d0 |test for dynamic k-factor beqs statick |if clear, k-factor is staticdynamick: bfextu %d0{#25:#3},%d0 |isolate register for dynamic k-factor lea p_regd,%a0 movel %a0@(%d0:l:4),%a0 jmp (%a0)statick: andiw #0x007f,%d0 |get k-factor bfexts %d0{#25:#7},%d0 |sign extend d0 for bindec leal ETEMP(%a6),%a0 |a0 will point to the packed decimal bsrl bindec |perform the convert; data at a6 leal FP_SCR1(%a6),%a0 |load a0 with result address bral p_writep_movez: leal ETEMP(%a6),%a0 |a0 will point to the packed decimal clrw 2(%a0) |clear lower word of exp clrl 4(%a0) |load second lword of ZERO clrl 8(%a0) |load third lword of ZERO bra p_write |go write resultsp_movei: fmovel #0,%FPSR |clear aiop leal ETEMP(%a6),%a0 |a0 will point to the packed decimal clrw 2(%a0) |clear lower word of exp bra p_write |go write the resultp_moven: leal ETEMP(%a6),%a0 |a0 will point to the packed decimal clrw 2(%a0) |clear lower word of exp bra p_write |go write the result|| Routines to read the dynamic k-factor from Dn.|p_dyd0: movel USER_D0(%a6),%d0 bras statickp_dyd1: movel USER_D1(%a6),%d0 bras statickp_dyd2: movel %d2,%d0 bras statickp_dyd3: movel %d3,%d0 bras statickp_dyd4: movel %d4,%d0 bras statickp_dyd5: movel %d5,%d0 bras statickp_dyd6: movel %d6,%d0 bra statickp_dyd7: movel %d7,%d0 bra statick |end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -