[BACK]Return to fpu_emulate.c CVS log [TXT][DIR] Up to [local] / sys / arch / m68k / fpe

Annotation of sys/arch/m68k/fpe/fpu_emulate.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: fpu_emulate.c,v 1.15 2006/06/11 20:43:28 miod Exp $   */
                      2: /*     $NetBSD: fpu_emulate.c,v 1.25 2003/09/22 14:18:34 cl Exp $      */
                      3:
                      4: /*
                      5:  * Copyright (c) 1995 Gordon W. Ross
                      6:  * some portion Copyright (c) 1995 Ken Nakata
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission.
                     19:  * 4. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *      This product includes software developed by Gordon Ross
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34:
                     35: /*
                     36:  * mc68881 emulator
                     37:  * XXX - Just a start at it for now...
                     38:  */
                     39:
                     40: #include <sys/types.h>
                     41: #include <sys/signal.h>
                     42: #include <sys/systm.h>
                     43: #include <machine/frame.h>
                     44:
                     45: #if defined(DDB) && defined(DEBUG_FPE)
                     46: #include <machine/db_machdep.h>
                     47: #endif
                     48:
                     49: #include <m68k/fpe/fpu_emulate.h>
                     50:
                     51: int fpu_emul_fmovmcr(struct fpemu *fe, struct instruction *insn, int *);
                     52: int fpu_emul_fmovm(struct fpemu *fe, struct instruction *insn, int *);
                     53: int fpu_emul_arith(struct fpemu *fe, struct instruction *insn, int *);
                     54: int fpu_emul_type1(struct fpemu *fe, struct instruction *insn, int *);
                     55: int fpu_emul_brcc(struct fpemu *fe, struct instruction *insn);
                     56: int test_cc(struct fpemu *fe, int pred);
                     57: struct fpn *fpu_cmp(struct fpemu *fe);
                     58:
                     59: #if DEBUG_FPE
                     60: #  define DUMP_INSN(insn)                                              \
                     61:     printf("fpu_emulate: insn={adv=%d,siz=%d,op=%04x,w1=%04x}\n",      \
                     62:           (insn)->is_advance, (insn)->is_datasize,                     \
                     63:           (insn)->is_opcode, (insn)->is_word1)
                     64: #else
                     65: #  define DUMP_INSN(insn)
                     66: #endif
                     67:
                     68: /*
                     69:  * Emulate a floating-point instruction.
                     70:  * Return zero for success, else signal number.
                     71:  * (Typically: zero, SIGFPE, SIGILL, SIGSEGV)
                     72:  */
                     73: int
                     74: fpu_emulate(struct frame *frame, struct fpframe *fpf, int *typ)
                     75: {
                     76:     static struct instruction insn;
                     77:     static struct fpemu fe;
                     78:     int optype, sig;
                     79:     u_int16_t word;
                     80:
                     81:
                     82:     /* initialize insn.is_datasize to tell it is *not* initialized */
                     83:     insn.is_datasize = -1;
                     84:
                     85:     fe.fe_frame = frame;
                     86:     fe.fe_fpframe = fpf;
                     87:     fe.fe_fpsr = fpf->fpf_fpsr;
                     88:     fe.fe_fpcr = fpf->fpf_fpcr;
                     89:
                     90: #if DEBUG_FPE
                     91:     printf("ENTERING fpu_emulate: FPSR=%08x, FPCR=%08x\n",
                     92:           fe.fe_fpsr, fe.fe_fpcr);
                     93: #endif
                     94:
                     95:     /* always set this (to avoid a warning) */
                     96:     insn.is_pc = frame->f_pc;
                     97:     insn.is_nextpc = 0;
                     98:     if (frame->f_format == 4) {
                     99:        /*
                    100:         * A format 4 is generated by the 68{EC,LC}040.  The PC is
                    101:         * already set to the instruction following the faulting
                    102:         * instruction.  We need to calculate that, anyway.  The
                    103:         * fslw is the PC of the faulted instruction, which is what
                    104:         * we expect to be in f_pc.
                    105:         *
                    106:         * XXX - This is a hack; it assumes we at least know the
                    107:         * sizes of all instructions we run across.
                    108:         * XXX TODO: This may not be true, so we might want to save the PC
                    109:         * in order to restore it later.
                    110:         */
                    111:        /* insn.is_nextpc = frame->f_pc; */
                    112:        insn.is_pc = frame->f_fmt4.f_fslw;
                    113:        frame->f_pc = insn.is_pc;
                    114:     }
                    115:
                    116:     if (copyin((void *)insn.is_pc, &word, sizeof(word)) != 0) {
                    117: #ifdef DEBUG
                    118:        printf("fpu_emulate: fault reading opcode\n");
                    119: #endif
                    120:        return (SIGSEGV);
                    121:     }
                    122:
                    123:     if ((word & 0xf000) != 0xf000) {
                    124: #ifdef DEBUG
                    125:        printf("fpu_emulate: not coproc. insn.: opcode=0x%x\n", word);
                    126: #endif
                    127:        return (SIGILL);
                    128:     }
                    129:
                    130:     if ((word & 0x0E00) != 0x0200) {
                    131: #ifdef DEBUG
                    132:        printf("fpu_emulate: bad coproc. id: opcode=0x%x\n", word);
                    133: #endif
                    134:        *typ = ILL_COPROC;
                    135:        return (SIGILL);
                    136:     }
                    137:
                    138:     insn.is_opcode = word;
                    139:     optype = (word & 0x01C0);
                    140:
                    141:     if (copyin((void *)(insn.is_pc + 2), &word, sizeof(word)) != 0) {
                    142: #ifdef DEBUG
                    143:        printf("fpu_emulate: fault reading word1\n");
                    144: #endif
                    145:        return (SIGSEGV);
                    146:     }
                    147:     insn.is_word1 = word;
                    148:     /* all FPU instructions are at least 4-byte long */
                    149:     insn.is_advance = 4;
                    150:
                    151:     DUMP_INSN(&insn);
                    152:
                    153:     /*
                    154:      * Which family (or type) of opcode is it?
                    155:      * Tests ordered by likelihood (hopefully).
                    156:      * Certainly, type 0 is the most common.
                    157:      */
                    158:     if (optype == 0x0000) {
                    159:        /* type=0: generic */
                    160:        if ((word & 0xc000) == 0xc000) {
                    161: #if DEBUG_FPE
                    162:            printf("fpu_emulate: fmovm FPr\n");
                    163: #endif
                    164:            sig = fpu_emul_fmovm(&fe, &insn, typ);
                    165:        } else if ((word & 0xc000) == 0x8000) {
                    166: #if DEBUG_FPE
                    167:            printf("fpu_emulate: fmovm FPcr\n");
                    168: #endif
                    169:            sig = fpu_emul_fmovmcr(&fe, &insn, typ);
                    170:        } else if ((word & 0xe000) == 0x6000) {
                    171:            /* fstore = fmove FPn,mem */
                    172: #if DEBUG_FPE
                    173:            printf("fpu_emulate: fmove to mem\n");
                    174: #endif
                    175:            sig = fpu_emul_fstore(&fe, &insn, typ);
                    176:        } else if ((word & 0xfc00) == 0x5c00) {
                    177:            /* fmovecr */
                    178: #if DEBUG_FPE
                    179:            printf("fpu_emulate: fmovecr\n");
                    180: #endif
                    181:            sig = fpu_emul_fmovecr(&fe, &insn, typ);
                    182:        } else if ((word & 0xa07f) == 0x26) {
                    183:            /* fscale */
                    184: #if DEBUG_FPE
                    185:            printf("fpu_emulate: fscale\n");
                    186: #endif
                    187:            sig = fpu_emul_fscale(&fe, &insn, typ);
                    188:        } else {
                    189: #if DEBUG_FPE
                    190:            printf("fpu_emulate: other type0\n");
                    191: #endif
                    192:            /* all other type0 insns are arithmetic */
                    193:            sig = fpu_emul_arith(&fe, &insn, typ);
                    194:        }
                    195:        if (sig == 0) {
                    196: #if DEBUG_FPE
                    197:            printf("fpu_emulate: type 0 returned 0\n");
                    198: #endif
                    199:            sig = fpu_upd_excp(&fe);
                    200:        }
                    201:     } else if (optype == 0x0080 || optype == 0x00C0) {
                    202:        /* type=2 or 3: fbcc, short or long disp. */
                    203: #if DEBUG_FPE
                    204:        printf("fpu_emulate: fbcc %s\n",
                    205:               (optype & 0x40) ? "long" : "short");
                    206: #endif
                    207:        sig = fpu_emul_brcc(&fe, &insn);
                    208:     } else if (optype == 0x0040) {
                    209:        /* type=1: fdbcc, fscc, ftrapcc */
                    210: #if DEBUG_FPE
                    211:        printf("fpu_emulate: type1\n");
                    212: #endif
                    213:        sig = fpu_emul_type1(&fe, &insn, typ);
                    214:     } else {
                    215:        /* type=4: fsave    (privileged) */
                    216:        /* type=5: frestore (privileged) */
                    217:        /* type=6: reserved */
                    218:        /* type=7: reserved */
                    219: #ifdef DEBUG
                    220:        printf("fpu_emulate: bad opcode type: opcode=0x%x\n", insn.is_opcode);
                    221: #endif
                    222:        *typ = ILL_PRVOPC;
                    223:        sig = SIGILL;
                    224:     }
                    225:
                    226:     DUMP_INSN(&insn);
                    227:
                    228:      /*
                    229:       * XXX it is not clear to me, if we should progress the PC always,
                    230:       * for SIGFPE || 0, or only for 0; however, without SIGFPE, we
                    231:       * don't pass the signalling regression  tests.   -is
                    232:       */
                    233:     if ((sig == 0) || (sig == SIGFPE))
                    234:        frame->f_pc += insn.is_advance;
                    235: #if defined(DDB) && defined(DEBUG_FPE)
                    236:     else {
                    237:        printf("fpu_emulate: sig=%d, opcode=%x, word1=%x\n",
                    238:               sig, insn.is_opcode, insn.is_word1);
                    239:        kdb_trap(-1, (db_regs_t *)frame);
                    240:     }
                    241: #endif
                    242: #if 0 /* XXX something is wrong */
                    243:     if (frame->f_format == 4) {
                    244:        /* XXX Restore PC -- 68{EC,LC}040 only */
                    245:        if (insn.is_nextpc)
                    246:                frame->f_pc = insn.is_nextpc;
                    247:     }
                    248: #endif
                    249:
                    250: #if DEBUG_FPE
                    251:     printf("EXITING fpu_emulate: w/FPSR=%08x, FPCR=%08x\n",
                    252:           fe.fe_fpsr, fe.fe_fpcr);
                    253: #endif
                    254:
                    255:     if (*typ == 0)
                    256:        switch (sig) {
                    257:        case SIGSEGV:
                    258:                *typ = SEGV_MAPERR;
                    259:                break;
                    260:        case SIGILL:
                    261:                *typ = ILL_ILLOPC;
                    262:                break;
                    263:        case SIGFPE:
                    264:                *typ = FPE_FLTINV;
                    265:                break;
                    266:        }
                    267:     return (sig);
                    268: }
                    269:
                    270: /* update accrued exception bits and see if there's an FP exception */
                    271: int
                    272: fpu_upd_excp(fe)
                    273:      struct fpemu *fe;
                    274: {
                    275:     u_int fpsr;
                    276:     u_int fpcr;
                    277:
                    278:     fpsr = fe->fe_fpsr;
                    279:     fpcr = fe->fe_fpcr;
                    280:     /* update fpsr accrued exception bits; each insn doesn't have to
                    281:        update this */
                    282:     if (fpsr & (FPSR_BSUN | FPSR_SNAN | FPSR_OPERR)) {
                    283:        fpsr |= FPSR_AIOP;
                    284:     }
                    285:     if (fpsr & FPSR_OVFL) {
                    286:        fpsr |= FPSR_AOVFL;
                    287:     }
                    288:     if ((fpsr & FPSR_UNFL) && (fpsr & FPSR_INEX2)) {
                    289:        fpsr |= FPSR_AUNFL;
                    290:     }
                    291:     if (fpsr & FPSR_DZ) {
                    292:        fpsr |= FPSR_ADZ;
                    293:     }
                    294:     if (fpsr & (FPSR_INEX1 | FPSR_INEX2 | FPSR_OVFL)) {
                    295:        fpsr |= FPSR_AINEX;
                    296:     }
                    297:
                    298:     fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr;
                    299:
                    300:     return (fpsr & fpcr & FPSR_EXCP) ? SIGFPE : 0;
                    301: }
                    302:
                    303: /* update fpsr according to fp (= result of an fp op) */
                    304: u_int
                    305: fpu_upd_fpsr(fe, fp)
                    306:      struct fpemu *fe;
                    307:      struct fpn *fp;
                    308: {
                    309:     u_int fpsr;
                    310:
                    311: #if DEBUG_FPE
                    312:     printf("fpu_upd_fpsr: previous fpsr=%08x\n", fe->fe_fpsr);
                    313: #endif
                    314:     /* clear all condition code */
                    315:     fpsr = fe->fe_fpsr & ~FPSR_CCB;
                    316:
                    317: #if DEBUG_FPE
                    318:     printf("fpu_upd_fpsr: result is a ");
                    319: #endif
                    320:     if (fp->fp_sign) {
                    321: #if DEBUG_FPE
                    322:        printf("negative ");
                    323: #endif
                    324:        fpsr |= FPSR_NEG;
                    325: #if DEBUG_FPE
                    326:     } else {
                    327:        printf("positive ");
                    328: #endif
                    329:     }
                    330:
                    331:     switch (fp->fp_class) {
                    332:     case FPC_SNAN:
                    333: #if DEBUG_FPE
                    334:        printf("signaling NAN\n");
                    335: #endif
                    336:        fpsr |= (FPSR_NAN | FPSR_SNAN);
                    337:        break;
                    338:     case FPC_QNAN:
                    339: #if DEBUG_FPE
                    340:        printf("quiet NAN\n");
                    341: #endif
                    342:        fpsr |= FPSR_NAN;
                    343:        break;
                    344:     case FPC_ZERO:
                    345: #if DEBUG_FPE
                    346:        printf("Zero\n");
                    347: #endif
                    348:        fpsr |= FPSR_ZERO;
                    349:        break;
                    350:     case FPC_INF:
                    351: #if DEBUG_FPE
                    352:        printf("Inf\n");
                    353: #endif
                    354:        fpsr |= FPSR_INF;
                    355:        break;
                    356:     default:
                    357: #if DEBUG_FPE
                    358:        printf("Number\n");
                    359: #endif
                    360:        /* anything else is treated as if it is a number */
                    361:        break;
                    362:     }
                    363:
                    364:     fe->fe_fpsr = fe->fe_fpframe->fpf_fpsr = fpsr;
                    365:
                    366: #if DEBUG_FPE
                    367:     printf("fpu_upd_fpsr: new fpsr=%08x\n", fe->fe_fpframe->fpf_fpsr);
                    368: #endif
                    369:
                    370:     return fpsr;
                    371: }
                    372:
                    373: int
                    374: fpu_emul_fmovmcr(struct fpemu *fe, struct instruction *insn, int *typ)
                    375: {
                    376:     struct frame *frame = fe->fe_frame;
                    377:     struct fpframe *fpf = fe->fe_fpframe;
                    378:     int sig;
                    379:     int reglist;
                    380:     int fpu_to_mem;
                    381:
                    382:     /* move to/from control registers */
                    383:     reglist = (insn->is_word1 & 0x1c00) >> 10;
                    384:     /* Bit 13 selects direction (FPU to/from Mem) */
                    385:     fpu_to_mem = insn->is_word1 & 0x2000;
                    386:
                    387:     insn->is_datasize = 4;
                    388:     insn->is_advance = 4;
                    389:     sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode, typ);
                    390:     if (sig) { return sig; }
                    391:
                    392:     if (reglist != 1 && reglist != 2 && reglist != 4 &&
                    393:        (insn->is_ea.ea_flags & EA_DIRECT)) {
                    394:        /* attempted to copy more than one FPcr to CPU regs */
                    395: #ifdef DEBUG
                    396:        printf("fpu_emul_fmovmcr: tried to copy too many FPcr\n");
                    397: #endif
                    398:        return SIGILL;
                    399:     }
                    400:
                    401:     if (reglist & 4) {
                    402:        /* fpcr */
                    403:        if ((insn->is_ea.ea_flags & EA_DIRECT) &&
                    404:            insn->is_ea.ea_regnum >= 8 /* address reg */) {
                    405:            /* attempted to copy FPCR to An */
                    406: #ifdef DEBUG
                    407:            printf("fpu_emul_fmovmcr: tried to copy FPCR from/to A%d\n",
                    408:                   insn->is_ea.ea_regnum & 7);
                    409: #endif
                    410:            return SIGILL;
                    411:        }
                    412:        if (fpu_to_mem) {
                    413:            sig = fpu_store_ea(frame, insn, &insn->is_ea,
                    414:                               (char *)&fpf->fpf_fpcr);
                    415:        } else {
                    416:            sig = fpu_load_ea(frame, insn, &insn->is_ea,
                    417:                              (char *)&fpf->fpf_fpcr, typ);
                    418:        }
                    419:     }
                    420:     if (sig) { return sig; }
                    421:
                    422:     if (reglist & 2) {
                    423:        /* fpsr */
                    424:        if ((insn->is_ea.ea_flags & EA_DIRECT) &&
                    425:            insn->is_ea.ea_regnum >= 8 /* address reg */) {
                    426:            /* attempted to copy FPSR to An */
                    427: #ifdef DEBUG
                    428:            printf("fpu_emul_fmovmcr: tried to copy FPSR from/to A%d\n",
                    429:                   insn->is_ea.ea_regnum & 7);
                    430: #endif
                    431:            return SIGILL;
                    432:        }
                    433:        if (fpu_to_mem) {
                    434:            sig = fpu_store_ea(frame, insn, &insn->is_ea,
                    435:                               (char *)&fpf->fpf_fpsr);
                    436:        } else {
                    437:            sig = fpu_load_ea(frame, insn, &insn->is_ea,
                    438:                              (char *)&fpf->fpf_fpsr, typ);
                    439:        }
                    440:     }
                    441:     if (sig) { return sig; }
                    442:
                    443:     if (reglist & 1) {
                    444:        /* fpiar - can be moved to/from An */
                    445:        if (fpu_to_mem) {
                    446:            sig = fpu_store_ea(frame, insn, &insn->is_ea,
                    447:                               (char *)&fpf->fpf_fpiar);
                    448:        } else {
                    449:            sig = fpu_load_ea(frame, insn, &insn->is_ea,
                    450:                              (char *)&fpf->fpf_fpiar, typ);
                    451:        }
                    452:     }
                    453:     return sig;
                    454: }
                    455:
                    456: /*
                    457:  * type 0: fmovem
                    458:  * Separated out of fpu_emul_type0 for efficiency.
                    459:  * In this function, we know:
                    460:  *   (opcode & 0x01C0) == 0
                    461:  *   (word1 & 0x8000) == 0x8000
                    462:  *
                    463:  * No conversion or rounding is done by this instruction,
                    464:  * and the FPSR is not affected.
                    465:  */
                    466: int
                    467: fpu_emul_fmovm(struct fpemu *fe, struct instruction *insn, int *typ)
                    468: {
                    469:     struct frame *frame = fe->fe_frame;
                    470:     struct fpframe *fpf = fe->fe_fpframe;
                    471:     int word1, sig;
                    472:     int reglist, regmask, regnum;
                    473:     int fpu_to_mem, order;
                    474:     int w1_post_incr;
                    475:     int *fpregs;
                    476:
                    477:     insn->is_advance = 4;
                    478:     insn->is_datasize = 12;
                    479:     word1 = insn->is_word1;
                    480:
                    481:     /* Bit 13 selects direction (FPU to/from Mem) */
                    482:     fpu_to_mem = word1 & 0x2000;
                    483:
                    484:     /*
                    485:      * Bits 12,11 select register list mode:
                    486:      * 0,0: Static  reg list, pre-decr.
                    487:      * 0,1: Dynamic reg list, pre-decr.
                    488:      * 1,0: Static  reg list, post-incr.
                    489:      * 1,1: Dynamic reg list, post-incr
                    490:      */
                    491:     w1_post_incr = word1 & 0x1000;
                    492:     if (word1 & 0x0800) {
                    493:        /* dynamic reg list */
                    494:        reglist = frame->f_regs[(word1 & 0x70) >> 4];
                    495:     } else {
                    496:        reglist = word1;
                    497:     }
                    498:     reglist &= 0xFF;
                    499:
                    500:     /* Get effective address. (modreg=opcode&077) */
                    501:     sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode, typ);
                    502:     if (sig) { return sig; }
                    503:
                    504:     /* Get address of soft coprocessor regs. */
                    505:     fpregs = &fpf->fpf_regs[0];
                    506:
                    507:     if (insn->is_ea.ea_flags & EA_PREDECR) {
                    508:        regnum = 7;
                    509:        order = -1;
                    510:     } else {
                    511:        regnum = 0;
                    512:        order = 1;
                    513:     }
                    514:
                    515:     regmask = 0x80;
                    516:     while ((0 <= regnum) && (regnum < 8)) {
                    517:        if (regmask & reglist) {
                    518:            if (fpu_to_mem) {
                    519:                sig = fpu_store_ea(frame, insn, &insn->is_ea,
                    520:                                   (char *)&fpregs[regnum * 3]);
                    521: #if DEBUG_FPE
                    522:                printf("fpu_emul_fmovm: FP%d (%08x,%08x,%08x) saved\n",
                    523:                       regnum, fpregs[regnum * 3], fpregs[regnum * 3 + 1],
                    524:                       fpregs[regnum * 3 + 2]);
                    525: #endif
                    526:            } else {            /* mem to fpu */
                    527:                sig = fpu_load_ea(frame, insn, &insn->is_ea,
                    528:                                  (char *)&fpregs[regnum * 3], typ);
                    529: #if DEBUG_FPE
                    530:                printf("fpu_emul_fmovm: FP%d (%08x,%08x,%08x) loaded\n",
                    531:                       regnum, fpregs[regnum * 3], fpregs[regnum * 3 + 1],
                    532:                       fpregs[regnum * 3 + 2]);
                    533: #endif
                    534:            }
                    535:            if (sig) { break; }
                    536:        }
                    537:        regnum += order;
                    538:        regmask >>= 1;
                    539:     }
                    540:
                    541:     return sig;
                    542: }
                    543:
                    544: struct fpn *
                    545: fpu_cmp(fe)
                    546:      struct fpemu *fe;
                    547: {
                    548:     struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2;
                    549:
                    550:     /* take care of special cases */
                    551:     if (x->fp_class < 0 || y->fp_class < 0) {
                    552:        /* if either of two is a SNAN, result is SNAN */
                    553:        x->fp_class = (y->fp_class < x->fp_class) ? y->fp_class : x->fp_class;
                    554:     } else if (x->fp_class == FPC_INF) {
                    555:        if (y->fp_class == FPC_INF) {
                    556:            /* both infinities */
                    557:            if (x->fp_sign == y->fp_sign) {
                    558:                x->fp_class = FPC_ZERO; /* return a signed zero */
                    559:            } else {
                    560:                x->fp_class = FPC_NUM; /* return a faked number w/x's sign */
                    561:                x->fp_exp = 16383;
                    562:                x->fp_mant[0] = FP_1;
                    563:            }
                    564:        } else {
                    565:            /* y is a number */
                    566:            x->fp_class = FPC_NUM; /* return a forged number w/x's sign */
                    567:            x->fp_exp = 16383;
                    568:            x->fp_mant[0] = FP_1;
                    569:        }
                    570:     } else if (y->fp_class == FPC_INF) {
                    571:        /* x is a Num but y is an Inf */
                    572:        /* return a forged number w/y's sign inverted */
                    573:        x->fp_class = FPC_NUM;
                    574:        x->fp_sign = !y->fp_sign;
                    575:        x->fp_exp = 16383;
                    576:        x->fp_mant[0] = FP_1;
                    577:     } else {
                    578:        /* x and y are both numbers or zeros, or pair of a number and a zero */
                    579:        y->fp_sign = !y->fp_sign;
                    580:        x = fpu_add(fe);        /* (x - y) */
                    581:        /*
                    582:         * FCMP does not set Inf bit in CC, so return a forged number
                    583:         * (value doesn't matter) if Inf is the result of fsub.
                    584:         */
                    585:        if (x->fp_class == FPC_INF) {
                    586:            x->fp_class = FPC_NUM;
                    587:            x->fp_exp = 16383;
                    588:            x->fp_mant[0] = FP_1;
                    589:        }
                    590:     }
                    591:     return x;
                    592: }
                    593:
                    594: /*
                    595:  * arithmetic oprations
                    596:  */
                    597: int
                    598: fpu_emul_arith(struct fpemu *fe, struct instruction *insn, int *typ)
                    599: {
                    600:     struct frame *frame = fe->fe_frame;
                    601:     u_int *fpregs = &(fe->fe_fpframe->fpf_regs[0]);
                    602:     struct fpn *res;
                    603:     int word1, sig = 0;
                    604:     int regnum, format;
                    605:     int discard_result = 0;
                    606:     u_int buf[3];
                    607: #if DEBUG_FPE
                    608:     int flags;
                    609:     char regname;
                    610: #endif
                    611:
                    612:     fe->fe_fpsr &= ~FPSR_EXCP;
                    613:
                    614:     DUMP_INSN(insn);
                    615:
                    616: #if DEBUG_FPE
                    617:     printf("fpu_emul_arith: FPSR = %08x, FPCR = %08x\n",
                    618:           fe->fe_fpsr, fe->fe_fpcr);
                    619: #endif
                    620:
                    621:     word1 = insn->is_word1;
                    622:     format = (word1 >> 10) & 7;
                    623:     regnum = (word1 >> 7) & 7;
                    624:
                    625:     /* fetch a source operand : may not be used */
                    626: #if DEBUG_FPE
                    627:     printf("fpu_emul_arith: dst/src FP%d=%08x,%08x,%08x\n",
                    628:           regnum, fpregs[regnum*3], fpregs[regnum*3+1],
                    629:           fpregs[regnum*3+2]);
                    630: #endif
                    631:
                    632:     fpu_explode(fe, &fe->fe_f1, FTYPE_EXT, &fpregs[regnum * 3]);
                    633:
                    634:     DUMP_INSN(insn);
                    635:
                    636:     /* get the other operand which is always the source */
                    637:     if ((word1 & 0x4000) == 0) {
                    638: #if DEBUG_FPE
                    639:        printf("fpu_emul_arith: FP%d op FP%d => FP%d\n",
                    640:               format, regnum, regnum);
                    641:        printf("fpu_emul_arith: src opr FP%d=%08x,%08x,%08x\n",
                    642:               format, fpregs[format*3], fpregs[format*3+1],
                    643:               fpregs[format*3+2]);
                    644: #endif
                    645:        fpu_explode(fe, &fe->fe_f2, FTYPE_EXT, &fpregs[format * 3]);
                    646:     } else {
                    647:        /* the operand is in memory */
                    648:        if (format == FTYPE_DBL) {
                    649:            insn->is_datasize = 8;
                    650:        } else if (format == FTYPE_SNG || format == FTYPE_LNG) {
                    651:            insn->is_datasize = 4;
                    652:        } else if (format == FTYPE_WRD) {
                    653:            insn->is_datasize = 2;
                    654:        } else if (format == FTYPE_BYT) {
                    655:            insn->is_datasize = 1;
                    656:        } else if (format == FTYPE_EXT) {
                    657:            insn->is_datasize = 12;
                    658:        } else {
                    659:            /* invalid or unsupported operand format */
                    660:            *typ = ILL_ILLOPN;
                    661:            sig = SIGILL;
                    662:            return sig;
                    663:        }
                    664:
                    665:        /* Get effective address. (modreg=opcode&077) */
                    666:        sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode, typ);
                    667:        if (sig) {
                    668: #if DEBUG_FPE
                    669:            printf("fpu_emul_arith: error in fpu_decode_ea\n");
                    670: #endif
                    671:            return sig;
                    672:        }
                    673:
                    674:        DUMP_INSN(insn);
                    675:
                    676: #if DEBUG_FPE
                    677:        printf("fpu_emul_arith: addr mode = ");
                    678:        flags = insn->is_ea.ea_flags;
                    679:        regname = (insn->is_ea.ea_regnum & 8) ? 'a' : 'd';
                    680:
                    681:        if (flags & EA_DIRECT) {
                    682:            printf("%c%d\n",
                    683:                   regname, insn->is_ea.ea_regnum & 7);
                    684:        } else if (flags & EA_PC_REL) {
                    685:            if (flags & EA_OFFSET) {
                    686:                printf("pc@(%d)\n", insn->is_ea.ea_offset);
                    687:            } else if (flags & EA_INDEXED) {
                    688:                printf("pc@(...)\n");
                    689:            }
                    690:        } else if (flags & EA_PREDECR) {
                    691:            printf("%c%d@-\n",
                    692:                   regname, insn->is_ea.ea_regnum & 7);
                    693:        } else if (flags & EA_POSTINCR) {
                    694:            printf("%c%d@+\n", regname, insn->is_ea.ea_regnum & 7);
                    695:        } else if (flags & EA_OFFSET) {
                    696:            printf("%c%d@(%d)\n", regname, insn->is_ea.ea_regnum & 7,
                    697:                   insn->is_ea.ea_offset);
                    698:        } else if (flags & EA_INDEXED) {
                    699:            printf("%c%d@(...)\n", regname, insn->is_ea.ea_regnum & 7);
                    700:        } else if (flags & EA_ABS) {
                    701:            printf("0x%08x\n", insn->is_ea.ea_absaddr);
                    702:        } else if (flags & EA_IMMED) {
                    703:
                    704:            printf("#0x%08x,%08x,%08x\n", insn->is_ea.ea_immed[0],
                    705:                   insn->is_ea.ea_immed[1], insn->is_ea.ea_immed[2]);
                    706:        } else {
                    707:            printf("%c%d@\n", regname, insn->is_ea.ea_regnum & 7);
                    708:        }
                    709: #endif /* DEBUG_FPE */
                    710:
                    711:        fpu_load_ea(frame, insn, &insn->is_ea, (char *)buf, typ);
                    712:        if (format == FTYPE_WRD) {
                    713:            /* sign-extend */
                    714:            buf[0] &= 0xffff;
                    715:            if (buf[0] & 0x8000) {
                    716:                buf[0] |= 0xffff0000;
                    717:            }
                    718:            format = FTYPE_LNG;
                    719:        } else if (format == FTYPE_BYT) {
                    720:            /* sign-extend */
                    721:            buf[0] &= 0xff;
                    722:            if (buf[0] & 0x80) {
                    723:                buf[0] |= 0xffffff00;
                    724:            }
                    725:            format = FTYPE_LNG;
                    726:        }
                    727: #if DEBUG_FPE
                    728:        printf("fpu_emul_arith: src = %08x %08x %08x, siz = %d\n",
                    729:               buf[0], buf[1], buf[2], insn->is_datasize);
                    730: #endif
                    731:        fpu_explode(fe, &fe->fe_f2, format, buf);
                    732:     }
                    733:
                    734:     DUMP_INSN(insn);
                    735:
                    736:     /* An arithmetic instruction emulate function has a prototype of
                    737:      * struct fpn *fpu_op(struct fpemu *);
                    738:
                    739:      * 1) If the instruction is monadic, then fpu_op() must use
                    740:      * fe->fe_f2 as its operand, and return a pointer to the
                    741:      * result.
                    742:
                    743:      * 2) If the instruction is diadic, then fpu_op() must use
                    744:      * fe->fe_f1 and fe->fe_f2 as its two operands, and return a
                    745:      * pointer to the result.
                    746:
                    747:      */
                    748:     res = 0;
                    749:     switch (word1 & 0x3f) {
                    750:     case 0x00:                 /* fmove */
                    751:        res = &fe->fe_f2;
                    752:        break;
                    753:
                    754:     case 0x01:                 /* fint */
                    755:        res = fpu_int(fe);
                    756:        break;
                    757:
                    758:     case 0x03:                 /* fintrz */
                    759:        res = fpu_intrz(fe);
                    760:        break;
                    761:
                    762:     case 0x04:                 /* fsqrt */
                    763:        res = fpu_sqrt(fe);
                    764:        break;
                    765:
                    766:     case 0x06:                 /* flognp1 */
                    767:        res = fpu_lognp1(fe);
                    768:        break;
                    769:
                    770:     case 0x14:                 /* flogn */
                    771:        res = fpu_logn(fe);
                    772:        break;
                    773:
                    774:     case 0x15:                 /* flog10 */
                    775:        res = fpu_log10(fe);
                    776:        break;
                    777:
                    778:     case 0x16:                 /* flog2 */
                    779:        res = fpu_log2(fe);
                    780:        break;
                    781:
                    782:     case 0x18:                 /* fabs */
                    783:        fe->fe_f2.fp_sign = 0;
                    784:        res = &fe->fe_f2;
                    785:        break;
                    786:
                    787:     case 0x1A:                 /* fneg */
                    788:        fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign;
                    789:        res = &fe->fe_f2;
                    790:        break;
                    791:
                    792:     case 0x1E:                 /* fgetexp */
                    793:        res = fpu_getexp(fe);
                    794:        break;
                    795:
                    796:     case 0x1F:                 /* fgetman */
                    797:        res = fpu_getman(fe);
                    798:        break;
                    799:
                    800:     case 0x20:                 /* fdiv */
                    801:     case 0x24:                 /* fsgldiv: cheating - better than nothing */
                    802:        res = fpu_div(fe);
                    803:        break;
                    804:
                    805:     case 0x21:                 /* fmod */
                    806:        res = fpu_mod(fe);
                    807:        break;
                    808:
                    809:     case 0x28:                 /* fsub */
                    810:        fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */
                    811:     case 0x22:                 /* fadd */
                    812:        res = fpu_add(fe);
                    813:        break;
                    814:
                    815:     case 0x23:                 /* fmul */
                    816:     case 0x27:                 /* fsglmul: cheating - better than nothing */
                    817:        res = fpu_mul(fe);
                    818:        break;
                    819:
                    820:     case 0x25:                 /* frem */
                    821:        res = fpu_rem(fe);
                    822:        break;
                    823:
                    824:     case 0x26:
                    825:        /* fscale is handled by a separate function */
                    826:        break;
                    827:
                    828:     case 0x38:                 /* fcmp */
                    829:        res = fpu_cmp(fe);
                    830:        discard_result = 1;
                    831:        break;
                    832:
                    833:     case 0x3A:                 /* ftst */
                    834:        res = &fe->fe_f2;
                    835:        discard_result = 1;
                    836:        break;
                    837:
                    838:     case 0x02:                 /* fsinh */
                    839:     case 0x08:                 /* fetoxm1 */
                    840:     case 0x09:                 /* ftanh */
                    841:     case 0x0A:                 /* fatan */
                    842:     case 0x0C:                 /* fasin */
                    843:     case 0x0D:                 /* fatanh */
                    844:     case 0x0E:                 /* fsin */
                    845:     case 0x0F:                 /* ftan */
                    846:     case 0x10:                 /* fetox */
                    847:     case 0x11:                 /* ftwotox */
                    848:     case 0x12:                 /* ftentox */
                    849:     case 0x19:                 /* fcosh */
                    850:     case 0x1C:                 /* facos */
                    851:     case 0x1D:                 /* fcos */
                    852:     case 0x30:                 /* fsincos */
                    853:     case 0x31:                 /* fsincos */
                    854:     case 0x32:                 /* fsincos */
                    855:     case 0x33:                 /* fsincos */
                    856:     case 0x34:                 /* fsincos */
                    857:     case 0x35:                 /* fsincos */
                    858:     case 0x36:                 /* fsincos */
                    859:     case 0x37:                 /* fsincos */
                    860:     default:
                    861: #ifdef DEBUG
                    862:        printf("fpu_emul_arith: bad opcode=0x%x, word1=0x%x\n",
                    863:               insn->is_opcode, insn->is_word1);
                    864: #endif
                    865:        sig = SIGILL;
                    866:     } /* switch (word1 & 0x3f) */
                    867:
                    868:     if (!discard_result && sig == 0) {
                    869:        fpu_implode(fe, res, FTYPE_EXT, &fpregs[regnum * 3]);
                    870: #if DEBUG_FPE
                    871:        printf("fpu_emul_arith: %08x,%08x,%08x stored in FP%d\n",
                    872:               fpregs[regnum*3], fpregs[regnum*3+1],
                    873:               fpregs[regnum*3+2], regnum);
                    874:     } else if (sig == 0) {
                    875:        static char *class_name[] = { "SNAN", "QNAN", "ZERO", "NUM", "INF" };
                    876:        printf("fpu_emul_arith: result(%s,%c,%d,%08x,%08x,%08x) discarded\n",
                    877:               class_name[res->fp_class + 2],
                    878:               res->fp_sign ? '-' : '+', res->fp_exp,
                    879:               res->fp_mant[0], res->fp_mant[1],
                    880:               res->fp_mant[2]);
                    881:     } else {
                    882:        printf("fpu_emul_arith: received signal %d\n", sig);
                    883: #endif
                    884:     }
                    885:
                    886:     /* update fpsr according to the result of operation */
                    887:     fpu_upd_fpsr(fe, res);
                    888:
                    889: #if DEBUG_FPE
                    890:     printf("fpu_emul_arith: FPSR = %08x, FPCR = %08x\n",
                    891:           fe->fe_fpsr, fe->fe_fpcr);
                    892: #endif
                    893:
                    894:     DUMP_INSN(insn);
                    895:
                    896:     return sig;
                    897: }
                    898:
                    899: /* test condition code according to the predicate in the opcode.
                    900:  * returns -1 when the predicate evaluates to true, 0 when false.
                    901:  * signal numbers are returned when an error is detected.
                    902:  */
                    903: int
                    904: test_cc(fe, pred)
                    905:      struct fpemu *fe;
                    906:      int pred;
                    907: {
                    908:     int result, sig_bsun, invert;
                    909:     int fpsr;
                    910:
                    911:     fpsr = fe->fe_fpsr;
                    912:     invert = 0;
                    913:     fpsr &= ~FPSR_EXCP;                /* clear all exceptions */
                    914: #if DEBUG_FPE
                    915:     printf("test_cc: fpsr=0x%08x\n", fpsr);
                    916: #endif
                    917:     pred &= 0x3f;              /* lowest 6 bits */
                    918:
                    919: #if DEBUG_FPE
                    920:     printf("test_cc: ");
                    921: #endif
                    922:
                    923:     if (pred >= 0x20) {
                    924:        return SIGILL;
                    925:     } else if (pred & 0x10) {
                    926:        /* IEEE nonaware tests */
                    927:        sig_bsun = 1;
                    928:        pred &= 0x0f;           /* lower 4 bits */
                    929:     } else {
                    930:        /* IEEE aware tests */
                    931: #if DEBUG_FPE
                    932:        printf("IEEE ");
                    933: #endif
                    934:        sig_bsun = 0;
                    935:     }
                    936:
                    937:     if (pred & 0x08) {
                    938: #if DEBUG_FPE
                    939:        printf("Not ");
                    940: #endif
                    941:        /* predicate is "NOT ..." */
                    942:        pred ^= 0xf;            /* invert */
                    943:        invert = -1;
                    944:     }
                    945:     switch (pred) {
                    946:     case 0:                    /* (Signaling) False */
                    947: #if DEBUG_FPE
                    948:        printf("False");
                    949: #endif
                    950:        result = 0;
                    951:        break;
                    952:     case 1:                    /* (Signaling) Equal */
                    953: #if DEBUG_FPE
                    954:        printf("Equal");
                    955: #endif
                    956:        result = -((fpsr & FPSR_ZERO) == FPSR_ZERO);
                    957:        break;
                    958:     case 2:                    /* Greater Than */
                    959: #if DEBUG_FPE
                    960:        printf("GT");
                    961: #endif
                    962:        result = -((fpsr & (FPSR_NAN|FPSR_ZERO|FPSR_NEG)) == 0);
                    963:        break;
                    964:     case 3:                    /* Greater or Equal */
                    965: #if DEBUG_FPE
                    966:        printf("GE");
                    967: #endif
                    968:        result = -((fpsr & FPSR_ZERO) ||
                    969:                   (fpsr & (FPSR_NAN|FPSR_NEG)) == 0);
                    970:        break;
                    971:     case 4:                    /* Less Than */
                    972: #if DEBUG_FPE
                    973:        printf("LT");
                    974: #endif
                    975:        result = -((fpsr & (FPSR_NAN|FPSR_ZERO|FPSR_NEG)) == FPSR_NEG);
                    976:        break;
                    977:     case 5:                    /* Less or Equal */
                    978: #if DEBUG_FPE
                    979:        printf("LE");
                    980: #endif
                    981:        result = -((fpsr & FPSR_ZERO) ||
                    982:                   ((fpsr & (FPSR_NAN|FPSR_NEG)) == FPSR_NEG));
                    983:        break;
                    984:     case 6:                    /* Greater or Less than */
                    985: #if DEBUG_FPE
                    986:        printf("GLT");
                    987: #endif
                    988:        result = -((fpsr & (FPSR_NAN|FPSR_ZERO)) == 0);
                    989:        break;
                    990:     case 7:                    /* Greater, Less or Equal */
                    991: #if DEBUG_FPE
                    992:        printf("GLE");
                    993: #endif
                    994:        result = -((fpsr & FPSR_NAN) == 0);
                    995:        break;
                    996:     default:
                    997:        /* invalid predicate */
                    998:        return SIGILL;
                    999:     }
                   1000:     result ^= invert;          /* if the predicate is "NOT ...", then
                   1001:                                   invert the result */
                   1002: #if DEBUG_FPE
                   1003:     printf("=> %s (%d)\n", result ? "true" : "false", result);
                   1004: #endif
                   1005:     /* if it's an IEEE unaware test and NAN is set, BSUN is set */
                   1006:     if (sig_bsun && (fpsr & FPSR_NAN)) {
                   1007:        fpsr |= FPSR_BSUN;
                   1008:     }
                   1009:
                   1010:     /* put fpsr back */
                   1011:     fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr;
                   1012:
                   1013:     return result;
                   1014: }
                   1015:
                   1016: /*
                   1017:  * type 1: fdbcc, fscc, ftrapcc
                   1018:  * In this function, we know:
                   1019:  *   (opcode & 0x01C0) == 0x0040
                   1020:  */
                   1021: int
                   1022: fpu_emul_type1(struct fpemu *fe, struct instruction *insn, int *typ)
                   1023: {
                   1024:     struct frame *frame = fe->fe_frame;
                   1025:     int advance, sig, branch;
                   1026:     int16_t displ;
                   1027:
                   1028:     branch = test_cc(fe, insn->is_word1);
                   1029:     fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr;
                   1030:
                   1031:     insn->is_advance = 4;
                   1032:     sig = 0;
                   1033:
                   1034:     switch (insn->is_opcode & 070) {
                   1035:     case 010:                  /* fdbcc */
                   1036:        if (branch == -1) {
                   1037:            /* advance */
                   1038:            insn->is_advance = 6;
                   1039:        } else if (!branch) {
                   1040:            /* decrement Dn and if (Dn != -1) branch */
                   1041:            u_int16_t count = frame->f_regs[insn->is_opcode & 7];
                   1042:
                   1043:            if (count-- != 0) {
                   1044:                if (copyin((void *)(insn->is_pc + insn->is_advance), &displ,
                   1045:                    sizeof(displ)) != 0) {
                   1046: #ifdef DEBUG
                   1047:                    printf("fpu_emul_type1: fault reading displacement\n");
                   1048: #endif
                   1049:                    return SIGSEGV;
                   1050:                }
                   1051:                insn->is_advance += (int)displ;
                   1052:                /* XXX insn->is_nextpc = insn->is_pc + insn->is_advance; */
                   1053:            } else {
                   1054:                insn->is_advance = 6;
                   1055:            }
                   1056:            /* write it back */
                   1057:            frame->f_regs[insn->is_opcode & 7] &= 0xffff0000;
                   1058:            frame->f_regs[insn->is_opcode & 7] |= (u_int32_t)count;
                   1059:        } else {                /* got a signal */
                   1060:            sig = SIGFPE;
                   1061:        }
                   1062:        break;
                   1063:
                   1064:     case 070:                  /* ftrapcc or fscc */
                   1065:        advance = 4;
                   1066:        if ((insn->is_opcode & 07) >= 2) {
                   1067:            switch (insn->is_opcode & 07) {
                   1068:            case 3:             /* long opr */
                   1069:                advance += 2;
                   1070:            case 2:             /* word opr */
                   1071:                advance += 2;
                   1072:            case 4:             /* no opr */
                   1073:                break;
                   1074:            default:
                   1075:                return SIGILL;
                   1076:                break;
                   1077:            }
                   1078:
                   1079:            if (branch == 0) {
                   1080:                /* no trap */
                   1081:                insn->is_advance = advance;
                   1082:                sig = 0;
                   1083:            } else {
                   1084:                /* trap */
                   1085:                sig = SIGILL;
                   1086:                *typ = ILL_ILLTRP;
                   1087:            }
                   1088:            break;
                   1089:        } /* if ((insn->is_opcode & 7) < 2), fall through to FScc */
                   1090:
                   1091:     default:                   /* fscc */
                   1092:        insn->is_advance = 4;
                   1093:        insn->is_datasize = 1;  /* always byte */
                   1094:        sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode, typ);
                   1095:        if (sig) {
                   1096:            break;
                   1097:        }
                   1098:        if (branch == -1 || branch == 0) {
                   1099:            /* set result */
                   1100:            sig = fpu_store_ea(frame, insn, &insn->is_ea, (char *)&branch);
                   1101:        } else {
                   1102:            /* got an exception */
                   1103:            sig = branch;
                   1104:        }
                   1105:        break;
                   1106:     }
                   1107:     return sig;
                   1108: }
                   1109:
                   1110: /*
                   1111:  * Type 2 or 3: fbcc (also fnop)
                   1112:  * In this function, we know:
                   1113:  *   (opcode & 0x0180) == 0x0080
                   1114:  */
                   1115: int
                   1116: fpu_emul_brcc(fe, insn)
                   1117:      struct fpemu *fe;
                   1118:      struct instruction *insn;
                   1119: {
                   1120:     int displ;
                   1121:     int sig;
                   1122:     u_int16_t word2;
                   1123:
                   1124:     /*
                   1125:      * Get branch displacement.
                   1126:      */
                   1127:     insn->is_advance = 4;
                   1128:     displ = insn->is_word1;
                   1129:
                   1130:     if (insn->is_opcode & 0x40) {
                   1131:        if (copyin((void *)(insn->is_pc + insn->is_advance), &word2,
                   1132:            sizeof(word2)) != 0) {
                   1133: #ifdef DEBUG
                   1134:            printf("fpu_emul_brcc: fault reading word2\n");
                   1135: #endif
                   1136:            return SIGSEGV;
                   1137:        }
                   1138:        displ <<= 16;
                   1139:        displ |= word2;
                   1140:        insn->is_advance += 2;
                   1141:     } else /* displacement is word sized */
                   1142:         if (displ & 0x8000)
                   1143:            displ |= 0xFFFF0000;
                   1144:
                   1145:     /* XXX: If CC, insn->is_pc += displ */
                   1146:     sig = test_cc(fe, insn->is_opcode);
                   1147:     fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr;
                   1148:
                   1149:     if (fe->fe_fpsr & fe->fe_fpcr & FPSR_EXCP) {
                   1150:        return SIGFPE;          /* caught an exception */
                   1151:     }
                   1152:     if (sig == -1) {
                   1153:        /* branch does take place; 2 is the offset to the 1st disp word */
                   1154:        insn->is_advance = displ + 2;
                   1155:        /* XXX insn->is_nextpc = insn->is_pc + insn->is_advance; */
                   1156:     } else if (sig) {
                   1157:        return SIGILL;          /* got a signal */
                   1158:     }
                   1159: #if DEBUG_FPE
                   1160:     printf("fpu_emul_brcc: %s insn @ %x (%x+%x) (disp=%x)\n",
                   1161:           (sig == -1) ? "BRANCH to" : "NEXT",
                   1162:           insn->is_pc + insn->is_advance, insn->is_pc, insn->is_advance,
                   1163:           displ);
                   1164: #endif
                   1165:     return 0;
                   1166: }

CVSweb