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

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

1.1     ! nbrk        1: *      $OpenBSD: scale.sa,v 1.2 1996/05/29 21:05:36 niklas Exp $
        !             2: *      $NetBSD: scale.sa,v 1.3 1994/10/26 07:49:34 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: *      scale.sa 3.3 7/30/91
        !            36: *
        !            37: *      The entry point sSCALE computes the destination operand
        !            38: *      scaled by the source operand.  If the absoulute value of
        !            39: *      the source operand is (>= 2^14) an overflow or underflow
        !            40: *      is returned.
        !            41: *
        !            42: *      The entry point sscale is called from do_func to emulate
        !            43: *      the fscale unimplemented instruction.
        !            44: *
        !            45: *      Input: Double-extended destination operand in FPTEMP,
        !            46: *              double-extended source operand in ETEMP.
        !            47: *
        !            48: *      Output: The function returns scale(X,Y) to fp0.
        !            49: *
        !            50: *      Modifies: fp0.
        !            51: *
        !            52: *      Algorithm:
        !            53: *
        !            54:
        !            55: SCALE    IDNT    2,1 Motorola 040 Floating Point Software Package
        !            56:
        !            57:        section 8
        !            58:
        !            59:        include fpsp.h
        !            60:
        !            61:        xref    t_ovfl2
        !            62:        xref    t_unfl
        !            63:        xref    round
        !            64:        xref    t_resdnrm
        !            65:
        !            66: SRC_BNDS dc.w  $3fff,$400c
        !            67:
        !            68: *
        !            69: * This entry point is used by the unimplemented instruction exception
        !            70: * handler.
        !            71: *
        !            72: *
        !            73: *
        !            74: *      FSCALE
        !            75: *
        !            76:        xdef    sscale
        !            77: sscale:
        !            78:        fmove.l         #0,fpcr         ;clr user enabled exc
        !            79:        clr.l           d1
        !            80:        move.w          FPTEMP(a6),d1   ;get dest exponent
        !            81:        smi             L_SCR1(a6)      ;use L_SCR1 to hold sign
        !            82:        andi.l          #$7fff,d1       ;strip sign
        !            83:        move.w          ETEMP(a6),d0    ;check src bounds
        !            84:        andi.w          #$7fff,d0       ;clr sign bit
        !            85:        cmp2.w          SRC_BNDS,d0
        !            86:        bcc.b           src_in
        !            87:        cmpi.w          #$400c,d0       ;test for too large
        !            88:        bge.w           src_out
        !            89: *
        !            90: * The source input is below 1, so we check for denormalized numbers
        !            91: * and set unfl.
        !            92: *
        !            93: src_small:
        !            94:        move.b          DTAG(a6),d0
        !            95:        andi.b          #$e0,d0
        !            96:        tst.b           d0
        !            97:        beq.b           no_denorm
        !            98:        st              STORE_FLG(a6)   ;dest already contains result
        !            99:        or.l            #unfl_mask,USER_FPSR(a6) ;set UNFL
        !           100: den_done:
        !           101:        lea.l           FPTEMP(a6),a0
        !           102:        bra             t_resdnrm
        !           103: no_denorm:
        !           104:        fmove.l         USER_FPCR(a6),FPCR
        !           105:        fmove.x         FPTEMP(a6),fp0  ;simply return dest
        !           106:        rts
        !           107:
        !           108:
        !           109: *
        !           110: * Source is within 2^14 range.  To perform the int operation,
        !           111: * move it to d0.
        !           112: *
        !           113: src_in:
        !           114:        fmove.x         ETEMP(a6),fp0   ;move in src for int
        !           115:        fmove.l         #rz_mode,fpcr   ;force rz for src conversion
        !           116:        fmove.l         fp0,d0          ;int src to d0
        !           117:        fmove.l         #0,FPSR         ;clr status from above
        !           118:        tst.w           ETEMP(a6)       ;check src sign
        !           119:        blt.w           src_neg
        !           120: *
        !           121: * Source is positive.  Add the src to the dest exponent.
        !           122: * The result can be denormalized, if src = 0, or overflow,
        !           123: * if the result of the add sets a bit in the upper word.
        !           124: *
        !           125: src_pos:
        !           126:        tst.w           d1              ;check for denorm
        !           127:        beq.w           dst_dnrm
        !           128:        add.l           d0,d1           ;add src to dest exp
        !           129:        beq.b           denorm          ;if zero, result is denorm
        !           130:        cmpi.l          #$7fff,d1       ;test for overflow
        !           131:        bge.b           ovfl
        !           132:        tst.b           L_SCR1(a6)
        !           133:        beq.b           spos_pos
        !           134:        or.w            #$8000,d1
        !           135: spos_pos:
        !           136:        move.w          d1,FPTEMP(a6)   ;result in FPTEMP
        !           137:        fmove.l         USER_FPCR(a6),FPCR
        !           138:        fmove.x         FPTEMP(a6),fp0  ;write result to fp0
        !           139:        rts
        !           140: ovfl:
        !           141:        tst.b           L_SCR1(a6)
        !           142:        beq.b           sovl_pos
        !           143:        or.w            #$8000,d1
        !           144: sovl_pos:
        !           145:        move.w          FPTEMP(a6),ETEMP(a6)    ;result in ETEMP
        !           146:        move.l          FPTEMP_HI(a6),ETEMP_HI(a6)
        !           147:        move.l          FPTEMP_LO(a6),ETEMP_LO(a6)
        !           148:        bra             t_ovfl2
        !           149:
        !           150: denorm:
        !           151:        tst.b           L_SCR1(a6)
        !           152:        beq.b           den_pos
        !           153:        or.w            #$8000,d1
        !           154: den_pos:
        !           155:        tst.l           FPTEMP_HI(a6)   ;check j bit
        !           156:        blt.b           nden_exit       ;if set, not denorm
        !           157:        move.w          d1,ETEMP(a6)    ;input expected in ETEMP
        !           158:        move.l          FPTEMP_HI(a6),ETEMP_HI(a6)
        !           159:        move.l          FPTEMP_LO(a6),ETEMP_LO(a6)
        !           160:        or.l            #unfl_bit,USER_FPSR(a6) ;set unfl
        !           161:        lea.l           ETEMP(a6),a0
        !           162:        bra             t_resdnrm
        !           163: nden_exit:
        !           164:        move.w          d1,FPTEMP(a6)   ;result in FPTEMP
        !           165:        fmove.l         USER_FPCR(a6),FPCR
        !           166:        fmove.x         FPTEMP(a6),fp0  ;write result to fp0
        !           167:        rts
        !           168:
        !           169: *
        !           170: * Source is negative.  Add the src to the dest exponent.
        !           171: * (The result exponent will be reduced).  The result can be
        !           172: * denormalized.
        !           173: *
        !           174: src_neg:
        !           175:        add.l           d0,d1           ;add src to dest
        !           176:        beq.b           denorm          ;if zero, result is denorm
        !           177:        blt.b           fix_dnrm        ;if negative, result is
        !           178: *                                      ;needing denormalization
        !           179:        tst.b           L_SCR1(a6)
        !           180:        beq.b           sneg_pos
        !           181:        or.w            #$8000,d1
        !           182: sneg_pos:
        !           183:        move.w          d1,FPTEMP(a6)   ;result in FPTEMP
        !           184:        fmove.l         USER_FPCR(a6),FPCR
        !           185:        fmove.x         FPTEMP(a6),fp0  ;write result to fp0
        !           186:        rts
        !           187:
        !           188:
        !           189: *
        !           190: * The result exponent is below denorm value.  Test for catastrophic
        !           191: * underflow and force zero if true.  If not, try to shift the
        !           192: * mantissa right until a zero exponent exists.
        !           193: *
        !           194: fix_dnrm:
        !           195:        cmpi.w          #$ffc0,d1       ;lower bound for normalization
        !           196:        blt.w           fix_unfl        ;if lower, catastrophic unfl
        !           197:        move.w          d1,d0           ;use d0 for exp
        !           198:        move.l          d2,-(a7)        ;free d2 for norm
        !           199:        move.l          FPTEMP_HI(a6),d1
        !           200:        move.l          FPTEMP_LO(a6),d2
        !           201:        clr.l           L_SCR2(a6)
        !           202: fix_loop:
        !           203:        add.w           #1,d0           ;drive d0 to 0
        !           204:        lsr.l           #1,d1           ;while shifting the
        !           205:        roxr.l          #1,d2           ;mantissa to the right
        !           206:        bcc.b           no_carry
        !           207:        st              L_SCR2(a6)      ;use L_SCR2 to capture inex
        !           208: no_carry:
        !           209:        tst.w           d0              ;it is finished when
        !           210:        blt.b           fix_loop        ;d0 is zero or the mantissa
        !           211:        tst.b           L_SCR2(a6)
        !           212:        beq.b           tst_zero
        !           213:        or.l            #unfl_inx_mask,USER_FPSR(a6)
        !           214: *                                      ;set unfl, aunfl, ainex
        !           215: *
        !           216: * Test for zero. If zero, simply use fmove to return +/- zero
        !           217: * to the fpu.
        !           218: *
        !           219: tst_zero:
        !           220:        clr.w           FPTEMP_EX(a6)
        !           221:        tst.b           L_SCR1(a6)      ;test for sign
        !           222:        beq.b           tst_con
        !           223:        or.w            #$8000,FPTEMP_EX(a6) ;set sign bit
        !           224: tst_con:
        !           225:        move.l          d1,FPTEMP_HI(a6)
        !           226:        move.l          d2,FPTEMP_LO(a6)
        !           227:        move.l          (a7)+,d2
        !           228:        tst.l           d1
        !           229:        bne.b           not_zero
        !           230:        tst.l           FPTEMP_LO(a6)
        !           231:        bne.b           not_zero
        !           232: *
        !           233: * Result is zero.  Check for rounding mode to set lsb.  If the
        !           234: * mode is rp, and the zero is positive, return smallest denorm.
        !           235: * If the mode is rm, and the zero is negative, return smallest
        !           236: * negative denorm.
        !           237: *
        !           238:        btst.b          #5,FPCR_MODE(a6) ;test if rm or rp
        !           239:        beq.b           no_dir
        !           240:        btst.b          #4,FPCR_MODE(a6) ;check which one
        !           241:        beq.b           zer_rm
        !           242: zer_rp:
        !           243:        tst.b           L_SCR1(a6)      ;check sign
        !           244:        bne.b           no_dir          ;if set, neg op, no inc
        !           245:        move.l          #1,FPTEMP_LO(a6) ;set lsb
        !           246:        bra.b           sm_dnrm
        !           247: zer_rm:
        !           248:        tst.b           L_SCR1(a6)      ;check sign
        !           249:        beq.b           no_dir          ;if clr, neg op, no inc
        !           250:        move.l          #1,FPTEMP_LO(a6) ;set lsb
        !           251:        or.l            #neg_mask,USER_FPSR(a6) ;set N
        !           252:        bra.b           sm_dnrm
        !           253: no_dir:
        !           254:        fmove.l         USER_FPCR(a6),FPCR
        !           255:        fmove.x         FPTEMP(a6),fp0  ;use fmove to set cc's
        !           256:        rts
        !           257:
        !           258: *
        !           259: * The rounding mode changed the zero to a smallest denorm. Call
        !           260: * t_resdnrm with exceptional operand in ETEMP.
        !           261: *
        !           262: sm_dnrm:
        !           263:        move.l          FPTEMP_EX(a6),ETEMP_EX(a6)
        !           264:        move.l          FPTEMP_HI(a6),ETEMP_HI(a6)
        !           265:        move.l          FPTEMP_LO(a6),ETEMP_LO(a6)
        !           266:        lea.l           ETEMP(a6),a0
        !           267:        bra             t_resdnrm
        !           268:
        !           269: *
        !           270: * Result is still denormalized.
        !           271: *
        !           272: not_zero:
        !           273:        or.l            #unfl_mask,USER_FPSR(a6) ;set unfl
        !           274:        tst.b           L_SCR1(a6)      ;check for sign
        !           275:        beq.b           fix_exit
        !           276:        or.l            #neg_mask,USER_FPSR(a6) ;set N
        !           277: fix_exit:
        !           278:        bra.b           sm_dnrm
        !           279:
        !           280:
        !           281: *
        !           282: * The result has underflowed to zero. Return zero and set
        !           283: * unfl, aunfl, and ainex.
        !           284: *
        !           285: fix_unfl:
        !           286:        or.l            #unfl_inx_mask,USER_FPSR(a6)
        !           287:        btst.b          #5,FPCR_MODE(a6) ;test if rm or rp
        !           288:        beq.b           no_dir2
        !           289:        btst.b          #4,FPCR_MODE(a6) ;check which one
        !           290:        beq.b           zer_rm2
        !           291: zer_rp2:
        !           292:        tst.b           L_SCR1(a6)      ;check sign
        !           293:        bne.b           no_dir2         ;if set, neg op, no inc
        !           294:        clr.l           FPTEMP_EX(a6)
        !           295:        clr.l           FPTEMP_HI(a6)
        !           296:        move.l          #1,FPTEMP_LO(a6) ;set lsb
        !           297:        bra.b           sm_dnrm         ;return smallest denorm
        !           298: zer_rm2:
        !           299:        tst.b           L_SCR1(a6)      ;check sign
        !           300:        beq.b           no_dir2         ;if clr, neg op, no inc
        !           301:        move.w          #$8000,FPTEMP_EX(a6)
        !           302:        clr.l           FPTEMP_HI(a6)
        !           303:        move.l          #1,FPTEMP_LO(a6) ;set lsb
        !           304:        or.l            #neg_mask,USER_FPSR(a6) ;set N
        !           305:        bra.w           sm_dnrm         ;return smallest denorm
        !           306:
        !           307: no_dir2:
        !           308:        tst.b           L_SCR1(a6)
        !           309:        bge.b           pos_zero
        !           310: neg_zero:
        !           311:        clr.l           FP_SCR1(a6)     ;clear the exceptional operand
        !           312:        clr.l           FP_SCR1+4(a6)   ;for gen_except.
        !           313:        clr.l           FP_SCR1+8(a6)
        !           314:        fmove.s         #:80000000,fp0
        !           315:        rts
        !           316: pos_zero:
        !           317:        clr.l           FP_SCR1(a6)     ;clear the exceptional operand
        !           318:        clr.l           FP_SCR1+4(a6)   ;for gen_except.
        !           319:        clr.l           FP_SCR1+8(a6)
        !           320:        fmove.s         #:00000000,fp0
        !           321:        rts
        !           322:
        !           323: *
        !           324: * The destination is a denormalized number.  It must be handled
        !           325: * by first shifting the bits in the mantissa until it is normalized,
        !           326: * then adding the remainder of the source to the exponent.
        !           327: *
        !           328: dst_dnrm:
        !           329:        movem.l         d2/d3,-(a7)
        !           330:        move.w          FPTEMP_EX(a6),d1
        !           331:        move.l          FPTEMP_HI(a6),d2
        !           332:        move.l          FPTEMP_LO(a6),d3
        !           333: dst_loop:
        !           334:        tst.l           d2              ;test for normalized result
        !           335:        blt.b           dst_norm        ;exit loop if so
        !           336:        tst.l           d0              ;otherwise, test shift count
        !           337:        beq.b           dst_fin         ;if zero, shifting is done
        !           338:        subq.l          #1,d0           ;dec src
        !           339:        add.l           d3,d3
        !           340:        addx.l          d2,d2
        !           341:        bra.b           dst_loop
        !           342: *
        !           343: * Destination became normalized.  Simply add the remaining
        !           344: * portion of the src to the exponent.
        !           345: *
        !           346: dst_norm:
        !           347:        add.w           d0,d1           ;dst is normalized; add src
        !           348:        tst.b           L_SCR1(a6)
        !           349:        beq.b           dnrm_pos
        !           350:        or.w            #$8000,d1
        !           351: dnrm_pos:
        !           352:        movem.w         d1,FPTEMP_EX(a6)
        !           353:        movem.l         d2,FPTEMP_HI(a6)
        !           354:        movem.l         d3,FPTEMP_LO(a6)
        !           355:        fmove.l         USER_FPCR(a6),FPCR
        !           356:        fmove.x         FPTEMP(a6),fp0
        !           357:        movem.l         (a7)+,d2/d3
        !           358:        rts
        !           359:
        !           360: *
        !           361: * Destination remained denormalized.  Call t_excdnrm with
        !           362: * exceptional operand in ETEMP.
        !           363: *
        !           364: dst_fin:
        !           365:        tst.b           L_SCR1(a6)      ;check for sign
        !           366:        beq.b           dst_exit
        !           367:        or.l            #neg_mask,USER_FPSR(a6) ;set N
        !           368:        or.w            #$8000,d1
        !           369: dst_exit:
        !           370:        movem.w         d1,ETEMP_EX(a6)
        !           371:        movem.l         d2,ETEMP_HI(a6)
        !           372:        movem.l         d3,ETEMP_LO(a6)
        !           373:        or.l            #unfl_mask,USER_FPSR(a6) ;set unfl
        !           374:        movem.l         (a7)+,d2/d3
        !           375:        lea.l           ETEMP(a6),a0
        !           376:        bra             t_resdnrm
        !           377:
        !           378: *
        !           379: * Source is outside of 2^14 range.  Test the sign and branch
        !           380: * to the appropriate exception handler.
        !           381: *
        !           382: src_out:
        !           383:        tst.b           L_SCR1(a6)
        !           384:        beq.b           scro_pos
        !           385:        or.w            #$8000,d1
        !           386: scro_pos:
        !           387:        move.l          FPTEMP_HI(a6),ETEMP_HI(a6)
        !           388:        move.l          FPTEMP_LO(a6),ETEMP_LO(a6)
        !           389:        tst.w           ETEMP(a6)
        !           390:        blt.b           res_neg
        !           391: res_pos:
        !           392:        move.w          d1,ETEMP(a6)    ;result in ETEMP
        !           393:        bra             t_ovfl2
        !           394: res_neg:
        !           395:        move.w          d1,ETEMP(a6)    ;result in ETEMP
        !           396:        lea.l           ETEMP(a6),a0
        !           397:        bra             t_unfl
        !           398:        end

CVSweb