📄 res_func.s
字号:
andiw #0x8000,%d0 orw #0x3fff,%d0 //force the exponent to +/- 1 movew %d0,FPTEMP_EX(%a6) //in the denorm movel USER_FPCR(%a6),%d0 andil #0x30,%d0 fmovel %d0,%fpcr //set up users rmode and X fmovex FPTEMP(%a6),%fp0 fsubx ETEMP(%a6),%fp0 fmovel %fpsr,%d1 orl %d1,USER_FPSR(%a6) //capture cc's and inex from fadd leal WBTEMP(%a6),%a0 //point a0 to wbtemp in frame fmovex %fp0,WBTEMP(%a6) //write result to memory lsrl #4,%d0 //put rmode in lower 2 bits movel USER_FPCR(%a6),%d1 andil #0xc0,%d1 lsrl #6,%d1 //put precision in upper word swap %d1 orl %d0,%d1 //set up for round call clrl %d0 //force sticky to zero bclrb #sign_bit,WBTEMP_EX(%a6) sne WBTEMP_SGN(%a6) bsrl round //round result to users rmode & prec bfclr WBTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format beq frcfpnr bsetb #sign_bit,WBTEMP_EX(%a6) bra frcfpnrsub_u_srcd: movew ETEMP_EX(%a6),%d0 andiw #0x8000,%d0 orw #0x3fff,%d0 //force the exponent to +/- 1 movew %d0,ETEMP_EX(%a6) //in the denorm movel USER_FPCR(%a6),%d0 andil #0x30,%d0 fmovel %d0,%fpcr //set up users rmode and X fmovex FPTEMP(%a6),%fp0 fsubx ETEMP(%a6),%fp0 fmovel %fpsr,%d1 orl %d1,USER_FPSR(%a6) //capture cc's and inex from fadd leal WBTEMP(%a6),%a0 //point a0 to wbtemp in frame fmovex %fp0,WBTEMP(%a6) //write result to memory lsrl #4,%d0 //put rmode in lower 2 bits movel USER_FPCR(%a6),%d1 andil #0xc0,%d1 lsrl #6,%d1 //put precision in upper word swap %d1 orl %d0,%d1 //set up for round call clrl %d0 //force sticky to zero bclrb #sign_bit,WBTEMP_EX(%a6) sne WBTEMP_SGN(%a6) bsrl round //round result to users rmode & prec bfclr WBTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format beq frcfpnr bsetb #sign_bit,WBTEMP_EX(%a6) bra frcfpnr//// Signs are unlike://sub_diff: cmpb #0x0f,DNRM_FLG(%a6) //is dest the denorm? bnes sub_s_srcdsub_s_destd: leal ETEMP(%a6),%a0 movel USER_FPCR(%a6),%d0 andil #0x30,%d0 lsrl #4,%d0 //put rmode in lower 2 bits movel USER_FPCR(%a6),%d1 andil #0xc0,%d1 lsrl #6,%d1 //put precision in upper word swap %d1 orl %d0,%d1 //set up for round call movel #0x20000000,%d0 //set sticky for round//// Since the dest is the denorm, the sign is the opposite of the// norm sign.// eoriw #0x8000,ETEMP_EX(%a6) //flip sign on result tstw ETEMP_EX(%a6) bgts sub_s_dwr orl #neg_mask,USER_FPSR(%a6)sub_s_dwr: bclrb #sign_bit,ETEMP_EX(%a6) sne ETEMP_SGN(%a6) bsrl round //round result to users rmode & prec bfclr ETEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format beqs sub_s_dclr bsetb #sign_bit,ETEMP_EX(%a6)sub_s_dclr: leal WBTEMP(%a6),%a0 movel ETEMP(%a6),(%a0) //write result to wbtemp movel ETEMP_HI(%a6),4(%a0) movel ETEMP_LO(%a6),8(%a0) bra sub_ckovfsub_s_srcd: leal FPTEMP(%a6),%a0 movel USER_FPCR(%a6),%d0 andil #0x30,%d0 lsrl #4,%d0 //put rmode in lower 2 bits movel USER_FPCR(%a6),%d1 andil #0xc0,%d1 lsrl #6,%d1 //put precision in upper word swap %d1 orl %d0,%d1 //set up for round call movel #0x20000000,%d0 //set sticky for round bclrb #sign_bit,FPTEMP_EX(%a6) sne FPTEMP_SGN(%a6) bsrl round //round result to users rmode & prec bfclr FPTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format beqs sub_s_sclr bsetb #sign_bit,FPTEMP_EX(%a6)sub_s_sclr: leal WBTEMP(%a6),%a0 movel FPTEMP(%a6),(%a0) //write result to wbtemp movel FPTEMP_HI(%a6),4(%a0) movel FPTEMP_LO(%a6),8(%a0) tstw FPTEMP_EX(%a6) bgt sub_ckovf orl #neg_mask,USER_FPSR(%a6)sub_ckovf: movew WBTEMP_EX(%a6),%d0 andiw #0x7fff,%d0 cmpiw #0x7fff,%d0 bne frcfpnr//// The result has overflowed to $7fff exponent. Set I, ovfl,// and aovfl, and clr the mantissa (incorrectly set by the// round routine.)// orl #inf_mask+ovfl_inx_mask,USER_FPSR(%a6) clrl 4(%a0) bra frcfpnr//// Inst is fcmp.//wrap_cmp: cmpb #0xff,DNRM_FLG(%a6) //if both ops denorm, beq fix_stk //restore to fpu//// One of the ops is denormalized. Test for wrap condition// and complete the instruction.// cmpb #0x0f,DNRM_FLG(%a6) //check for dest denorm bnes cmp_srcdcmp_destd: bsrl ckinf_ns bne fix_stk bfextu ETEMP_EX(%a6){#1:#15},%d0 //get src exp (always pos) bfexts FPTEMP_EX(%a6){#1:#15},%d1 //get dest exp (always neg) subl %d1,%d0 //subtract dest from src cmpl #0x8000,%d0 blt fix_stk //if less, not wrap case tstw ETEMP_EX(%a6) //set N to ~sign_of(src) bge cmp_setn rtscmp_srcd: bsrl ckinf_nd bne fix_stk bfextu FPTEMP_EX(%a6){#1:#15},%d0 //get dest exp (always pos) bfexts ETEMP_EX(%a6){#1:#15},%d1 //get src exp (always neg) subl %d1,%d0 //subtract src from dest cmpl #0x8000,%d0 blt fix_stk //if less, not wrap case tstw FPTEMP_EX(%a6) //set N to sign_of(dest) blt cmp_setn rtscmp_setn: orl #neg_mask,USER_FPSR(%a6) rts//// Inst is fmul.//wrap_mul: cmpb #0xff,DNRM_FLG(%a6) //if both ops denorm, beq force_unf //force an underflow (really!)//// One of the ops is denormalized. Test for wrap condition// and complete the instruction.// cmpb #0x0f,DNRM_FLG(%a6) //check for dest denorm bnes mul_srcdmul_destd: bsrl ckinf_ns bne fix_stk bfextu ETEMP_EX(%a6){#1:#15},%d0 //get src exp (always pos) bfexts FPTEMP_EX(%a6){#1:#15},%d1 //get dest exp (always neg) addl %d1,%d0 //subtract dest from src bgt fix_stk bra force_unfmul_srcd: bsrl ckinf_nd bne fix_stk bfextu FPTEMP_EX(%a6){#1:#15},%d0 //get dest exp (always pos) bfexts ETEMP_EX(%a6){#1:#15},%d1 //get src exp (always neg) addl %d1,%d0 //subtract src from dest bgt fix_stk //// This code handles the case of the instruction resulting in // an underflow condition.//force_unf: bclrb #E1,E_BYTE(%a6) orl #unfinx_mask,USER_FPSR(%a6) clrw NMNEXC(%a6) clrb WBTEMP_SGN(%a6) movew ETEMP_EX(%a6),%d0 //find the sign of the result movew FPTEMP_EX(%a6),%d1 eorw %d1,%d0 andiw #0x8000,%d0 beqs frcunfcont st WBTEMP_SGN(%a6)frcunfcont: lea WBTEMP(%a6),%a0 //point a0 to memory location movew CMDREG1B(%a6),%d0 btstl #6,%d0 //test for forced precision beqs frcunf_fpcr btstl #2,%d0 //check for double bnes frcunf_dbl movel #0x1,%d0 //inst is forced single bras frcunf_rndfrcunf_dbl: movel #0x2,%d0 //inst is forced double bras frcunf_rndfrcunf_fpcr: bfextu FPCR_MODE(%a6){#0:#2},%d0 //inst not forced - use fpcr precfrcunf_rnd: bsrl unf_sub //get correct result based on// ;round precision/mode. This // ;sets FPSR_CC correctly bfclr WBTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format beqs frcfpn bsetb #sign_bit,WBTEMP_EX(%a6) bra frcfpn//// Write the result to the user's fpn. All results must be HUGE to be// written; otherwise the results would have overflowed or underflowed.// If the rounding precision is single or double, the ovf_res routine// is needed to correctly supply the max value.//frcfpnr: movew CMDREG1B(%a6),%d0 btstl #6,%d0 //test for forced precision beqs frcfpn_fpcr btstl #2,%d0 //check for double bnes frcfpn_dbl movel #0x1,%d0 //inst is forced single bras frcfpn_rndfrcfpn_dbl: movel #0x2,%d0 //inst is forced double bras frcfpn_rndfrcfpn_fpcr: bfextu FPCR_MODE(%a6){#0:#2},%d0 //inst not forced - use fpcr prec tstb %d0 beqs frcfpn //if extended, write what you gotfrcfpn_rnd: bclrb #sign_bit,WBTEMP_EX(%a6) sne WBTEMP_SGN(%a6) bsrl ovf_res //get correct result based on// ;round precision/mode. This // ;sets FPSR_CC correctly bfclr WBTEMP_SGN(%a6){#0:#8} //convert back to IEEE ext format beqs frcfpn_clr bsetb #sign_bit,WBTEMP_EX(%a6)frcfpn_clr: orl #ovfinx_mask,USER_FPSR(%a6)// // Perform the write.//frcfpn: bfextu CMDREG1B(%a6){#6:#3},%d0 //extract fp destination register cmpib #3,%d0 bles frc0123 //check if dest is fp0-fp3 movel #7,%d1 subl %d0,%d1 clrl %d0 bsetl %d1,%d0 fmovemx WBTEMP(%a6),%d0 rtsfrc0123: cmpib #0,%d0 beqs frc0_dst cmpib #1,%d0 beqs frc1_dst cmpib #2,%d0 beqs frc2_dst frc3_dst: movel WBTEMP_EX(%a6),USER_FP3(%a6) movel WBTEMP_HI(%a6),USER_FP3+4(%a6) movel WBTEMP_LO(%a6),USER_FP3+8(%a6) rtsfrc2_dst: movel WBTEMP_EX(%a6),USER_FP2(%a6) movel WBTEMP_HI(%a6),USER_FP2+4(%a6) movel WBTEMP_LO(%a6),USER_FP2+8(%a6) rtsfrc1_dst: movel WBTEMP_EX(%a6),USER_FP1(%a6) movel WBTEMP_HI(%a6),USER_FP1+4(%a6) movel WBTEMP_LO(%a6),USER_FP1+8(%a6) rtsfrc0_dst: movel WBTEMP_EX(%a6),USER_FP0(%a6) movel WBTEMP_HI(%a6),USER_FP0+4(%a6) movel WBTEMP_LO(%a6),USER_FP0+8(%a6) rts//// Write etemp to fpn.// A check is made on enabled and signalled snan exceptions,// and the destination is not overwritten if this condition exists.// This code is designed to make fmoveins of unsupported data types// faster.//wr_etemp: btstb #snan_bit,FPSR_EXCEPT(%a6) //if snan is set, and beqs fmoveinc //enabled, force restore btstb #snan_bit,FPCR_ENABLE(%a6) //and don't overwrite beqs fmoveinc //the dest movel ETEMP_EX(%a6),FPTEMP_EX(%a6) //set up fptemp sign for // ;snan handler tstb ETEMP(%a6) //check for negative blts snan_neg rtssnan_neg: orl #neg_bit,USER_FPSR(%a6) //snan is negative; set N rtsfmoveinc: clrw NMNEXC(%a6) bclrb #E1,E_BYTE(%a6) moveb STAG(%a6),%d0 //check if stag is inf andib #0xe0,%d0 cmpib #0x40,%d0 bnes fminc_cnan orl #inf_mask,USER_FPSR(%a6) //if inf, nothing yet has set I tstw LOCAL_EX(%a0) //check sign bges fminc_con orl #neg_mask,USER_FPSR(%a6) bra fminc_confminc_cnan: cmpib #0x60,%d0 //check if stag is NaN bnes fminc_czero orl #nan_mask,USER_FPSR(%a6) //if nan, nothing yet has set NaN movel ETEMP_EX(%a6),FPTEMP_EX(%a6) //set up fptemp sign for // ;snan handler tstw LOCAL_EX(%a0) //check sign bges fminc_con orl #neg_mask,USER_FPSR(%a6) bra fminc_confminc_czero: cmpib #0x20,%d0 //check if zero bnes fminc_con orl #z_mask,USER_FPSR(%a6) //if zero, set Z tstw LOCAL_EX(%a0) //check sign bges fminc_con orl #neg_mask,USER_FPSR(%a6)fminc_con: bfextu CMDREG1B(%a6){#6:#3},%d0 //extract fp destination register cmpib #3,%d0 bles fp0123 //check if dest is fp0-fp3 movel #7,%d1 subl %d0,%d1 clrl %d0 bsetl %d1,%d0 fmovemx ETEMP(%a6),%d0 rtsfp0123: cmpib #0,%d0 beqs fp0_dst cmpib #1,%d0 beqs fp1_dst cmpib #2,%d0 beqs fp2_dst fp3_dst: movel ETEMP_EX(%a6),USER_FP3(%a6) movel ETEMP_HI(%a6),USER_FP3+4(%a6) movel ETEMP_LO(%a6),USER_FP3+8(%a6) rtsfp2_dst: movel ETEMP_EX(%a6),USER_FP2(%a6) movel ETEMP_HI(%a6),USER_FP2+4(%a6) movel ETEMP_LO(%a6),USER_FP2+8(%a6) rtsfp1_dst: movel ETEMP_EX(%a6),USER_FP1(%a6) movel ETEMP_HI(%a6),USER_FP1+4(%a6) movel ETEMP_LO(%a6),USER_FP1+8(%a6) rtsfp0_dst: movel ETEMP_EX(%a6),USER_FP0(%a6) movel ETEMP_HI(%a6),USER_FP0+4(%a6) movel ETEMP_LO(%a6),USER_FP0+8(%a6) rtsopclass3: st CU_ONLY(%a6) movew CMDREG1B(%a6),%d0 //check if packed moveout andiw #0x0c00,%d0 //isolate last 2 bits of size field cmpiw #0x0c00,%d0 //if size is 011 or 111, it is packed beq pack_out //else it is norm or denorm bra mv_out //// MOVE OUT//mv_tbl: .long li .long sgp .long xp .long mvout_end //should never be taken .long wi .long dp .long bi .long mvout_end //should never be takenmv_out: bfextu CMDREG1B(%a6){#3:#3},%d1 //put source specifier in d1 leal mv_tbl,%a0 movel %a0@(%d1:l:4),%a0 jmp (%a0)//// This exit is for move-out to memory. The aunfl bit is // set if the result is inex and unfl is signalled.//mvout_end: btstb #inex2_bit,FPSR_EXCEPT(%a6) beqs no_aufl btstb #unfl_bit,FPSR_EXCEPT(%a6) beqs no_aufl bsetb #aunfl_bit,FPSR_AEXCEPT(%a6)no_aufl: clrw NMNEXC(%a6) bclrb #E1,E_BYTE(%a6) fmovel #0,%FPSR //clear any cc bits from res_func//// Return ETEMP to extended format from internal extended format so// that gen_except will have a correctly signed value for ovfl/unfl// handlers.// bfclr ETEMP_SGN(%a6){#0:#8} beqs mvout_con bsetb #sign_bit,ETEMP_EX(%a6)mvout_con: rts//// This exit is for move-out to int register. The aunfl bit is // not set in any case for this move.//mvouti_end: clrw NMNEXC(%a6) bclrb #E1,E_BYTE(%a6) fmovel #0,%FPSR //clear any cc bits from res_func//// Return ETEMP to extended format from internal extended format so// that gen_except will have a correctly signed value for ovfl/unfl// handlers.// bfclr ETEMP_SGN(%a6){#0:#8} beqs mvouti_con bsetb #sign_bit,ETEMP_EX(%a6)mvouti_con: rts//// li is used to handle a long integer source specifier//li: moveql #4,%d0 //set byte count btstb #7,STAG(%a6) //check for extended denorm bne int_dnrm //if so, branch fmovemx ETEMP(%a6),%fp0-%fp0 fcmpd #0x41dfffffffc00000,%fp0// 41dfffffffc00000 in dbl prec = 401d0000fffffffe00000000 in ext prec fbge lo_plrg fcmpd #0xc1e0000000000000,%fp0// c1e0000000000000 in dbl prec = c01e00008000000000000000 in ext prec fble lo_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 fmovel %fp0,L_SCR1(%a6) //let the 040 perform conversion fmovel %fpsr,%d1 orl %d1,USER_FPSR(%a6) //capture inex2/ainex if set bra int_wrtlo_plrg: movel #0x7fffffff,L_SCR1(%a6) //answer is largest positive int fbeq int_wrt //exact answer fcmpd #0x41dfffffffe00000,%fp0// 41dfffffffe00000 in dbl prec = 401d0000ffffffff00000000 in ext prec fbge int_operr //set operr bra int_inx //set inexactlo_nlrg: movel #0x80000000,L_SCR1(%a6) fbeq int_wrt //exact answer fcmpd #0xc1e0000000100000,%fp0// c1e0000000100000 in dbl prec = c01e00008000000080000000 in ext prec fblt int_operr //set operr bra int_inx //set inexact//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -