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

Annotation of sys/arch/m68k/fpsp/round.sa, Revision 1.1

1.1     ! nbrk        1: *      $OpenBSD: round.sa,v 1.3 2005/11/15 21:09:45 miod Exp $
        !             2: *      $NetBSD: round.sa,v 1.3 1994/10/26 07:49:24 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: *      round.sa 3.4 7/29/91
        !            36: *
        !            37: *      handle rounding and normalization tasks
        !            38: *
        !            39:
        !            40: ROUND  IDNT    2,1 Motorola 040 Floating Point Software Package
        !            41:
        !            42:        section 8
        !            43:
        !            44:        include fpsp.h
        !            45:
        !            46: *
        !            47: *      round --- round result according to precision/mode
        !            48: *
        !            49: *      a0 points to the input operand in the internal extended format
        !            50: *      d1(high word) contains rounding precision:
        !            51: *              ext = $0000xxxx
        !            52: *              sgl = $0001xxxx
        !            53: *              dbl = $0002xxxx
        !            54: *      d1(low word) contains rounding mode:
        !            55: *              RN  = $xxxx0000
        !            56: *              RZ  = $xxxx0001
        !            57: *              RM  = $xxxx0010
        !            58: *              RP  = $xxxx0011
        !            59: *      d0{31:29} contains the g,r,s bits (extended)
        !            60: *
        !            61: *      On return the value pointed to by a0 is correctly rounded,
        !            62: *      a0 is preserved and the g-r-s bits in d0 are cleared.
        !            63: *      The result is not typed - the tag field is invalid.  The
        !            64: *      result is still in the internal extended format.
        !            65: *
        !            66: *      The INEX bit of USER_FPSR will be set if the rounded result was
        !            67: *      inexact (i.e. if any of the g-r-s bits were set).
        !            68: *
        !            69:
        !            70:        xdef    round
        !            71: round:
        !            72: * If g=r=s=0 then result is exact and round is done, else set
        !            73: * the inex flag in status reg and continue.
        !            74: *
        !            75:        bsr.b   ext_grs                 ;this subroutine looks at the
        !            76: *                                      :rounding precision and sets
        !            77: *                                      ;the appropriate g-r-s bits.
        !            78:        tst.l   d0                      ;if grs are zero, go force
        !            79:        bne.w   rnd_cont                ;lower bits to zero for size
        !            80:
        !            81:        swap    d1                      ;set up d1.w for round prec.
        !            82:        bra.w   truncate
        !            83:
        !            84: rnd_cont:
        !            85: *
        !            86: * Use rounding mode as an index into a jump table for these modes.
        !            87: *
        !            88:        or.l    #inx2a_mask,USER_FPSR(a6) ;set inex2/ainex
        !            89:        lea     mode_tab,a1
        !            90:        move.l  (a1,d1.w*4),a1
        !            91:        jmp     (a1)
        !            92: *
        !            93: * Jump table indexed by rounding mode in d1.w.  All following assumes
        !            94: * grs != 0.
        !            95: *
        !            96: mode_tab:
        !            97:        dc.l    rnd_near
        !            98:        dc.l    rnd_zero
        !            99:        dc.l    rnd_mnus
        !           100:        dc.l    rnd_plus
        !           101: *
        !           102: *      ROUND PLUS INFINITY
        !           103: *
        !           104: *      If sign of fp number = 0 (positive), then add 1 to l.
        !           105: *
        !           106: rnd_plus:
        !           107:        swap    d1                      ;set up d1 for round prec.
        !           108:        tst.b   LOCAL_SGN(a0)           ;check for sign
        !           109:        bmi.w   truncate                ;if positive then truncate
        !           110:        move.l  #$ffffffff,d0           ;force g,r,s to be all f's
        !           111:        lea     add_to_l,a1
        !           112:        move.l  (a1,d1.w*4),a1
        !           113:        jmp     (a1)
        !           114: *
        !           115: *      ROUND MINUS INFINITY
        !           116: *
        !           117: *      If sign of fp number = 1 (negative), then add 1 to l.
        !           118: *
        !           119: rnd_mnus:
        !           120:        swap    d1                      ;set up d1 for round prec.
        !           121:        tst.b   LOCAL_SGN(a0)           ;check for sign
        !           122:        bpl.w   truncate                ;if negative then truncate
        !           123:        move.l  #$ffffffff,d0           ;force g,r,s to be all f's
        !           124:        lea     add_to_l,a1
        !           125:        move.l  (a1,d1.w*4),a1
        !           126:        jmp     (a1)
        !           127: *
        !           128: *      ROUND ZERO
        !           129: *
        !           130: *      Always truncate.
        !           131: rnd_zero:
        !           132:        swap    d1                      ;set up d1 for round prec.
        !           133:        bra.w   truncate
        !           134: *
        !           135: *
        !           136: *      ROUND NEAREST
        !           137: *
        !           138: *      If (g=1), then add 1 to l and if (r=s=0), then clear l
        !           139: *      Note that this will round to even in case of a tie.
        !           140: *
        !           141: rnd_near:
        !           142:        swap    d1                      ;set up d1 for round prec.
        !           143:        add.l   d0,d0                   ;shift g-bit to c-bit
        !           144:        bcc.w   truncate                ;if (g=1) then
        !           145:        lea     add_to_l,a1
        !           146:        move.l  (a1,d1.w*4),a1
        !           147:        jmp     (a1)
        !           148:
        !           149: *
        !           150: *      ext_grs --- extract guard, round and sticky bits
        !           151: *
        !           152: * Input:       d1 =            PREC:ROUND
        !           153: * Output:      d0{31:29}=      guard, round, sticky
        !           154: *
        !           155: * The ext_grs extract the guard/round/sticky bits according to the
        !           156: * selected rounding precision. It is called by the round subroutine
        !           157: * only.  All registers except d0 are kept intact. d0 becomes an
        !           158: * updated guard,round,sticky in d0{31:29}
        !           159: *
        !           160: * Notes: the ext_grs uses the round PREC, and therefore has to swap d1
        !           161: *       prior to usage, and needs to restore d1 to original.
        !           162: *
        !           163: ext_grs:
        !           164:        swap    d1                      ;have d1.w point to round precision
        !           165:        tst.w   d1
        !           166:        bne.b   sgl_or_dbl
        !           167:        bra.b   end_ext_grs
        !           168:
        !           169: sgl_or_dbl:
        !           170:        movem.l d2/d3,-(a7)             ;make some temp registers
        !           171:        cmpi.w  #1,d1
        !           172:        bne.b   grs_dbl
        !           173: grs_sgl:
        !           174:        bfextu  LOCAL_HI(a0){24:2},d3   ;sgl prec. g-r are 2 bits right
        !           175:        move.l  #30,d2                  ;of the sgl prec. limits
        !           176:        lsl.l   d2,d3                   ;shift g-r bits to MSB of d3
        !           177:        move.l  LOCAL_HI(a0),d2         ;get word 2 for s-bit test
        !           178:        andi.l  #$0000003f,d2           ;s bit is the or of all other
        !           179:        bne.b   st_stky                 ;bits to the right of g-r
        !           180:        tst.l   LOCAL_LO(a0)            ;test lower mantissa
        !           181:        bne.b   st_stky                 ;if any are set, set sticky
        !           182:        tst.l   d0                      ;test original g,r,s
        !           183:        bne.b   st_stky                 ;if any are set, set sticky
        !           184:        bra.b   end_sd                  ;if words 3 and 4 are clr, exit
        !           185: grs_dbl:
        !           186:        bfextu  LOCAL_LO(a0){21:2},d3   ;dbl-prec. g-r are 2 bits right
        !           187:        move.l  #30,d2                  ;of the dbl prec. limits
        !           188:        lsl.l   d2,d3                   ;shift g-r bits to the MSB of d3
        !           189:        move.l  LOCAL_LO(a0),d2         ;get lower mantissa  for s-bit test
        !           190:        andi.l  #$000001ff,d2           ;s bit is the or-ing of all
        !           191:        bne.b   st_stky                 ;other bits to the right of g-r
        !           192:        tst.l   d0                      ;test word original g,r,s
        !           193:        bne.b   st_stky                 ;if any are set, set sticky
        !           194:        bra.b   end_sd                  ;if clear, exit
        !           195: st_stky:
        !           196:        bset    #rnd_stky_bit,d3
        !           197: end_sd:
        !           198:        move.l  d3,d0                   ;return grs to d0
        !           199:        movem.l (a7)+,d2/d3             ;restore scratch registers
        !           200: end_ext_grs:
        !           201:        swap    d1                      ;restore d1 to original
        !           202:        rts
        !           203:
        !           204: ********************  Local Equates
        !           205: ad_1_sgl equ   $00000100       constant to add 1 to l-bit in sgl prec
        !           206: ad_1_dbl equ   $00000800       constant to add 1 to l-bit in dbl prec
        !           207:
        !           208:
        !           209: *Jump table for adding 1 to the l-bit indexed by rnd prec
        !           210:
        !           211: add_to_l:
        !           212:        dc.l    add_ext
        !           213:        dc.l    add_sgl
        !           214:        dc.l    add_dbl
        !           215:        dc.l    add_dbl
        !           216: *
        !           217: *      ADD SINGLE
        !           218: *
        !           219: add_sgl:
        !           220:        add.l   #ad_1_sgl,LOCAL_HI(a0)
        !           221:        bcc.b   scc_clr                 ;no mantissa overflow
        !           222:        roxr.w  LOCAL_HI(a0)            ;shift v-bit back in
        !           223:        roxr.w  LOCAL_HI+2(a0)          ;shift v-bit back in
        !           224:        add.w   #$1,LOCAL_EX(a0)        ;and incr exponent
        !           225: scc_clr:
        !           226:        tst.l   d0                      ;test for rs = 0
        !           227:        bne.b   sgl_done
        !           228:        andi.w  #$fe00,LOCAL_HI+2(a0)   ;clear the l-bit
        !           229: sgl_done:
        !           230:        andi.l  #$ffffff00,LOCAL_HI(a0) ;truncate bits beyond sgl limit
        !           231:        clr.l   LOCAL_LO(a0)            ;clear d2
        !           232:        rts
        !           233:
        !           234: *
        !           235: *      ADD EXTENDED
        !           236: *
        !           237: add_ext:
        !           238:        addq.l  #1,LOCAL_LO(a0)         ;add 1 to l-bit
        !           239:        bcc.b   xcc_clr                 ;test for carry out
        !           240:        addq.l  #1,LOCAL_HI(a0)         ;propogate carry
        !           241:        bcc.b   xcc_clr
        !           242:        roxr.w  LOCAL_HI(a0)            ;mant is 0 so restore v-bit
        !           243:        roxr.w  LOCAL_HI+2(a0)          ;mant is 0 so restore v-bit
        !           244:        roxr.w  LOCAL_LO(a0)
        !           245:        roxr.w  LOCAL_LO+2(a0)
        !           246:        add.w   #$1,LOCAL_EX(a0)        ;and inc exp
        !           247: xcc_clr:
        !           248:        tst.l   d0                      ;test rs = 0
        !           249:        bne.b   add_ext_done
        !           250:        andi.b  #$fe,LOCAL_LO+3(a0)     ;clear the l bit
        !           251: add_ext_done:
        !           252:        rts
        !           253: *
        !           254: *      ADD DOUBLE
        !           255: *
        !           256: add_dbl:
        !           257:        add.l   #ad_1_dbl,LOCAL_LO(a0)
        !           258:        bcc.b   dcc_clr
        !           259:        addq.l  #1,LOCAL_HI(a0)         ;propogate carry
        !           260:        bcc.b   dcc_clr
        !           261:        roxr.w  LOCAL_HI(a0)            ;mant is 0 so restore v-bit
        !           262:        roxr.w  LOCAL_HI+2(a0)          ;mant is 0 so restore v-bit
        !           263:        roxr.w  LOCAL_LO(a0)
        !           264:        roxr.w  LOCAL_LO+2(a0)
        !           265:        add.w   #$1,LOCAL_EX(a0)        ;incr exponent
        !           266: dcc_clr:
        !           267:        tst.l   d0                      ;test for rs = 0
        !           268:        bne.b   dbl_done
        !           269:        andi.w  #$f000,LOCAL_LO+2(a0)   ;clear the l-bit
        !           270:
        !           271: dbl_done:
        !           272:        andi.l  #$fffff800,LOCAL_LO(a0) ;truncate bits beyond dbl limit
        !           273:        rts
        !           274:
        !           275: error:
        !           276:        rts
        !           277: *
        !           278: * Truncate all other bits
        !           279: *
        !           280: trunct:
        !           281:        dc.l    end_rnd
        !           282:        dc.l    sgl_done
        !           283:        dc.l    dbl_done
        !           284:        dc.l    dbl_done
        !           285:
        !           286: truncate:
        !           287:        lea     trunct,a1
        !           288:        move.l  (a1,d1.w*4),a1
        !           289:        jmp     (a1)
        !           290:
        !           291: end_rnd:
        !           292:        rts
        !           293:
        !           294: *
        !           295: *      NORMALIZE
        !           296: *
        !           297: * These routines (nrm_zero & nrm_set) normalize the unnorm.  This
        !           298: * is done by shifting the mantissa left while decrementing the
        !           299: * exponent.
        !           300: *
        !           301: * NRM_SET shifts and decrements until there is a 1 set in the integer
        !           302: * bit of the mantissa (msb in d1).
        !           303: *
        !           304: * NRM_ZERO shifts and decrements until there is a 1 set in the integer
        !           305: * bit of the mantissa (msb in d1) unless this would mean the exponent
        !           306: * would go less than 0.  In that case the number becomes a denorm - the
        !           307: * exponent (d0) is set to 0 and the mantissa (d1 & d2) is not
        !           308: * normalized.
        !           309: *
        !           310: * Note that both routines have been optimized (for the worst case) and
        !           311: * therefore do not have the easy to follow decrement/shift loop.
        !           312: *
        !           313: *      NRM_ZERO
        !           314: *
        !           315: *      Distance to first 1 bit in mantissa = X
        !           316: *      Distance to 0 from exponent = Y
        !           317: *      If X < Y
        !           318: *      Then
        !           319: *        nrm_set
        !           320: *      Else
        !           321: *        shift mantissa by Y
        !           322: *        set exponent = 0
        !           323: *
        !           324: *input:
        !           325: *      FP_SCR1 = exponent, ms mantissa part, ls mantissa part
        !           326: *output:
        !           327: *      L_SCR1{4} = fpte15 or ete15 bit
        !           328: *
        !           329:        xdef    nrm_zero
        !           330: nrm_zero:
        !           331:        move.w  LOCAL_EX(a0),d0
        !           332:        cmp.w   #64,d0          ;see if exp > 64
        !           333:        bmi.b   d0_less
        !           334:        bsr     nrm_set         ;exp > 64 so exp won't exceed 0
        !           335:        rts
        !           336: d0_less:
        !           337:        movem.l d2/d3/d5/d6,-(a7)
        !           338:        move.l  LOCAL_HI(a0),d1
        !           339:        move.l  LOCAL_LO(a0),d2
        !           340:
        !           341:        bfffo   d1{0:32},d3     ;get the distance to the first 1
        !           342: *                              ;in ms mant
        !           343:        beq.b   ms_clr          ;branch if no bits were set
        !           344:        cmp.w   d3,d0           ;of X>Y
        !           345:        bmi.b   greater         ;then exp will go past 0 (neg) if
        !           346: *                              ;it is just shifted
        !           347:        bsr     nrm_set         ;else exp won't go past 0
        !           348:        movem.l (a7)+,d2/d3/d5/d6
        !           349:        rts
        !           350: greater:
        !           351:        move.l  d2,d6           ;save ls mant in d6
        !           352:        lsl.l   d0,d2           ;shift ls mant by count
        !           353:        lsl.l   d0,d1           ;shift ms mant by count
        !           354:        move.l  #32,d5
        !           355:        sub.l   d0,d5           ;make op a denorm by shifting bits
        !           356:        lsr.l   d5,d6           ;by the number in the exp, then
        !           357: *                              ;set exp = 0.
        !           358:        or.l    d6,d1           ;shift the ls mant bits into the ms mant
        !           359:        clr.l   d0              ;same as if decremented exp to 0
        !           360: *                              ;while shifting
        !           361:        move.w  d0,LOCAL_EX(a0)
        !           362:        move.l  d1,LOCAL_HI(a0)
        !           363:        move.l  d2,LOCAL_LO(a0)
        !           364:        movem.l (a7)+,d2/d3/d5/d6
        !           365:        rts
        !           366: ms_clr:
        !           367:        bfffo   d2{0:32},d3     ;check if any bits set in ls mant
        !           368:        beq.b   all_clr         ;branch if none set
        !           369:        add.w   #32,d3
        !           370:        cmp.w   d3,d0           ;if X>Y
        !           371:        bmi.b   greater         ;then branch
        !           372:        bsr     nrm_set         ;else exp won't go past 0
        !           373:        movem.l (a7)+,d2/d3/d5/d6
        !           374:        rts
        !           375: all_clr:
        !           376:        clr.w   LOCAL_EX(a0)    ;no mantissa bits set. Set exp = 0.
        !           377:        movem.l (a7)+,d2/d3/d5/d6
        !           378:        rts
        !           379: *
        !           380: *      NRM_SET
        !           381: *
        !           382:        xdef    nrm_set
        !           383: nrm_set:
        !           384:        move.l  d7,-(a7)
        !           385:        bfffo   LOCAL_HI(a0){0:32},d7 ;find first 1 in ms mant to d7)
        !           386:        beq.b   lower           ;branch if ms mant is all 0's
        !           387:
        !           388:        move.l  d6,-(a7)
        !           389:
        !           390:        sub.w   d7,LOCAL_EX(a0) ;sub exponent by count
        !           391:        move.l  LOCAL_HI(a0),d0 ;d0 has ms mant
        !           392:        move.l  LOCAL_LO(a0),d1 ;d1 has ls mant
        !           393:
        !           394:        lsl.l   d7,d0           ;shift first 1 to j bit position
        !           395:        move.l  d1,d6           ;copy ls mant into d6
        !           396:        lsl.l   d7,d6           ;shift ls mant by count
        !           397:        move.l  d6,LOCAL_LO(a0) ;store ls mant into memory
        !           398:        moveq.l #32,d6
        !           399:        sub.l   d7,d6           ;continue shift
        !           400:        lsr.l   d6,d1           ;shift off all bits but those that will
        !           401: *                              ;be shifted into ms mant
        !           402:        or.l    d1,d0           ;shift the ls mant bits into the ms mant
        !           403:        move.l  d0,LOCAL_HI(a0) ;store ms mant into memory
        !           404:        movem.l (a7)+,d7/d6     ;restore registers
        !           405:        rts
        !           406:
        !           407: *
        !           408: * We get here if ms mant was = 0, and we assume ls mant has bits
        !           409: * set (otherwise this would have been tagged a zero not a denorm).
        !           410: *
        !           411: lower:
        !           412:        move.w  LOCAL_EX(a0),d0 ;d0 has exponent
        !           413:        move.l  LOCAL_LO(a0),d1 ;d1 has ls mant
        !           414:        sub.w   #32,d0          ;account for ms mant being all zeros
        !           415:        bfffo   d1{0:32},d7     ;find first 1 in ls mant to d7)
        !           416:        sub.w   d7,d0           ;subtract shift count from exp
        !           417:        lsl.l   d7,d1           ;shift first 1 to integer bit in ms mant
        !           418:        move.w  d0,LOCAL_EX(a0) ;store ms mant
        !           419:        move.l  d1,LOCAL_HI(a0) ;store exp
        !           420:        clr.l   LOCAL_LO(a0)    ;clear ls mant
        !           421:        move.l  (a7)+,d7
        !           422:        rts
        !           423: *
        !           424: *      denorm --- denormalize an intermediate result
        !           425: *
        !           426: *      Used by underflow.
        !           427: *
        !           428: * Input:
        !           429: *      a0       points to the operand to be denormalized
        !           430: *               (in the internal extended format)
        !           431: *
        !           432: *      d0:      rounding precision
        !           433: * Output:
        !           434: *      a0       points to the denormalized result
        !           435: *               (in the internal extended format)
        !           436: *
        !           437: *      d0      is guard,round,sticky
        !           438: *
        !           439: * d0 comes into this routine with the rounding precision. It
        !           440: * is then loaded with the denormalized exponent threshold for the
        !           441: * rounding precision.
        !           442: *
        !           443:
        !           444:        xdef    denorm
        !           445: denorm:
        !           446:        btst.b  #6,LOCAL_EX(a0) ;check for exponents between $7fff-$4000
        !           447:        beq.b   no_sgn_ext
        !           448:        bset.b  #7,LOCAL_EX(a0) ;sign extend if it is so
        !           449: no_sgn_ext:
        !           450:
        !           451:        tst.b   d0              ;if 0 then extended precision
        !           452:        bne.b   not_ext         ;else branch
        !           453:
        !           454:        clr.l   d1              ;load d1 with ext threshold
        !           455:        clr.l   d0              ;clear the sticky flag
        !           456:        bsr     dnrm_lp         ;denormalize the number
        !           457:        tst.b   d1              ;check for inex
        !           458:        beq.w   no_inex         ;if clr, no inex
        !           459:        bra.b   dnrm_inex       ;if set, set inex
        !           460:
        !           461: not_ext:
        !           462:        cmpi.l  #1,d0           ;if 1 then single precision
        !           463:        beq.b   load_sgl        ;else must be 2, double prec
        !           464:
        !           465: load_dbl:
        !           466:        move.w  #dbl_thresh,d1  ;put copy of threshold in d1
        !           467:        move.l  d1,d0           ;copy d1 into d0
        !           468:        sub.w   LOCAL_EX(a0),d0 ;diff = threshold - exp
        !           469:        cmp.w   #67,d0          ;if diff > 67 (mant + grs bits)
        !           470:        bpl.b   chk_stky        ;then branch (all bits would be
        !           471: *                              ; shifted off in denorm routine)
        !           472:        clr.l   d0              ;else clear the sticky flag
        !           473:        bsr     dnrm_lp         ;denormalize the number
        !           474:        tst.b   d1              ;check flag
        !           475:        beq.b   no_inex         ;if clr, no inex
        !           476:        bra.b   dnrm_inex       ;if set, set inex
        !           477:
        !           478: load_sgl:
        !           479:        move.w  #sgl_thresh,d1  ;put copy of threshold in d1
        !           480:        move.l  d1,d0           ;copy d1 into d0
        !           481:        sub.w   LOCAL_EX(a0),d0 ;diff = threshold - exp
        !           482:        cmp.w   #67,d0          ;if diff > 67 (mant + grs bits)
        !           483:        bpl.b   chk_stky        ;then branch (all bits would be
        !           484: *                              ; shifted off in denorm routine)
        !           485:        clr.l   d0              ;else clear the sticky flag
        !           486:        bsr     dnrm_lp         ;denormalize the number
        !           487:        tst.b   d1              ;check flag
        !           488:        beq.b   no_inex         ;if clr, no inex
        !           489:        bra.b   dnrm_inex       ;if set, set inex
        !           490:
        !           491: chk_stky:
        !           492:        tst.l   LOCAL_HI(a0)    ;check for any bits set
        !           493:        bne.b   set_stky
        !           494:        tst.l   LOCAL_LO(a0)    ;check for any bits set
        !           495:        bne.b   set_stky
        !           496:        bra.b   clr_mant
        !           497: set_stky:
        !           498:        or.l    #inx2a_mask,USER_FPSR(a6) ;set inex2/ainex
        !           499:        move.l  #$20000000,d0   ;set sticky bit in return value
        !           500: clr_mant:
        !           501:        move.w  d1,LOCAL_EX(a0)         ;load exp with threshold
        !           502:        clr.l   LOCAL_HI(a0)    ;set d1 = 0 (ms mantissa)
        !           503:        clr.l   LOCAL_LO(a0)            ;set d2 = 0 (ms mantissa)
        !           504:        rts
        !           505: dnrm_inex:
        !           506:        or.l    #inx2a_mask,USER_FPSR(a6) ;set inex2/ainex
        !           507: no_inex:
        !           508:        rts
        !           509:
        !           510: *
        !           511: *      dnrm_lp --- normalize exponent/mantissa to specified threshold
        !           512: *
        !           513: * Input:
        !           514: *      a0              points to the operand to be denormalized
        !           515: *      d0{31:29}       initial guard,round,sticky
        !           516: *      d1{15:0}        denormalization threshold
        !           517: * Output:
        !           518: *      a0              points to the denormalized operand
        !           519: *      d0{31:29}       final guard,round,sticky
        !           520: *      d1.b            inexact flag:  all ones means inexact result
        !           521: *
        !           522: * The LOCAL_LO and LOCAL_GRS parts of the value are copied to FP_SCR2
        !           523: * so that bfext can be used to extract the new low part of the mantissa.
        !           524: * Dnrm_lp can be called with a0 pointing to ETEMP or WBTEMP and there
        !           525: * is no LOCAL_GRS scratch word following it on the fsave frame.
        !           526: *
        !           527:        xdef    dnrm_lp
        !           528: dnrm_lp:
        !           529:        move.l  d2,-(sp)                ;save d2 for temp use
        !           530:        btst.b  #E3,E_BYTE(a6)          ;test for type E3 exception
        !           531:        beq.b   not_E3                  ;not type E3 exception
        !           532:        bfextu  WBTEMP_GRS(a6){6:3},d2  ;extract guard,round, sticky  bit
        !           533:        move.l  #29,d0
        !           534:        lsl.l   d0,d2                   ;shift g,r,s to their postions
        !           535:        move.l  d2,d0
        !           536: not_E3:
        !           537:        move.l  (sp)+,d2                ;restore d2
        !           538:        move.l  LOCAL_LO(a0),FP_SCR2+LOCAL_LO(a6)
        !           539:        move.l  d0,FP_SCR2+LOCAL_GRS(a6)
        !           540:        move.l  d1,d0                   ;copy the denorm threshold
        !           541:        sub.w   LOCAL_EX(a0),d1         ;d1 = threshold - uns exponent
        !           542:        ble.b   no_lp                   ;d1 <= 0
        !           543:        cmp.w   #32,d1
        !           544:        blt.b   case_1                  ;0 = d1 < 32
        !           545:        cmp.w   #64,d1
        !           546:        blt.b   case_2                  ;32 <= d1 < 64
        !           547:        bra.w   case_3                  ;d1 >= 64
        !           548: *
        !           549: * No normalization necessary
        !           550: *
        !           551: no_lp:
        !           552:        clr.b   d1                      ;set no inex2 reported
        !           553:        move.l  FP_SCR2+LOCAL_GRS(a6),d0        ;restore original g,r,s
        !           554:        rts
        !           555: *
        !           556: * case (0<d1<32)
        !           557: *
        !           558: case_1:
        !           559:        move.l  d2,-(sp)
        !           560:        move.w  d0,LOCAL_EX(a0)         ;exponent = denorm threshold
        !           561:        move.l  #32,d0
        !           562:        sub.w   d1,d0                   ;d0 = 32 - d1
        !           563:        bfextu  LOCAL_EX(a0){d0:32},d2
        !           564:        bfextu  d2{d1:d0},d2            ;d2 = new LOCAL_HI
        !           565:        bfextu  LOCAL_HI(a0){d0:32},d1  ;d1 = new LOCAL_LO
        !           566:        bfextu  FP_SCR2+LOCAL_LO(a6){d0:32},d0  ;d0 = new G,R,S
        !           567:        move.l  d2,LOCAL_HI(a0)         ;store new LOCAL_HI
        !           568:        move.l  d1,LOCAL_LO(a0)         ;store new LOCAL_LO
        !           569:        clr.b   d1
        !           570:        bftst   d0{2:30}
        !           571:        beq.b   c1nstky
        !           572:        bset.l  #rnd_stky_bit,d0
        !           573:        st.b    d1
        !           574: c1nstky:
        !           575:        move.l  FP_SCR2+LOCAL_GRS(a6),d2        ;restore original g,r,s
        !           576:        andi.l  #$e0000000,d2           ;clear all but G,R,S
        !           577:        tst.l   d2                      ;test if original G,R,S are clear
        !           578:        beq.b   grs_clear
        !           579:        or.l    #$20000000,d0           ;set sticky bit in d0
        !           580: grs_clear:
        !           581:        andi.l  #$e0000000,d0           ;clear all but G,R,S
        !           582:        move.l  (sp)+,d2
        !           583:        rts
        !           584: *
        !           585: * case (32<=d1<64)
        !           586: *
        !           587: case_2:
        !           588:        move.l  d2,-(sp)
        !           589:        move.w  d0,LOCAL_EX(a0)         ;unsigned exponent = threshold
        !           590:        sub.w   #32,d1                  ;d1 now between 0 and 32
        !           591:        move.l  #32,d0
        !           592:        sub.w   d1,d0                   ;d0 = 32 - d1
        !           593:        bfextu  LOCAL_EX(a0){d0:32},d2
        !           594:        bfextu  d2{d1:d0},d2            ;d2 = new LOCAL_LO
        !           595:        bfextu  LOCAL_HI(a0){d0:32},d1  ;d1 = new G,R,S
        !           596:        bftst   d1{2:30}
        !           597:        bne.b   c2_sstky                ;bra if sticky bit to be set
        !           598:        bftst   FP_SCR2+LOCAL_LO(a6){d0:32}
        !           599:        bne.b   c2_sstky                ;bra if sticky bit to be set
        !           600:        move.l  d1,d0
        !           601:        clr.b   d1
        !           602:        bra.b   end_c2
        !           603: c2_sstky:
        !           604:        move.l  d1,d0
        !           605:        bset.l  #rnd_stky_bit,d0
        !           606:        st.b    d1
        !           607: end_c2:
        !           608:        clr.l   LOCAL_HI(a0)            ;store LOCAL_HI = 0
        !           609:        move.l  d2,LOCAL_LO(a0)         ;store LOCAL_LO
        !           610:        move.l  FP_SCR2+LOCAL_GRS(a6),d2        ;restore original g,r,s
        !           611:        andi.l  #$e0000000,d2           ;clear all but G,R,S
        !           612:        tst.l   d2                      ;test if original G,R,S are clear
        !           613:        beq.b   clear_grs
        !           614:        or.l    #$20000000,d0           ;set sticky bit in d0
        !           615: clear_grs:
        !           616:        andi.l  #$e0000000,d0           ;get rid of all but G,R,S
        !           617:        move.l  (sp)+,d2
        !           618:        rts
        !           619: *
        !           620: * d1 >= 64 Force the exponent to be the denorm threshold with the
        !           621: * correct sign.
        !           622: *
        !           623: case_3:
        !           624:        move.w  d0,LOCAL_EX(a0)
        !           625:        tst.w   LOCAL_SGN(a0)
        !           626:        bge.b   c3con
        !           627: c3neg:
        !           628:        or.l    #$80000000,LOCAL_EX(a0)
        !           629: c3con:
        !           630:        cmp.w   #64,d1
        !           631:        beq.b   sixty_four
        !           632:        cmp.w   #65,d1
        !           633:        beq.b   sixty_five
        !           634: *
        !           635: * Shift value is out of range.  Set d1 for inex2 flag and
        !           636: * return a zero with the given threshold.
        !           637: *
        !           638:        clr.l   LOCAL_HI(a0)
        !           639:        clr.l   LOCAL_LO(a0)
        !           640:        move.l  #$20000000,d0
        !           641:        st.b    d1
        !           642:        rts
        !           643:
        !           644: sixty_four:
        !           645:        move.l  LOCAL_HI(a0),d0
        !           646:        bfextu  d0{2:30},d1
        !           647:        andi.l  #$c0000000,d0
        !           648:        bra.b   c3com
        !           649:
        !           650: sixty_five:
        !           651:        move.l  LOCAL_HI(a0),d0
        !           652:        bfextu  d0{1:31},d1
        !           653:        andi.l  #$80000000,d0
        !           654:        lsr.l   #1,d0                   ;shift high bit into R bit
        !           655:
        !           656: c3com:
        !           657:        tst.l   d1
        !           658:        bne.b   c3ssticky
        !           659:        tst.l   LOCAL_LO(a0)
        !           660:        bne.b   c3ssticky
        !           661:        tst.b   FP_SCR2+LOCAL_GRS(a6)
        !           662:        bne.b   c3ssticky
        !           663:        clr.b   d1
        !           664:        bra.b   c3end
        !           665:
        !           666: c3ssticky:
        !           667:        bset.l  #rnd_stky_bit,d0
        !           668:        st.b    d1
        !           669: c3end:
        !           670:        clr.l   LOCAL_HI(a0)
        !           671:        clr.l   LOCAL_LO(a0)
        !           672:        rts
        !           673:
        !           674:        end

CVSweb