📄 decbin.s
字号:
|| decbin.sa 3.3 12/19/90|| Description: Converts normalized packed bcd value pointed to by| register A6 to extended-precision value in FP0.|| Input: Normalized packed bcd value in ETEMP(a6).|| Output: Exact floating-point representation of the packed bcd value.|| Saves and Modifies: D2-D5|| Speed: The program decbin takes ??? cycles to execute.|| Object Size:|| External Reference(s): None.|| Algorithm:| Expected is a normal bcd (i.e. non-exceptional; all inf, zero,| and NaN operands are dispatched without entering this routine)| value in 68881/882 format at location ETEMP(A6).|| A1. Convert the bcd exponent to binary by successive adds and muls.| Set the sign according to SE. Subtract 16 to compensate| for the mantissa which is to be interpreted as 17 integer| digits, rather than 1 integer and 16 fraction digits.| Note: this operation can never overflow.|| A2. Convert the bcd mantissa to binary by successive| adds and muls in FP0. Set the sign according to SM.| The mantissa digits will be converted with the decimal point| assumed following the least-significant digit.| Note: this operation can never overflow.|| A3. Count the number of leading/trailing zeros in the| bcd string. If SE is positive, count the leading zeros;| if negative, count the trailing zeros. Set the adjusted| exponent equal to the exponent from A1 and the zero count| added if SM = 1 and subtracted if SM = 0. Scale the| mantissa the equivalent of forcing in the bcd value:|| SM = 0 a non-zero digit in the integer position| SM = 1 a non-zero digit in Mant0, lsd of the fraction|| this will insure that any value, regardless of its| representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted| consistently.|| A4. Calculate the factor 10^exp in FP1 using a table of| 10^(2^n) values. To reduce the error in forming factors| greater than 10^27, a directed rounding scheme is used with| tables rounded to RN, RM, and RP, according to the table| in the comments of the pwrten section.|| A5. Form the final binary number by scaling the mantissa by| the exponent factor. This is done by multiplying the| mantissa in FP0 by the factor in FP1 if the adjusted| exponent sign is positive, and dividing FP0 by FP1 if| it is negative.|| Clean up and return. Check if the final mul or div resulted| in an inex2 exception. If so, set inex1 in the fpsr and | check if the inex1 exception is enabled. If so, set d7 upper| word to $0100. This will signal unimp.sa that an enabled inex1| exception occurred. Unimp will fix the stack.| | Copyright (C) Motorola, Inc. 1990| All Rights Reserved|| THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA | The copyright notice above does not evidence any | actual or intended publication of such source code.|DECBIN idnt 2,1 | Motorola 040 Floating Point Software Package |section 8 .include "fpsp.h"|| PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded| to nearest, minus, and plus, respectively. The tables include| 10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}. No rounding| is required until the power is greater than 27, however, all| tables include the first 5 for ease of indexing.| |xref PTENRN |xref PTENRM |xref PTENRPRTABLE: .byte 0,0,0,0 .byte 2,3,2,3 .byte 2,3,3,2 .byte 3,2,2,3 .global decbin .global calc_e .global pwrten .global calc_m .global norm .global ap_st_z .global ap_st_n| .set FNIBS,7 .set FSTRT,0| .set ESTRT,4 .set EDIGITS,2 | || Constants in single precisionFZERO: .long 0x00000000FONE: .long 0x3F800000FTEN: .long 0x41200000 .set TEN,10|decbin: | fmovel #0,FPCR ;clr real fpcr moveml %d2-%d5,-(%a7)|| Calculate exponent:| 1. Copy bcd value in memory for use as a working copy.| 2. Calculate absolute value of exponent in d1 by mul and add.| 3. Correct for exponent sign.| 4. Subtract 16 to compensate for interpreting the mant as all integer digits.| (i.e., all digits assumed left of the decimal point.)|| Register usage:|| calc_e:| (*) d0: temp digit storage| (*) d1: accumulator for binary exponent| (*) d2: digit count| (*) d3: offset pointer| ( ) d4: first word of bcd| ( ) a0: pointer to working bcd value| ( ) a6: pointer to original bcd value| (*) FP_SCR1: working copy of original bcd value| (*) L_SCR1: copy of original exponent word|calc_e: movel #EDIGITS,%d2 |# of nibbles (digits) in fraction part moveql #ESTRT,%d3 |counter to pick up digits leal FP_SCR1(%a6),%a0 |load tmp bcd storage address movel ETEMP(%a6),(%a0) |save input bcd value movel ETEMP_HI(%a6),4(%a0) |save words 2 and 3 movel ETEMP_LO(%a6),8(%a0) |and work with these movel (%a0),%d4 |get first word of bcd clrl %d1 |zero d1 for accumulatore_gd: mulul #TEN,%d1 |mul partial product by one digit place bfextu %d4{%d3:#4},%d0 |get the digit and zero extend into d0 addl %d0,%d1 |d1 = d1 + d0 addqb #4,%d3 |advance d3 to the next digit dbf %d2,e_gd |if we have used all 3 digits, exit loop btst #30,%d4 |get SE beqs e_pos |don't negate if pos negl %d1 |negate before subtractinge_pos: subl #16,%d1 |sub to compensate for shift of mant bges e_save |if still pos, do not neg negl %d1 |now negative, make pos and set SE orl #0x40000000,%d4 |set SE in d4, orl #0x40000000,(%a0) |and in working bcde_save: movel %d1,L_SCR1(%a6) |save exp in memory||| Calculate mantissa:| 1. Calculate absolute value of mantissa in fp0 by mul and add.| 2. Correct for mantissa sign.| (i.e., all digits assumed left of the decimal point.)|| Register usage:|| calc_m:| (*) d0: temp digit storage| (*) d1: lword counter| (*) d2: digit count| (*) d3: offset pointer| ( ) d4: words 2 and 3 of bcd| ( ) a0: pointer to working bcd value| ( ) a6: pointer to original bcd value| (*) fp0: mantissa accumulator| ( ) FP_SCR1: working copy of original bcd value| ( ) L_SCR1: copy of original exponent word|calc_m: moveql #1,%d1 |word counter, init to 1 fmoves FZERO,%fp0 |accumulator||| Since the packed number has a long word between the first & second parts,| get the integer digit then skip down & get the rest of the| mantissa. We will unroll the loop once.| bfextu (%a0){#28:#4},%d0 |integer part is ls digit in long word faddb %d0,%fp0 |add digit to sum in fp0||| Get the rest of the mantissa.|loadlw: movel (%a0,%d1.L*4),%d4 |load mantissa longword into d4 moveql #FSTRT,%d3 |counter to pick up digits moveql #FNIBS,%d2 |reset number of digits per a0 ptrmd2b: fmuls FTEN,%fp0 |fp0 = fp0 * 10 bfextu %d4{%d3:#4},%d0 |get the digit and zero extend faddb %d0,%fp0 |fp0 = fp0 + digit||| If all the digits (8) in that long word have been converted (d2=0),| then inc d1 (=2) to point to the next long word and reset d3 to 0| to initialize the digit offset, and set d2 to 7 for the digit count;| else continue with this long word.| addqb #4,%d3 |advance d3 to the next digit dbf %d2,md2b |check for last digit in this lwnextlw: addql #1,%d1 |inc lw pointer in mantissa cmpl #2,%d1 |test for last lw ble loadlw |if not, get last one || Check the sign of the mant and make the value in fp0 the same sign.|m_sign: btst #31,(%a0) |test sign of the mantissa beq ap_st_z |if clear, go to append/strip zeros fnegx %fp0 |if set, negate fp0 || Append/strip zeros:|| For adjusted exponents which have an absolute value greater than 27*,| this routine calculates the amount needed to normalize the mantissa| for the adjusted exponent. That number is subtracted from the exp| 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 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 descending 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -