1 /* $NetBSD: fpu_calcea.c,v 1.26 2011/07/18 14:11:27 isaki Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Gordon W. Ross 5 * portion Copyright (c) 1995 Ken Nakata 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 4. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Gordon Ross 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "opt_m68k_arch.h" 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: fpu_calcea.c,v 1.26 2011/07/18 14:11:27 isaki Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/signal.h> 41 #include <sys/systm.h> 42 #include <machine/frame.h> 43 #include <m68k/m68k.h> 44 45 #include "fpu_emulate.h" 46 47 #ifdef DEBUG_FPE 48 #define DPRINTF(x) printf x 49 #else 50 #define DPRINTF(x) do {} while (/* CONSTCOND */ 0) 51 #endif 52 53 /* 54 * Prototypes of static functions 55 */ 56 static int decode_ea6(struct frame *, struct instruction *, 57 struct insn_ea *, int); 58 static int fetch_immed(struct frame *, struct instruction *, int *); 59 static int fetch_disp(struct frame *, struct instruction *, int, int *); 60 static int calc_ea(struct insn_ea *, char *, char **); 61 62 /* 63 * Helper routines for dealing with "effective address" values. 64 */ 65 66 /* 67 * Decode an effective address into internal form. 68 * Returns zero on success, else signal number. 69 */ 70 int 71 fpu_decode_ea(struct frame *frame, struct instruction *insn, 72 struct insn_ea *ea, int modreg) 73 { 74 int sig; 75 76 #ifdef DIAGNOSTIC 77 if (insn->is_datasize < 0) 78 panic("%s: called with uninitialized datasize", __func__); 79 #endif 80 81 sig = 0; 82 83 /* Set the most common value here. */ 84 ea->ea_regnum = 8 + (modreg & 7); 85 86 if ((modreg & 060) == 0) { 87 /* register direct */ 88 ea->ea_regnum = modreg & 0xf; 89 ea->ea_flags = EA_DIRECT; 90 DPRINTF(("%s: register direct reg=%d\n", 91 __func__, ea->ea_regnum)); 92 } else if ((modreg & 077) == 074) { 93 /* immediate */ 94 ea->ea_flags = EA_IMMED; 95 sig = fetch_immed(frame, insn, &ea->ea_immed[0]); 96 DPRINTF(("%s: immediate size=%d\n", 97 __func__, insn->is_datasize)); 98 } 99 /* 100 * rest of the address modes need to be separately 101 * handled for the LC040 and the others. 102 */ 103 #if 0 /* XXX */ 104 else if (frame->f_format == 4 && frame->f_fmt4.f_fa) { 105 /* LC040 */ 106 ea->ea_flags = EA_FRAME_EA; 107 ea->ea_fea = frame->f_fmt4.f_fa; 108 DPRINTF(("%s: 68LC040 - in-frame EA (%p) size %d\n", 109 __func__, (void *)ea->ea_fea, insn->is_datasize)); 110 if ((modreg & 070) == 030) { 111 /* postincrement mode */ 112 ea->ea_flags |= EA_POSTINCR; 113 } else if ((modreg & 070) == 040) { 114 /* predecrement mode */ 115 ea->ea_flags |= EA_PREDECR; 116 #ifdef M68060 117 #if defined(M68020) || defined(M68030) || defined(M68040) 118 if (cputype == CPU_68060) 119 #endif 120 if (insn->is_datasize == 12) 121 ea->ea_fea -= 8; 122 #endif 123 } 124 } 125 #endif /* XXX */ 126 else { 127 /* 020/030 */ 128 switch (modreg & 070) { 129 130 case 020: /* (An) */ 131 ea->ea_flags = 0; 132 DPRINTF(("%s: register indirect reg=%d\n", 133 __func__, ea->ea_regnum)); 134 break; 135 136 case 030: /* (An)+ */ 137 ea->ea_flags = EA_POSTINCR; 138 DPRINTF(("%s: reg indirect postincrement reg=%d\n", 139 __func__, ea->ea_regnum)); 140 break; 141 142 case 040: /* -(An) */ 143 ea->ea_flags = EA_PREDECR; 144 DPRINTF(("%s: reg indirect predecrement reg=%d\n", 145 __func__, ea->ea_regnum)); 146 break; 147 148 case 050: /* (d16,An) */ 149 ea->ea_flags = EA_OFFSET; 150 sig = fetch_disp(frame, insn, 1, &ea->ea_offset); 151 DPRINTF(("%s: reg indirect with displacement reg=%d\n", 152 __func__, ea->ea_regnum)); 153 break; 154 155 case 060: /* (d8,An,Xn) */ 156 ea->ea_flags = EA_INDEXED; 157 sig = decode_ea6(frame, insn, ea, modreg); 158 break; 159 160 case 070: /* misc. */ 161 ea->ea_regnum = (modreg & 7); 162 switch (modreg & 7) { 163 164 case 0: /* (xxxx).W */ 165 ea->ea_flags = EA_ABS; 166 sig = fetch_disp(frame, insn, 1, 167 &ea->ea_absaddr); 168 DPRINTF(("%s: absolute address (word)\n", 169 __func__)); 170 break; 171 172 case 1: /* (xxxxxxxx).L */ 173 ea->ea_flags = EA_ABS; 174 sig = fetch_disp(frame, insn, 2, 175 &ea->ea_absaddr); 176 DPRINTF(("%s: absolute address (long)\n", 177 __func__)); 178 break; 179 180 case 2: /* (d16,PC) */ 181 ea->ea_flags = EA_PC_REL | EA_OFFSET; 182 sig = fetch_disp(frame, insn, 1, 183 &ea->ea_absaddr); 184 DPRINTF(("%s: pc relative word displacement\n", 185 __func__)); 186 break; 187 188 case 3: /* (d8,PC,Xn) */ 189 ea->ea_flags = EA_PC_REL | EA_INDEXED; 190 sig = decode_ea6(frame, insn, ea, modreg); 191 break; 192 193 case 4: /* #data */ 194 /* it should have been taken care of earlier */ 195 default: 196 DPRINTF(("%s: invalid addr mode (7,%d)\n", 197 __func__, modreg & 7)); 198 return SIGILL; 199 } 200 break; 201 } 202 } 203 ea->ea_moffs = 0; 204 205 return sig; 206 } 207 208 /* 209 * Decode Mode=6 address modes 210 */ 211 static int 212 decode_ea6(struct frame *frame, struct instruction *insn, struct insn_ea *ea, 213 int modreg) 214 { 215 int extword, idx; 216 int basedisp, outerdisp; 217 int bd_size, od_size; 218 int sig; 219 220 extword = fusword((void *)(insn->is_pc + insn->is_advance)); 221 if (extword < 0) { 222 return SIGSEGV; 223 } 224 insn->is_advance += 2; 225 226 /* get register index */ 227 ea->ea_idxreg = (extword >> 12) & 0xf; 228 idx = frame->f_regs[ea->ea_idxreg]; 229 if ((extword & 0x0800) == 0) { 230 /* if word sized index, sign-extend */ 231 idx &= 0xffff; 232 if (idx & 0x8000) { 233 idx |= 0xffff0000; 234 } 235 } 236 /* scale register index */ 237 idx <<= ((extword >> 9) & 3); 238 239 if ((extword & 0x100) == 0) { 240 /* brief extension word - sign-extend the displacement */ 241 basedisp = (extword & 0xff); 242 if (basedisp & 0x80) { 243 basedisp |= 0xffffff00; 244 } 245 246 ea->ea_basedisp = idx + basedisp; 247 ea->ea_outerdisp = 0; 248 DPRINTF(("%s: brief ext word idxreg=%d, basedisp=%08x\n", 249 __func__, ea->ea_idxreg, ea->ea_basedisp)); 250 } else { 251 /* full extension word */ 252 if (extword & 0x80) { 253 ea->ea_flags |= EA_BASE_SUPPRSS; 254 } 255 bd_size = ((extword >> 4) & 3) - 1; 256 od_size = (extword & 3) - 1; 257 sig = fetch_disp(frame, insn, bd_size, &basedisp); 258 if (sig) 259 return sig; 260 if (od_size >= 0) 261 ea->ea_flags |= EA_MEM_INDIR; 262 sig = fetch_disp(frame, insn, od_size, &outerdisp); 263 if (sig) 264 return sig; 265 266 switch (extword & 0x44) { 267 case 0: /* preindexed */ 268 ea->ea_basedisp = basedisp + idx; 269 ea->ea_outerdisp = outerdisp; 270 break; 271 case 4: /* postindexed */ 272 ea->ea_basedisp = basedisp; 273 ea->ea_outerdisp = outerdisp + idx; 274 break; 275 case 0x40: /* no index */ 276 ea->ea_basedisp = basedisp; 277 ea->ea_outerdisp = outerdisp; 278 break; 279 default: 280 DPRINTF(("%s: invalid indirect mode: ext word %04x\n", 281 __func__, extword)); 282 return SIGILL; 283 break; 284 } 285 DPRINTF(("%s: full ext idxreg=%d, basedisp=%x, outerdisp=%x\n", 286 __func__, 287 ea->ea_idxreg, ea->ea_basedisp, ea->ea_outerdisp)); 288 } 289 DPRINTF(("%s: regnum=%d, flags=%x\n", 290 __func__, ea->ea_regnum, ea->ea_flags)); 291 return 0; 292 } 293 294 /* 295 * Load a value from an effective address. 296 * Returns zero on success, else signal number. 297 */ 298 int 299 fpu_load_ea(struct frame *frame, struct instruction *insn, struct insn_ea *ea, 300 char *dst) 301 { 302 int *reg; 303 char *src; 304 int len, step; 305 int sig; 306 307 #ifdef DIAGNOSTIC 308 if (ea->ea_regnum & ~0xF) 309 panic("%s: bad regnum", __func__); 310 #endif 311 312 DPRINTF(("%s: frame at %p\n", __func__, frame)); 313 /* dst is always int or larger. */ 314 len = insn->is_datasize; 315 if (len < 4) 316 dst += (4 - len); 317 step = (len == 1 && ea->ea_regnum == 15 /* sp */) ? 2 : len; 318 319 #if 0 320 if (ea->ea_flags & EA_FRAME_EA) { 321 /* Using LC040 frame EA */ 322 #ifdef DEBUG_FPE 323 if (ea->ea_flags & (EA_PREDECR|EA_POSTINCR)) { 324 printf("%s: frame ea %08x w/r%d\n", 325 __func__, ea->ea_fea, ea->ea_regnum); 326 } else { 327 printf("%s: frame ea %08x\n", __func__, ea->ea_fea); 328 } 329 #endif 330 src = (char *)ea->ea_fea; 331 copyin(src + ea->ea_moffs, dst, len); 332 if (ea->ea_flags & EA_PREDECR) { 333 frame->f_regs[ea->ea_regnum] = ea->ea_fea; 334 ea->ea_fea -= step; 335 ea->ea_moffs = 0; 336 } else if (ea->ea_flags & EA_POSTINCR) { 337 ea->ea_fea += step; 338 frame->f_regs[ea->ea_regnum] = ea->ea_fea; 339 ea->ea_moffs = 0; 340 } else { 341 ea->ea_moffs += step; 342 } 343 /* That's it, folks */ 344 } else 345 #endif 346 if (ea->ea_flags & EA_DIRECT) { 347 if (len > 4) { 348 DPRINTF(("%s: operand doesn't fit CPU reg\n", 349 __func__)); 350 return SIGILL; 351 } 352 if (ea->ea_moffs > 0) { 353 DPRINTF(("%s: more than one move from CPU reg\n", 354 __func__)); 355 return SIGILL; 356 } 357 src = (char *)&frame->f_regs[ea->ea_regnum]; 358 /* The source is an int. */ 359 if (len < 4) { 360 src += (4 - len); 361 DPRINTF(("%s: short/byte opr - addr adjusted\n", 362 __func__)); 363 } 364 DPRINTF(("%s: src %p\n", __func__, src)); 365 memcpy(dst, src, len); 366 } else if (ea->ea_flags & EA_IMMED) { 367 DPRINTF(("%s: immed %08x%08x%08x size %d\n", __func__, 368 ea->ea_immed[0], ea->ea_immed[1], ea->ea_immed[2], len)); 369 src = (char *)&ea->ea_immed[0]; 370 if (len < 4) { 371 src += (4 - len); 372 DPRINTF(("%s: short/byte immed opr - addr adjusted\n", 373 __func__)); 374 } 375 memcpy(dst, src, len); 376 } else if (ea->ea_flags & EA_ABS) { 377 DPRINTF(("%s: abs addr %08x\n", __func__, ea->ea_absaddr)); 378 src = (char *)ea->ea_absaddr; 379 copyin(src, dst, len); 380 } else /* register indirect */ { 381 if (ea->ea_flags & EA_PC_REL) { 382 DPRINTF(("%s: using PC\n", __func__)); 383 reg = NULL; 384 /* 385 * Grab the register contents. 4 is offset to the first 386 * extension word from the opcode 387 */ 388 src = (char *)insn->is_pc + 4; 389 DPRINTF(("%s: pc relative pc+4 = %p\n", __func__, src)); 390 } else /* not PC relative */ { 391 DPRINTF(("%s: using register %c%d\n", 392 __func__, 393 (ea->ea_regnum >= 8) ? 'a' : 'd', 394 ea->ea_regnum & 7)); 395 /* point to the register */ 396 reg = &frame->f_regs[ea->ea_regnum]; 397 398 if (ea->ea_flags & EA_PREDECR) { 399 DPRINTF(("%s: predecr mode - " 400 "reg decremented\n", __func__)); 401 *reg -= step; 402 ea->ea_moffs = 0; 403 } 404 405 /* Grab the register contents. */ 406 src = (char *)*reg; 407 DPRINTF(("%s: reg indirect reg = %p\n", __func__, src)); 408 } 409 410 sig = calc_ea(ea, src, &src); 411 if (sig) 412 return sig; 413 414 copyin(src + ea->ea_moffs, dst, len); 415 416 /* do post-increment */ 417 if (ea->ea_flags & EA_POSTINCR) { 418 if (ea->ea_flags & EA_PC_REL) { 419 DPRINTF(("%s: tried to postincrement PC\n", 420 __func__)); 421 return SIGILL; 422 } 423 *reg += step; 424 ea->ea_moffs = 0; 425 DPRINTF(("%s: postinc mode - reg incremented\n", 426 __func__)); 427 } else { 428 ea->ea_moffs += len; 429 } 430 } 431 432 return 0; 433 } 434 435 /* 436 * Store a value at the effective address. 437 * Returns zero on success, else signal number. 438 */ 439 int 440 fpu_store_ea(struct frame *frame, struct instruction *insn, struct insn_ea *ea, 441 char *src) 442 { 443 int *reg; 444 char *dst; 445 int len, step; 446 int sig; 447 448 #ifdef DIAGNOSTIC 449 if (ea->ea_regnum & ~0xf) 450 panic("%s: bad regnum", __func__); 451 #endif 452 453 if (ea->ea_flags & (EA_IMMED|EA_PC_REL)) { 454 /* not alterable address mode */ 455 DPRINTF(("%s: not alterable address mode\n", __func__)); 456 return SIGILL; 457 } 458 459 /* src is always int or larger. */ 460 len = insn->is_datasize; 461 if (len < 4) 462 src += (4 - len); 463 step = (len == 1 && ea->ea_regnum == 15 /* sp */) ? 2 : len; 464 465 if (ea->ea_flags & EA_FRAME_EA) { 466 /* Using LC040 frame EA */ 467 #ifdef DEBUG_FPE 468 if (ea->ea_flags & (EA_PREDECR|EA_POSTINCR)) { 469 printf("%s: frame ea %08x w/r%d\n", 470 __func__, ea->ea_fea, ea->ea_regnum); 471 } else { 472 printf("%s: frame ea %08x\n", __func__, ea->ea_fea); 473 } 474 #endif 475 dst = (char *)ea->ea_fea; 476 copyout(src, dst + ea->ea_moffs, len); 477 if (ea->ea_flags & EA_PREDECR) { 478 frame->f_regs[ea->ea_regnum] = ea->ea_fea; 479 ea->ea_fea -= step; 480 ea->ea_moffs = 0; 481 } else if (ea->ea_flags & EA_POSTINCR) { 482 ea->ea_fea += step; 483 frame->f_regs[ea->ea_regnum] = ea->ea_fea; 484 ea->ea_moffs = 0; 485 } else { 486 ea->ea_moffs += step; 487 } 488 /* That's it, folks */ 489 } else if (ea->ea_flags & EA_ABS) { 490 DPRINTF(("%s: abs addr %08x\n", __func__, ea->ea_absaddr)); 491 dst = (char *)ea->ea_absaddr; 492 copyout(src, dst + ea->ea_moffs, len); 493 ea->ea_moffs += len; 494 } else if (ea->ea_flags & EA_DIRECT) { 495 if (len > 4) { 496 DPRINTF(("%s: operand doesn't fit CPU reg\n", 497 __func__)); 498 return SIGILL; 499 } 500 if (ea->ea_moffs > 0) { 501 DPRINTF(("%s: more than one move to CPU reg\n", 502 __func__)); 503 return SIGILL; 504 } 505 dst = (char *)&frame->f_regs[ea->ea_regnum]; 506 /* The destination is an int. */ 507 if (len < 4) { 508 dst += (4 - len); 509 DPRINTF(("%s: short/byte opr - dst addr adjusted\n", 510 __func__)); 511 } 512 DPRINTF(("%s: dst %p\n", __func__, dst)); 513 memcpy(dst, src, len); 514 } else /* One of MANY indirect forms... */ { 515 DPRINTF(("%s: using register %c%d\n", __func__, 516 (ea->ea_regnum >= 8) ? 'a' : 'd', ea->ea_regnum & 7)); 517 /* point to the register */ 518 reg = &(frame->f_regs[ea->ea_regnum]); 519 520 /* do pre-decrement */ 521 if (ea->ea_flags & EA_PREDECR) { 522 DPRINTF(("%s: predecr mode - reg decremented\n", 523 __func__)); 524 *reg -= step; 525 ea->ea_moffs = 0; 526 } 527 528 /* calculate the effective address */ 529 sig = calc_ea(ea, (char *)*reg, &dst); 530 if (sig) 531 return sig; 532 533 DPRINTF(("%s: dst addr=%p+%d\n", __func__, dst, ea->ea_moffs)); 534 copyout(src, dst + ea->ea_moffs, len); 535 536 /* do post-increment */ 537 if (ea->ea_flags & EA_POSTINCR) { 538 *reg += step; 539 ea->ea_moffs = 0; 540 DPRINTF(("%s: postinc mode - reg incremented\n", 541 __func__)); 542 } else { 543 ea->ea_moffs += len; 544 } 545 } 546 547 return 0; 548 } 549 550 /* 551 * fetch_immed: fetch immediate operand 552 */ 553 static int 554 fetch_immed(struct frame *frame, struct instruction *insn, int *dst) 555 { 556 int data, ext_bytes; 557 558 ext_bytes = insn->is_datasize; 559 560 if (0 < ext_bytes) { 561 data = fusword((void *)(insn->is_pc + insn->is_advance)); 562 if (data < 0) 563 return SIGSEGV; 564 if (ext_bytes == 1) { 565 /* sign-extend byte to long */ 566 data &= 0xff; 567 if (data & 0x80) 568 data |= 0xffffff00; 569 } else if (ext_bytes == 2) { 570 /* sign-extend word to long */ 571 data &= 0xffff; 572 if (data & 0x8000) 573 data |= 0xffff0000; 574 } 575 insn->is_advance += 2; 576 dst[0] = data; 577 } 578 if (2 < ext_bytes) { 579 data = fusword((void *)(insn->is_pc + insn->is_advance)); 580 if (data < 0) 581 return SIGSEGV; 582 insn->is_advance += 2; 583 dst[0] <<= 16; 584 dst[0] |= data; 585 } 586 if (4 < ext_bytes) { 587 data = fusword((void *)(insn->is_pc + insn->is_advance)); 588 if (data < 0) 589 return SIGSEGV; 590 dst[1] = data << 16; 591 data = fusword((void *)(insn->is_pc + insn->is_advance + 2)); 592 if (data < 0) 593 return SIGSEGV; 594 insn->is_advance += 4; 595 dst[1] |= data; 596 } 597 if (8 < ext_bytes) { 598 data = fusword((void *)(insn->is_pc + insn->is_advance)); 599 if (data < 0) 600 return SIGSEGV; 601 dst[2] = data << 16; 602 data = fusword((void *)(insn->is_pc + insn->is_advance + 2)); 603 if (data < 0) 604 return SIGSEGV; 605 insn->is_advance += 4; 606 dst[2] |= data; 607 } 608 609 return 0; 610 } 611 612 /* 613 * fetch_disp: fetch displacement in full extension words 614 */ 615 static int 616 fetch_disp(struct frame *frame, struct instruction *insn, int size, int *res) 617 { 618 int disp, word; 619 620 if (size == 1) { 621 word = fusword((void *)(insn->is_pc + insn->is_advance)); 622 if (word < 0) 623 return SIGSEGV; 624 disp = word & 0xffff; 625 if (disp & 0x8000) { 626 /* sign-extend */ 627 disp |= 0xffff0000; 628 } 629 insn->is_advance += 2; 630 } else if (size == 2) { 631 word = fusword((void *)(insn->is_pc + insn->is_advance)); 632 if (word < 0) 633 return SIGSEGV; 634 disp = word << 16; 635 word = fusword((void *)(insn->is_pc + insn->is_advance + 2)); 636 if (word < 0) 637 return SIGSEGV; 638 disp |= (word & 0xffff); 639 insn->is_advance += 4; 640 } else { 641 disp = 0; 642 } 643 *res = disp; 644 return 0; 645 } 646 647 /* 648 * Calculates an effective address for all address modes except for 649 * register direct, absolute, and immediate modes. However, it does 650 * not take care of predecrement/postincrement of register content. 651 * Returns a signal value (0 == no error). 652 */ 653 static int 654 calc_ea(struct insn_ea *ea, char *ptr, char **eaddr) 655 /* ptr: base address (usually a register content) */ 656 /* eaddr: pointer to result pointer */ 657 { 658 int data, word; 659 660 DPRINTF(("%s: reg indirect (reg) = %p\n", __func__, ptr)); 661 662 if (ea->ea_flags & EA_OFFSET) { 663 /* apply the signed offset */ 664 DPRINTF(("%s: offset %d\n", __func__, ea->ea_offset)); 665 ptr += ea->ea_offset; 666 } else if (ea->ea_flags & EA_INDEXED) { 667 DPRINTF(("%s: indexed mode\n", __func__)); 668 669 if (ea->ea_flags & EA_BASE_SUPPRSS) { 670 /* base register is suppressed */ 671 ptr = (char *)ea->ea_basedisp; 672 } else { 673 ptr += ea->ea_basedisp; 674 } 675 676 if (ea->ea_flags & EA_MEM_INDIR) { 677 DPRINTF(("%s: mem indir mode: basedisp=%08x, " 678 "outerdisp=%08x\n", 679 __func__, ea->ea_basedisp, ea->ea_outerdisp)); 680 DPRINTF(("%s: addr fetched from %p\n", __func__, ptr)); 681 /* memory indirect modes */ 682 word = fusword(ptr); 683 if (word < 0) 684 return SIGSEGV; 685 word <<= 16; 686 data = fusword(ptr + 2); 687 if (data < 0) 688 return SIGSEGV; 689 word |= data; 690 DPRINTF(("%s: fetched ptr 0x%08x\n", __func__, word)); 691 ptr = (char *)word + ea->ea_outerdisp; 692 } 693 } 694 695 *eaddr = ptr; 696 697 return 0; 698 } 699