18c2ecf20Sopenharmony_ci| 28c2ecf20Sopenharmony_ci| decbin.sa 3.3 12/19/90 38c2ecf20Sopenharmony_ci| 48c2ecf20Sopenharmony_ci| Description: Converts normalized packed bcd value pointed to by 58c2ecf20Sopenharmony_ci| register A6 to extended-precision value in FP0. 68c2ecf20Sopenharmony_ci| 78c2ecf20Sopenharmony_ci| Input: Normalized packed bcd value in ETEMP(a6). 88c2ecf20Sopenharmony_ci| 98c2ecf20Sopenharmony_ci| Output: Exact floating-point representation of the packed bcd value. 108c2ecf20Sopenharmony_ci| 118c2ecf20Sopenharmony_ci| Saves and Modifies: D2-D5 128c2ecf20Sopenharmony_ci| 138c2ecf20Sopenharmony_ci| Speed: The program decbin takes ??? cycles to execute. 148c2ecf20Sopenharmony_ci| 158c2ecf20Sopenharmony_ci| Object Size: 168c2ecf20Sopenharmony_ci| 178c2ecf20Sopenharmony_ci| External Reference(s): None. 188c2ecf20Sopenharmony_ci| 198c2ecf20Sopenharmony_ci| Algorithm: 208c2ecf20Sopenharmony_ci| Expected is a normal bcd (i.e. non-exceptional; all inf, zero, 218c2ecf20Sopenharmony_ci| and NaN operands are dispatched without entering this routine) 228c2ecf20Sopenharmony_ci| value in 68881/882 format at location ETEMP(A6). 238c2ecf20Sopenharmony_ci| 248c2ecf20Sopenharmony_ci| A1. Convert the bcd exponent to binary by successive adds and muls. 258c2ecf20Sopenharmony_ci| Set the sign according to SE. Subtract 16 to compensate 268c2ecf20Sopenharmony_ci| for the mantissa which is to be interpreted as 17 integer 278c2ecf20Sopenharmony_ci| digits, rather than 1 integer and 16 fraction digits. 288c2ecf20Sopenharmony_ci| Note: this operation can never overflow. 298c2ecf20Sopenharmony_ci| 308c2ecf20Sopenharmony_ci| A2. Convert the bcd mantissa to binary by successive 318c2ecf20Sopenharmony_ci| adds and muls in FP0. Set the sign according to SM. 328c2ecf20Sopenharmony_ci| The mantissa digits will be converted with the decimal point 338c2ecf20Sopenharmony_ci| assumed following the least-significant digit. 348c2ecf20Sopenharmony_ci| Note: this operation can never overflow. 358c2ecf20Sopenharmony_ci| 368c2ecf20Sopenharmony_ci| A3. Count the number of leading/trailing zeros in the 378c2ecf20Sopenharmony_ci| bcd string. If SE is positive, count the leading zeros; 388c2ecf20Sopenharmony_ci| if negative, count the trailing zeros. Set the adjusted 398c2ecf20Sopenharmony_ci| exponent equal to the exponent from A1 and the zero count 408c2ecf20Sopenharmony_ci| added if SM = 1 and subtracted if SM = 0. Scale the 418c2ecf20Sopenharmony_ci| mantissa the equivalent of forcing in the bcd value: 428c2ecf20Sopenharmony_ci| 438c2ecf20Sopenharmony_ci| SM = 0 a non-zero digit in the integer position 448c2ecf20Sopenharmony_ci| SM = 1 a non-zero digit in Mant0, lsd of the fraction 458c2ecf20Sopenharmony_ci| 468c2ecf20Sopenharmony_ci| this will insure that any value, regardless of its 478c2ecf20Sopenharmony_ci| representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted 488c2ecf20Sopenharmony_ci| consistently. 498c2ecf20Sopenharmony_ci| 508c2ecf20Sopenharmony_ci| A4. Calculate the factor 10^exp in FP1 using a table of 518c2ecf20Sopenharmony_ci| 10^(2^n) values. To reduce the error in forming factors 528c2ecf20Sopenharmony_ci| greater than 10^27, a directed rounding scheme is used with 538c2ecf20Sopenharmony_ci| tables rounded to RN, RM, and RP, according to the table 548c2ecf20Sopenharmony_ci| in the comments of the pwrten section. 558c2ecf20Sopenharmony_ci| 568c2ecf20Sopenharmony_ci| A5. Form the final binary number by scaling the mantissa by 578c2ecf20Sopenharmony_ci| the exponent factor. This is done by multiplying the 588c2ecf20Sopenharmony_ci| mantissa in FP0 by the factor in FP1 if the adjusted 598c2ecf20Sopenharmony_ci| exponent sign is positive, and dividing FP0 by FP1 if 608c2ecf20Sopenharmony_ci| it is negative. 618c2ecf20Sopenharmony_ci| 628c2ecf20Sopenharmony_ci| Clean up and return. Check if the final mul or div resulted 638c2ecf20Sopenharmony_ci| in an inex2 exception. If so, set inex1 in the fpsr and 648c2ecf20Sopenharmony_ci| check if the inex1 exception is enabled. If so, set d7 upper 658c2ecf20Sopenharmony_ci| word to $0100. This will signal unimp.sa that an enabled inex1 668c2ecf20Sopenharmony_ci| exception occurred. Unimp will fix the stack. 678c2ecf20Sopenharmony_ci| 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 708c2ecf20Sopenharmony_ci| All Rights Reserved 718c2ecf20Sopenharmony_ci| 728c2ecf20Sopenharmony_ci| For details on the license for this file, please see the 738c2ecf20Sopenharmony_ci| file, README, in this same directory. 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci|DECBIN idnt 2,1 | Motorola 040 Floating Point Software Package 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci |section 8 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci#include "fpsp.h" 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci| 828c2ecf20Sopenharmony_ci| PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded 838c2ecf20Sopenharmony_ci| to nearest, minus, and plus, respectively. The tables include 848c2ecf20Sopenharmony_ci| 10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}. No rounding 858c2ecf20Sopenharmony_ci| is required until the power is greater than 27, however, all 868c2ecf20Sopenharmony_ci| tables include the first 5 for ease of indexing. 878c2ecf20Sopenharmony_ci| 888c2ecf20Sopenharmony_ci |xref PTENRN 898c2ecf20Sopenharmony_ci |xref PTENRM 908c2ecf20Sopenharmony_ci |xref PTENRP 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciRTABLE: .byte 0,0,0,0 938c2ecf20Sopenharmony_ci .byte 2,3,2,3 948c2ecf20Sopenharmony_ci .byte 2,3,3,2 958c2ecf20Sopenharmony_ci .byte 3,2,2,3 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci .global decbin 988c2ecf20Sopenharmony_ci .global calc_e 998c2ecf20Sopenharmony_ci .global pwrten 1008c2ecf20Sopenharmony_ci .global calc_m 1018c2ecf20Sopenharmony_ci .global norm 1028c2ecf20Sopenharmony_ci .global ap_st_z 1038c2ecf20Sopenharmony_ci .global ap_st_n 1048c2ecf20Sopenharmony_ci| 1058c2ecf20Sopenharmony_ci .set FNIBS,7 1068c2ecf20Sopenharmony_ci .set FSTRT,0 1078c2ecf20Sopenharmony_ci| 1088c2ecf20Sopenharmony_ci .set ESTRT,4 1098c2ecf20Sopenharmony_ci .set EDIGITS,2 | 1108c2ecf20Sopenharmony_ci| 1118c2ecf20Sopenharmony_ci| Constants in single precision 1128c2ecf20Sopenharmony_ciFZERO: .long 0x00000000 1138c2ecf20Sopenharmony_ciFONE: .long 0x3F800000 1148c2ecf20Sopenharmony_ciFTEN: .long 0x41200000 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci .set TEN,10 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci| 1198c2ecf20Sopenharmony_cidecbin: 1208c2ecf20Sopenharmony_ci | fmovel #0,FPCR ;clr real fpcr 1218c2ecf20Sopenharmony_ci moveml %d2-%d5,-(%a7) 1228c2ecf20Sopenharmony_ci| 1238c2ecf20Sopenharmony_ci| Calculate exponent: 1248c2ecf20Sopenharmony_ci| 1. Copy bcd value in memory for use as a working copy. 1258c2ecf20Sopenharmony_ci| 2. Calculate absolute value of exponent in d1 by mul and add. 1268c2ecf20Sopenharmony_ci| 3. Correct for exponent sign. 1278c2ecf20Sopenharmony_ci| 4. Subtract 16 to compensate for interpreting the mant as all integer digits. 1288c2ecf20Sopenharmony_ci| (i.e., all digits assumed left of the decimal point.) 1298c2ecf20Sopenharmony_ci| 1308c2ecf20Sopenharmony_ci| Register usage: 1318c2ecf20Sopenharmony_ci| 1328c2ecf20Sopenharmony_ci| calc_e: 1338c2ecf20Sopenharmony_ci| (*) d0: temp digit storage 1348c2ecf20Sopenharmony_ci| (*) d1: accumulator for binary exponent 1358c2ecf20Sopenharmony_ci| (*) d2: digit count 1368c2ecf20Sopenharmony_ci| (*) d3: offset pointer 1378c2ecf20Sopenharmony_ci| ( ) d4: first word of bcd 1388c2ecf20Sopenharmony_ci| ( ) a0: pointer to working bcd value 1398c2ecf20Sopenharmony_ci| ( ) a6: pointer to original bcd value 1408c2ecf20Sopenharmony_ci| (*) FP_SCR1: working copy of original bcd value 1418c2ecf20Sopenharmony_ci| (*) L_SCR1: copy of original exponent word 1428c2ecf20Sopenharmony_ci| 1438c2ecf20Sopenharmony_cicalc_e: 1448c2ecf20Sopenharmony_ci movel #EDIGITS,%d2 |# of nibbles (digits) in fraction part 1458c2ecf20Sopenharmony_ci moveql #ESTRT,%d3 |counter to pick up digits 1468c2ecf20Sopenharmony_ci leal FP_SCR1(%a6),%a0 |load tmp bcd storage address 1478c2ecf20Sopenharmony_ci movel ETEMP(%a6),(%a0) |save input bcd value 1488c2ecf20Sopenharmony_ci movel ETEMP_HI(%a6),4(%a0) |save words 2 and 3 1498c2ecf20Sopenharmony_ci movel ETEMP_LO(%a6),8(%a0) |and work with these 1508c2ecf20Sopenharmony_ci movel (%a0),%d4 |get first word of bcd 1518c2ecf20Sopenharmony_ci clrl %d1 |zero d1 for accumulator 1528c2ecf20Sopenharmony_cie_gd: 1538c2ecf20Sopenharmony_ci mulul #TEN,%d1 |mul partial product by one digit place 1548c2ecf20Sopenharmony_ci bfextu %d4{%d3:#4},%d0 |get the digit and zero extend into d0 1558c2ecf20Sopenharmony_ci addl %d0,%d1 |d1 = d1 + d0 1568c2ecf20Sopenharmony_ci addqb #4,%d3 |advance d3 to the next digit 1578c2ecf20Sopenharmony_ci dbf %d2,e_gd |if we have used all 3 digits, exit loop 1588c2ecf20Sopenharmony_ci btst #30,%d4 |get SE 1598c2ecf20Sopenharmony_ci beqs e_pos |don't negate if pos 1608c2ecf20Sopenharmony_ci negl %d1 |negate before subtracting 1618c2ecf20Sopenharmony_cie_pos: 1628c2ecf20Sopenharmony_ci subl #16,%d1 |sub to compensate for shift of mant 1638c2ecf20Sopenharmony_ci bges e_save |if still pos, do not neg 1648c2ecf20Sopenharmony_ci negl %d1 |now negative, make pos and set SE 1658c2ecf20Sopenharmony_ci orl #0x40000000,%d4 |set SE in d4, 1668c2ecf20Sopenharmony_ci orl #0x40000000,(%a0) |and in working bcd 1678c2ecf20Sopenharmony_cie_save: 1688c2ecf20Sopenharmony_ci movel %d1,L_SCR1(%a6) |save exp in memory 1698c2ecf20Sopenharmony_ci| 1708c2ecf20Sopenharmony_ci| 1718c2ecf20Sopenharmony_ci| Calculate mantissa: 1728c2ecf20Sopenharmony_ci| 1. Calculate absolute value of mantissa in fp0 by mul and add. 1738c2ecf20Sopenharmony_ci| 2. Correct for mantissa sign. 1748c2ecf20Sopenharmony_ci| (i.e., all digits assumed left of the decimal point.) 1758c2ecf20Sopenharmony_ci| 1768c2ecf20Sopenharmony_ci| Register usage: 1778c2ecf20Sopenharmony_ci| 1788c2ecf20Sopenharmony_ci| calc_m: 1798c2ecf20Sopenharmony_ci| (*) d0: temp digit storage 1808c2ecf20Sopenharmony_ci| (*) d1: lword counter 1818c2ecf20Sopenharmony_ci| (*) d2: digit count 1828c2ecf20Sopenharmony_ci| (*) d3: offset pointer 1838c2ecf20Sopenharmony_ci| ( ) d4: words 2 and 3 of bcd 1848c2ecf20Sopenharmony_ci| ( ) a0: pointer to working bcd value 1858c2ecf20Sopenharmony_ci| ( ) a6: pointer to original bcd value 1868c2ecf20Sopenharmony_ci| (*) fp0: mantissa accumulator 1878c2ecf20Sopenharmony_ci| ( ) FP_SCR1: working copy of original bcd value 1888c2ecf20Sopenharmony_ci| ( ) L_SCR1: copy of original exponent word 1898c2ecf20Sopenharmony_ci| 1908c2ecf20Sopenharmony_cicalc_m: 1918c2ecf20Sopenharmony_ci moveql #1,%d1 |word counter, init to 1 1928c2ecf20Sopenharmony_ci fmoves FZERO,%fp0 |accumulator 1938c2ecf20Sopenharmony_ci| 1948c2ecf20Sopenharmony_ci| 1958c2ecf20Sopenharmony_ci| Since the packed number has a long word between the first & second parts, 1968c2ecf20Sopenharmony_ci| get the integer digit then skip down & get the rest of the 1978c2ecf20Sopenharmony_ci| mantissa. We will unroll the loop once. 1988c2ecf20Sopenharmony_ci| 1998c2ecf20Sopenharmony_ci bfextu (%a0){#28:#4},%d0 |integer part is ls digit in long word 2008c2ecf20Sopenharmony_ci faddb %d0,%fp0 |add digit to sum in fp0 2018c2ecf20Sopenharmony_ci| 2028c2ecf20Sopenharmony_ci| 2038c2ecf20Sopenharmony_ci| Get the rest of the mantissa. 2048c2ecf20Sopenharmony_ci| 2058c2ecf20Sopenharmony_ciloadlw: 2068c2ecf20Sopenharmony_ci movel (%a0,%d1.L*4),%d4 |load mantissa longword into d4 2078c2ecf20Sopenharmony_ci moveql #FSTRT,%d3 |counter to pick up digits 2088c2ecf20Sopenharmony_ci moveql #FNIBS,%d2 |reset number of digits per a0 ptr 2098c2ecf20Sopenharmony_cimd2b: 2108c2ecf20Sopenharmony_ci fmuls FTEN,%fp0 |fp0 = fp0 * 10 2118c2ecf20Sopenharmony_ci bfextu %d4{%d3:#4},%d0 |get the digit and zero extend 2128c2ecf20Sopenharmony_ci faddb %d0,%fp0 |fp0 = fp0 + digit 2138c2ecf20Sopenharmony_ci| 2148c2ecf20Sopenharmony_ci| 2158c2ecf20Sopenharmony_ci| If all the digits (8) in that long word have been converted (d2=0), 2168c2ecf20Sopenharmony_ci| then inc d1 (=2) to point to the next long word and reset d3 to 0 2178c2ecf20Sopenharmony_ci| to initialize the digit offset, and set d2 to 7 for the digit count; 2188c2ecf20Sopenharmony_ci| else continue with this long word. 2198c2ecf20Sopenharmony_ci| 2208c2ecf20Sopenharmony_ci addqb #4,%d3 |advance d3 to the next digit 2218c2ecf20Sopenharmony_ci dbf %d2,md2b |check for last digit in this lw 2228c2ecf20Sopenharmony_cinextlw: 2238c2ecf20Sopenharmony_ci addql #1,%d1 |inc lw pointer in mantissa 2248c2ecf20Sopenharmony_ci cmpl #2,%d1 |test for last lw 2258c2ecf20Sopenharmony_ci ble loadlw |if not, get last one 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci| 2288c2ecf20Sopenharmony_ci| Check the sign of the mant and make the value in fp0 the same sign. 2298c2ecf20Sopenharmony_ci| 2308c2ecf20Sopenharmony_cim_sign: 2318c2ecf20Sopenharmony_ci btst #31,(%a0) |test sign of the mantissa 2328c2ecf20Sopenharmony_ci beq ap_st_z |if clear, go to append/strip zeros 2338c2ecf20Sopenharmony_ci fnegx %fp0 |if set, negate fp0 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci| 2368c2ecf20Sopenharmony_ci| Append/strip zeros: 2378c2ecf20Sopenharmony_ci| 2388c2ecf20Sopenharmony_ci| For adjusted exponents which have an absolute value greater than 27*, 2398c2ecf20Sopenharmony_ci| this routine calculates the amount needed to normalize the mantissa 2408c2ecf20Sopenharmony_ci| for the adjusted exponent. That number is subtracted from the exp 2418c2ecf20Sopenharmony_ci| if the exp was positive, and added if it was negative. The purpose 2428c2ecf20Sopenharmony_ci| of this is to reduce the value of the exponent and the possibility 2438c2ecf20Sopenharmony_ci| of error in calculation of pwrten. 2448c2ecf20Sopenharmony_ci| 2458c2ecf20Sopenharmony_ci| 1. Branch on the sign of the adjusted exponent. 2468c2ecf20Sopenharmony_ci| 2p.(positive exp) 2478c2ecf20Sopenharmony_ci| 2. Check M16 and the digits in lwords 2 and 3 in descending order. 2488c2ecf20Sopenharmony_ci| 3. Add one for each zero encountered until a non-zero digit. 2498c2ecf20Sopenharmony_ci| 4. Subtract the count from the exp. 2508c2ecf20Sopenharmony_ci| 5. Check if the exp has crossed zero in #3 above; make the exp abs 2518c2ecf20Sopenharmony_ci| and set SE. 2528c2ecf20Sopenharmony_ci| 6. Multiply the mantissa by 10**count. 2538c2ecf20Sopenharmony_ci| 2n.(negative exp) 2548c2ecf20Sopenharmony_ci| 2. Check the digits in lwords 3 and 2 in descending order. 2558c2ecf20Sopenharmony_ci| 3. Add one for each zero encountered until a non-zero digit. 2568c2ecf20Sopenharmony_ci| 4. Add the count to the exp. 2578c2ecf20Sopenharmony_ci| 5. Check if the exp has crossed zero in #3 above; clear SE. 2588c2ecf20Sopenharmony_ci| 6. Divide the mantissa by 10**count. 2598c2ecf20Sopenharmony_ci| 2608c2ecf20Sopenharmony_ci| *Why 27? If the adjusted exponent is within -28 < expA < 28, than 2618c2ecf20Sopenharmony_ci| any adjustment due to append/strip zeros will drive the resultant 2628c2ecf20Sopenharmony_ci| exponent towards zero. Since all pwrten constants with a power 2638c2ecf20Sopenharmony_ci| of 27 or less are exact, there is no need to use this routine to 2648c2ecf20Sopenharmony_ci| attempt to lessen the resultant exponent. 2658c2ecf20Sopenharmony_ci| 2668c2ecf20Sopenharmony_ci| Register usage: 2678c2ecf20Sopenharmony_ci| 2688c2ecf20Sopenharmony_ci| ap_st_z: 2698c2ecf20Sopenharmony_ci| (*) d0: temp digit storage 2708c2ecf20Sopenharmony_ci| (*) d1: zero count 2718c2ecf20Sopenharmony_ci| (*) d2: digit count 2728c2ecf20Sopenharmony_ci| (*) d3: offset pointer 2738c2ecf20Sopenharmony_ci| ( ) d4: first word of bcd 2748c2ecf20Sopenharmony_ci| (*) d5: lword counter 2758c2ecf20Sopenharmony_ci| ( ) a0: pointer to working bcd value 2768c2ecf20Sopenharmony_ci| ( ) FP_SCR1: working copy of original bcd value 2778c2ecf20Sopenharmony_ci| ( ) L_SCR1: copy of original exponent word 2788c2ecf20Sopenharmony_ci| 2798c2ecf20Sopenharmony_ci| 2808c2ecf20Sopenharmony_ci| First check the absolute value of the exponent to see if this 2818c2ecf20Sopenharmony_ci| routine is necessary. If so, then check the sign of the exponent 2828c2ecf20Sopenharmony_ci| and do append (+) or strip (-) zeros accordingly. 2838c2ecf20Sopenharmony_ci| This section handles a positive adjusted exponent. 2848c2ecf20Sopenharmony_ci| 2858c2ecf20Sopenharmony_ciap_st_z: 2868c2ecf20Sopenharmony_ci movel L_SCR1(%a6),%d1 |load expA for range test 2878c2ecf20Sopenharmony_ci cmpl #27,%d1 |test is with 27 2888c2ecf20Sopenharmony_ci ble pwrten |if abs(expA) <28, skip ap/st zeros 2898c2ecf20Sopenharmony_ci btst #30,(%a0) |check sign of exp 2908c2ecf20Sopenharmony_ci bne ap_st_n |if neg, go to neg side 2918c2ecf20Sopenharmony_ci clrl %d1 |zero count reg 2928c2ecf20Sopenharmony_ci movel (%a0),%d4 |load lword 1 to d4 2938c2ecf20Sopenharmony_ci bfextu %d4{#28:#4},%d0 |get M16 in d0 2948c2ecf20Sopenharmony_ci bnes ap_p_fx |if M16 is non-zero, go fix exp 2958c2ecf20Sopenharmony_ci addql #1,%d1 |inc zero count 2968c2ecf20Sopenharmony_ci moveql #1,%d5 |init lword counter 2978c2ecf20Sopenharmony_ci movel (%a0,%d5.L*4),%d4 |get lword 2 to d4 2988c2ecf20Sopenharmony_ci bnes ap_p_cl |if lw 2 is zero, skip it 2998c2ecf20Sopenharmony_ci addql #8,%d1 |and inc count by 8 3008c2ecf20Sopenharmony_ci addql #1,%d5 |inc lword counter 3018c2ecf20Sopenharmony_ci movel (%a0,%d5.L*4),%d4 |get lword 3 to d4 3028c2ecf20Sopenharmony_ciap_p_cl: 3038c2ecf20Sopenharmony_ci clrl %d3 |init offset reg 3048c2ecf20Sopenharmony_ci moveql #7,%d2 |init digit counter 3058c2ecf20Sopenharmony_ciap_p_gd: 3068c2ecf20Sopenharmony_ci bfextu %d4{%d3:#4},%d0 |get digit 3078c2ecf20Sopenharmony_ci bnes ap_p_fx |if non-zero, go to fix exp 3088c2ecf20Sopenharmony_ci addql #4,%d3 |point to next digit 3098c2ecf20Sopenharmony_ci addql #1,%d1 |inc digit counter 3108c2ecf20Sopenharmony_ci dbf %d2,ap_p_gd |get next digit 3118c2ecf20Sopenharmony_ciap_p_fx: 3128c2ecf20Sopenharmony_ci movel %d1,%d0 |copy counter to d2 3138c2ecf20Sopenharmony_ci movel L_SCR1(%a6),%d1 |get adjusted exp from memory 3148c2ecf20Sopenharmony_ci subl %d0,%d1 |subtract count from exp 3158c2ecf20Sopenharmony_ci bges ap_p_fm |if still pos, go to pwrten 3168c2ecf20Sopenharmony_ci negl %d1 |now its neg; get abs 3178c2ecf20Sopenharmony_ci movel (%a0),%d4 |load lword 1 to d4 3188c2ecf20Sopenharmony_ci orl #0x40000000,%d4 | and set SE in d4 3198c2ecf20Sopenharmony_ci orl #0x40000000,(%a0) | and in memory 3208c2ecf20Sopenharmony_ci| 3218c2ecf20Sopenharmony_ci| Calculate the mantissa multiplier to compensate for the striping of 3228c2ecf20Sopenharmony_ci| zeros from the mantissa. 3238c2ecf20Sopenharmony_ci| 3248c2ecf20Sopenharmony_ciap_p_fm: 3258c2ecf20Sopenharmony_ci movel #PTENRN,%a1 |get address of power-of-ten table 3268c2ecf20Sopenharmony_ci clrl %d3 |init table index 3278c2ecf20Sopenharmony_ci fmoves FONE,%fp1 |init fp1 to 1 3288c2ecf20Sopenharmony_ci moveql #3,%d2 |init d2 to count bits in counter 3298c2ecf20Sopenharmony_ciap_p_el: 3308c2ecf20Sopenharmony_ci asrl #1,%d0 |shift lsb into carry 3318c2ecf20Sopenharmony_ci bccs ap_p_en |if 1, mul fp1 by pwrten factor 3328c2ecf20Sopenharmony_ci fmulx (%a1,%d3),%fp1 |mul by 10**(d3_bit_no) 3338c2ecf20Sopenharmony_ciap_p_en: 3348c2ecf20Sopenharmony_ci addl #12,%d3 |inc d3 to next rtable entry 3358c2ecf20Sopenharmony_ci tstl %d0 |check if d0 is zero 3368c2ecf20Sopenharmony_ci bnes ap_p_el |if not, get next bit 3378c2ecf20Sopenharmony_ci fmulx %fp1,%fp0 |mul mantissa by 10**(no_bits_shifted) 3388c2ecf20Sopenharmony_ci bra pwrten |go calc pwrten 3398c2ecf20Sopenharmony_ci| 3408c2ecf20Sopenharmony_ci| This section handles a negative adjusted exponent. 3418c2ecf20Sopenharmony_ci| 3428c2ecf20Sopenharmony_ciap_st_n: 3438c2ecf20Sopenharmony_ci clrl %d1 |clr counter 3448c2ecf20Sopenharmony_ci moveql #2,%d5 |set up d5 to point to lword 3 3458c2ecf20Sopenharmony_ci movel (%a0,%d5.L*4),%d4 |get lword 3 3468c2ecf20Sopenharmony_ci bnes ap_n_cl |if not zero, check digits 3478c2ecf20Sopenharmony_ci subl #1,%d5 |dec d5 to point to lword 2 3488c2ecf20Sopenharmony_ci addql #8,%d1 |inc counter by 8 3498c2ecf20Sopenharmony_ci movel (%a0,%d5.L*4),%d4 |get lword 2 3508c2ecf20Sopenharmony_ciap_n_cl: 3518c2ecf20Sopenharmony_ci movel #28,%d3 |point to last digit 3528c2ecf20Sopenharmony_ci moveql #7,%d2 |init digit counter 3538c2ecf20Sopenharmony_ciap_n_gd: 3548c2ecf20Sopenharmony_ci bfextu %d4{%d3:#4},%d0 |get digit 3558c2ecf20Sopenharmony_ci bnes ap_n_fx |if non-zero, go to exp fix 3568c2ecf20Sopenharmony_ci subql #4,%d3 |point to previous digit 3578c2ecf20Sopenharmony_ci addql #1,%d1 |inc digit counter 3588c2ecf20Sopenharmony_ci dbf %d2,ap_n_gd |get next digit 3598c2ecf20Sopenharmony_ciap_n_fx: 3608c2ecf20Sopenharmony_ci movel %d1,%d0 |copy counter to d0 3618c2ecf20Sopenharmony_ci movel L_SCR1(%a6),%d1 |get adjusted exp from memory 3628c2ecf20Sopenharmony_ci subl %d0,%d1 |subtract count from exp 3638c2ecf20Sopenharmony_ci bgts ap_n_fm |if still pos, go fix mantissa 3648c2ecf20Sopenharmony_ci negl %d1 |take abs of exp and clr SE 3658c2ecf20Sopenharmony_ci movel (%a0),%d4 |load lword 1 to d4 3668c2ecf20Sopenharmony_ci andl #0xbfffffff,%d4 | and clr SE in d4 3678c2ecf20Sopenharmony_ci andl #0xbfffffff,(%a0) | and in memory 3688c2ecf20Sopenharmony_ci| 3698c2ecf20Sopenharmony_ci| Calculate the mantissa multiplier to compensate for the appending of 3708c2ecf20Sopenharmony_ci| zeros to the mantissa. 3718c2ecf20Sopenharmony_ci| 3728c2ecf20Sopenharmony_ciap_n_fm: 3738c2ecf20Sopenharmony_ci movel #PTENRN,%a1 |get address of power-of-ten table 3748c2ecf20Sopenharmony_ci clrl %d3 |init table index 3758c2ecf20Sopenharmony_ci fmoves FONE,%fp1 |init fp1 to 1 3768c2ecf20Sopenharmony_ci moveql #3,%d2 |init d2 to count bits in counter 3778c2ecf20Sopenharmony_ciap_n_el: 3788c2ecf20Sopenharmony_ci asrl #1,%d0 |shift lsb into carry 3798c2ecf20Sopenharmony_ci bccs ap_n_en |if 1, mul fp1 by pwrten factor 3808c2ecf20Sopenharmony_ci fmulx (%a1,%d3),%fp1 |mul by 10**(d3_bit_no) 3818c2ecf20Sopenharmony_ciap_n_en: 3828c2ecf20Sopenharmony_ci addl #12,%d3 |inc d3 to next rtable entry 3838c2ecf20Sopenharmony_ci tstl %d0 |check if d0 is zero 3848c2ecf20Sopenharmony_ci bnes ap_n_el |if not, get next bit 3858c2ecf20Sopenharmony_ci fdivx %fp1,%fp0 |div mantissa by 10**(no_bits_shifted) 3868c2ecf20Sopenharmony_ci| 3878c2ecf20Sopenharmony_ci| 3888c2ecf20Sopenharmony_ci| Calculate power-of-ten factor from adjusted and shifted exponent. 3898c2ecf20Sopenharmony_ci| 3908c2ecf20Sopenharmony_ci| Register usage: 3918c2ecf20Sopenharmony_ci| 3928c2ecf20Sopenharmony_ci| pwrten: 3938c2ecf20Sopenharmony_ci| (*) d0: temp 3948c2ecf20Sopenharmony_ci| ( ) d1: exponent 3958c2ecf20Sopenharmony_ci| (*) d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp 3968c2ecf20Sopenharmony_ci| (*) d3: FPCR work copy 3978c2ecf20Sopenharmony_ci| ( ) d4: first word of bcd 3988c2ecf20Sopenharmony_ci| (*) a1: RTABLE pointer 3998c2ecf20Sopenharmony_ci| calc_p: 4008c2ecf20Sopenharmony_ci| (*) d0: temp 4018c2ecf20Sopenharmony_ci| ( ) d1: exponent 4028c2ecf20Sopenharmony_ci| (*) d3: PWRTxx table index 4038c2ecf20Sopenharmony_ci| ( ) a0: pointer to working copy of bcd 4048c2ecf20Sopenharmony_ci| (*) a1: PWRTxx pointer 4058c2ecf20Sopenharmony_ci| (*) fp1: power-of-ten accumulator 4068c2ecf20Sopenharmony_ci| 4078c2ecf20Sopenharmony_ci| Pwrten calculates the exponent factor in the selected rounding mode 4088c2ecf20Sopenharmony_ci| according to the following table: 4098c2ecf20Sopenharmony_ci| 4108c2ecf20Sopenharmony_ci| Sign of Mant Sign of Exp Rounding Mode PWRTEN Rounding Mode 4118c2ecf20Sopenharmony_ci| 4128c2ecf20Sopenharmony_ci| ANY ANY RN RN 4138c2ecf20Sopenharmony_ci| 4148c2ecf20Sopenharmony_ci| + + RP RP 4158c2ecf20Sopenharmony_ci| - + RP RM 4168c2ecf20Sopenharmony_ci| + - RP RM 4178c2ecf20Sopenharmony_ci| - - RP RP 4188c2ecf20Sopenharmony_ci| 4198c2ecf20Sopenharmony_ci| + + RM RM 4208c2ecf20Sopenharmony_ci| - + RM RP 4218c2ecf20Sopenharmony_ci| + - RM RP 4228c2ecf20Sopenharmony_ci| - - RM RM 4238c2ecf20Sopenharmony_ci| 4248c2ecf20Sopenharmony_ci| + + RZ RM 4258c2ecf20Sopenharmony_ci| - + RZ RM 4268c2ecf20Sopenharmony_ci| + - RZ RP 4278c2ecf20Sopenharmony_ci| - - RZ RP 4288c2ecf20Sopenharmony_ci| 4298c2ecf20Sopenharmony_ci| 4308c2ecf20Sopenharmony_cipwrten: 4318c2ecf20Sopenharmony_ci movel USER_FPCR(%a6),%d3 |get user's FPCR 4328c2ecf20Sopenharmony_ci bfextu %d3{#26:#2},%d2 |isolate rounding mode bits 4338c2ecf20Sopenharmony_ci movel (%a0),%d4 |reload 1st bcd word to d4 4348c2ecf20Sopenharmony_ci asll #2,%d2 |format d2 to be 4358c2ecf20Sopenharmony_ci bfextu %d4{#0:#2},%d0 | {FPCR[6],FPCR[5],SM,SE} 4368c2ecf20Sopenharmony_ci addl %d0,%d2 |in d2 as index into RTABLE 4378c2ecf20Sopenharmony_ci leal RTABLE,%a1 |load rtable base 4388c2ecf20Sopenharmony_ci moveb (%a1,%d2),%d0 |load new rounding bits from table 4398c2ecf20Sopenharmony_ci clrl %d3 |clear d3 to force no exc and extended 4408c2ecf20Sopenharmony_ci bfins %d0,%d3{#26:#2} |stuff new rounding bits in FPCR 4418c2ecf20Sopenharmony_ci fmovel %d3,%FPCR |write new FPCR 4428c2ecf20Sopenharmony_ci asrl #1,%d0 |write correct PTENxx table 4438c2ecf20Sopenharmony_ci bccs not_rp |to a1 4448c2ecf20Sopenharmony_ci leal PTENRP,%a1 |it is RP 4458c2ecf20Sopenharmony_ci bras calc_p |go to init section 4468c2ecf20Sopenharmony_cinot_rp: 4478c2ecf20Sopenharmony_ci asrl #1,%d0 |keep checking 4488c2ecf20Sopenharmony_ci bccs not_rm 4498c2ecf20Sopenharmony_ci leal PTENRM,%a1 |it is RM 4508c2ecf20Sopenharmony_ci bras calc_p |go to init section 4518c2ecf20Sopenharmony_cinot_rm: 4528c2ecf20Sopenharmony_ci leal PTENRN,%a1 |it is RN 4538c2ecf20Sopenharmony_cicalc_p: 4548c2ecf20Sopenharmony_ci movel %d1,%d0 |copy exp to d0;use d0 4558c2ecf20Sopenharmony_ci bpls no_neg |if exp is negative, 4568c2ecf20Sopenharmony_ci negl %d0 |invert it 4578c2ecf20Sopenharmony_ci orl #0x40000000,(%a0) |and set SE bit 4588c2ecf20Sopenharmony_cino_neg: 4598c2ecf20Sopenharmony_ci clrl %d3 |table index 4608c2ecf20Sopenharmony_ci fmoves FONE,%fp1 |init fp1 to 1 4618c2ecf20Sopenharmony_cie_loop: 4628c2ecf20Sopenharmony_ci asrl #1,%d0 |shift next bit into carry 4638c2ecf20Sopenharmony_ci bccs e_next |if zero, skip the mul 4648c2ecf20Sopenharmony_ci fmulx (%a1,%d3),%fp1 |mul by 10**(d3_bit_no) 4658c2ecf20Sopenharmony_cie_next: 4668c2ecf20Sopenharmony_ci addl #12,%d3 |inc d3 to next rtable entry 4678c2ecf20Sopenharmony_ci tstl %d0 |check if d0 is zero 4688c2ecf20Sopenharmony_ci bnes e_loop |not zero, continue shifting 4698c2ecf20Sopenharmony_ci| 4708c2ecf20Sopenharmony_ci| 4718c2ecf20Sopenharmony_ci| Check the sign of the adjusted exp and make the value in fp0 the 4728c2ecf20Sopenharmony_ci| same sign. If the exp was pos then multiply fp1*fp0; 4738c2ecf20Sopenharmony_ci| else divide fp0/fp1. 4748c2ecf20Sopenharmony_ci| 4758c2ecf20Sopenharmony_ci| Register Usage: 4768c2ecf20Sopenharmony_ci| norm: 4778c2ecf20Sopenharmony_ci| ( ) a0: pointer to working bcd value 4788c2ecf20Sopenharmony_ci| (*) fp0: mantissa accumulator 4798c2ecf20Sopenharmony_ci| ( ) fp1: scaling factor - 10**(abs(exp)) 4808c2ecf20Sopenharmony_ci| 4818c2ecf20Sopenharmony_cinorm: 4828c2ecf20Sopenharmony_ci btst #30,(%a0) |test the sign of the exponent 4838c2ecf20Sopenharmony_ci beqs mul |if clear, go to multiply 4848c2ecf20Sopenharmony_cidiv: 4858c2ecf20Sopenharmony_ci fdivx %fp1,%fp0 |exp is negative, so divide mant by exp 4868c2ecf20Sopenharmony_ci bras end_dec 4878c2ecf20Sopenharmony_cimul: 4888c2ecf20Sopenharmony_ci fmulx %fp1,%fp0 |exp is positive, so multiply by exp 4898c2ecf20Sopenharmony_ci| 4908c2ecf20Sopenharmony_ci| 4918c2ecf20Sopenharmony_ci| Clean up and return with result in fp0. 4928c2ecf20Sopenharmony_ci| 4938c2ecf20Sopenharmony_ci| If the final mul/div in decbin incurred an inex exception, 4948c2ecf20Sopenharmony_ci| it will be inex2, but will be reported as inex1 by get_op. 4958c2ecf20Sopenharmony_ci| 4968c2ecf20Sopenharmony_ciend_dec: 4978c2ecf20Sopenharmony_ci fmovel %FPSR,%d0 |get status register 4988c2ecf20Sopenharmony_ci bclrl #inex2_bit+8,%d0 |test for inex2 and clear it 4998c2ecf20Sopenharmony_ci fmovel %d0,%FPSR |return status reg w/o inex2 5008c2ecf20Sopenharmony_ci beqs no_exc |skip this if no exc 5018c2ecf20Sopenharmony_ci orl #inx1a_mask,USER_FPSR(%a6) |set inex1/ainex 5028c2ecf20Sopenharmony_cino_exc: 5038c2ecf20Sopenharmony_ci moveml (%a7)+,%d2-%d5 5048c2ecf20Sopenharmony_ci rts 5058c2ecf20Sopenharmony_ci |end 506