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

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

1.1     ! nbrk        1: *      $OpenBSD: x_operr.sa,v 1.3 2001/09/20 17:02:30 mpech Exp $
        !             2: *      $NetBSD: x_operr.sa,v 1.4 1994/10/26 07:50: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: *      x_operr.sa 3.5 7/1/91
        !            36: *
        !            37: *      fpsp_operr --- FPSP handler for operand error exception
        !            38: *
        !            39: *      See 68040 User's Manual pp. 9-44f
        !            40: *
        !            41: * Note 1: For trap disabled 040 does the following:
        !            42: * If the dest is a fp reg, then an extended precision non_signaling
        !            43: * NAN is stored in the dest reg.  If the dest format is b, w, or l and
        !            44: * the source op is a NAN, then garbage is stored as the result (actually
        !            45: * the upper 32 bits of the mantissa are sent to the integer unit). If
        !            46: * the dest format is integer (b, w, l) and the operr is caused by
        !            47: * integer overflow, or the source op is inf, then the result stored is
        !            48: * garbage.
        !            49: * There are three cases in which operr is incorrectly signaled on the
        !            50: * 040.  This occurs for move_out of format b, w, or l for the largest
        !            51: * negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
        !            52: *
        !            53: *        On opclass = 011 fmove.(b,w,l) that causes a conversion
        !            54: *        overflow -> OPERR, the exponent in wbte (and fpte) is:
        !            55: *              byte    56 - (62 - exp)
        !            56: *              word    48 - (62 - exp)
        !            57: *              long    32 - (62 - exp)
        !            58: *
        !            59: *                      where exp = (true exp) - 1
        !            60: *
        !            61: *  So, wbtemp and fptemp will contain the following on erroneoulsy
        !            62: *        signalled operr:
        !            63: *                      fpts = 1
        !            64: *                      fpte = $4000  (15 bit externally)
        !            65: *              byte    fptm = $ffffffff ffffff80
        !            66: *              word    fptm = $ffffffff ffff8000
        !            67: *              long    fptm = $ffffffff 80000000
        !            68: *
        !            69: * Note 2: For trap enabled 040 does the following:
        !            70: * If the inst is move_out, then same as Note 1.
        !            71: * If the inst is not move_out, the dest is not modified.
        !            72: * The exceptional operand is not defined for integer overflow
        !            73: * during a move_out.
        !            74: *
        !            75:
        !            76: X_OPERR        IDNT    2,1 Motorola 040 Floating Point Software Package
        !            77:
        !            78:        section 8
        !            79:
        !            80:        include fpsp.h
        !            81:
        !            82:        xref    mem_write
        !            83:        xref    real_operr
        !            84:        xref    real_inex
        !            85:        xref    get_fline
        !            86:        xref    fpsp_done
        !            87:        xref    reg_dest
        !            88:
        !            89:        xdef    fpsp_operr
        !            90: fpsp_operr:
        !            91: *
        !            92:        link            a6,#-LOCAL_SIZE
        !            93:        fsave           -(a7)
        !            94:        movem.l         d0-d1/a0-a1,USER_DA(a6)
        !            95:        fmovem.x        fp0-fp3,USER_FP0(a6)
        !            96:        fmovem.l        fpcr/fpsr/fpiar,USER_FPCR(a6)
        !            97:
        !            98: *
        !            99: * Check if this is an opclass 3 instruction.
        !           100: *  If so, fall through, else branch to operr_end
        !           101: *
        !           102:        btst.b  #TFLAG,T_BYTE(a6)
        !           103:        beq.b   operr_end
        !           104:
        !           105: *
        !           106: * If the destination size is B,W,or L, the operr must be
        !           107: * handled here.
        !           108: *
        !           109:        move.l  CMDREG1B(a6),d0
        !           110:        bfextu  d0{3:3},d0      ;0=long, 4=word, 6=byte
        !           111:        tst.b   d0              ;determine size; check long
        !           112:        beq.w   operr_long
        !           113:        cmpi.b  #4,d0           ;check word
        !           114:        beq.w   operr_word
        !           115:        cmpi.b  #6,d0           ;check byte
        !           116:        beq.w   operr_byte
        !           117:
        !           118: *
        !           119: * The size is not B,W,or L, so the operr is handled by the
        !           120: * kernel handler.  Set the operr bits and clean up, leaving
        !           121: * only the integer exception frame on the stack, and the
        !           122: * fpu in the original exceptional state.
        !           123: *
        !           124: operr_end:
        !           125:        bset.b          #operr_bit,FPSR_EXCEPT(a6)
        !           126:        bset.b          #aiop_bit,FPSR_AEXCEPT(a6)
        !           127:
        !           128:        movem.l         USER_DA(a6),d0-d1/a0-a1
        !           129:        fmovem.x        USER_FP0(a6),fp0-fp3
        !           130:        fmovem.l        USER_FPCR(a6),fpcr/fpsr/fpiar
        !           131:        frestore        (a7)+
        !           132:        unlk            a6
        !           133:        bra.l           real_operr
        !           134:
        !           135: operr_long:
        !           136:        moveq.l #4,d1           ;write size to d1
        !           137:        move.b  STAG(a6),d0     ;test stag for nan
        !           138:        andi.b  #$e0,d0         ;clr all but tag
        !           139:        cmpi.b  #$60,d0         ;check for nan
        !           140:        beq     operr_nan
        !           141:        cmpi.l  #$80000000,FPTEMP_LO(a6) ;test if ls lword is special
        !           142:        bne.b   chklerr         ;if not equal, check for incorrect operr
        !           143:        bsr     check_upper     ;check if exp and ms mant are special
        !           144:        tst.l   d0
        !           145:        bne.b   chklerr         ;if d0 is true, check for incorrect operr
        !           146:        move.l  #$80000000,d0   ;store special case result
        !           147:        bsr     operr_store
        !           148:        bra.w   not_enabled     ;clean and exit
        !           149: *
        !           150: *      CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
        !           151: *
        !           152: chklerr:
        !           153:        move.w  FPTEMP_EX(a6),d0
        !           154:        and.w   #$7FFF,d0       ;ignore sign bit
        !           155:        cmp.w   #$3FFE,d0       ;this is the only possible exponent value
        !           156:        bne.b   chklerr2
        !           157: fixlong:
        !           158:        move.l  FPTEMP_LO(a6),d0
        !           159:        bsr     operr_store
        !           160:        bra.w   not_enabled
        !           161: chklerr2:
        !           162:        move.w  FPTEMP_EX(a6),d0
        !           163:        and.w   #$7FFF,d0       ;ignore sign bit
        !           164:        cmp.w   #$4000,d0
        !           165:        bcc.w   store_max       ;exponent out of range
        !           166:
        !           167:        move.l  FPTEMP_LO(a6),d0
        !           168:        and.l   #$7FFF0000,d0   ;look for all 1's on bits 30-16
        !           169:        cmp.l   #$7FFF0000,d0
        !           170:        beq.b   fixlong
        !           171:
        !           172:        tst.l   FPTEMP_LO(a6)
        !           173:        bpl.b   chklepos
        !           174:        cmp.l   #$FFFFFFFF,FPTEMP_HI(a6)
        !           175:        beq.b   fixlong
        !           176:        bra.w   store_max
        !           177: chklepos:
        !           178:        tst.l   FPTEMP_HI(a6)
        !           179:        beq.b   fixlong
        !           180:        bra.w   store_max
        !           181:
        !           182: operr_word:
        !           183:        moveq.l #2,d1           ;write size to d1
        !           184:        move.b  STAG(a6),d0     ;test stag for nan
        !           185:        andi.b  #$e0,d0         ;clr all but tag
        !           186:        cmpi.b  #$60,d0         ;check for nan
        !           187:        beq.w   operr_nan
        !           188:        cmpi.l  #$ffff8000,FPTEMP_LO(a6) ;test if ls lword is special
        !           189:        bne.b   chkwerr         ;if not equal, check for incorrect operr
        !           190:        bsr     check_upper     ;check if exp and ms mant are special
        !           191:        tst.l   d0
        !           192:        bne.b   chkwerr         ;if d0 is true, check for incorrect operr
        !           193:        move.l  #$80000000,d0   ;store special case result
        !           194:        bsr     operr_store
        !           195:        bra.w   not_enabled     ;clean and exit
        !           196: *
        !           197: *      CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
        !           198: *
        !           199: chkwerr:
        !           200:        move.w  FPTEMP_EX(a6),d0
        !           201:        and.w   #$7FFF,d0       ;ignore sign bit
        !           202:        cmp.w   #$3FFE,d0       ;this is the only possible exponent value
        !           203:        bne.b   store_max
        !           204:        move.l  FPTEMP_LO(a6),d0
        !           205:        swap    d0
        !           206:        bsr     operr_store
        !           207:        bra.w   not_enabled
        !           208:
        !           209: operr_byte:
        !           210:        moveq.l #1,d1           ;write size to d1
        !           211:        move.b  STAG(a6),d0     ;test stag for nan
        !           212:        andi.b  #$e0,d0         ;clr all but tag
        !           213:        cmpi.b  #$60,d0         ;check for nan
        !           214:        beq.b   operr_nan
        !           215:        cmpi.l  #$ffffff80,FPTEMP_LO(a6) ;test if ls lword is special
        !           216:        bne.b   chkberr         ;if not equal, check for incorrect operr
        !           217:        bsr     check_upper     ;check if exp and ms mant are special
        !           218:        tst.l   d0
        !           219:        bne.b   chkberr         ;if d0 is true, check for incorrect operr
        !           220:        move.l  #$80000000,d0   ;store special case result
        !           221:        bsr     operr_store
        !           222:        bra.w   not_enabled     ;clean and exit
        !           223: *
        !           224: *      CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
        !           225: *
        !           226: chkberr:
        !           227:        move.w  FPTEMP_EX(a6),d0
        !           228:        and.w   #$7FFF,d0       ;ignore sign bit
        !           229:        cmp.w   #$3FFE,d0       ;this is the only possible exponent value
        !           230:        bne.b   store_max
        !           231:        move.l  FPTEMP_LO(a6),d0
        !           232:        asl.l   #8,d0
        !           233:        swap    d0
        !           234:        bsr     operr_store
        !           235:        bra.w   not_enabled
        !           236:
        !           237: *
        !           238: * This operr condition is not of the special case.  Set operr
        !           239: * and aiop and write the portion of the nan to memory for the
        !           240: * given size.
        !           241: *
        !           242: operr_nan:
        !           243:        or.l    #opaop_mask,USER_FPSR(a6) ;set operr & aiop
        !           244:
        !           245:        move.l  ETEMP_HI(a6),d0 ;output will be from upper 32 bits
        !           246:        bsr     operr_store
        !           247:        bra     end_operr
        !           248: *
        !           249: * Store_max loads the max pos or negative for the size, sets
        !           250: * the operr and aiop bits, and clears inex and ainex, incorrectly
        !           251: * set by the 040.
        !           252: *
        !           253: store_max:
        !           254:        or.l    #opaop_mask,USER_FPSR(a6) ;set operr & aiop
        !           255:        bclr.b  #inex2_bit,FPSR_EXCEPT(a6)
        !           256:        bclr.b  #ainex_bit,FPSR_AEXCEPT(a6)
        !           257:        fmove.l #0,FPSR
        !           258:
        !           259:        tst.w   FPTEMP_EX(a6)   ;check sign
        !           260:        blt.b   load_neg
        !           261:        move.l  #$7fffffff,d0
        !           262:        bsr     operr_store
        !           263:        bra     end_operr
        !           264: load_neg:
        !           265:        move.l  #$80000000,d0
        !           266:        bsr     operr_store
        !           267:        bra     end_operr
        !           268:
        !           269: *
        !           270: * This routine stores the data in d0, for the given size in d1,
        !           271: * to memory or data register as required.  A read of the fline
        !           272: * is required to determine the destination.
        !           273: *
        !           274: operr_store:
        !           275:        move.l  d0,L_SCR1(a6)   ;move write data to L_SCR1
        !           276:        move.l  d1,-(a7)        ;save register size
        !           277:        bsr.l   get_fline       ;fline returned in d0
        !           278:        move.l  (a7)+,d1
        !           279:        bftst   d0{26:3}                ;if mode is zero, dest is Dn
        !           280:        bne.b   dest_mem
        !           281: *
        !           282: * Destination is Dn.  Get register number from d0. Data is on
        !           283: * the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
        !           284: *
        !           285:        andi.l  #7,d0           ;isolate register number
        !           286:        cmpi.l  #4,d1
        !           287:        beq.b   op_long         ;the most frequent case
        !           288:        cmpi.l  #2,d1
        !           289:        bne.b   op_con
        !           290:        or.l    #8,d0
        !           291:        bra.b   op_con
        !           292: op_long:
        !           293:        or.l    #$10,d0
        !           294: op_con:
        !           295:        move.l  d0,d1           ;format size:reg for reg_dest
        !           296:        bra.l   reg_dest        ;call to reg_dest returns to caller
        !           297: *                              ;of operr_store
        !           298: *
        !           299: * Destination is memory.  Get <ea> from integer exception frame
        !           300: * and call mem_write.
        !           301: *
        !           302: dest_mem:
        !           303:        lea.l   L_SCR1(a6),a0   ;put ptr to write data in a0
        !           304:        move.l  EXC_EA(a6),a1   ;put user destination address in a1
        !           305:        move.l  d1,d0           ;put size in d0
        !           306:        bsr.l   mem_write
        !           307:        rts
        !           308: *
        !           309: * Check the exponent for $c000 and the upper 32 bits of the
        !           310: * mantissa for $ffffffff.  If both are true, return d0 clr
        !           311: * and store the lower n bits of the least lword of FPTEMP
        !           312: * to d0 for write out.  If not, it is a real operr, and set d0.
        !           313: *
        !           314: check_upper:
        !           315:        cmpi.l  #$ffffffff,FPTEMP_HI(a6) ;check if first byte is all 1's
        !           316:        bne.b   true_operr      ;if not all 1's then was true operr
        !           317:        cmpi.w  #$c000,FPTEMP_EX(a6) ;check if incorrectly signalled
        !           318:        beq.b   not_true_operr  ;branch if not true operr
        !           319:        cmpi.w  #$bfff,FPTEMP_EX(a6) ;check if incorrectly signalled
        !           320:        beq.b   not_true_operr  ;branch if not true operr
        !           321: true_operr:
        !           322:        move.l  #1,d0           ;signal real operr
        !           323:        rts
        !           324: not_true_operr:
        !           325:        clr.l   d0              ;signal no real operr
        !           326:        rts
        !           327:
        !           328: *
        !           329: * End_operr tests for operr enabled.  If not, it cleans up the stack
        !           330: * and does an rte.  If enabled, it cleans up the stack and branches
        !           331: * to the kernel operr handler with only the integer exception
        !           332: * frame on the stack and the fpu in the original exceptional state
        !           333: * with correct data written to the destination.
        !           334: *
        !           335: end_operr:
        !           336:        btst.b          #operr_bit,FPCR_ENABLE(a6)
        !           337:        beq.b           not_enabled
        !           338: enabled:
        !           339:        movem.l         USER_DA(a6),d0-d1/a0-a1
        !           340:        fmovem.x        USER_FP0(a6),fp0-fp3
        !           341:        fmovem.l        USER_FPCR(a6),fpcr/fpsr/fpiar
        !           342:        frestore        (a7)+
        !           343:        unlk            a6
        !           344:        bra.l           real_operr
        !           345:
        !           346: not_enabled:
        !           347: *
        !           348: * It is possible to have either inex2 or inex1 exceptions with the
        !           349: * operr.  If the inex enable bit is set in the FPCR, and either
        !           350: * inex2 or inex1 occurred, we must clean up and branch to the
        !           351: * real inex handler.
        !           352: *
        !           353: ck_inex:
        !           354:        move.b  FPCR_ENABLE(a6),d0
        !           355:        and.b   FPSR_EXCEPT(a6),d0
        !           356:        andi.b  #$3,d0
        !           357:        beq.w   operr_exit
        !           358: *
        !           359: * Inexact enabled and reported, and we must take an inexact exception.
        !           360: *
        !           361: take_inex:
        !           362:        move.b          #INEX_VEC,EXC_VEC+1(a6)
        !           363:        move.l          USER_FPSR(a6),FPSR_SHADOW(a6)
        !           364:        or.l            #sx_mask,E_BYTE(a6)
        !           365:        movem.l         USER_DA(a6),d0-d1/a0-a1
        !           366:        fmovem.x        USER_FP0(a6),fp0-fp3
        !           367:        fmovem.l        USER_FPCR(a6),fpcr/fpsr/fpiar
        !           368:        frestore        (a7)+
        !           369:        unlk            a6
        !           370:        bra.l           real_inex
        !           371: *
        !           372: * Since operr is only an E1 exception, there is no need to frestore
        !           373: * any state back to the fpu.
        !           374: *
        !           375: operr_exit:
        !           376:        movem.l         USER_DA(a6),d0-d1/a0-a1
        !           377:        fmovem.x        USER_FP0(a6),fp0-fp3
        !           378:        fmovem.l        USER_FPCR(a6),fpcr/fpsr/fpiar
        !           379:        unlk            a6
        !           380:        bra.l           fpsp_done
        !           381:
        !           382:        end

CVSweb