📄 decbin.s
字号:
| 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 + -