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