📄 decbin.s
字号:
// 2n.(negative exp)// 2. Check the digits in lwords 3 and 2 in descending order.// 3. Add one for each zero encountered until a non-zero digit.// 4. Add the count to the exp.// 5. Check if the exp has crossed zero in #3 above; clear SE.// 6. Divide the mantissa by 10**count.//// *Why 27? If the adjusted exponent is within -28 < expA < 28, than// any adjustment due to append/strip zeros will drive the resultant// exponent towards zero. Since all pwrten constants with a power// of 27 or less are exact, there is no need to use this routine to// attempt to lessen the resultant exponent.//// Register usage://// ap_st_z:// (*) d0: temp digit storage// (*) d1: zero count// (*) d2: digit count// (*) d3: offset pointer// ( ) d4: first word of bcd// (*) d5: lword counter// ( ) a0: pointer to working bcd value// ( ) FP_SCR1: working copy of original bcd value// ( ) L_SCR1: copy of original exponent word////// First check the absolute value of the exponent to see if this// routine is necessary. If so, then check the sign of the exponent// and do append (+) or strip (-) zeros accordingly.// This section handles a positive adjusted exponent.//ap_st_z: movel L_SCR1(%a6),%d1 //load expA for range test cmpl #27,%d1 //test is with 27 ble pwrten //if abs(expA) <28, skip ap/st zeros btst #30,(%a0) //check sign of exp bne ap_st_n //if neg, go to neg side clrl %d1 //zero count reg movel (%a0),%d4 //load lword 1 to d4 bfextu %d4{#28:#4},%d0 //get M16 in d0 bnes ap_p_fx //if M16 is non-zero, go fix exp addql #1,%d1 //inc zero count moveql #1,%d5 //init lword counter movel (%a0,%d5.L*4),%d4 //get lword 2 to d4 bnes ap_p_cl //if lw 2 is zero, skip it addql #8,%d1 //and inc count by 8 addql #1,%d5 //inc lword counter movel (%a0,%d5.L*4),%d4 //get lword 3 to d4ap_p_cl: clrl %d3 //init offset reg moveql #7,%d2 //init digit counterap_p_gd: bfextu %d4{%d3:#4},%d0 //get digit bnes ap_p_fx //if non-zero, go to fix exp addql #4,%d3 //point to next digit addql #1,%d1 //inc digit counter dbf %d2,ap_p_gd //get next digitap_p_fx: movel %d1,%d0 //copy counter to d2 movel L_SCR1(%a6),%d1 //get adjusted exp from memory subl %d0,%d1 //subtract count from exp bges ap_p_fm //if still pos, go to pwrten negl %d1 //now its neg; get abs movel (%a0),%d4 //load lword 1 to d4 orl #0x40000000,%d4 // and set SE in d4 orl #0x40000000,(%a0) // and in memory//// Calculate the mantissa multiplier to compensate for the striping of// zeros from the mantissa.//ap_p_fm: movel #PTENRN,%a1 //get address of power-of-ten table clrl %d3 //init table index fmoves FONE,%fp1 //init fp1 to 1 moveql #3,%d2 //init d2 to count bits in counterap_p_el: asrl #1,%d0 //shift lsb into carry bccs ap_p_en //if 1, mul fp1 by pwrten factor fmulx (%a1,%d3),%fp1 //mul by 10**(d3_bit_no)ap_p_en: addl #12,%d3 //inc d3 to next rtable entry tstl %d0 //check if d0 is zero bnes ap_p_el //if not, get next bit fmulx %fp1,%fp0 //mul mantissa by 10**(no_bits_shifted) bra pwrten //go calc pwrten//// This section handles a negative adjusted exponent.//ap_st_n: clrl %d1 //clr counter moveql #2,%d5 //set up d5 to point to lword 3 movel (%a0,%d5.L*4),%d4 //get lword 3 bnes ap_n_cl //if not zero, check digits subl #1,%d5 //dec d5 to point to lword 2 addql #8,%d1 //inc counter by 8 movel (%a0,%d5.L*4),%d4 //get lword 2ap_n_cl: movel #28,%d3 //point to last digit moveql #7,%d2 //init digit counterap_n_gd: bfextu %d4{%d3:#4},%d0 //get digit bnes ap_n_fx //if non-zero, go to exp fix subql #4,%d3 //point to previous digit addql #1,%d1 //inc digit counter dbf %d2,ap_n_gd //get next digitap_n_fx: movel %d1,%d0 //copy counter to d0 movel L_SCR1(%a6),%d1 //get adjusted exp from memory subl %d0,%d1 //subtract count from exp bgts ap_n_fm //if still pos, go fix mantissa negl %d1 //take abs of exp and clr SE movel (%a0),%d4 //load lword 1 to d4 andl #0xbfffffff,%d4 // and clr SE in d4 andl #0xbfffffff,(%a0) // and in memory//// Calculate the mantissa multiplier to compensate for the appending of// zeros to the mantissa.//ap_n_fm: movel #PTENRN,%a1 //get address of power-of-ten table clrl %d3 //init table index fmoves FONE,%fp1 //init fp1 to 1 moveql #3,%d2 //init d2 to count bits in counterap_n_el: asrl #1,%d0 //shift lsb into carry bccs ap_n_en //if 1, mul fp1 by pwrten factor fmulx (%a1,%d3),%fp1 //mul by 10**(d3_bit_no)ap_n_en: addl #12,%d3 //inc d3 to next rtable entry tstl %d0 //check if d0 is zero bnes ap_n_el //if not, get next bit fdivx %fp1,%fp0 //div mantissa by 10**(no_bits_shifted)////// Calculate power-of-ten factor from adjusted and shifted exponent.//// Register usage://// pwrten:// (*) d0: temp// ( ) d1: exponent// (*) d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp// (*) d3: FPCR work copy// ( ) d4: first word of bcd// (*) a1: RTABLE pointer// calc_p:// (*) d0: temp// ( ) d1: exponent// (*) d3: PWRTxx table index// ( ) a0: pointer to working copy of bcd// (*) a1: PWRTxx pointer// (*) fp1: power-of-ten accumulator//// Pwrten calculates the exponent factor in the selected rounding mode// according to the following table:// // Sign of Mant Sign of Exp Rounding Mode PWRTEN Rounding Mode//// ANY ANY RN RN//// + + RP RP// - + RP RM// + - RP RM// - - RP RP//// + + RM RM// - + RM RP// + - RM RP// - - RM RM//// + + RZ RM// - + RZ RM// + - RZ RP// - - RZ RP////pwrten: movel USER_FPCR(%a6),%d3 //get user's FPCR bfextu %d3{#26:#2},%d2 //isolate rounding mode bits movel (%a0),%d4 //reload 1st bcd word to d4 asll #2,%d2 //format d2 to be bfextu %d4{#0:#2},%d0 // {FPCR[6],FPCR[5],SM,SE} addl %d0,%d2 //in d2 as index into RTABLE leal RTABLE,%a1 //load rtable base moveb (%a1,%d2),%d0 //load new rounding bits from table clrl %d3 //clear d3 to force no exc and extended bfins %d0,%d3{#26:#2} //stuff new rounding bits in FPCR fmovel %d3,%FPCR //write new FPCR asrl #1,%d0 //write correct PTENxx table bccs not_rp //to a1 leal PTENRP,%a1 //it is RP bras calc_p //go to init sectionnot_rp: asrl #1,%d0 //keep checking bccs not_rm leal PTENRM,%a1 //it is RM bras calc_p //go to init sectionnot_rm: leal PTENRN,%a1 //it is RNcalc_p: movel %d1,%d0 //copy exp to d0;use d0 bpls no_neg //if exp is negative, negl %d0 //invert it orl #0x40000000,(%a0) //and set SE bitno_neg: clrl %d3 //table index fmoves FONE,%fp1 //init fp1 to 1e_loop: asrl #1,%d0 //shift next bit into carry bccs e_next //if zero, skip the mul fmulx (%a1,%d3),%fp1 //mul by 10**(d3_bit_no)e_next: addl #12,%d3 //inc d3 to next rtable entry tstl %d0 //check if d0 is zero bnes e_loop //not zero, continue shifting////// Check the sign of the adjusted exp and make the value in fp0 the// same sign. If the exp was pos then multiply fp1*fp0;// else divide fp0/fp1.//// Register Usage:// norm:// ( ) a0: pointer to working bcd value// (*) fp0: mantissa accumulator// ( ) fp1: scaling factor - 10**(abs(exp))//norm: btst #30,(%a0) //test the sign of the exponent beqs mul //if clear, go to multiplydiv: fdivx %fp1,%fp0 //exp is negative, so divide mant by exp bras end_decmul: fmulx %fp1,%fp0 //exp is positive, so multiply by exp////// Clean up and return with result in fp0.//// If the final mul/div in decbin incurred an inex exception,// it will be inex2, but will be reported as inex1 by get_op.//end_dec: fmovel %FPSR,%d0 //get status register bclrl #inex2_bit+8,%d0 //test for inex2 and clear it fmovel %d0,%FPSR //return status reg w/o inex2 beqs no_exc //skip this if no exc orl #inx1a_mask,USER_FPSR(%a6) //set inex1/ainexno_exc: moveml (%a7)+,%d2-%d5 rts |end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -