📄 res_func.s
字号:
// wi is used to handle a word integer source specifier//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_end xp: 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_end sp_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_end dp_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 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 + -