📄 decbin.s
字号:
//// $Id: decbin.S,v 1.2 1999/07/26 22:11:02 joel Exp $//// 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.defs"//// 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -