[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

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