decbin.sa revision 1.5
11.5Sandvar* $NetBSD: decbin.sa,v 1.5 2024/02/05 21:46:05 andvar Exp $ 21.2Scgd 31.1Smycroft* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 41.1Smycroft* M68000 Hi-Performance Microprocessor Division 51.1Smycroft* M68040 Software Package 61.1Smycroft* 71.1Smycroft* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc. 81.1Smycroft* All rights reserved. 91.1Smycroft* 101.1Smycroft* THE SOFTWARE is provided on an "AS IS" basis and without warranty. 111.1Smycroft* To the maximum extent permitted by applicable law, 121.1Smycroft* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 131.1Smycroft* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 141.1Smycroft* PARTICULAR PURPOSE and any warranty against infringement with 151.1Smycroft* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) 161.1Smycroft* and any accompanying written materials. 171.1Smycroft* 181.1Smycroft* To the maximum extent permitted by applicable law, 191.1Smycroft* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 201.1Smycroft* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS 211.1Smycroft* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR 221.1Smycroft* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE 231.1Smycroft* SOFTWARE. Motorola assumes no responsibility for the maintenance 241.1Smycroft* and support of the SOFTWARE. 251.1Smycroft* 261.1Smycroft* You are hereby granted a copyright license to use, modify, and 271.1Smycroft* distribute the SOFTWARE so long as this entire notice is retained 281.1Smycroft* without alteration in any modified and/or redistributed versions, 291.1Smycroft* and that such modified versions are clearly identified as such. 301.1Smycroft* No licenses are granted by implication, estoppel or otherwise 311.1Smycroft* under any patents or trademarks of Motorola, Inc. 321.1Smycroft 331.1Smycroft* 341.1Smycroft* decbin.sa 3.3 12/19/90 351.1Smycroft* 361.1Smycroft* Description: Converts normalized packed bcd value pointed to by 371.1Smycroft* register A6 to extended-precision value in FP0. 381.1Smycroft* 391.1Smycroft* Input: Normalized packed bcd value in ETEMP(a6). 401.1Smycroft* 411.1Smycroft* Output: Exact floating-point representation of the packed bcd value. 421.1Smycroft* 431.1Smycroft* Saves and Modifies: D2-D5 441.1Smycroft* 451.1Smycroft* Speed: The program decbin takes ??? cycles to execute. 461.1Smycroft* 471.1Smycroft* Object Size: 481.1Smycroft* 491.1Smycroft* External Reference(s): None. 501.1Smycroft* 511.1Smycroft* Algorithm: 521.1Smycroft* Expected is a normal bcd (i.e. non-exceptional; all inf, zero, 531.1Smycroft* and NaN operands are dispatched without entering this routine) 541.1Smycroft* value in 68881/882 format at location ETEMP(A6). 551.1Smycroft* 561.1Smycroft* A1. Convert the bcd exponent to binary by successive adds and muls. 571.1Smycroft* Set the sign according to SE. Subtract 16 to compensate 581.1Smycroft* for the mantissa which is to be interpreted as 17 integer 591.1Smycroft* digits, rather than 1 integer and 16 fraction digits. 601.1Smycroft* Note: this operation can never overflow. 611.1Smycroft* 621.1Smycroft* A2. Convert the bcd mantissa to binary by successive 631.1Smycroft* adds and muls in FP0. Set the sign according to SM. 641.1Smycroft* The mantissa digits will be converted with the decimal point 651.1Smycroft* assumed following the least-significant digit. 661.1Smycroft* Note: this operation can never overflow. 671.1Smycroft* 681.1Smycroft* A3. Count the number of leading/trailing zeros in the 691.1Smycroft* bcd string. If SE is positive, count the leading zeros; 701.1Smycroft* if negative, count the trailing zeros. Set the adjusted 711.1Smycroft* exponent equal to the exponent from A1 and the zero count 721.1Smycroft* added if SM = 1 and subtracted if SM = 0. Scale the 731.1Smycroft* mantissa the equivalent of forcing in the bcd value: 741.1Smycroft* 751.1Smycroft* SM = 0 a non-zero digit in the integer position 761.1Smycroft* SM = 1 a non-zero digit in Mant0, lsd of the fraction 771.1Smycroft* 781.1Smycroft* this will insure that any value, regardless of its 791.1Smycroft* representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted 801.1Smycroft* consistently. 811.1Smycroft* 821.1Smycroft* A4. Calculate the factor 10^exp in FP1 using a table of 831.1Smycroft* 10^(2^n) values. To reduce the error in forming factors 841.1Smycroft* greater than 10^27, a directed rounding scheme is used with 851.1Smycroft* tables rounded to RN, RM, and RP, according to the table 861.1Smycroft* in the comments of the pwrten section. 871.1Smycroft* 881.1Smycroft* A5. Form the final binary number by scaling the mantissa by 891.1Smycroft* the exponent factor. This is done by multiplying the 901.1Smycroft* mantissa in FP0 by the factor in FP1 if the adjusted 911.1Smycroft* exponent sign is positive, and dividing FP0 by FP1 if 921.1Smycroft* it is negative. 931.1Smycroft* 941.1Smycroft* Clean up and return. Check if the final mul or div resulted 951.1Smycroft* in an inex2 exception. If so, set inex1 in the fpsr and 961.1Smycroft* check if the inex1 exception is enabled. If so, set d7 upper 971.1Smycroft* word to $0100. This will signal unimp.sa that an enabled inex1 981.3Swiz* exception occurred. Unimp will fix the stack. 991.1Smycroft* 1001.1Smycroft 1011.1SmycroftDECBIN IDNT 2,1 Motorola 040 Floating Point Software Package 1021.1Smycroft 1031.1Smycroft section 8 1041.1Smycroft 1051.1Smycroft include fpsp.h 1061.1Smycroft 1071.1Smycroft* 1081.1Smycroft* PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded 1091.1Smycroft* to nearest, minus, and plus, respectively. The tables include 1101.1Smycroft* 10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}. No rounding 1111.1Smycroft* is required until the power is greater than 27, however, all 1121.1Smycroft* tables include the first 5 for ease of indexing. 1131.1Smycroft* 1141.1Smycroft xref PTENRN 1151.1Smycroft xref PTENRM 1161.1Smycroft xref PTENRP 1171.1Smycroft 1181.1SmycroftRTABLE dc.b 0,0,0,0 1191.1Smycroft dc.b 2,3,2,3 1201.1Smycroft dc.b 2,3,3,2 1211.1Smycroft dc.b 3,2,2,3 1221.1Smycroft 1231.1Smycroft xdef decbin 1241.1Smycroft xdef calc_e 1251.1Smycroft xdef pwrten 1261.1Smycroft xdef calc_m 1271.1Smycroft xdef norm 1281.1Smycroft xdef ap_st_z 1291.1Smycroft xdef ap_st_n 1301.1Smycroft* 1311.1SmycroftFNIBS equ 7 1321.1SmycroftFSTRT equ 0 1331.1Smycroft* 1341.1SmycroftESTRT equ 4 1351.1SmycroftEDIGITS equ 2 1361.1Smycroft* 1371.1Smycroft* Constants in single precision 1381.1SmycroftFZERO dc.l $00000000 1391.1SmycroftFONE dc.l $3F800000 1401.1SmycroftFTEN dc.l $41200000 1411.1Smycroft 1421.1SmycroftTEN equ 10 1431.1Smycroft 1441.1Smycroft* 1451.1Smycroftdecbin: 1461.1Smycroft fmove.l #0,FPCR ;clr real fpcr 1471.1Smycroft movem.l d2-d5,-(a7) 1481.1Smycroft* 1491.1Smycroft* Calculate exponent: 1501.1Smycroft* 1. Copy bcd value in memory for use as a working copy. 1511.1Smycroft* 2. Calculate absolute value of exponent in d1 by mul and add. 1521.1Smycroft* 3. Correct for exponent sign. 1531.1Smycroft* 4. Subtract 16 to compensate for interpreting the mant as all integer digits. 1541.1Smycroft* (i.e., all digits assumed left of the decimal point.) 1551.1Smycroft* 1561.1Smycroft* Register usage: 1571.1Smycroft* 1581.1Smycroft* calc_e: 1591.1Smycroft* (*) d0: temp digit storage 1601.1Smycroft* (*) d1: accumulator for binary exponent 1611.1Smycroft* (*) d2: digit count 1621.1Smycroft* (*) d3: offset pointer 1631.1Smycroft* ( ) d4: first word of bcd 1641.1Smycroft* ( ) a0: pointer to working bcd value 1651.1Smycroft* ( ) a6: pointer to original bcd value 1661.1Smycroft* (*) FP_SCR1: working copy of original bcd value 1671.1Smycroft* (*) L_SCR1: copy of original exponent word 1681.1Smycroft* 1691.1Smycroftcalc_e: 1701.1Smycroft move.l #EDIGITS,d2 ;# of nibbles (digits) in fraction part 1711.1Smycroft moveq.l #ESTRT,d3 ;counter to pick up digits 1721.1Smycroft lea.l FP_SCR1(a6),a0 ;load tmp bcd storage address 1731.1Smycroft move.l ETEMP(a6),(a0) ;save input bcd value 1741.1Smycroft move.l ETEMP_HI(a6),4(a0) ;save words 2 and 3 1751.1Smycroft move.l ETEMP_LO(a6),8(a0) ;and work with these 1761.1Smycroft move.l (a0),d4 ;get first word of bcd 1771.1Smycroft clr.l d1 ;zero d1 for accumulator 1781.1Smycrofte_gd: 1791.1Smycroft mulu.l #TEN,d1 ;mul partial product by one digit place 1801.1Smycroft bfextu d4{d3:4},d0 ;get the digit and zero extend into d0 1811.1Smycroft add.l d0,d1 ;d1 = d1 + d0 1821.1Smycroft addq.b #4,d3 ;advance d3 to the next digit 1831.1Smycroft dbf.w d2,e_gd ;if we have used all 3 digits, exit loop 1841.1Smycroft btst #30,d4 ;get SE 1851.1Smycroft beq.b e_pos ;don't negate if pos 1861.1Smycroft neg.l d1 ;negate before subtracting 1871.1Smycrofte_pos: 1881.1Smycroft sub.l #16,d1 ;sub to compensate for shift of mant 1891.1Smycroft bge.b e_save ;if still pos, do not neg 1901.1Smycroft neg.l d1 ;now negative, make pos and set SE 1911.1Smycroft or.l #$40000000,d4 ;set SE in d4, 1921.1Smycroft or.l #$40000000,(a0) ;and in working bcd 1931.1Smycrofte_save: 1941.1Smycroft move.l d1,L_SCR1(a6) ;save exp in memory 1951.1Smycroft* 1961.1Smycroft* 1971.1Smycroft* Calculate mantissa: 1981.1Smycroft* 1. Calculate absolute value of mantissa in fp0 by mul and add. 1991.1Smycroft* 2. Correct for mantissa sign. 2001.1Smycroft* (i.e., all digits assumed left of the decimal point.) 2011.1Smycroft* 2021.1Smycroft* Register usage: 2031.1Smycroft* 2041.1Smycroft* calc_m: 2051.1Smycroft* (*) d0: temp digit storage 2061.1Smycroft* (*) d1: lword counter 2071.1Smycroft* (*) d2: digit count 2081.1Smycroft* (*) d3: offset pointer 2091.1Smycroft* ( ) d4: words 2 and 3 of bcd 2101.1Smycroft* ( ) a0: pointer to working bcd value 2111.1Smycroft* ( ) a6: pointer to original bcd value 2121.1Smycroft* (*) fp0: mantissa accumulator 2131.1Smycroft* ( ) FP_SCR1: working copy of original bcd value 2141.1Smycroft* ( ) L_SCR1: copy of original exponent word 2151.1Smycroft* 2161.1Smycroftcalc_m: 2171.1Smycroft moveq.l #1,d1 ;word counter, init to 1 2181.1Smycroft fmove.s FZERO,fp0 ;accumulator 2191.1Smycroft* 2201.1Smycroft* 2211.1Smycroft* Since the packed number has a long word between the first & second parts, 2221.1Smycroft* get the integer digit then skip down & get the rest of the 2231.1Smycroft* mantissa. We will unroll the loop once. 2241.1Smycroft* 2251.1Smycroft bfextu (a0){28:4},d0 ;integer part is ls digit in long word 2261.1Smycroft fadd.b d0,fp0 ;add digit to sum in fp0 2271.1Smycroft* 2281.1Smycroft* 2291.1Smycroft* Get the rest of the mantissa. 2301.1Smycroft* 2311.1Smycroftloadlw: 2321.1Smycroft move.l (a0,d1.L*4),d4 ;load mantissa lonqword into d4 2331.1Smycroft moveq.l #FSTRT,d3 ;counter to pick up digits 2341.1Smycroft moveq.l #FNIBS,d2 ;reset number of digits per a0 ptr 2351.1Smycroftmd2b: 2361.1Smycroft fmul.s FTEN,fp0 ;fp0 = fp0 * 10 2371.1Smycroft bfextu d4{d3:4},d0 ;get the digit and zero extend 2381.1Smycroft fadd.b d0,fp0 ;fp0 = fp0 + digit 2391.1Smycroft* 2401.1Smycroft* 2411.1Smycroft* If all the digits (8) in that long word have been converted (d2=0), 2421.1Smycroft* then inc d1 (=2) to point to the next long word and reset d3 to 0 2431.1Smycroft* to initialize the digit offset, and set d2 to 7 for the digit count; 2441.1Smycroft* else continue with this long word. 2451.1Smycroft* 2461.1Smycroft addq.b #4,d3 ;advance d3 to the next digit 2471.1Smycroft dbf.w d2,md2b ;check for last digit in this lw 2481.1Smycroftnextlw: 2491.1Smycroft addq.l #1,d1 ;inc lw pointer in mantissa 2501.1Smycroft cmp.l #2,d1 ;test for last lw 2511.1Smycroft ble loadlw ;if not, get last one 2521.1Smycroft 2531.1Smycroft* 2541.1Smycroft* Check the sign of the mant and make the value in fp0 the same sign. 2551.1Smycroft* 2561.1Smycroftm_sign: 2571.1Smycroft btst #31,(a0) ;test sign of the mantissa 2581.4Sbriggs beq.b short_ap_st_z ;if clear, go to append/strip zeros 2591.1Smycroft fneg.x fp0 ;if set, negate fp0 2601.1Smycroft 2611.1Smycroft* 2621.1Smycroft* Append/strip zeros: 2631.1Smycroft* 2641.1Smycroft* For adjusted exponents which have an absolute value greater than 27*, 2651.1Smycroft* this routine calculates the amount needed to normalize the mantissa 2661.1Smycroft* for the adjusted exponent. That number is subtracted from the exp 2671.1Smycroft* if the exp was positive, and added if it was negative. The purpose 2681.1Smycroft* of this is to reduce the value of the exponent and the possibility 2691.1Smycroft* of error in calculation of pwrten. 2701.1Smycroft* 2711.1Smycroft* 1. Branch on the sign of the adjusted exponent. 2721.1Smycroft* 2p.(positive exp) 2731.5Sandvar* 2. Check M16 and the digits in lwords 2 and 3 in descending order. 2741.1Smycroft* 3. Add one for each zero encountered until a non-zero digit. 2751.1Smycroft* 4. Subtract the count from the exp. 2761.1Smycroft* 5. Check if the exp has crossed zero in #3 above; make the exp abs 2771.1Smycroft* and set SE. 2781.1Smycroft* 6. Multiply the mantissa by 10**count. 2791.1Smycroft* 2n.(negative exp) 2801.5Sandvar* 2. Check the digits in lwords 3 and 2 in descending order. 2811.1Smycroft* 3. Add one for each zero encountered until a non-zero digit. 2821.1Smycroft* 4. Add the count to the exp. 2831.1Smycroft* 5. Check if the exp has crossed zero in #3 above; clear SE. 2841.1Smycroft* 6. Divide the mantissa by 10**count. 2851.1Smycroft* 2861.1Smycroft* *Why 27? If the adjusted exponent is within -28 < expA < 28, than 2871.1Smycroft* any adjustment due to append/strip zeros will drive the resultane 2881.1Smycroft* exponent towards zero. Since all pwrten constants with a power 2891.1Smycroft* of 27 or less are exact, there is no need to use this routine to 2901.1Smycroft* attempt to lessen the resultant exponent. 2911.1Smycroft* 2921.1Smycroft* Register usage: 2931.1Smycroft* 2941.1Smycroft* ap_st_z: 2951.1Smycroft* (*) d0: temp digit storage 2961.1Smycroft* (*) d1: zero count 2971.1Smycroft* (*) d2: digit count 2981.1Smycroft* (*) d3: offset pointer 2991.1Smycroft* ( ) d4: first word of bcd 3001.1Smycroft* (*) d5: lword counter 3011.1Smycroft* ( ) a0: pointer to working bcd value 3021.1Smycroft* ( ) FP_SCR1: working copy of original bcd value 3031.1Smycroft* ( ) L_SCR1: copy of original exponent word 3041.1Smycroft* 3051.1Smycroft* 3061.1Smycroft* First check the absolute value of the exponent to see if this 3071.1Smycroft* routine is necessary. If so, then check the sign of the exponent 3081.1Smycroft* and do append (+) or strip (-) zeros accordingly. 3091.1Smycroft* This section handles a positive adjusted exponent. 3101.1Smycroft* 3111.1Smycroftap_st_z: 3121.4Sbriggsshort_ap_st_z: 3131.1Smycroft move.l L_SCR1(a6),d1 ;load expA for range test 3141.1Smycroft cmp.l #27,d1 ;test is with 27 3151.1Smycroft ble.w pwrten ;if abs(expA) <28, skip ap/st zeros 3161.1Smycroft btst #30,(a0) ;check sign of exp 3171.4Sbriggs bne.b short_ap_st_n ;if neg, go to neg side 3181.1Smycroft clr.l d1 ;zero count reg 3191.1Smycroft move.l (a0),d4 ;load lword 1 to d4 3201.1Smycroft bfextu d4{28:4},d0 ;get M16 in d0 3211.1Smycroft bne.b ap_p_fx ;if M16 is non-zero, go fix exp 3221.1Smycroft addq.l #1,d1 ;inc zero count 3231.1Smycroft moveq.l #1,d5 ;init lword counter 3241.1Smycroft move.l (a0,d5.L*4),d4 ;get lword 2 to d4 3251.1Smycroft bne.b ap_p_cl ;if lw 2 is zero, skip it 3261.1Smycroft addq.l #8,d1 ;and inc count by 8 3271.1Smycroft addq.l #1,d5 ;inc lword counter 3281.1Smycroft move.l (a0,d5.L*4),d4 ;get lword 3 to d4 3291.1Smycroftap_p_cl: 3301.1Smycroft clr.l d3 ;init offset reg 3311.1Smycroft moveq.l #7,d2 ;init digit counter 3321.1Smycroftap_p_gd: 3331.1Smycroft bfextu d4{d3:4},d0 ;get digit 3341.1Smycroft bne.b ap_p_fx ;if non-zero, go to fix exp 3351.1Smycroft addq.l #4,d3 ;point to next digit 3361.1Smycroft addq.l #1,d1 ;inc digit counter 3371.1Smycroft dbf.w d2,ap_p_gd ;get next digit 3381.1Smycroftap_p_fx: 3391.1Smycroft move.l d1,d0 ;copy counter to d2 3401.1Smycroft move.l L_SCR1(a6),d1 ;get adjusted exp from memory 3411.1Smycroft sub.l d0,d1 ;subtract count from exp 3421.1Smycroft bge.b ap_p_fm ;if still pos, go to pwrten 3431.1Smycroft neg.l d1 ;now its neg; get abs 3441.1Smycroft move.l (a0),d4 ;load lword 1 to d4 3451.1Smycroft or.l #$40000000,d4 ; and set SE in d4 3461.1Smycroft or.l #$40000000,(a0) ; and in memory 3471.1Smycroft* 3481.1Smycroft* Calculate the mantissa multiplier to compensate for the striping of 3491.1Smycroft* zeros from the mantissa. 3501.1Smycroft* 3511.1Smycroftap_p_fm: 3521.1Smycroft move.l #PTENRN,a1 ;get address of power-of-ten table 3531.1Smycroft clr.l d3 ;init table index 3541.1Smycroft fmove.s FONE,fp1 ;init fp1 to 1 3551.1Smycroft moveq.l #3,d2 ;init d2 to count bits in counter 3561.1Smycroftap_p_el: 3571.1Smycroft asr.l #1,d0 ;shift lsb into carry 3581.1Smycroft bcc.b ap_p_en ;if 1, mul fp1 by pwrten factor 3591.1Smycroft fmul.x (a1,d3),fp1 ;mul by 10**(d3_bit_no) 3601.1Smycroftap_p_en: 3611.1Smycroft add.l #12,d3 ;inc d3 to next rtable entry 3621.1Smycroft tst.l d0 ;check if d0 is zero 3631.1Smycroft bne.b ap_p_el ;if not, get next bit 3641.1Smycroft fmul.x fp1,fp0 ;mul mantissa by 10**(no_bits_shifted) 3651.4Sbriggs bra.b short_pwrten ;go calc pwrten 3661.1Smycroft* 3671.1Smycroft* This section handles a negative adjusted exponent. 3681.1Smycroft* 3691.1Smycroftap_st_n: 3701.4Sbriggsshort_ap_st_n: 3711.1Smycroft clr.l d1 ;clr counter 3721.1Smycroft moveq.l #2,d5 ;set up d5 to point to lword 3 3731.1Smycroft move.l (a0,d5.L*4),d4 ;get lword 3 3741.1Smycroft bne.b ap_n_cl ;if not zero, check digits 3751.1Smycroft sub.l #1,d5 ;dec d5 to point to lword 2 3761.1Smycroft addq.l #8,d1 ;inc counter by 8 3771.1Smycroft move.l (a0,d5.L*4),d4 ;get lword 2 3781.1Smycroftap_n_cl: 3791.1Smycroft move.l #28,d3 ;point to last digit 3801.1Smycroft moveq.l #7,d2 ;init digit counter 3811.1Smycroftap_n_gd: 3821.1Smycroft bfextu d4{d3:4},d0 ;get digit 3831.1Smycroft bne.b ap_n_fx ;if non-zero, go to exp fix 3841.1Smycroft subq.l #4,d3 ;point to previous digit 3851.1Smycroft addq.l #1,d1 ;inc digit counter 3861.1Smycroft dbf.w d2,ap_n_gd ;get next digit 3871.1Smycroftap_n_fx: 3881.1Smycroft move.l d1,d0 ;copy counter to d0 3891.1Smycroft move.l L_SCR1(a6),d1 ;get adjusted exp from memory 3901.1Smycroft sub.l d0,d1 ;subtract count from exp 3911.1Smycroft bgt.b ap_n_fm ;if still pos, go fix mantissa 3921.1Smycroft neg.l d1 ;take abs of exp and clr SE 3931.1Smycroft move.l (a0),d4 ;load lword 1 to d4 3941.1Smycroft and.l #$bfffffff,d4 ; and clr SE in d4 3951.1Smycroft and.l #$bfffffff,(a0) ; and in memory 3961.1Smycroft* 3971.1Smycroft* Calculate the mantissa multiplier to compensate for the appending of 3981.1Smycroft* zeros to the mantissa. 3991.1Smycroft* 4001.1Smycroftap_n_fm: 4011.1Smycroft move.l #PTENRN,a1 ;get address of power-of-ten table 4021.1Smycroft clr.l d3 ;init table index 4031.1Smycroft fmove.s FONE,fp1 ;init fp1 to 1 4041.1Smycroft moveq.l #3,d2 ;init d2 to count bits in counter 4051.1Smycroftap_n_el: 4061.1Smycroft asr.l #1,d0 ;shift lsb into carry 4071.1Smycroft bcc.b ap_n_en ;if 1, mul fp1 by pwrten factor 4081.1Smycroft fmul.x (a1,d3),fp1 ;mul by 10**(d3_bit_no) 4091.1Smycroftap_n_en: 4101.1Smycroft add.l #12,d3 ;inc d3 to next rtable entry 4111.1Smycroft tst.l d0 ;check if d0 is zero 4121.1Smycroft bne.b ap_n_el ;if not, get next bit 4131.1Smycroft fdiv.x fp1,fp0 ;div mantissa by 10**(no_bits_shifted) 4141.1Smycroft* 4151.1Smycroft* 4161.1Smycroft* Calculate power-of-ten factor from adjusted and shifted exponent. 4171.1Smycroft* 4181.1Smycroft* Register usage: 4191.1Smycroft* 4201.1Smycroft* pwrten: 4211.1Smycroft* (*) d0: temp 4221.1Smycroft* ( ) d1: exponent 4231.1Smycroft* (*) d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp 4241.1Smycroft* (*) d3: FPCR work copy 4251.1Smycroft* ( ) d4: first word of bcd 4261.1Smycroft* (*) a1: RTABLE pointer 4271.1Smycroft* calc_p: 4281.1Smycroft* (*) d0: temp 4291.1Smycroft* ( ) d1: exponent 4301.1Smycroft* (*) d3: PWRTxx table index 4311.1Smycroft* ( ) a0: pointer to working copy of bcd 4321.1Smycroft* (*) a1: PWRTxx pointer 4331.1Smycroft* (*) fp1: power-of-ten accumulator 4341.1Smycroft* 4351.1Smycroft* Pwrten calculates the exponent factor in the selected rounding mode 4361.1Smycroft* according to the following table: 4371.1Smycroft* 4381.1Smycroft* Sign of Mant Sign of Exp Rounding Mode PWRTEN Rounding Mode 4391.1Smycroft* 4401.1Smycroft* ANY ANY RN RN 4411.1Smycroft* 4421.1Smycroft* + + RP RP 4431.1Smycroft* - + RP RM 4441.1Smycroft* + - RP RM 4451.1Smycroft* - - RP RP 4461.1Smycroft* 4471.1Smycroft* + + RM RM 4481.1Smycroft* - + RM RP 4491.1Smycroft* + - RM RP 4501.1Smycroft* - - RM RM 4511.1Smycroft* 4521.1Smycroft* + + RZ RM 4531.1Smycroft* - + RZ RM 4541.1Smycroft* + - RZ RP 4551.1Smycroft* - - RZ RP 4561.1Smycroft* 4571.1Smycroft* 4581.1Smycroftpwrten: 4591.4Sbriggsshort_pwrten: 4601.1Smycroft move.l USER_FPCR(a6),d3 ;get user's FPCR 4611.1Smycroft bfextu d3{26:2},d2 ;isolate rounding mode bits 4621.1Smycroft move.l (a0),d4 ;reload 1st bcd word to d4 4631.1Smycroft asl.l #2,d2 ;format d2 to be 4641.1Smycroft bfextu d4{0:2},d0 ; {FPCR[6],FPCR[5],SM,SE} 4651.1Smycroft add.l d0,d2 ;in d2 as index into RTABLE 4661.1Smycroft lea.l RTABLE,a1 ;load rtable base 4671.1Smycroft move.b (a1,d2),d0 ;load new rounding bits from table 4681.1Smycroft clr.l d3 ;clear d3 to force no exc and extended 4691.1Smycroft bfins d0,d3{26:2} ;stuff new rounding bits in FPCR 4701.1Smycroft fmove.l d3,FPCR ;write new FPCR 4711.1Smycroft asr.l #1,d0 ;write correct PTENxx table 4721.1Smycroft bcc.b not_rp ;to a1 4731.1Smycroft lea.l PTENRP,a1 ;it is RP 4741.1Smycroft bra.b calc_p ;go to init section 4751.1Smycroftnot_rp: 4761.1Smycroft asr.l #1,d0 ;keep checking 4771.1Smycroft bcc.b not_rm 4781.1Smycroft lea.l PTENRM,a1 ;it is RM 4791.1Smycroft bra.b calc_p ;go to init section 4801.1Smycroftnot_rm: 4811.1Smycroft lea.l PTENRN,a1 ;it is RN 4821.1Smycroftcalc_p: 4831.1Smycroft move.l d1,d0 ;copy exp to d0;use d0 4841.1Smycroft bpl.b no_neg ;if exp is negative, 4851.1Smycroft neg.l d0 ;invert it 4861.1Smycroft or.l #$40000000,(a0) ;and set SE bit 4871.1Smycroftno_neg: 4881.1Smycroft clr.l d3 ;table index 4891.1Smycroft fmove.s FONE,fp1 ;init fp1 to 1 4901.1Smycrofte_loop: 4911.1Smycroft asr.l #1,d0 ;shift next bit into carry 4921.1Smycroft bcc.b e_next ;if zero, skip the mul 4931.1Smycroft fmul.x (a1,d3),fp1 ;mul by 10**(d3_bit_no) 4941.1Smycrofte_next: 4951.1Smycroft add.l #12,d3 ;inc d3 to next rtable entry 4961.1Smycroft tst.l d0 ;check if d0 is zero 4971.1Smycroft bne.b e_loop ;not zero, continue shifting 4981.1Smycroft* 4991.1Smycroft* 5001.1Smycroft* Check the sign of the adjusted exp and make the value in fp0 the 5011.1Smycroft* same sign. If the exp was pos then multiply fp1*fp0; 5021.1Smycroft* else divide fp0/fp1. 5031.1Smycroft* 5041.1Smycroft* Register Usage: 5051.1Smycroft* norm: 5061.1Smycroft* ( ) a0: pointer to working bcd value 5071.1Smycroft* (*) fp0: mantissa accumulator 5081.1Smycroft* ( ) fp1: scaling factor - 10**(abs(exp)) 5091.1Smycroft* 5101.1Smycroftnorm: 5111.1Smycroft btst #30,(a0) ;test the sign of the exponent 5121.1Smycroft beq.b mul ;if clear, go to multiply 5131.1Smycroftdiv: 5141.1Smycroft fdiv.x fp1,fp0 ;exp is negative, so divide mant by exp 5151.1Smycroft bra.b end_dec 5161.1Smycroftmul: 5171.1Smycroft fmul.x fp1,fp0 ;exp is positive, so multiply by exp 5181.1Smycroft* 5191.1Smycroft* 5201.1Smycroft* Clean up and return with result in fp0. 5211.1Smycroft* 5221.1Smycroft* If the final mul/div in decbin incurred an inex exception, 5231.1Smycroft* it will be inex2, but will be reported as inex1 by get_op. 5241.1Smycroft* 5251.1Smycroftend_dec: 5261.1Smycroft fmove.l FPSR,d0 ;get status register 5271.1Smycroft bclr.l #inex2_bit+8,d0 ;test for inex2 and clear it 5281.1Smycroft fmove.l d0,FPSR ;return status reg w/o inex2 5291.1Smycroft beq.b no_exc ;skip this if no exc 5301.1Smycroft or.l #inx1a_mask,USER_FPSR(a6) ;set inex1/ainex 5311.1Smycroftno_exc: 5321.1Smycroft movem.l (a7)+,d2-d5 5331.1Smycroft rts 5341.1Smycroft end 535