[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     ! 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