[BACK]Return to decbin.sa CVS log [TXT][DIR] Up to [local] / sys / arch / m68k / fpsp

Annotation of sys/arch/m68k/fpsp/decbin.sa, Revision 1.1.1.1

1.1       nbrk        1: *      $OpenBSD: decbin.sa,v 1.3 2001/09/20 17:02:30 mpech Exp $
                      2: *      $NetBSD: decbin.sa,v 1.2 1994/10/26 07:48:59 cgd Exp $
                      3:
                      4: *      MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
                      5: *      M68000 Hi-Performance Microprocessor Division
                      6: *      M68040 Software Package
                      7: *
                      8: *      M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
                      9: *      All rights reserved.
                     10: *
                     11: *      THE SOFTWARE is provided on an "AS IS" basis and without warranty.
                     12: *      To the maximum extent permitted by applicable law,
                     13: *      MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
                     14: *      INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
                     15: *      PARTICULAR PURPOSE and any warranty against infringement with
                     16: *      regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
                     17: *      and any accompanying written materials.
                     18: *
                     19: *      To the maximum extent permitted by applicable law,
                     20: *      IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
                     21: *      (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
                     22: *      PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
                     23: *      OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
                     24: *      SOFTWARE.  Motorola assumes no responsibility for the maintenance
                     25: *      and support of the SOFTWARE.
                     26: *
                     27: *      You are hereby granted a copyright license to use, modify, and
                     28: *      distribute the SOFTWARE so long as this entire notice is retained
                     29: *      without alteration in any modified and/or redistributed versions,
                     30: *      and that such modified versions are clearly identified as such.
                     31: *      No licenses are granted by implication, estoppel or otherwise
                     32: *      under any patents or trademarks of Motorola, Inc.
                     33:
                     34: *
                     35: *      decbin.sa 3.3 12/19/90
                     36: *
                     37: *      Description: Converts normalized packed bcd value pointed to by
                     38: *      register A6 to extended-precision value in FP0.
                     39: *
                     40: *      Input: Normalized packed bcd value in ETEMP(a6).
                     41: *
                     42: *      Output: Exact floating-point representation of the packed bcd value.
                     43: *
                     44: *      Saves and Modifies: D2-D5
                     45: *
                     46: *      Speed: The program decbin takes ??? cycles to execute.
                     47: *
                     48: *      Object Size:
                     49: *
                     50: *      External Reference(s): None.
                     51: *
                     52: *      Algorithm:
                     53: *      Expected is a normal bcd (i.e. non-exceptional; all inf, zero,
                     54: *      and NaN operands are dispatched without entering this routine)
                     55: *      value in 68881/882 format at location ETEMP(A6).
                     56: *
                     57: *      A1.     Convert the bcd exponent to binary by successive adds and muls.
                     58: *      Set the sign according to SE. Subtract 16 to compensate
                     59: *      for the mantissa which is to be interpreted as 17 integer
                     60: *      digits, rather than 1 integer and 16 fraction digits.
                     61: *      Note: this operation can never overflow.
                     62: *
                     63: *      A2. Convert the bcd mantissa to binary by successive
                     64: *      adds and muls in FP0. Set the sign according to SM.
                     65: *      The mantissa digits will be converted with the decimal point
                     66: *      assumed following the least-significant digit.
                     67: *      Note: this operation can never overflow.
                     68: *
                     69: *      A3. Count the number of leading/trailing zeros in the
                     70: *      bcd string.  If SE is positive, count the leading zeros;
                     71: *      if negative, count the trailing zeros.  Set the adjusted
                     72: *      exponent equal to the exponent from A1 and the zero count
                     73: *      added if SM = 1 and subtracted if SM = 0.  Scale the
                     74: *      mantissa the equivalent of forcing in the bcd value:
                     75: *
                     76: *      SM = 0  a non-zero digit in the integer position
                     77: *      SM = 1  a non-zero digit in Mant0, lsd of the fraction
                     78: *
                     79: *      this will insure that any value, regardless of its
                     80: *      representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted
                     81: *      consistently.
                     82: *
                     83: *      A4. Calculate the factor 10^exp in FP1 using a table of
                     84: *      10^(2^n) values.  To reduce the error in forming factors
                     85: *      greater than 10^27, a directed rounding scheme is used with
                     86: *      tables rounded to RN, RM, and RP, according to the table
                     87: *      in the comments of the pwrten section.
                     88: *
                     89: *      A5. Form the final binary number by scaling the mantissa by
                     90: *      the exponent factor.  This is done by multiplying the
                     91: *      mantissa in FP0 by the factor in FP1 if the adjusted
                     92: *      exponent sign is positive, and dividing FP0 by FP1 if
                     93: *      it is negative.
                     94: *
                     95: *      Clean up and return.  Check if the final mul or div resulted
                     96: *      in an inex2 exception.  If so, set inex1 in the fpsr and
                     97: *      check if the inex1 exception is enabled.  If so, set d7 upper
                     98: *      word to $0100.  This will signal unimp.sa that an enabled inex1
                     99: *      exception occurred.  Unimp will fix the stack.
                    100: *
                    101:
                    102: DECBIN    IDNT    2,1 Motorola 040 Floating Point Software Package
                    103:
                    104:        section 8
                    105:
                    106:        include fpsp.h
                    107:
                    108: *
                    109: *      PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded
                    110: *      to nearest, minus, and plus, respectively.  The tables include
                    111: *      10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}.  No rounding
                    112: *      is required until the power is greater than 27, however, all
                    113: *      tables include the first 5 for ease of indexing.
                    114: *
                    115:        xref    PTENRN
                    116:        xref    PTENRM
                    117:        xref    PTENRP
                    118:
                    119: RTABLE dc.b    0,0,0,0
                    120:        dc.b    2,3,2,3
                    121:        dc.b    2,3,3,2
                    122:        dc.b    3,2,2,3
                    123:
                    124:        xdef    decbin
                    125:        xdef    calc_e
                    126:        xdef    pwrten
                    127:        xdef    calc_m
                    128:        xdef    norm
                    129:        xdef    ap_st_z
                    130:        xdef    ap_st_n
                    131: *
                    132: FNIBS  equ     7
                    133: FSTRT  equ     0
                    134: *
                    135: ESTRT  equ     4
                    136: EDIGITS equ    2
                    137: *
                    138: * Constants in single precision
                    139: FZERO  dc.l    $00000000
                    140: FONE   dc.l    $3F800000
                    141: FTEN   dc.l    $41200000
                    142:
                    143: TEN    equ     10
                    144:
                    145: *
                    146: decbin:
                    147:        fmove.l #0,FPCR         ;clr real fpcr
                    148:        movem.l d2-d5,-(a7)
                    149: *
                    150: * Calculate exponent:
                    151: *  1. Copy bcd value in memory for use as a working copy.
                    152: *  2. Calculate absolute value of exponent in d1 by mul and add.
                    153: *  3. Correct for exponent sign.
                    154: *  4. Subtract 16 to compensate for interpreting the mant as all integer digits.
                    155: *     (i.e., all digits assumed left of the decimal point.)
                    156: *
                    157: * Register usage:
                    158: *
                    159: *  calc_e:
                    160: *      (*)  d0: temp digit storage
                    161: *      (*)  d1: accumulator for binary exponent
                    162: *      (*)  d2: digit count
                    163: *      (*)  d3: offset pointer
                    164: *      ( )  d4: first word of bcd
                    165: *      ( )  a0: pointer to working bcd value
                    166: *      ( )  a6: pointer to original bcd value
                    167: *      (*)  FP_SCR1: working copy of original bcd value
                    168: *      (*)  L_SCR1: copy of original exponent word
                    169: *
                    170: calc_e:
                    171:        move.l  #EDIGITS,d2     ;# of nibbles (digits) in fraction part
                    172:        moveq.l #ESTRT,d3       ;counter to pick up digits
                    173:        lea.l   FP_SCR1(a6),a0  ;load tmp bcd storage address
                    174:        move.l  ETEMP(a6),(a0)  ;save input bcd value
                    175:        move.l  ETEMP_HI(a6),4(a0) ;save words 2 and 3
                    176:        move.l  ETEMP_LO(a6),8(a0) ;and work with these
                    177:        move.l  (a0),d4         ;get first word of bcd
                    178:        clr.l   d1              ;zero d1 for accumulator
                    179: e_gd:
                    180:        mulu.l  #TEN,d1         ;mul partial product by one digit place
                    181:        bfextu  d4{d3:4},d0     ;get the digit and zero extend into d0
                    182:        add.l   d0,d1           ;d1 = d1 + d0
                    183:        addq.b  #4,d3           ;advance d3 to the next digit
                    184:        dbf.w   d2,e_gd         ;if we have used all 3 digits, exit loop
                    185:        btst    #30,d4          ;get SE
                    186:        beq.b   e_pos           ;don't negate if pos
                    187:        neg.l   d1              ;negate before subtracting
                    188: e_pos:
                    189:        sub.l   #16,d1          ;sub to compensate for shift of mant
                    190:        bge.b   e_save          ;if still pos, do not neg
                    191:        neg.l   d1              ;now negative, make pos and set SE
                    192:        or.l    #$40000000,d4   ;set SE in d4,
                    193:        or.l    #$40000000,(a0) ;and in working bcd
                    194: e_save:
                    195:        move.l  d1,L_SCR1(a6)   ;save exp in memory
                    196: *
                    197: *
                    198: * Calculate mantissa:
                    199: *  1. Calculate absolute value of mantissa in fp0 by mul and add.
                    200: *  2. Correct for mantissa sign.
                    201: *     (i.e., all digits assumed left of the decimal point.)
                    202: *
                    203: * Register usage:
                    204: *
                    205: *  calc_m:
                    206: *      (*)  d0: temp digit storage
                    207: *      (*)  d1: lword counter
                    208: *      (*)  d2: digit count
                    209: *      (*)  d3: offset pointer
                    210: *      ( )  d4: words 2 and 3 of bcd
                    211: *      ( )  a0: pointer to working bcd value
                    212: *      ( )  a6: pointer to original bcd value
                    213: *      (*) fp0: mantissa accumulator
                    214: *      ( )  FP_SCR1: working copy of original bcd value
                    215: *      ( )  L_SCR1: copy of original exponent word
                    216: *
                    217: calc_m:
                    218:        moveq.l #1,d1           ;word counter, init to 1
                    219:        fmove.s FZERO,fp0       ;accumulator
                    220: *
                    221: *
                    222: *  Since the packed number has a long word between the first & second parts,
                    223: *  get the integer digit then skip down & get the rest of the
                    224: *  mantissa.  We will unroll the loop once.
                    225: *
                    226:        bfextu  (a0){28:4},d0   ;integer part is ls digit in long word
                    227:        fadd.b  d0,fp0          ;add digit to sum in fp0
                    228: *
                    229: *
                    230: *  Get the rest of the mantissa.
                    231: *
                    232: loadlw:
                    233:        move.l  (a0,d1.L*4),d4  ;load mantissa lonqword into d4
                    234:        moveq.l #FSTRT,d3       ;counter to pick up digits
                    235:        moveq.l #FNIBS,d2       ;reset number of digits per a0 ptr
                    236: md2b:
                    237:        fmul.s  FTEN,fp0        ;fp0 = fp0 * 10
                    238:        bfextu  d4{d3:4},d0     ;get the digit and zero extend
                    239:        fadd.b  d0,fp0          ;fp0 = fp0 + digit
                    240: *
                    241: *
                    242: *  If all the digits (8) in that long word have been converted (d2=0),
                    243: *  then inc d1 (=2) to point to the next long word and reset d3 to 0
                    244: *  to initialize the digit offset, and set d2 to 7 for the digit count;
                    245: *  else continue with this long word.
                    246: *
                    247:        addq.b  #4,d3           ;advance d3 to the next digit
                    248:        dbf.w   d2,md2b         ;check for last digit in this lw
                    249: nextlw:
                    250:        addq.l  #1,d1           ;inc lw pointer in mantissa
                    251:        cmp.l   #2,d1           ;test for last lw
                    252:        ble     loadlw          ;if not, get last one
                    253:
                    254: *
                    255: *  Check the sign of the mant and make the value in fp0 the same sign.
                    256: *
                    257: m_sign:
                    258:        btst    #31,(a0)        ;test sign of the mantissa
                    259:        beq.b   ap_st_z         ;if clear, go to append/strip zeros
                    260:        fneg.x  fp0             ;if set, negate fp0
                    261:
                    262: *
                    263: * Append/strip zeros:
                    264: *
                    265: *  For adjusted exponents which have an absolute value greater than 27*,
                    266: *  this routine calculates the amount needed to normalize the mantissa
                    267: *  for the adjusted exponent.  That number is subtracted from the exp
                    268: *  if the exp was positive, and added if it was negative.  The purpose
                    269: *  of this is to reduce the value of the exponent and the possibility
                    270: *  of error in calculation of pwrten.
                    271: *
                    272: *  1. Branch on the sign of the adjusted exponent.
                    273: *  2p.(positive exp)
                    274: *   2. Check M16 and the digits in lwords 2 and 3 in decending order.
                    275: *   3. Add one for each zero encountered until a non-zero digit.
                    276: *   4. Subtract the count from the exp.
                    277: *   5. Check if the exp has crossed zero in #3 above; make the exp abs
                    278: *         and set SE.
                    279: *      6. Multiply the mantissa by 10**count.
                    280: *  2n.(negative exp)
                    281: *   2. Check the digits in lwords 3 and 2 in decending order.
                    282: *   3. Add one for each zero encountered until a non-zero digit.
                    283: *   4. Add the count to the exp.
                    284: *   5. Check if the exp has crossed zero in #3 above; clear SE.
                    285: *   6. Divide the mantissa by 10**count.
                    286: *
                    287: *  *Why 27?  If the adjusted exponent is within -28 < expA < 28, than
                    288: *   any adjustment due to append/strip zeros will drive the resultane
                    289: *   exponent towards zero.  Since all pwrten constants with a power
                    290: *   of 27 or less are exact, there is no need to use this routine to
                    291: *   attempt to lessen the resultant exponent.
                    292: *
                    293: * Register usage:
                    294: *
                    295: *  ap_st_z:
                    296: *      (*)  d0: temp digit storage
                    297: *      (*)  d1: zero count
                    298: *      (*)  d2: digit count
                    299: *      (*)  d3: offset pointer
                    300: *      ( )  d4: first word of bcd
                    301: *      (*)  d5: lword counter
                    302: *      ( )  a0: pointer to working bcd value
                    303: *      ( )  FP_SCR1: working copy of original bcd value
                    304: *      ( )  L_SCR1: copy of original exponent word
                    305: *
                    306: *
                    307: * First check the absolute value of the exponent to see if this
                    308: * routine is necessary.  If so, then check the sign of the exponent
                    309: * and do append (+) or strip (-) zeros accordingly.
                    310: * This section handles a positive adjusted exponent.
                    311: *
                    312: ap_st_z:
                    313:        move.l  L_SCR1(a6),d1   ;load expA for range test
                    314:        cmp.l   #27,d1          ;test is with 27
                    315:        ble.w   pwrten          ;if abs(expA) <28, skip ap/st zeros
                    316:        btst    #30,(a0)        ;check sign of exp
                    317:        bne.b   ap_st_n         ;if neg, go to neg side
                    318:        clr.l   d1              ;zero count reg
                    319:        move.l  (a0),d4         ;load lword 1 to d4
                    320:        bfextu  d4{28:4},d0     ;get M16 in d0
                    321:        bne.b   ap_p_fx         ;if M16 is non-zero, go fix exp
                    322:        addq.l  #1,d1           ;inc zero count
                    323:        moveq.l #1,d5           ;init lword counter
                    324:        move.l  (a0,d5.L*4),d4  ;get lword 2 to d4
                    325:        bne.b   ap_p_cl         ;if lw 2 is zero, skip it
                    326:        addq.l  #8,d1           ;and inc count by 8
                    327:        addq.l  #1,d5           ;inc lword counter
                    328:        move.l  (a0,d5.L*4),d4  ;get lword 3 to d4
                    329: ap_p_cl:
                    330:        clr.l   d3              ;init offset reg
                    331:        moveq.l #7,d2           ;init digit counter
                    332: ap_p_gd:
                    333:        bfextu  d4{d3:4},d0     ;get digit
                    334:        bne.b   ap_p_fx         ;if non-zero, go to fix exp
                    335:        addq.l  #4,d3           ;point to next digit
                    336:        addq.l  #1,d1           ;inc digit counter
                    337:        dbf.w   d2,ap_p_gd      ;get next digit
                    338: ap_p_fx:
                    339:        move.l  d1,d0           ;copy counter to d2
                    340:        move.l  L_SCR1(a6),d1   ;get adjusted exp from memory
                    341:        sub.l   d0,d1           ;subtract count from exp
                    342:        bge.b   ap_p_fm         ;if still pos, go to pwrten
                    343:        neg.l   d1              ;now its neg; get abs
                    344:        move.l  (a0),d4         ;load lword 1 to d4
                    345:        or.l    #$40000000,d4   ; and set SE in d4
                    346:        or.l    #$40000000,(a0) ; and in memory
                    347: *
                    348: * Calculate the mantissa multiplier to compensate for the striping of
                    349: * zeros from the mantissa.
                    350: *
                    351: ap_p_fm:
                    352:        move.l  #PTENRN,a1      ;get address of power-of-ten table
                    353:        clr.l   d3              ;init table index
                    354:        fmove.s FONE,fp1        ;init fp1 to 1
                    355:        moveq.l #3,d2           ;init d2 to count bits in counter
                    356: ap_p_el:
                    357:        asr.l   #1,d0           ;shift lsb into carry
                    358:        bcc.b   ap_p_en         ;if 1, mul fp1 by pwrten factor
                    359:        fmul.x  (a1,d3),fp1     ;mul by 10**(d3_bit_no)
                    360: ap_p_en:
                    361:        add.l   #12,d3          ;inc d3 to next rtable entry
                    362:        tst.l   d0              ;check if d0 is zero
                    363:        bne.b   ap_p_el         ;if not, get next bit
                    364:        fmul.x  fp1,fp0         ;mul mantissa by 10**(no_bits_shifted)
                    365:        bra.b   pwrten          ;go calc pwrten
                    366: *
                    367: * This section handles a negative adjusted exponent.
                    368: *
                    369: ap_st_n:
                    370:        clr.l   d1              ;clr counter
                    371:        moveq.l #2,d5           ;set up d5 to point to lword 3
                    372:        move.l  (a0,d5.L*4),d4  ;get lword 3
                    373:        bne.b   ap_n_cl         ;if not zero, check digits
                    374:        sub.l   #1,d5           ;dec d5 to point to lword 2
                    375:        addq.l  #8,d1           ;inc counter by 8
                    376:        move.l  (a0,d5.L*4),d4  ;get lword 2
                    377: ap_n_cl:
                    378:        move.l  #28,d3          ;point to last digit
                    379:        moveq.l #7,d2           ;init digit counter
                    380: ap_n_gd:
                    381:        bfextu  d4{d3:4},d0     ;get digit
                    382:        bne.b   ap_n_fx         ;if non-zero, go to exp fix
                    383:        subq.l  #4,d3           ;point to previous digit
                    384:        addq.l  #1,d1           ;inc digit counter
                    385:        dbf.w   d2,ap_n_gd      ;get next digit
                    386: ap_n_fx:
                    387:        move.l  d1,d0           ;copy counter to d0
                    388:        move.l  L_SCR1(a6),d1   ;get adjusted exp from memory
                    389:        sub.l   d0,d1           ;subtract count from exp
                    390:        bgt.b   ap_n_fm         ;if still pos, go fix mantissa
                    391:        neg.l   d1              ;take abs of exp and clr SE
                    392:        move.l  (a0),d4         ;load lword 1 to d4
                    393:        and.l   #$bfffffff,d4   ; and clr SE in d4
                    394:        and.l   #$bfffffff,(a0) ; and in memory
                    395: *
                    396: * Calculate the mantissa multiplier to compensate for the appending of
                    397: * zeros to the mantissa.
                    398: *
                    399: ap_n_fm:
                    400:        move.l  #PTENRN,a1      ;get address of power-of-ten table
                    401:        clr.l   d3              ;init table index
                    402:        fmove.s FONE,fp1        ;init fp1 to 1
                    403:        moveq.l #3,d2           ;init d2 to count bits in counter
                    404: ap_n_el:
                    405:        asr.l   #1,d0           ;shift lsb into carry
                    406:        bcc.b   ap_n_en         ;if 1, mul fp1 by pwrten factor
                    407:        fmul.x  (a1,d3),fp1     ;mul by 10**(d3_bit_no)
                    408: ap_n_en:
                    409:        add.l   #12,d3          ;inc d3 to next rtable entry
                    410:        tst.l   d0              ;check if d0 is zero
                    411:        bne.b   ap_n_el         ;if not, get next bit
                    412:        fdiv.x  fp1,fp0         ;div mantissa by 10**(no_bits_shifted)
                    413: *
                    414: *
                    415: * Calculate power-of-ten factor from adjusted and shifted exponent.
                    416: *
                    417: * Register usage:
                    418: *
                    419: *  pwrten:
                    420: *      (*)  d0: temp
                    421: *      ( )  d1: exponent
                    422: *      (*)  d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp
                    423: *      (*)  d3: FPCR work copy
                    424: *      ( )  d4: first word of bcd
                    425: *      (*)  a1: RTABLE pointer
                    426: *  calc_p:
                    427: *      (*)  d0: temp
                    428: *      ( )  d1: exponent
                    429: *      (*)  d3: PWRTxx table index
                    430: *      ( )  a0: pointer to working copy of bcd
                    431: *      (*)  a1: PWRTxx pointer
                    432: *      (*) fp1: power-of-ten accumulator
                    433: *
                    434: * Pwrten calculates the exponent factor in the selected rounding mode
                    435: * according to the following table:
                    436: *
                    437: *      Sign of Mant  Sign of Exp  Rounding Mode  PWRTEN Rounding Mode
                    438: *
                    439: *      ANY       ANY   RN      RN
                    440: *
                    441: *       +         +    RP      RP
                    442: *       -         +    RP      RM
                    443: *       +         -    RP      RM
                    444: *       -         -    RP      RP
                    445: *
                    446: *       +         +    RM      RM
                    447: *       -         +    RM      RP
                    448: *       +         -    RM      RP
                    449: *       -         -    RM      RM
                    450: *
                    451: *       +         +    RZ      RM
                    452: *       -         +    RZ      RM
                    453: *       +         -    RZ      RP
                    454: *       -         -    RZ      RP
                    455: *
                    456: *
                    457: pwrten:
                    458:        move.l  USER_FPCR(a6),d3 ;get user's FPCR
                    459:        bfextu  d3{26:2},d2     ;isolate rounding mode bits
                    460:        move.l  (a0),d4         ;reload 1st bcd word to d4
                    461:        asl.l   #2,d2           ;format d2 to be
                    462:        bfextu  d4{0:2},d0      ; {FPCR[6],FPCR[5],SM,SE}
                    463:        add.l   d0,d2           ;in d2 as index into RTABLE
                    464:        lea.l   RTABLE,a1       ;load rtable base
                    465:        move.b  (a1,d2),d0      ;load new rounding bits from table
                    466:        clr.l   d3                      ;clear d3 to force no exc and extended
                    467:        bfins   d0,d3{26:2}     ;stuff new rounding bits in FPCR
                    468:        fmove.l d3,FPCR         ;write new FPCR
                    469:        asr.l   #1,d0           ;write correct PTENxx table
                    470:        bcc.b   not_rp          ;to a1
                    471:        lea.l   PTENRP,a1       ;it is RP
                    472:        bra.b   calc_p          ;go to init section
                    473: not_rp:
                    474:        asr.l   #1,d0           ;keep checking
                    475:        bcc.b   not_rm
                    476:        lea.l   PTENRM,a1       ;it is RM
                    477:        bra.b   calc_p          ;go to init section
                    478: not_rm:
                    479:        lea.l   PTENRN,a1       ;it is RN
                    480: calc_p:
                    481:        move.l  d1,d0           ;copy exp to d0;use d0
                    482:        bpl.b   no_neg          ;if exp is negative,
                    483:        neg.l   d0              ;invert it
                    484:        or.l    #$40000000,(a0) ;and set SE bit
                    485: no_neg:
                    486:        clr.l   d3              ;table index
                    487:        fmove.s FONE,fp1        ;init fp1 to 1
                    488: e_loop:
                    489:        asr.l   #1,d0           ;shift next bit into carry
                    490:        bcc.b   e_next          ;if zero, skip the mul
                    491:        fmul.x  (a1,d3),fp1     ;mul by 10**(d3_bit_no)
                    492: e_next:
                    493:        add.l   #12,d3          ;inc d3 to next rtable entry
                    494:        tst.l   d0              ;check if d0 is zero
                    495:        bne.b   e_loop          ;not zero, continue shifting
                    496: *
                    497: *
                    498: *  Check the sign of the adjusted exp and make the value in fp0 the
                    499: *  same sign. If the exp was pos then multiply fp1*fp0;
                    500: *  else divide fp0/fp1.
                    501: *
                    502: * Register Usage:
                    503: *  norm:
                    504: *      ( )  a0: pointer to working bcd value
                    505: *      (*) fp0: mantissa accumulator
                    506: *      ( ) fp1: scaling factor - 10**(abs(exp))
                    507: *
                    508: norm:
                    509:        btst    #30,(a0)        ;test the sign of the exponent
                    510:        beq.b   mul             ;if clear, go to multiply
                    511: div:
                    512:        fdiv.x  fp1,fp0         ;exp is negative, so divide mant by exp
                    513:        bra.b   end_dec
                    514: mul:
                    515:        fmul.x  fp1,fp0         ;exp is positive, so multiply by exp
                    516: *
                    517: *
                    518: * Clean up and return with result in fp0.
                    519: *
                    520: * If the final mul/div in decbin incurred an inex exception,
                    521: * it will be inex2, but will be reported as inex1 by get_op.
                    522: *
                    523: end_dec:
                    524:        fmove.l FPSR,d0         ;get status register
                    525:        bclr.l  #inex2_bit+8,d0 ;test for inex2 and clear it
                    526:        fmove.l d0,FPSR         ;return status reg w/o inex2
                    527:        beq.b   no_exc          ;skip this if no exc
                    528:        or.l    #inx1a_mask,USER_FPSR(a6) ;set inex1/ainex
                    529: no_exc:
                    530:        movem.l (a7)+,d2-d5
                    531:        rts
                    532:        end

CVSweb