[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

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