📄 decbin.s
字号:
| if the exp was positive, and added if it was negative. The purpose| of this is to reduce the value of the exponent and the possibility| of error in calculation of __x_pwrten.|| 1. Branch on the sign of the adjusted exponent.| 2p.(positive exp)| 2. Check M16 and the digits in lwords 2 and 3 in decending order.| 3. Add one for each zero encountered until a non-zero digit.| 4. Subtract the count from the exp.| 5. Check if the exp has crossed zero in #3 above| make the exp abs| and set SE.| 6. Multiply the mantissa by 10**count.| 2n.(negative exp)| 2. Check the digits in lwords 3 and 2 in decending 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 resultane| exponent towards zero. Since all __x_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:|| __x_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.|__x_ap_st_z: movel a6@(L_SCR1),d1 | load expA for range test cmpl #27,d1 | test is with 27 jle __x_pwrten | if abs(expA) <28, skip ap/st zeros btst #30,a0@ | check sign of exp jne __x_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 jne 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 jne 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 jne 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 a6@(L_SCR1),d1 | get adjusted exp from memory subl d0,d1 | subtract count from exp jge ap_p_fm | if still pos, go to __x_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 #__x_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 jcc ap_p_en | if 1, mul fp1 by __x_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 jne ap_p_el | if not, get next bit fmulx fp1,fp0 | mul mantissa by 10**(no_bits_shifted) jra __x_pwrten | go calc __x_pwrten|| This section handles a negative adjusted exponent.|__x_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 jne 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 jne 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 a6@(L_SCR1),d1 | get adjusted exp from memory subl d0,d1 | subtract count from exp jgt 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 #__x_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 jcc ap_n_en | if 1, mul fp1 by __x_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 jne 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:|| __x_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||__x_pwrten: movel a6@(USER_FPCR),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 lea 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 jcc not_rp | to a1 lea __x_PTENRP,a1 | it is RP jra calc_p | go to init sectionnot_rp: asrl #1,d0 | keep checking jcc not_rm lea __x_PTENRM,a1 | it is RM jra calc_p | go to init sectionnot_rm: lea __x_PTENRN,a1 | it is RNcalc_p: movel d1,d0 | copy exp to d0| use d0 jpl 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 jcc 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 jne 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:| __x_norm:| ( ) a0: pointer to working bcd value| (*) fp0: mantissa accumulator| ( ) fp1: scaling factor - 10**(abs(exp))|__x_norm: btst #30,a0@ | test the sign of the exponent jeq mul | if clear, go to multiplydiv: fdivx fp1,fp0 | exp is negative, so divide mant by exp jra 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 __x_decbin incurred an inex exception,| it will be inex2, but will be reported as inex1 by __x_get_op.|end_dec: fmovel FPSR,d0 | get status register bclr #__x_inex2_bit+8,d0 | test for inex2 and clear it fmovel d0,FPSR | return status reg w/o inex2 jeq no_exc | skip this if no exc orl #inx1a_mask,a6@(USER_FPSR) | set inex1/ainexno_exc: moveml a7@+,d2-d5 rts| end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -