[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

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