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

Annotation of sys/arch/m68k/fpe/fpu_calcea.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: fpu_calcea.c,v 1.11 2006/01/30 21:23:22 miod Exp $    */
        !             2: /*     $NetBSD: fpu_calcea.c,v 1.16 2004/02/13 11:36:14 wiz Exp $      */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Gordon W. Ross
        !             6:  * 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: #include <sys/param.h>
        !            36: #include <sys/signal.h>
        !            37: #include <sys/systm.h>
        !            38: #include <machine/frame.h>
        !            39:
        !            40: #include "fpu_emulate.h"
        !            41:
        !            42: /*
        !            43:  * Prototypes of local functions
        !            44:  */
        !            45: int decode_ea6(struct frame *frame, struct instruction *insn,
        !            46:                           struct insn_ea *ea, int modreg, int *typ);
        !            47: int fetch_immed(struct frame *frame, struct instruction *insn,
        !            48:                            int *dst);
        !            49: int fetch_disp(struct frame *frame, struct instruction *insn,
        !            50:                           int size, int *res);
        !            51: int calc_ea(struct insn_ea *ea, char *ptr, char **eaddr);
        !            52:
        !            53: /*
        !            54:  * Helper routines for dealing with "effective address" values.
        !            55:  */
        !            56:
        !            57: /*
        !            58:  * Decode an effective address into internal form.
        !            59:  * Returns zero on success, else signal number.
        !            60:  */
        !            61: int
        !            62: fpu_decode_ea(struct frame *frame, struct instruction *insn, struct insn_ea *ea,
        !            63:     int modreg, int *typ)
        !            64: {
        !            65:     int sig;
        !            66:
        !            67: #ifdef DEBUG
        !            68:     if (insn->is_datasize < 0) {
        !            69:        panic("decode_ea: called with uninitialized datasize");
        !            70:     }
        !            71: #endif
        !            72:
        !            73:     sig = 0;
        !            74:
        !            75:     /* Set the most common value here. */
        !            76:     ea->ea_regnum = 8 + (modreg & 7);
        !            77:
        !            78:     if ((modreg & 060) == 0) {
        !            79:        /* register direct */
        !            80:        ea->ea_regnum = modreg & 0xf;
        !            81:        ea->ea_flags = EA_DIRECT;
        !            82: #ifdef DEBUG_FPE
        !            83:        printf("decode_ea: register direct reg=%d\n", ea->ea_regnum);
        !            84: #endif
        !            85:     } else if ((modreg & 077) == 074) {
        !            86:        /* immediate */
        !            87:        ea->ea_flags = EA_IMMED;
        !            88:        sig = fetch_immed(frame, insn, &ea->ea_immed[0]);
        !            89: #ifdef DEBUG_FPE
        !            90:        printf("decode_ea: immediate size=%d\n", insn->is_datasize);
        !            91: #endif
        !            92:     }
        !            93:     /*
        !            94:      * rest of the address modes need to be separately
        !            95:      * handled for the LC040 and the others.
        !            96:      */
        !            97: #if 0 /* XXX */
        !            98:     else if (frame->f_format == 4 && frame->f_fmt4.f_fa) {
        !            99:        /* LC040 */
        !           100:        ea->ea_flags = EA_FRAME_EA;
        !           101:        ea->ea_fea = frame->f_fmt4.f_fa;
        !           102: #ifdef DEBUG_FPE
        !           103:        printf("decode_ea: 68LC040 - in-frame EA (%p) size %d\n",
        !           104:                (void *)ea->ea_fea, insn->is_datasize);
        !           105: #endif
        !           106:        if ((modreg & 070) == 030) {
        !           107:            /* postincrement mode */
        !           108:            ea->ea_flags |= EA_POSTINCR;
        !           109:        } else if ((modreg & 070) == 040) {
        !           110:            /* predecrement mode */
        !           111:            ea->ea_flags |= EA_PREDECR;
        !           112: #ifdef M68060
        !           113: #if defined(M68020) || defined(M68030) || defined(M68040)
        !           114:            if (cputype == CPU_68060)
        !           115: #endif
        !           116:                if (insn->is_datasize == 12)
        !           117:                        ea->ea_fea -= 8;
        !           118: #endif
        !           119:        }
        !           120:     }
        !           121: #endif /* XXX */
        !           122:     else {
        !           123:        /* 020/030 */
        !           124:        switch (modreg & 070) {
        !           125:
        !           126:        case 020:                       /* (An) */
        !           127:            ea->ea_flags = 0;
        !           128: #ifdef DEBUG_FPE
        !           129:            printf("decode_ea: register indirect reg=%d\n", ea->ea_regnum);
        !           130: #endif
        !           131:            break;
        !           132:
        !           133:        case 030:                       /* (An)+ */
        !           134:            ea->ea_flags = EA_POSTINCR;
        !           135: #ifdef DEBUG_FPE
        !           136:            printf("decode_ea: reg indirect postincrement reg=%d\n",
        !           137:                   ea->ea_regnum);
        !           138: #endif
        !           139:            break;
        !           140:
        !           141:        case 040:                       /* -(An) */
        !           142:            ea->ea_flags = EA_PREDECR;
        !           143: #ifdef DEBUG_FPE
        !           144:            printf("decode_ea: reg indirect predecrement reg=%d\n",
        !           145:                   ea->ea_regnum);
        !           146: #endif
        !           147:            break;
        !           148:
        !           149:        case 050:                       /* (d16,An) */
        !           150:            ea->ea_flags = EA_OFFSET;
        !           151:            sig = fetch_disp(frame, insn, 1, &ea->ea_offset);
        !           152: #ifdef DEBUG_FPE
        !           153:            printf("decode_ea: reg indirect with displacement reg=%d\n",
        !           154:                   ea->ea_regnum);
        !           155: #endif
        !           156:            break;
        !           157:
        !           158:        case 060:                       /* (d8,An,Xn) */
        !           159:            ea->ea_flags = EA_INDEXED;
        !           160:            sig = decode_ea6(frame, insn, ea, modreg, typ);
        !           161:            break;
        !           162:
        !           163:        case 070:                       /* misc. */
        !           164:            ea->ea_regnum = (modreg & 7);
        !           165:            switch (modreg & 7) {
        !           166:
        !           167:            case 0:                     /* (xxxx).W */
        !           168:                ea->ea_flags = EA_ABS;
        !           169:                sig = fetch_disp(frame, insn, 1, &ea->ea_absaddr);
        !           170: #ifdef DEBUG_FPE
        !           171:                printf("decode_ea: absolute address (word)\n");
        !           172: #endif
        !           173:                break;
        !           174:
        !           175:            case 1:                     /* (xxxxxxxx).L */
        !           176:                ea->ea_flags = EA_ABS;
        !           177:                sig = fetch_disp(frame, insn, 2, &ea->ea_absaddr);
        !           178: #ifdef DEBUG_FPE
        !           179:                printf("decode_ea: absolute address (long)\n");
        !           180: #endif
        !           181:                break;
        !           182:
        !           183:            case 2:                     /* (d16,PC) */
        !           184:                ea->ea_flags = EA_PC_REL | EA_OFFSET;
        !           185:                sig = fetch_disp(frame, insn, 1, &ea->ea_absaddr);
        !           186: #ifdef DEBUG_FPE
        !           187:                printf("decode_ea: pc relative word displacement\n");
        !           188: #endif
        !           189:                break;
        !           190:
        !           191:            case 3:                     /* (d8,PC,Xn) */
        !           192:                ea->ea_flags = EA_PC_REL | EA_INDEXED;
        !           193:                sig = decode_ea6(frame, insn, ea, modreg, typ);
        !           194:                break;
        !           195:
        !           196:            case 4:                     /* #data */
        !           197:                /* it should have been taken care of earlier */
        !           198:            default:
        !           199: #ifdef DEBUG_FPE
        !           200:                printf("decode_ea: invalid addr mode (7,%d)\n", modreg & 7);
        !           201: #endif
        !           202:                *typ = ILL_ILLADR;
        !           203:                return SIGILL;
        !           204:            } /* switch for mode 7 */
        !           205:            break;
        !           206:        } /* switch mode */
        !           207:     }
        !           208:     ea->ea_moffs = 0;
        !           209:
        !           210:     return sig;
        !           211: }
        !           212:
        !           213: /*
        !           214:  * Decode Mode=6 address modes
        !           215:  */
        !           216: int
        !           217: decode_ea6(struct frame *frame, struct instruction *insn, struct insn_ea *ea,
        !           218:     int modreg, int *typ)
        !           219: {
        !           220:     int idx;
        !           221:     int basedisp, outerdisp;
        !           222:     int bd_size, od_size;
        !           223:     int sig;
        !           224:     u_int16_t extword;
        !           225:
        !           226:     if (copyin((void *)(insn->is_pc + insn->is_advance), &extword,
        !           227:        sizeof(extword)) != 0) {
        !           228:        return SIGSEGV;
        !           229:     }
        !           230:     insn->is_advance += 2;
        !           231:
        !           232:     /* get register index */
        !           233:     ea->ea_idxreg = (extword >> 12) & 0xf;
        !           234:     idx = frame->f_regs[ea->ea_idxreg];
        !           235:     if ((extword & 0x0800) == 0) {
        !           236:        /* if word sized index, sign-extend */
        !           237:        idx &= 0xffff;
        !           238:        if (idx & 0x8000) {
        !           239:            idx |= 0xffff0000;
        !           240:        }
        !           241:     }
        !           242:     /* scale register index */
        !           243:     idx <<= ((extword >> 9) & 3);
        !           244:
        !           245:     if ((extword & 0x100) == 0) {
        !           246:        /* brief extension word - sign-extend the displacement */
        !           247:        basedisp = (extword & 0xff);
        !           248:        if (basedisp & 0x80) {
        !           249:            basedisp |= 0xffffff00;
        !           250:        }
        !           251:
        !           252:        ea->ea_basedisp = idx + basedisp;
        !           253:        ea->ea_outerdisp = 0;
        !           254: #if DEBUG_FPE
        !           255:        printf("decode_ea6: brief ext word idxreg=%d, basedisp=%08x\n",
        !           256:               ea->ea_idxreg, ea->ea_basedisp);
        !           257: #endif
        !           258:     } else {
        !           259:        /* full extension word */
        !           260:        if (extword & 0x80) {
        !           261:            ea->ea_flags |= EA_BASE_SUPPRSS;
        !           262:        }
        !           263:        bd_size = ((extword >> 4) & 3) - 1;
        !           264:        od_size = (extword & 3) - 1;
        !           265:        sig = fetch_disp(frame, insn, bd_size, &basedisp);
        !           266:        if (sig) {
        !           267:            return sig;
        !           268:        }
        !           269:        if (od_size >= 0) {
        !           270:            ea->ea_flags |= EA_MEM_INDIR;
        !           271:        }
        !           272:        sig = fetch_disp(frame, insn, od_size, &outerdisp);
        !           273:        if (sig) {
        !           274:            return sig;
        !           275:        }
        !           276:
        !           277:        switch (extword & 0x44) {
        !           278:        case 0:                 /* preindexed */
        !           279:            ea->ea_basedisp = basedisp + idx;
        !           280:            ea->ea_outerdisp = outerdisp;
        !           281:            break;
        !           282:        case 4:                 /* postindexed */
        !           283:            ea->ea_basedisp = basedisp;
        !           284:            ea->ea_outerdisp = outerdisp + idx;
        !           285:            break;
        !           286:        case 0x40:              /* no index */
        !           287:            ea->ea_basedisp = basedisp;
        !           288:            ea->ea_outerdisp = outerdisp;
        !           289:            break;
        !           290:        default:
        !           291: #ifdef DEBUG
        !           292:            printf("decode_ea6: invalid indirect mode: ext word %02x\n",
        !           293:                   extword);
        !           294: #endif
        !           295:            *typ = ILL_ILLADR;
        !           296:            return SIGILL;
        !           297:            break;
        !           298:        }
        !           299: #if DEBUG_FPE
        !           300:        printf("decode_ea6: full ext idxreg=%d, basedisp=%x, outerdisp=%x\n",
        !           301:               ea->ea_idxreg, ea->ea_basedisp, ea->ea_outerdisp);
        !           302: #endif
        !           303:     }
        !           304: #if DEBUG_FPE
        !           305:     printf("decode_ea6: regnum=%d, flags=%x\n",
        !           306:           ea->ea_regnum, ea->ea_flags);
        !           307: #endif
        !           308:     return 0;
        !           309: }
        !           310:
        !           311: /*
        !           312:  * Load a value from an effective address.
        !           313:  * Returns zero on success, else signal number.
        !           314:  */
        !           315: int
        !           316: fpu_load_ea(struct frame *frame, struct instruction *insn, struct insn_ea *ea,
        !           317:     char *dst, int *typ)
        !           318: {
        !           319:     int *reg;
        !           320:     char *src;
        !           321:     int len, step;
        !           322:     int sig;
        !           323:
        !           324: #ifdef DIAGNOSTIC
        !           325:     if (ea->ea_regnum & ~0xF) {
        !           326:        panic("load_ea: bad regnum");
        !           327:     }
        !           328: #endif
        !           329:
        !           330: #ifdef DEBUG_FPE
        !           331:     printf("load_ea: frame at %p\n", frame);
        !           332: #endif
        !           333:     /* dst is always int or larger. */
        !           334:     len = insn->is_datasize;
        !           335:     if (len < 4) {
        !           336:        dst += (4 - len);
        !           337:     }
        !           338:     step = (len == 1 && ea->ea_regnum == 15 /* sp */) ? 2 : len;
        !           339:
        !           340: #if 0
        !           341:     if (ea->ea_flags & EA_FRAME_EA) {
        !           342:        /* Using LC040 frame EA */
        !           343: #ifdef DEBUG_FPE
        !           344:        if (ea->ea_flags & (EA_PREDECR|EA_POSTINCR)) {
        !           345:            printf("load_ea: frame ea %08x w/r%d\n",
        !           346:                   ea->ea_fea, ea->ea_regnum);
        !           347:        } else {
        !           348:            printf("load_ea: frame ea %08x\n", ea->ea_fea);
        !           349:        }
        !           350: #endif
        !           351:        src = (char *)ea->ea_fea;
        !           352:        if (copyin(src + ea->ea_moffs, dst, len) != 0)
        !           353:            return (SIGSEGV);
        !           354:        if (ea->ea_flags & EA_PREDECR) {
        !           355:            frame->f_regs[ea->ea_regnum] = ea->ea_fea;
        !           356:            ea->ea_fea -= step;
        !           357:            ea->ea_moffs = 0;
        !           358:        } else if (ea->ea_flags & EA_POSTINCR) {
        !           359:            ea->ea_fea += step;
        !           360:            frame->f_regs[ea->ea_regnum] = ea->ea_fea;
        !           361:            ea->ea_moffs = 0;
        !           362:        } else {
        !           363:            ea->ea_moffs += step;
        !           364:        }
        !           365:        /* That's it, folks */
        !           366:     } else if (ea->ea_flags & EA_DIRECT) {
        !           367:        if (len > 4) {
        !           368: #ifdef DEBUG
        !           369:            printf("load_ea: operand doesn't fit CPU reg\n");
        !           370: #endif
        !           371:            return SIGILL;
        !           372:        }
        !           373:        if (ea->ea_moffs > 0) {
        !           374: #ifdef DEBUG
        !           375:            printf("load_ea: more than one move from CPU reg\n");
        !           376: #endif
        !           377:            return SIGILL;
        !           378:        }
        !           379:        src = (char *)&frame->f_regs[ea->ea_regnum];
        !           380:        /* The source is an int. */
        !           381:        if (len < 4) {
        !           382:            src += (4 - len);
        !           383: #ifdef DEBUG_FPE
        !           384:            printf("load_ea: short/byte opr - addr adjusted\n");
        !           385: #endif
        !           386:        }
        !           387: #ifdef DEBUG_FPE
        !           388:        printf("load_ea: src %p\n", src);
        !           389: #endif
        !           390:        memcpy(dst, src, len);
        !           391:     } else
        !           392: #endif /* 0 */
        !           393:     if (ea->ea_flags & EA_IMMED) {
        !           394: #ifdef DEBUG_FPE
        !           395:        printf("load_ea: immed %08x%08x%08x size %d\n",
        !           396:               ea->ea_immed[0], ea->ea_immed[1], ea->ea_immed[2], len);
        !           397: #endif
        !           398:        src = (char *)&ea->ea_immed[0];
        !           399:        if (len < 4) {
        !           400:            src += (4 - len);
        !           401: #ifdef DEBUG_FPE
        !           402:            printf("load_ea: short/byte immed opr - addr adjusted\n");
        !           403: #endif
        !           404:        }
        !           405:        memcpy(dst, src, len);
        !           406:     } else if (ea->ea_flags & EA_ABS) {
        !           407: #ifdef DEBUG_FPE
        !           408:        printf("load_ea: abs addr %08x\n", ea->ea_absaddr);
        !           409: #endif
        !           410:        src = (char *)ea->ea_absaddr;
        !           411:        if (copyin(src, dst, len) != 0)
        !           412:            return (SIGSEGV);
        !           413:     } else /* register indirect */ {
        !           414:        if (ea->ea_flags & EA_PC_REL) {
        !           415: #ifdef DEBUG_FPE
        !           416:            printf("load_ea: using PC\n");
        !           417: #endif
        !           418:            reg = NULL;
        !           419:            /* Grab the register contents. 4 is offset to the first
        !           420:               extension word from the opcode */
        !           421:            src = (char *)insn->is_pc + 4;
        !           422: #ifdef DEBUG_FPE
        !           423:            printf("load_ea: pc relative pc+4 = %p\n", src);
        !           424: #endif
        !           425:        } else /* not PC relative */ {
        !           426: #ifdef DEBUG_FPE
        !           427:            printf("load_ea: using register %c%d\n",
        !           428:                   (ea->ea_regnum >= 8) ? 'a' : 'd', ea->ea_regnum & 7);
        !           429: #endif
        !           430:            /* point to the register */
        !           431:            reg = &frame->f_regs[ea->ea_regnum];
        !           432:
        !           433:            if (ea->ea_flags & EA_PREDECR) {
        !           434: #ifdef DEBUG_FPE
        !           435:                printf("load_ea: predecr mode - reg decremented\n");
        !           436: #endif
        !           437:                *reg -= step;
        !           438:                ea->ea_moffs = 0;
        !           439:            }
        !           440:
        !           441:            /* Grab the register contents. */
        !           442:            src = (char *)*reg;
        !           443: #ifdef DEBUG_FPE
        !           444:            printf("load_ea: reg indirect reg = %p\n", src);
        !           445: #endif
        !           446:        }
        !           447:
        !           448:        sig = calc_ea(ea, src, &src);
        !           449:        if (sig)
        !           450:            return sig;
        !           451:
        !           452:        if (copyin(src + ea->ea_moffs, dst, len) != 0)
        !           453:            return (SIGSEGV);
        !           454:
        !           455:        /* do post-increment */
        !           456:        if (ea->ea_flags & EA_POSTINCR) {
        !           457:            if (ea->ea_flags & EA_PC_REL) {
        !           458: #ifdef DEBUG
        !           459:                printf("load_ea: tried to postincrement PC\n");
        !           460: #endif
        !           461:                *typ = ILL_ILLADR;
        !           462:                return SIGILL;
        !           463:            }
        !           464:            *reg += step;
        !           465:            ea->ea_moffs = 0;
        !           466: #ifdef DEBUG_FPE
        !           467:            printf("load_ea: postinc mode - reg incremented\n");
        !           468: #endif
        !           469:        } else {
        !           470:            ea->ea_moffs += len;
        !           471:        }
        !           472:     }
        !           473:
        !           474:     return 0;
        !           475: }
        !           476:
        !           477: /*
        !           478:  * Store a value at the effective address.
        !           479:  * Returns zero on success, else signal number.
        !           480:  */
        !           481: int
        !           482: fpu_store_ea(frame, insn, ea, src)
        !           483:      struct frame *frame;
        !           484:      struct instruction *insn;
        !           485:      struct insn_ea *ea;
        !           486:      char *src;
        !           487: {
        !           488:     int *reg;
        !           489:     char *dst;
        !           490:     int len, step;
        !           491:     int sig;
        !           492:
        !           493: #ifdef DIAGNOSTIC
        !           494:     if (ea->ea_regnum & ~0xf) {
        !           495:        panic("store_ea: bad regnum");
        !           496:     }
        !           497: #endif
        !           498:
        !           499:     if (ea->ea_flags & (EA_IMMED|EA_PC_REL)) {
        !           500:        /* not alterable address mode */
        !           501: #ifdef DEBUG
        !           502:        printf("store_ea: not alterable address mode\n");
        !           503: #endif
        !           504:        return SIGILL;
        !           505:     }
        !           506:
        !           507:     /* src is always int or larger. */
        !           508:     len = insn->is_datasize;
        !           509:     if (len < 4) {
        !           510:        src += (4 - len);
        !           511:     }
        !           512:     step = (len == 1 && ea->ea_regnum == 15 /* sp */) ? 2 : len;
        !           513:
        !           514:     if (ea->ea_flags & EA_FRAME_EA) {
        !           515:        /* Using LC040 frame EA */
        !           516: #ifdef DEBUG_FPE
        !           517:        if (ea->ea_flags & (EA_PREDECR|EA_POSTINCR)) {
        !           518:            printf("store_ea: frame ea %08x w/r%d\n",
        !           519:                   ea->ea_fea, ea->ea_regnum);
        !           520:        } else {
        !           521:            printf("store_ea: frame ea %08x\n", ea->ea_fea);
        !           522:        }
        !           523: #endif
        !           524:        dst = (char *)ea->ea_fea;
        !           525:        copyout(src, dst + ea->ea_moffs, len);
        !           526:        if (ea->ea_flags & EA_PREDECR) {
        !           527:            frame->f_regs[ea->ea_regnum] = ea->ea_fea;
        !           528:            ea->ea_fea -= step;
        !           529:            ea->ea_moffs = 0;
        !           530:        } else if (ea->ea_flags & EA_POSTINCR) {
        !           531:            ea->ea_fea += step;
        !           532:            frame->f_regs[ea->ea_regnum] = ea->ea_fea;
        !           533:            ea->ea_moffs = 0;
        !           534:        } else {
        !           535:            ea->ea_moffs += step;
        !           536:        }
        !           537:        /* That's it, folks */
        !           538:     } else if (ea->ea_flags & EA_ABS) {
        !           539: #ifdef DEBUG_FPE
        !           540:        printf("store_ea: abs addr %08x\n", ea->ea_absaddr);
        !           541: #endif
        !           542:        dst = (char *)ea->ea_absaddr;
        !           543:        copyout(src, dst + ea->ea_moffs, len);
        !           544:        ea->ea_moffs += len;
        !           545:     } else if (ea->ea_flags & EA_DIRECT) {
        !           546:        if (len > 4) {
        !           547: #ifdef DEBUG
        !           548:            printf("store_ea: operand doesn't fit CPU reg\n");
        !           549: #endif
        !           550:            return SIGILL;
        !           551:        }
        !           552:        if (ea->ea_moffs > 0) {
        !           553: #ifdef DEBUG
        !           554:            printf("store_ea: more than one move to CPU reg\n");
        !           555: #endif
        !           556:            return SIGILL;
        !           557:        }
        !           558:        dst = (char *)&frame->f_regs[ea->ea_regnum];
        !           559:        /* The destination is an int. */
        !           560:        if (len < 4) {
        !           561:            dst += (4 - len);
        !           562: #ifdef DEBUG_FPE
        !           563:            printf("store_ea: short/byte opr - dst addr adjusted\n");
        !           564: #endif
        !           565:        }
        !           566: #ifdef DEBUG_FPE
        !           567:        printf("store_ea: dst %p\n", dst);
        !           568: #endif
        !           569:        memcpy(dst, src, len);
        !           570:     } else /* One of MANY indirect forms... */ {
        !           571: #ifdef DEBUG_FPE
        !           572:        printf("store_ea: using register %c%d\n",
        !           573:               (ea->ea_regnum >= 8) ? 'a' : 'd', ea->ea_regnum & 7);
        !           574: #endif
        !           575:        /* point to the register */
        !           576:        reg = &(frame->f_regs[ea->ea_regnum]);
        !           577:
        !           578:        /* do pre-decrement */
        !           579:        if (ea->ea_flags & EA_PREDECR) {
        !           580: #ifdef DEBUG_FPE
        !           581:            printf("store_ea: predecr mode - reg decremented\n");
        !           582: #endif
        !           583:            *reg -= step;
        !           584:            ea->ea_moffs = 0;
        !           585:        }
        !           586:
        !           587:        /* calculate the effective address */
        !           588:        sig = calc_ea(ea, (char *)*reg, &dst);
        !           589:        if (sig)
        !           590:            return sig;
        !           591:
        !           592: #ifdef DEBUG_FPE
        !           593:        printf("store_ea: dst addr=%p+%d\n", dst, ea->ea_moffs);
        !           594: #endif
        !           595:        copyout(src, dst + ea->ea_moffs, len);
        !           596:
        !           597:        /* do post-increment */
        !           598:        if (ea->ea_flags & EA_POSTINCR) {
        !           599:            *reg += step;
        !           600:            ea->ea_moffs = 0;
        !           601: #ifdef DEBUG_FPE
        !           602:            printf("store_ea: postinc mode - reg incremented\n");
        !           603: #endif
        !           604:        } else {
        !           605:            ea->ea_moffs += len;
        !           606:        }
        !           607:     }
        !           608:
        !           609:     return 0;
        !           610: }
        !           611:
        !           612: /*
        !           613:  * fetch_immed: fetch immediate operand
        !           614:  */
        !           615: int
        !           616: fetch_immed(frame, insn, dst)
        !           617:      struct frame *frame;
        !           618:      struct instruction *insn;
        !           619:      int *dst;
        !           620: {
        !           621:        int data, ext_bytes;
        !           622:        u_int16_t tmp;
        !           623:
        !           624:        ext_bytes = insn->is_datasize;
        !           625:        if (ext_bytes < 0)
        !           626:                return (0);
        !           627:
        !           628:        if (ext_bytes <= 2) {
        !           629:                if (copyin((void *)(insn->is_pc + insn->is_advance), &tmp,
        !           630:                    sizeof(tmp)) != 0) {
        !           631:                        return SIGSEGV;
        !           632:                }
        !           633:                if (ext_bytes == 1) {
        !           634:                        /* sign-extend byte to long */
        !           635:                        data = (char)tmp;
        !           636:                } else {
        !           637:                        /* sign-extend word to long */
        !           638:                        data = (int)tmp;
        !           639:                }
        !           640:                insn->is_advance += 2;
        !           641:                dst[0] = data;
        !           642:                return (0);
        !           643:        }
        !           644:
        !           645:        /* if (ext_bytes > 2) { */
        !           646:                if (copyin((void *)(insn->is_pc + insn->is_advance), &dst[0],
        !           647:                    sizeof(dst[0])) != 0) {
        !           648:                        return SIGSEGV;
        !           649:                }
        !           650:                insn->is_advance += 4;
        !           651:        /* } */
        !           652:
        !           653:        if (ext_bytes > 4) {
        !           654:                if (copyin((void *)(insn->is_pc + insn->is_advance), &dst[1],
        !           655:                    sizeof(dst[1])) != 0) {
        !           656:                        return SIGSEGV;
        !           657:                }
        !           658:                insn->is_advance += 4;
        !           659:        }
        !           660:
        !           661:        if (ext_bytes > 8) {
        !           662:                if (copyin((void *)(insn->is_pc + insn->is_advance), &dst[2],
        !           663:                     sizeof(dst[2])) != 0) {
        !           664:                        return SIGSEGV;
        !           665:                }
        !           666:                insn->is_advance += 4;
        !           667:        }
        !           668:
        !           669:        return 0;
        !           670: }
        !           671:
        !           672: /*
        !           673:  * fetch_disp: fetch displacement in full extension words
        !           674:  */
        !           675: int
        !           676: fetch_disp(frame, insn, size, res)
        !           677:      struct frame *frame;
        !           678:      struct instruction *insn;
        !           679:      int size, *res;
        !           680: {
        !           681:        int disp;
        !           682:        u_int16_t word;
        !           683:
        !           684:        switch (size) {
        !           685:        case 1:
        !           686:                if (copyin((void *)(insn->is_pc + insn->is_advance), &word,
        !           687:                    sizeof(word)) != 0) {
        !           688:                        return SIGSEGV;
        !           689:                }
        !           690:                /* sign-extend */
        !           691:                disp = (int)word;
        !           692:                insn->is_advance += 2;
        !           693:                break;
        !           694:        case 2:
        !           695:                if (copyin((void *)(insn->is_pc + insn->is_advance), &disp,
        !           696:                    sizeof(disp)) != 0) {
        !           697:                        return SIGSEGV;
        !           698:                }
        !           699:                insn->is_advance += 4;
        !           700:                break;
        !           701:        default:
        !           702:                disp = 0;
        !           703:                break;
        !           704:        }
        !           705:
        !           706:        *res = disp;
        !           707:
        !           708:        return 0;
        !           709: }
        !           710:
        !           711: /*
        !           712:  * Calculates an effective address for all address modes except for
        !           713:  * register direct, absolute, and immediate modes.  However, it does
        !           714:  * not take care of predecrement/postincrement of register content.
        !           715:  * Returns a signal value (0 == no error).
        !           716:  */
        !           717: int
        !           718: calc_ea(ea, ptr, eaddr)
        !           719:      struct insn_ea *ea;
        !           720:      char *ptr;                /* base address (usually a register content) */
        !           721:      char **eaddr;     /* pointer to result pointer */
        !           722: {
        !           723:     int word;
        !           724:
        !           725: #if DEBUG_FPE
        !           726:     printf("calc_ea: reg indirect (reg) = %p\n", ptr);
        !           727: #endif
        !           728:
        !           729:     if (ea->ea_flags & EA_OFFSET) {
        !           730:        /* apply the signed offset */
        !           731: #if DEBUG_FPE
        !           732:        printf("calc_ea: offset %d\n", ea->ea_offset);
        !           733: #endif
        !           734:        ptr += ea->ea_offset;
        !           735:     } else if (ea->ea_flags & EA_INDEXED) {
        !           736: #if DEBUG_FPE
        !           737:        printf("calc_ea: indexed mode\n");
        !           738: #endif
        !           739:
        !           740:        if (ea->ea_flags & EA_BASE_SUPPRSS) {
        !           741:            /* base register is suppressed */
        !           742:            ptr = (char *)ea->ea_basedisp;
        !           743:        } else {
        !           744:            ptr += ea->ea_basedisp;
        !           745:        }
        !           746:
        !           747:        if (ea->ea_flags & EA_MEM_INDIR) {
        !           748: #if DEBUG_FPE
        !           749:            printf("calc_ea: mem indir mode: basedisp=%08x, outerdisp=%08x\n",
        !           750:                   ea->ea_basedisp, ea->ea_outerdisp);
        !           751:            printf("calc_ea: addr fetched from %p\n", ptr);
        !           752: #endif
        !           753:            /* memory indirect modes */
        !           754:            if (copyin(ptr, &word, sizeof(word)) != 0) {
        !           755:                return SIGSEGV;
        !           756:            }
        !           757: #if DEBUG_FPE
        !           758:            printf("calc_ea: fetched ptr 0x%08x\n", word);
        !           759: #endif
        !           760:            ptr = (char *)word + ea->ea_outerdisp;
        !           761:        }
        !           762:     }
        !           763:
        !           764:     *eaddr = ptr;
        !           765:
        !           766:     return 0;
        !           767: }

CVSweb