|
|
1.1 ! root 1: /* ! 2: * UAE - The Un*x Amiga Emulator ! 3: * ! 4: * MC68000 emulation ! 5: * ! 6: * (c) 1995 Bernd Schmidt ! 7: */ ! 8: ! 9: #define MMUOP_DEBUG 2 ! 10: #define DEBUG_CD32CDTVIO 0 ! 11: ! 12: #include "main.h" ! 13: #include "m68000.h" ! 14: #include "compat.h" ! 15: #include "sysconfig.h" ! 16: #include "sysdeps.h" ! 17: #include "hatari-glue.h" ! 18: #include "options_cpu.h" ! 19: #include "maccess.h" ! 20: #include "memory.h" ! 21: #include "newcpu.h" ! 22: #include "cpummu.h" ! 23: #include "cpummu030.h" ! 24: #ifdef WITH_SOFTFLOAT ! 25: #include "fpp-softfloat.h" ! 26: #else ! 27: #include "md-fpp.h" ! 28: #endif ! 29: #include "main.h" ! 30: #include "dsp.h" ! 31: #include "dimension.hpp" ! 32: #include "reset.h" ! 33: #include "cycInt.h" ! 34: #include "dialog.h" ! 35: #include "screen.h" ! 36: #include "video.h" ! 37: #include "log.h" ! 38: #include "debugui.h" ! 39: #include "debugcpu.h" ! 40: ! 41: ! 42: /* Opcode of faulting instruction */ ! 43: static uae_u16 last_op_for_exception_3; ! 44: /* PC at fault time */ ! 45: static uaecptr last_addr_for_exception_3; ! 46: /* Address that generated the exception */ ! 47: static uaecptr last_fault_for_exception_3; ! 48: /* read (0) or write (1) access */ ! 49: static int last_writeaccess_for_exception_3; ! 50: /* instruction (1) or data (0) access */ ! 51: static int last_instructionaccess_for_exception_3; ! 52: int mmu_enabled, mmu_triggered; ! 53: int cpu_cycles; ! 54: ! 55: const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 }; ! 56: const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 }; ! 57: ! 58: int movem_index1[256]; ! 59: int movem_index2[256]; ! 60: int movem_next[256]; ! 61: ! 62: cpuop_func *cpufunctbl[65536]; ! 63: ! 64: int OpcodeFamily; ! 65: struct mmufixup mmufixup[2]; ! 66: ! 67: uae_u32 fpp_get_fpsr (void); ! 68: ! 69: static struct cache030 icaches030[CACHELINES030]; ! 70: static struct cache030 dcaches030[CACHELINES030]; ! 71: ! 72: void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode); ! 73: ! 74: uae_u32 (*x_prefetch)(int); ! 75: uae_u32 (*x_next_iword)(void); ! 76: uae_u32 (*x_next_ilong)(void); ! 77: uae_u32 (*x_get_ilong)(int); ! 78: uae_u32 (*x_get_iword)(int); ! 79: uae_u32 (*x_get_ibyte)(int); ! 80: uae_u32 (*x_get_long)(uaecptr); ! 81: uae_u32 (*x_get_word)(uaecptr); ! 82: uae_u32 (*x_get_byte)(uaecptr); ! 83: void (*x_put_long)(uaecptr,uae_u32); ! 84: void (*x_put_word)(uaecptr,uae_u32); ! 85: void (*x_put_byte)(uaecptr,uae_u32); ! 86: ! 87: uae_u32 (*x_cp_next_iword)(void); ! 88: uae_u32 (*x_cp_next_ilong)(void); ! 89: uae_u32 (*x_cp_get_long)(uaecptr); ! 90: uae_u32 (*x_cp_get_word)(uaecptr); ! 91: uae_u32 (*x_cp_get_byte)(uaecptr); ! 92: void (*x_cp_put_long)(uaecptr,uae_u32); ! 93: void (*x_cp_put_word)(uaecptr,uae_u32); ! 94: void (*x_cp_put_byte)(uaecptr,uae_u32); ! 95: uae_u32 (REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM; ! 96: ! 97: // shared memory access functions ! 98: static void set_x_funcs (void) ! 99: { ! 100: if (currprefs.cpu_model == 68040) { ! 101: x_prefetch = get_iword_mmu040; ! 102: x_get_ilong = get_ilong_mmu040; ! 103: x_get_iword = get_iword_mmu040; ! 104: x_get_ibyte = get_ibyte_mmu040; ! 105: x_next_iword = next_iword_mmu040; ! 106: x_next_ilong = next_ilong_mmu040; ! 107: x_put_long = put_long_mmu040; ! 108: x_put_word = put_word_mmu040; ! 109: x_put_byte = put_byte_mmu040; ! 110: x_get_long = get_long_mmu040; ! 111: x_get_word = get_word_mmu040; ! 112: x_get_byte = get_byte_mmu040; ! 113: } else { ! 114: x_prefetch = get_iword_mmu030; ! 115: x_get_ilong = get_ilong_mmu030; ! 116: x_get_iword = get_iword_mmu030; ! 117: x_get_ibyte = get_ibyte_mmu030; ! 118: x_next_iword = next_iword_mmu030; ! 119: x_next_ilong = next_ilong_mmu030; ! 120: x_put_long = put_long_mmu030; ! 121: x_put_word = put_word_mmu030; ! 122: x_put_byte = put_byte_mmu030; ! 123: x_get_long = get_long_mmu030; ! 124: x_get_word = get_word_mmu030; ! 125: x_get_byte = get_byte_mmu030; ! 126: } ! 127: ! 128: if (currprefs.mmu_model == 68030) { ! 129: x_cp_put_long = put_long_mmu030_state; ! 130: x_cp_put_word = put_word_mmu030_state; ! 131: x_cp_put_byte = put_byte_mmu030_state; ! 132: x_cp_get_long = get_long_mmu030_state; ! 133: x_cp_get_word = get_word_mmu030_state; ! 134: x_cp_get_byte = get_byte_mmu030_state; ! 135: x_cp_next_iword = next_iword_mmu030_state; ! 136: x_cp_next_ilong = next_ilong_mmu030_state; ! 137: x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030; ! 138: } else { ! 139: x_cp_put_long = x_put_long; ! 140: x_cp_put_word = x_put_word; ! 141: x_cp_put_byte = x_put_byte; ! 142: x_cp_get_long = x_get_long; ! 143: x_cp_get_word = x_get_word; ! 144: x_cp_get_byte = x_get_byte; ! 145: x_cp_next_iword = x_next_iword; ! 146: x_cp_next_ilong = x_next_ilong; ! 147: x_cp_get_disp_ea_020 = x_get_disp_ea_020; ! 148: } ! 149: } ! 150: ! 151: void flush_cpu_caches_040(uae_u16 opcode) ! 152: { ! 153: int cache = (opcode >> 6) & 3; ! 154: if (!(cache & 2)) ! 155: return; ! 156: set_cpu_caches(true); ! 157: } ! 158: ! 159: void set_cpu_caches (bool flush) ! 160: { ! 161: int i; ! 162: ! 163: if (currprefs.cpu_model == 68030) { ! 164: if (regs.cacr & 0x08) { // clear instr cache ! 165: for (i = 0; i < CACHELINES030; i++) { ! 166: icaches030[i].valid[0] = 0; ! 167: icaches030[i].valid[1] = 0; ! 168: icaches030[i].valid[2] = 0; ! 169: icaches030[i].valid[3] = 0; ! 170: } ! 171: regs.cacr &= ~0x08; ! 172: } ! 173: if (regs.cacr & 0x04) { // clear entry in instr cache ! 174: icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0; ! 175: regs.cacr &= ~0x04; ! 176: } ! 177: if (regs.cacr & 0x800) { // clear data cache ! 178: for (i = 0; i < CACHELINES030; i++) { ! 179: dcaches030[i].valid[0] = 0; ! 180: dcaches030[i].valid[1] = 0; ! 181: dcaches030[i].valid[2] = 0; ! 182: dcaches030[i].valid[3] = 0; ! 183: } ! 184: regs.cacr &= ~0x800; ! 185: } ! 186: if (regs.cacr & 0x400) { // clear entry in data cache ! 187: dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0; ! 188: regs.cacr &= ~0x400; ! 189: } ! 190: #if 0 // FIXME ! 191: } else if (currprefs.cpu_model == 68040) { ! 192: if (ConfigureParams.System.bRealtime) { ! 193: if (regs.cacr & 0x8000) { ! 194: flush_icache(0, -1); ! 195: x_prefetch = getc_iword_mmu040; ! 196: x_get_ilong = getc_ilong_mmu040; ! 197: x_get_iword = getc_iword_mmu040; ! 198: x_get_ibyte = getc_ibyte_mmu040; ! 199: x_next_iword = nextc_iword_mmu040; ! 200: x_next_ilong = nextc_ilong_mmu040; ! 201: } else { ! 202: x_prefetch = get_iword_mmu040; ! 203: x_get_ilong = get_ilong_mmu040; ! 204: x_get_iword = get_iword_mmu040; ! 205: x_get_ibyte = get_ibyte_mmu040; ! 206: x_next_iword = next_iword_mmu040; ! 207: x_next_ilong = next_ilong_mmu040; ! 208: } ! 209: } ! 210: #endif ! 211: } ! 212: } ! 213: ! 214: static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode) ! 215: { ! 216: op_illg (opcode); ! 217: return 4; ! 218: } ! 219: static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode) ! 220: { ! 221: if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060) ! 222: op_illg (opcode); ! 223: else ! 224: op_unimpl (opcode); ! 225: return 4; ! 226: } ! 227: ! 228: void build_cpufunctbl (void) ! 229: { ! 230: int i, opcnt; ! 231: unsigned long opcode; ! 232: const struct cputbl *tbl = 0; ! 233: int lvl; ! 234: ! 235: switch (currprefs.cpu_model) ! 236: { ! 237: case 68040: ! 238: lvl = 4; ! 239: tbl = op_smalltbl_31_ff; ! 240: break; ! 241: case 68030: ! 242: lvl = 3; ! 243: tbl = op_smalltbl_32_ff; ! 244: break; ! 245: default: ! 246: changed_prefs.cpu_model = currprefs.cpu_model = 68030; ! 247: lvl = 3; ! 248: tbl = op_smalltbl_32_ff; ! 249: } ! 250: ! 251: if (tbl == 0) { ! 252: write_log ("no CPU emulation cores available CPU=%d!", currprefs.cpu_model); ! 253: DebugUI(); ! 254: } ! 255: ! 256: for (opcode = 0; opcode < 65536; opcode++) ! 257: cpufunctbl[opcode] = op_illg_1; ! 258: for (i = 0; tbl[i].handler != NULL; i++) { ! 259: opcode = tbl[i].opcode; ! 260: cpufunctbl[opcode] = tbl[i].handler; ! 261: } ! 262: ! 263: opcnt = 0; ! 264: for (opcode = 0; opcode < 65536; opcode++) { ! 265: cpuop_func *f; ! 266: ! 267: if (table68k[opcode].mnemo == i_ILLG) ! 268: continue; ! 269: if (table68k[opcode].clev > lvl) { ! 270: continue; ! 271: } ! 272: ! 273: if (table68k[opcode].handler != -1) { ! 274: int idx = table68k[opcode].handler; ! 275: f = cpufunctbl[idx]; ! 276: if (f == op_illg_1) ! 277: DebugUI(); ! 278: cpufunctbl[opcode] = f; ! 279: opcnt++; ! 280: } ! 281: } ! 282: write_log ("Building CPU, %d opcodes (%d %d)\n", ! 283: opcnt, lvl, currprefs.cpu_compatible ? 1 : 0); ! 284: write_log ("CPU=%d, MMU=%d, FPU=%d ($%02x)\n", ! 285: currprefs.cpu_model, currprefs.mmu_model, ! 286: currprefs.fpu_model, currprefs.fpu_revision); ! 287: set_cpu_caches (0); ! 288: if (currprefs.mmu_model) { ! 289: if (currprefs.cpu_model >= 68040) { ! 290: mmu_reset (); ! 291: mmu_set_tc (regs.tcr); ! 292: mmu_set_super (regs.s != 0); ! 293: } else { ! 294: mmu030_reset(1); ! 295: } ! 296: } ! 297: } ! 298: ! 299: static void prefs_changed_cpu (void) { ! 300: currprefs.cpu_model = changed_prefs.cpu_model; ! 301: currprefs.fpu_model = changed_prefs.fpu_model; ! 302: currprefs.fpu_revision = changed_prefs.fpu_revision; ! 303: currprefs.mmu_model = changed_prefs.mmu_model; ! 304: currprefs.cpu_compatible = changed_prefs.cpu_compatible; ! 305: } ! 306: ! 307: void check_prefs_changed_cpu (void) ! 308: { ! 309: bool changed = 0; ! 310: ! 311: if (changed ! 312: || currprefs.cpu_model != changed_prefs.cpu_model ! 313: || currprefs.fpu_model != changed_prefs.fpu_model ! 314: || currprefs.fpu_revision != changed_prefs.fpu_revision ! 315: || currprefs.mmu_model != changed_prefs.mmu_model ! 316: || currprefs.cpu_compatible != changed_prefs.cpu_compatible) { ! 317: ! 318: prefs_changed_cpu (); ! 319: build_cpufunctbl (); ! 320: changed = 1; ! 321: } ! 322: ! 323: if (currprefs.cpu_idle != changed_prefs.cpu_idle) { ! 324: currprefs.cpu_idle = changed_prefs.cpu_idle; ! 325: } ! 326: if (changed) ! 327: set_special (SPCFLAG_MODE_CHANGE); ! 328: ! 329: } ! 330: ! 331: void init_m68k (void) ! 332: { ! 333: int i; ! 334: ! 335: prefs_changed_cpu (); ! 336: ! 337: for (i = 0 ; i < 256 ; i++) { ! 338: int j; ! 339: for (j = 0 ; j < 8 ; j++) { ! 340: if (i & (1 << j)) break; ! 341: } ! 342: movem_index1[i] = j; ! 343: movem_index2[i] = 7-j; ! 344: movem_next[i] = i & (~(1 << j)); ! 345: } ! 346: ! 347: write_log ("Building CPU table for configuration: %d", currprefs.cpu_model); ! 348: regs.address_space_mask = 0xffffffff; ! 349: ! 350: if (currprefs.fpu_model > 0) ! 351: write_log ("/%d", currprefs.fpu_model); ! 352: if (currprefs.cpu_compatible) ! 353: write_log (" prefetch"); ! 354: write_log ("\n"); ! 355: ! 356: read_table68k (); ! 357: do_merges (); ! 358: ! 359: write_log ("%d CPU functions\n", nr_cpuop_funcs); ! 360: ! 361: build_cpufunctbl (); ! 362: set_x_funcs (); ! 363: } ! 364: ! 365: struct regstruct regs; ! 366: struct flag_struct regflags; ! 367: ! 368: #define get_word_debug(o) DBGMemory_ReadWord (o) ! 369: #define get_iword_debug(o) DBGMemory_ReadWord (o) ! 370: #define get_ilong_debug(o) DBGMemory_ReadLong (o) ! 371: ! 372: static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode) ! 373: { ! 374: uae_u16 dp; ! 375: uae_s8 disp8; ! 376: uae_s16 disp16; ! 377: int r; ! 378: uae_u32 dispreg; ! 379: uaecptr addr = pc; ! 380: uae_s32 offset = 0; ! 381: TCHAR buffer[80]; ! 382: ! 383: switch (mode){ ! 384: case Dreg: ! 385: _stprintf (buffer, _T("D%d"), reg); ! 386: break; ! 387: case Areg: ! 388: _stprintf (buffer, _T("A%d"), reg); ! 389: break; ! 390: case Aind: ! 391: _stprintf (buffer, _T("(A%d)"), reg); ! 392: addr = regs.regs[reg + 8]; ! 393: break; ! 394: case Aipi: ! 395: _stprintf (buffer, _T("(A%d)+"), reg); ! 396: addr = regs.regs[reg + 8]; ! 397: break; ! 398: case Apdi: ! 399: _stprintf (buffer, _T("-(A%d)"), reg); ! 400: addr = regs.regs[reg + 8]; ! 401: break; ! 402: case Ad16: ! 403: { ! 404: TCHAR offtxt[80]; ! 405: disp16 = get_iword_debug (pc); pc += 2; ! 406: if (disp16 < 0) ! 407: _stprintf (offtxt, _T("-$%04x"), -disp16); ! 408: else ! 409: _stprintf (offtxt, _T("$%04x"), disp16); ! 410: addr = m68k_areg (regs, reg) + disp16; ! 411: _stprintf (buffer, _T("(A%d, %s) == $%08x"), reg, offtxt, addr); ! 412: } ! 413: break; ! 414: case Ad8r: ! 415: dp = get_iword_debug (pc); pc += 2; ! 416: disp8 = dp & 0xFF; ! 417: r = (dp & 0x7000) >> 12; ! 418: dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r); ! 419: if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); ! 420: dispreg <<= (dp >> 9) & 3; ! 421: ! 422: if (dp & 0x100) { ! 423: uae_s32 outer = 0, disp = 0; ! 424: uae_s32 base = m68k_areg (regs, reg); ! 425: TCHAR name[10]; ! 426: _stprintf (name, _T("A%d, "), reg); ! 427: if (dp & 0x80) { base = 0; name[0] = 0; } ! 428: if (dp & 0x40) dispreg = 0; ! 429: if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; } ! 430: if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; } ! 431: base += disp; ! 432: ! 433: if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; } ! 434: if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; } ! 435: ! 436: if (!(dp & 4)) base += dispreg; ! 437: if ((dp & 3) && !safemode) base = get_ilong_debug (base); ! 438: if (dp & 4) base += dispreg; ! 439: ! 440: addr = base + outer; ! 441: _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name, ! 442: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', ! 443: 1 << ((dp >> 9) & 3), ! 444: disp, outer, addr); ! 445: } else { ! 446: addr = m68k_areg (regs, reg) + (uae_s32)((uae_s8)disp8) + dispreg; ! 447: _stprintf (buffer, _T("(A%d, %c%d.%c*%d, $%02x) == $%08x"), reg, ! 448: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', ! 449: 1 << ((dp >> 9) & 3), disp8, addr); ! 450: } ! 451: break; ! 452: case PC16: ! 453: disp16 = get_iword_debug (pc); pc += 2; ! 454: addr += (uae_s16)disp16; ! 455: _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr); ! 456: break; ! 457: case PC8r: ! 458: dp = get_iword_debug (pc); pc += 2; ! 459: disp8 = dp & 0xFF; ! 460: r = (dp & 0x7000) >> 12; ! 461: dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r); ! 462: if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); ! 463: dispreg <<= (dp >> 9) & 3; ! 464: ! 465: if (dp & 0x100) { ! 466: uae_s32 outer = 0, disp = 0; ! 467: uae_s32 base = addr; ! 468: TCHAR name[10]; ! 469: _stprintf (name, _T("PC, ")); ! 470: if (dp & 0x80) { base = 0; name[0] = 0; } ! 471: if (dp & 0x40) dispreg = 0; ! 472: if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; } ! 473: if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; } ! 474: base += disp; ! 475: ! 476: if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; } ! 477: if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; } ! 478: ! 479: if (!(dp & 4)) base += dispreg; ! 480: if ((dp & 3) && !safemode) base = get_ilong_debug (base); ! 481: if (dp & 4) base += dispreg; ! 482: ! 483: addr = base + outer; ! 484: _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name, ! 485: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', ! 486: 1 << ((dp >> 9) & 3), ! 487: disp, outer, addr); ! 488: } else { ! 489: addr += (uae_s32)((uae_s8)disp8) + dispreg; ! 490: _stprintf (buffer, _T("(PC, %c%d.%c*%d, $%02x) == $%08x"), dp & 0x8000 ? 'A' : 'D', ! 491: (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3), ! 492: disp8, addr); ! 493: } ! 494: break; ! 495: case absw: ! 496: addr = (uae_s32)(uae_s16)get_iword_debug (pc); ! 497: _stprintf (buffer, _T("$%08x"), addr); ! 498: pc += 2; ! 499: break; ! 500: case absl: ! 501: addr = get_ilong_debug (pc); ! 502: _stprintf (buffer, _T("$%08x"), addr); ! 503: pc += 4; ! 504: break; ! 505: case imm: ! 506: switch (size){ ! 507: case sz_byte: ! 508: _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff)); ! 509: pc += 2; ! 510: break; ! 511: case sz_word: ! 512: _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff)); ! 513: pc += 2; ! 514: break; ! 515: case sz_long: ! 516: _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc))); ! 517: pc += 4; ! 518: break; ! 519: case sz_single: ! 520: { ! 521: fptype fp; ! 522: to_single(&fp, get_ilong_debug(pc)); ! 523: _stprintf(buffer, _T("#%s"), fp_print(&fp)); ! 524: pc += 4; ! 525: } ! 526: break; ! 527: case sz_double: ! 528: { ! 529: fptype fp; ! 530: to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4)); ! 531: _stprintf(buffer, _T("#%s"), fp_print(&fp)); ! 532: pc += 8; ! 533: } ! 534: break; ! 535: case sz_extended: ! 536: { ! 537: fptype fp; ! 538: to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8)); ! 539: _stprintf(buffer, _T("#%s"), fp_print(&fp)); ! 540: pc += 12; ! 541: break; ! 542: } ! 543: case sz_packed: ! 544: _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8)); ! 545: pc += 12; ! 546: break; ! 547: default: ! 548: break; ! 549: } ! 550: break; ! 551: case imm0: ! 552: offset = (uae_s32)(uae_s8)get_iword_debug (pc); ! 553: _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff)); ! 554: addr = pc + 2 + offset; ! 555: pc += 2; ! 556: break; ! 557: case imm1: ! 558: offset = (uae_s32)(uae_s16)get_iword_debug (pc); ! 559: buffer[0] = 0; ! 560: _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff)); ! 561: addr = pc + offset; ! 562: pc += 2; ! 563: break; ! 564: case imm2: ! 565: offset = (uae_s32)get_ilong_debug (pc); ! 566: _stprintf (buffer, _T("#$%08x"), (uae_u32)offset); ! 567: addr = pc + offset; ! 568: pc += 4; ! 569: break; ! 570: case immi: ! 571: offset = (uae_s32)(uae_s8)(reg & 0xff); ! 572: _stprintf (buffer, _T("#$%08x"), (uae_u32)offset); ! 573: addr = pc + offset; ! 574: break; ! 575: default: ! 576: break; ! 577: } ! 578: if (buf == 0) ! 579: f_out (f, _T("%s"), buffer); ! 580: else ! 581: _tcscat (buf, buffer); ! 582: if (eaddr) ! 583: *eaddr = addr; ! 584: return pc; ! 585: } ! 586: ! 587: static void activate_trace(void) ! 588: { ! 589: unset_special (SPCFLAG_TRACE); ! 590: set_special (SPCFLAG_DOTRACE); ! 591: } ! 592: ! 593: void check_t0_trace(void) ! 594: { ! 595: if (regs.t0 && currprefs.cpu_model >= 68020) { ! 596: unset_special (SPCFLAG_TRACE); ! 597: set_special (SPCFLAG_DOTRACE); ! 598: } ! 599: } ! 600: ! 601: void REGPARAM2 MakeSR (void) ! 602: { ! 603: regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) ! 604: | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8) ! 605: | (GET_XFLG () << 4) | (GET_NFLG () << 3) ! 606: | (GET_ZFLG () << 2) | (GET_VFLG () << 1) ! 607: | GET_CFLG ()); ! 608: } ! 609: ! 610: static void MakeFromSR_x(int t0trace) ! 611: { ! 612: int oldm = regs.m; ! 613: int olds = regs.s; ! 614: int oldt0 = regs.t0; ! 615: int oldt1 = regs.t1; ! 616: ! 617: SET_XFLG ((regs.sr >> 4) & 1); ! 618: SET_NFLG ((regs.sr >> 3) & 1); ! 619: SET_ZFLG ((regs.sr >> 2) & 1); ! 620: SET_VFLG ((regs.sr >> 1) & 1); ! 621: SET_CFLG (regs.sr & 1); ! 622: if (regs.t1 == ((regs.sr >> 15) & 1) && ! 623: regs.t0 == ((regs.sr >> 14) & 1) && ! 624: regs.s == ((regs.sr >> 13) & 1) && ! 625: regs.m == ((regs.sr >> 12) & 1) && ! 626: regs.intmask == ((regs.sr >> 8) & 7)) ! 627: return; ! 628: regs.t1 = (regs.sr >> 15) & 1; ! 629: regs.t0 = (regs.sr >> 14) & 1; ! 630: regs.s = (regs.sr >> 13) & 1; ! 631: regs.m = (regs.sr >> 12) & 1; ! 632: regs.intmask = (regs.sr >> 8) & 7; ! 633: if (currprefs.cpu_model >= 68020) { ! 634: if (olds != regs.s) { ! 635: if (olds) { ! 636: if (oldm) ! 637: regs.msp = m68k_areg (regs, 7); ! 638: else ! 639: regs.isp = m68k_areg (regs, 7); ! 640: m68k_areg (regs, 7) = regs.usp; ! 641: } else { ! 642: regs.usp = m68k_areg (regs, 7); ! 643: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp; ! 644: } ! 645: } else if (olds && oldm != regs.m) { ! 646: if (oldm) { ! 647: regs.msp = m68k_areg (regs, 7); ! 648: m68k_areg (regs, 7) = regs.isp; ! 649: } else { ! 650: regs.isp = m68k_areg (regs, 7); ! 651: m68k_areg (regs, 7) = regs.msp; ! 652: } ! 653: } ! 654: } else { ! 655: regs.t0 = regs.m = 0; ! 656: if (olds != regs.s) { ! 657: if (olds) { ! 658: regs.isp = m68k_areg (regs, 7); ! 659: m68k_areg (regs, 7) = regs.usp; ! 660: } else { ! 661: regs.usp = m68k_areg (regs, 7); ! 662: m68k_areg (regs, 7) = regs.isp; ! 663: } ! 664: } ! 665: } ! 666: if (currprefs.mmu_model) ! 667: mmu_set_super (regs.s != 0); ! 668: ! 669: doint (); ! 670: if (regs.t1 || regs.t0) { ! 671: set_special (SPCFLAG_TRACE); ! 672: } else { ! 673: /* Keep SPCFLAG_DOTRACE, we still want a trace exception for ! 674: SR-modifying instructions (including STOP). */ ! 675: unset_special (SPCFLAG_TRACE); ! 676: } ! 677: // Stop SR-modification does not generate T0 ! 678: // If this SR modification set Tx bit, no trace until next instruction. ! 679: if ((oldt0 && t0trace && currprefs.cpu_model >= 68020) || oldt1) { ! 680: // Always trace if Tx bits were already set, even if this SR modification cleared them. ! 681: activate_trace(); ! 682: } ! 683: } ! 684: ! 685: void REGPARAM2 MakeFromSR_T0(void) ! 686: { ! 687: MakeFromSR_x(1); ! 688: } ! 689: void REGPARAM2 MakeFromSR(void) ! 690: { ! 691: MakeFromSR_x(0); ! 692: ! 693: } ! 694: ! 695: static void exception_check_trace (int nr) ! 696: { ! 697: unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE); ! 698: if (regs.t1 && !regs.t0) { ! 699: /* trace stays pending if exception is div by zero, chk, ! 700: * trapv or trap #x ! 701: */ ! 702: if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47)) ! 703: set_special (SPCFLAG_DOTRACE); ! 704: } ! 705: regs.t1 = regs.t0 = 0; ! 706: } ! 707: ! 708: static void exception_debug (int nr) ! 709: { ! 710: #ifdef DEBUGGER ! 711: if (!exception_debugging) ! 712: return; ! 713: printf ("Exception %d, PC=%08X\n", nr, M68K_GETPC); ! 714: DebugUI(); ! 715: #endif ! 716: } ! 717: ! 718: void cpu_halt (int e) ! 719: { ! 720: write_log("HALT!"); ! 721: DebugUI(); ! 722: } ! 723: ! 724: static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format) ! 725: { ! 726: int i; ! 727: ! 728: #if 0 ! 729: if (nr < 24 || nr > 31) { // do not print debugging for interrupts ! 730: write_log(_T("Building exception stack frame (format %X)\n"), format); ! 731: } ! 732: #endif ! 733: ! 734: switch (format) { ! 735: case 0x0: // four word stack frame ! 736: case 0x1: // throwaway four word stack frame ! 737: break; ! 738: case 0x2: // six word stack frame ! 739: m68k_areg (regs, 7) -= 4; ! 740: x_put_long (m68k_areg (regs, 7), oldpc); ! 741: break; ! 742: case 0x3: // floating point post-instruction stack frame (68040) ! 743: m68k_areg (regs, 7) -= 4; ! 744: x_put_long (m68k_areg (regs, 7), regs.fp_ea); ! 745: break; ! 746: case 0x7: // access error stack frame (68040) ! 747: ! 748: for (i = 3; i >= 0; i--) { ! 749: // WB1D/PD0,PD1,PD2,PD3 ! 750: m68k_areg (regs, 7) -= 4; ! 751: x_put_long (m68k_areg (regs, 7), mmu040_move16[i]); ! 752: } ! 753: ! 754: m68k_areg (regs, 7) -= 4; ! 755: x_put_long (m68k_areg (regs, 7), 0); // WB1A ! 756: m68k_areg (regs, 7) -= 4; ! 757: x_put_long (m68k_areg (regs, 7), 0); // WB2D ! 758: m68k_areg (regs, 7) -= 4; ! 759: x_put_long (m68k_areg (regs, 7), regs.wb2_address); // WB2A ! 760: m68k_areg (regs, 7) -= 4; ! 761: x_put_long (m68k_areg (regs, 7), regs.wb3_data); // WB3D ! 762: m68k_areg (regs, 7) -= 4; ! 763: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // WB3A ! 764: ! 765: m68k_areg (regs, 7) -= 4; ! 766: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // FA ! 767: ! 768: m68k_areg (regs, 7) -= 2; ! 769: x_put_word (m68k_areg (regs, 7), 0); ! 770: m68k_areg (regs, 7) -= 2; ! 771: x_put_word (m68k_areg (regs, 7), regs.wb2_status); ! 772: regs.wb2_status = 0; ! 773: m68k_areg (regs, 7) -= 2; ! 774: x_put_word (m68k_areg (regs, 7), regs.wb3_status); ! 775: regs.wb3_status = 0; ! 776: ! 777: m68k_areg (regs, 7) -= 2; ! 778: x_put_word (m68k_areg (regs, 7), ssw); ! 779: m68k_areg (regs, 7) -= 4; ! 780: x_put_long (m68k_areg (regs, 7), regs.mmu_effective_addr); ! 781: break; ! 782: case 0x9: // coprocessor mid-instruction stack frame (68020, 68030) ! 783: m68k_areg (regs, 7) -= 4; ! 784: x_put_long (m68k_areg (regs, 7), regs.fp_ea); ! 785: m68k_areg (regs, 7) -= 4; ! 786: x_put_long (m68k_areg (regs, 7), regs.fp_opword); ! 787: m68k_areg (regs, 7) -= 4; ! 788: x_put_long (m68k_areg (regs, 7), oldpc); ! 789: break; ! 790: case 0x8: // bus and address error stack frame (68010) ! 791: write_log(_T("Exception stack frame format %X not implemented\n"), format); ! 792: return; ! 793: case 0x4: // floating point unimplemented stack frame (68LC040, 68EC040) ! 794: // or 68060 bus access fault stack frame ! 795: m68k_areg (regs, 7) -= 4; ! 796: x_put_long (m68k_areg (regs, 7), ssw); ! 797: m68k_areg (regs, 7) -= 4; ! 798: x_put_long (m68k_areg (regs, 7), oldpc); ! 799: break; ! 800: case 0xB: // long bus cycle fault stack frame (68020, 68030) ! 801: // We always use B frame because it is easier to emulate, ! 802: // our PC always points at start of instruction but A frame assumes ! 803: // it is + 2 and handling this properly is not easy. ! 804: // Store state information to internal register space ! 805: for (i = 0; i < mmu030_idx + 1; i++) { ! 806: m68k_areg (regs, 7) -= 4; ! 807: x_put_long (m68k_areg (regs, 7), mmu030_ad[i].val); ! 808: } ! 809: while (i < 9) { ! 810: uae_u32 v = 0; ! 811: m68k_areg (regs, 7) -= 4; ! 812: // mmu030_idx is always small enough if instruction is FMOVEM. ! 813: if (mmu030_state[1] & MMU030_STATEFLAG1_FMOVEM) { ! 814: if (i == 7) ! 815: v = mmu030_fmovem_store[0]; ! 816: else if (i == 8) ! 817: v = mmu030_fmovem_store[1]; ! 818: } ! 819: x_put_long (m68k_areg (regs, 7), v); ! 820: i++; ! 821: } ! 822: // version & internal information (We store index here) ! 823: m68k_areg (regs, 7) -= 2; ! 824: x_put_word (m68k_areg (regs, 7), mmu030_idx); ! 825: // 3* internal registers ! 826: m68k_areg (regs, 7) -= 2; ! 827: x_put_word (m68k_areg (regs, 7), mmu030_state[2]); ! 828: m68k_areg (regs, 7) -= 2; ! 829: x_put_word (m68k_areg (regs, 7), mmu030_state[1]); ! 830: m68k_areg (regs, 7) -= 2; ! 831: x_put_word (m68k_areg (regs, 7), mmu030_state[0]); ! 832: // data input buffer = fault address ! 833: m68k_areg (regs, 7) -= 4; ! 834: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); ! 835: // 2xinternal ! 836: m68k_areg (regs, 7) -= 2; ! 837: x_put_word (m68k_areg (regs, 7), 0); ! 838: m68k_areg (regs, 7) -= 2; ! 839: x_put_word (m68k_areg (regs, 7), 0); ! 840: // stage b address ! 841: m68k_areg (regs, 7) -= 4; ! 842: x_put_long (m68k_areg (regs, 7), mm030_stageb_address); ! 843: // 2xinternal ! 844: m68k_areg (regs, 7) -= 4; ! 845: x_put_long (m68k_areg (regs, 7), mmu030_disp_store[1]); ! 846: /* fall through */ ! 847: case 0xA: // short bus cycle fault stack frame (68020, 68030) ! 848: m68k_areg (regs, 7) -= 4; ! 849: x_put_long (m68k_areg (regs, 7), mmu030_disp_store[0]); ! 850: m68k_areg (regs, 7) -= 4; ! 851: // Data output buffer = value that was going to be written ! 852: x_put_long (m68k_areg (regs, 7), (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) ? mmu030_data_buffer : mmu030_ad[mmu030_idx].val); ! 853: m68k_areg (regs, 7) -= 4; ! 854: x_put_long (m68k_areg (regs, 7), mmu030_opcode); // Internal register (opcode storage) ! 855: m68k_areg (regs, 7) -= 4; ! 856: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // data cycle fault address ! 857: m68k_areg (regs, 7) -= 2; ! 858: x_put_word (m68k_areg (regs, 7), 0); // Instr. pipe stage B ! 859: m68k_areg (regs, 7) -= 2; ! 860: x_put_word (m68k_areg (regs, 7), 0); // Instr. pipe stage C ! 861: m68k_areg (regs, 7) -= 2; ! 862: x_put_word (m68k_areg (regs, 7), ssw); ! 863: m68k_areg (regs, 7) -= 2; ! 864: x_put_word (m68k_areg (regs, 7), 0); // Internal register ! 865: break; ! 866: default: ! 867: write_log(_T("Unknown exception stack frame format: %X\n"), format); ! 868: return; ! 869: } ! 870: m68k_areg (regs, 7) -= 2; ! 871: x_put_word (m68k_areg (regs, 7), (format << 12) | (nr * 4)); ! 872: m68k_areg (regs, 7) -= 4; ! 873: x_put_long (m68k_areg (regs, 7), currpc); ! 874: m68k_areg (regs, 7) -= 2; ! 875: x_put_word (m68k_areg (regs, 7), regs.sr); ! 876: } ! 877: ! 878: // 68030 MMU ! 879: static void Exception_mmu030 (int nr, uaecptr oldpc) ! 880: { ! 881: uae_u32 currpc = m68k_getpc (), newpc; ! 882: ! 883: exception_debug (nr); ! 884: MakeSR (); ! 885: ! 886: if (!regs.s) { ! 887: regs.usp = m68k_areg (regs, 7); ! 888: m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; ! 889: regs.s = 1; ! 890: mmu_set_super (1); ! 891: } ! 892: ! 893: #if 0 ! 894: if (nr < 24 || nr > 31) { // do not print debugging for interrupts ! 895: write_log (_T("Exception_mmu030: Exception %i: %08x %08x %08x\n"), ! 896: nr, currpc, oldpc, regs.mmu_fault_addr); ! 897: } ! 898: #endif ! 899: ! 900: #if 0 ! 901: write_log (_T("Exception %d -> %08x\n", nr, newpc)); ! 902: #endif ! 903: ! 904: ! 905: newpc = x_get_long (regs.vbr + 4 * nr); ! 906: ! 907: if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */ ! 908: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0); ! 909: MakeSR(); /* this sets supervisor bit in status reg */ ! 910: regs.m = 0; /* clear the M bit (but frame 0x1 uses sr with M bit set) */ ! 911: regs.msp = m68k_areg (regs, 7); ! 912: m68k_areg (regs, 7) = regs.isp; ! 913: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1); ! 914: } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9 || nr == 56) { ! 915: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x2); ! 916: } else if (nr == 2) { ! 917: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0xB); ! 918: } else if (nr == 3) { ! 919: regs.mmu_fault_addr = last_fault_for_exception_3; ! 920: mmu030_state[0] = mmu030_state[1] = 0; ! 921: mmu030_data_buffer = 0; ! 922: Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr, 0xA); ! 923: } else if (nr >= 48 && nr < 55) { ! 924: if (regs.fpu_exp_pre) { ! 925: Exception_build_stack_frame(oldpc, regs.instruction_pc, 0, nr, 0x0); ! 926: } else { /* mid-instruction */ ! 927: Exception_build_stack_frame(regs.fpiar, currpc, 0, nr, 0x9); ! 928: } ! 929: } else { ! 930: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0); ! 931: } ! 932: ! 933: if (newpc & 1) { ! 934: if (nr == 2 || nr == 3) ! 935: cpu_halt (2); ! 936: else ! 937: exception3_read(regs.ir, newpc); ! 938: return; ! 939: } ! 940: m68k_setpci (newpc); ! 941: exception_check_trace (nr); ! 942: } ! 943: ! 944: ! 945: // 68040 MMU ! 946: static void Exception_mmu (int nr, uaecptr oldpc) ! 947: { ! 948: uae_u32 currpc = m68k_getpc (), newpc; ! 949: ! 950: exception_debug (nr); ! 951: MakeSR (); ! 952: ! 953: if (!regs.s) { ! 954: regs.usp = m68k_areg (regs, 7); ! 955: if (currprefs.cpu_model >= 68020 && currprefs.cpu_model < 68060) { ! 956: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp; ! 957: } else { ! 958: m68k_areg (regs, 7) = regs.isp; ! 959: } ! 960: regs.s = 1; ! 961: mmu_set_super (1); ! 962: } ! 963: ! 964: newpc = x_get_long (regs.vbr + 4 * nr); ! 965: #if 0 ! 966: write_log (_T("Exception %d: %08x -> %08x\n"), nr, currpc, newpc); ! 967: #endif ! 968: ! 969: if (nr == 2) { // bus error ! 970: //write_log (_T("Exception_mmu %08x %08x %08x\n"), currpc, oldpc, regs.mmu_fault_addr); ! 971: if (currprefs.mmu_model == 68040) ! 972: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x7); ! 973: else ! 974: Exception_build_stack_frame(regs.mmu_fault_addr, currpc, regs.mmu_fslw, nr, 0x4); ! 975: } else if (nr == 3) { // address error ! 976: Exception_build_stack_frame(last_fault_for_exception_3, currpc, 0, nr, 0x2); ! 977: write_log (_T("Exception %d (%x) at %x!\n"), nr, last_fault_for_exception_3, currpc); ! 978: } else if (nr == 5 || nr == 6 || nr == 7 || nr == 9) { ! 979: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2); ! 980: } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */ ! 981: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0); ! 982: MakeSR(); /* this sets supervisor bit in status reg */ ! 983: regs.m = 0; /* clear the M bit (but frame 0x1 uses sr with M bit set) */ ! 984: regs.msp = m68k_areg (regs, 7); ! 985: m68k_areg (regs, 7) = regs.isp; ! 986: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1); ! 987: } else if (nr == 60 || nr == 61) { ! 988: Exception_build_stack_frame(oldpc, regs.instruction_pc, regs.mmu_ssw, nr, 0x0); ! 989: } else if (nr >= 48 && nr <= 55) { ! 990: if (regs.fpu_exp_pre) { ! 991: if (currprefs.cpu_model == 68060 && nr == 55 && regs.fp_unimp_pend == 2) { // packed decimal real ! 992: Exception_build_stack_frame(regs.fp_ea, regs.instruction_pc, 0, nr, 0x2); ! 993: } else { ! 994: Exception_build_stack_frame(oldpc, regs.instruction_pc, 0, nr, 0x0); ! 995: } ! 996: } else { /* post-instruction */ ! 997: if (currprefs.cpu_model == 68060 && nr == 55 && regs.fp_unimp_pend == 2) { // packed decimal real ! 998: Exception_build_stack_frame(regs.fp_ea, currpc, 0, nr, 0x2); ! 999: } else { ! 1000: Exception_build_stack_frame(oldpc, currpc, 0, nr, 0x3); ! 1001: } ! 1002: } ! 1003: } else if (nr == 11 && regs.fp_unimp_ins) { ! 1004: regs.fp_unimp_ins = false; ! 1005: if ((currprefs.cpu_model == 68060 && (currprefs.fpu_model == 0 || (regs.pcr & 2))) || ! 1006: (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) { ! 1007: Exception_build_stack_frame(regs.fp_ea, currpc, regs.instruction_pc, nr, 0x4); ! 1008: } else { ! 1009: Exception_build_stack_frame(regs.fp_ea, currpc, regs.mmu_ssw, nr, 0x2); ! 1010: } ! 1011: } else { ! 1012: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0); ! 1013: } ! 1014: ! 1015: if (newpc & 1) { ! 1016: if (nr == 2 || nr == 3) ! 1017: cpu_halt (2); ! 1018: else ! 1019: exception3_read (regs.ir, newpc); ! 1020: return; ! 1021: } ! 1022: m68k_setpci (newpc); ! 1023: exception_check_trace (nr); ! 1024: } ! 1025: ! 1026: ! 1027: /* Handle exceptions. */ ! 1028: static void ExceptionX (int nr, uaecptr address) ! 1029: { ! 1030: if (currprefs.cpu_model == 68030) ! 1031: Exception_mmu030 (nr, m68k_getpc ()); ! 1032: else ! 1033: Exception_mmu (nr, m68k_getpc ()); ! 1034: } ! 1035: ! 1036: void REGPARAM2 Exception_cpu(int nr) ! 1037: { ! 1038: bool t0 = currprefs.cpu_model >= 68020 && regs.t0; ! 1039: ExceptionX (nr, -1); ! 1040: // check T0 trace ! 1041: if (t0) { ! 1042: activate_trace(); ! 1043: } ! 1044: } ! 1045: void REGPARAM2 Exception (int nr) ! 1046: { ! 1047: ExceptionX (nr, -1); ! 1048: } ! 1049: void REGPARAM2 ExceptionL (int nr, uaecptr address) ! 1050: { ! 1051: ExceptionX (nr, address); ! 1052: } ! 1053: ! 1054: static void do_interrupt (int nr, int Pending) ! 1055: { ! 1056: regs.stopped = 0; ! 1057: unset_special (SPCFLAG_STOP); ! 1058: assert (nr < 8 && nr >= 0); ! 1059: ! 1060: /* On Hatari, only video ints are using SPCFLAG_INT (see m68000.c) */ ! 1061: Exception (nr + 24); ! 1062: ! 1063: regs.intmask = nr; ! 1064: doint (); ! 1065: ! 1066: set_special (SPCFLAG_INT); ! 1067: } ! 1068: ! 1069: ! 1070: void m68k_reset (int hardreset) ! 1071: { ! 1072: regs.spcflags &= (SPCFLAG_MODE_CHANGE | SPCFLAG_BRK); ! 1073: regs.ipl = regs.ipl_pin = 0; ! 1074: regs.s = 1; ! 1075: regs.m = 0; ! 1076: regs.stopped = 0; ! 1077: regs.t1 = 0; ! 1078: regs.t0 = 0; ! 1079: SET_ZFLG (0); ! 1080: SET_XFLG (0); ! 1081: SET_CFLG (0); ! 1082: SET_VFLG (0); ! 1083: SET_NFLG (0); ! 1084: regs.intmask = 7; ! 1085: regs.vbr = regs.sfc = regs.dfc = 0; ! 1086: regs.irc = 0xffff; ! 1087: ! 1088: m68k_areg (regs, 7) = get_long (0); ! 1089: m68k_setpc (get_long (4)); ! 1090: ! 1091: fpu_reset (); ! 1092: ! 1093: regs.caar = regs.cacr = 0; ! 1094: regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0; ! 1095: regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0; ! 1096: ! 1097: mmufixup[0].reg = -1; ! 1098: mmufixup[1].reg = -1; ! 1099: if (currprefs.mmu_model) { ! 1100: if (currprefs.cpu_model >= 68040) { ! 1101: mmu_reset (); ! 1102: mmu_set_tc (regs.tcr); ! 1103: mmu_set_super (regs.s != 0); ! 1104: } ! 1105: else { ! 1106: mmu030_reset(hardreset); ! 1107: } ! 1108: } ! 1109: ! 1110: regs.pcr = 0; ! 1111: } ! 1112: ! 1113: void REGPARAM2 op_unimpl (uae_u16 opcode) ! 1114: { ! 1115: static int warned; ! 1116: if (warned < 20) { ! 1117: write_log (_T("68060 unimplemented opcode %04X, PC=%08x\n"), opcode, regs.instruction_pc); ! 1118: warned++; ! 1119: } ! 1120: ExceptionL (61, regs.instruction_pc); ! 1121: } ! 1122: ! 1123: uae_u32 REGPARAM2 op_illg (uae_u32 opcode) ! 1124: { ! 1125: uaecptr pc = m68k_getpc (); ! 1126: static int warned; ! 1127: ! 1128: if (warned < 20) { ! 1129: write_log ("Illegal instruction: %04x at %08X\n", opcode, pc); ! 1130: warned++; ! 1131: } ! 1132: ! 1133: if ((opcode & 0xF000)==0xA000) ! 1134: Exception (10); ! 1135: else ! 1136: if ((opcode & 0xF000)==0xF000) ! 1137: Exception (11); ! 1138: else ! 1139: Exception (4); ! 1140: return 4; ! 1141: } ! 1142: ! 1143: #ifdef CPUEMU_0 ! 1144: ! 1145: // 68030 (68851) MMU instructions only ! 1146: bool mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa) ! 1147: { ! 1148: bool fline = false; ! 1149: ! 1150: if (extra & 0x8000) { ! 1151: fline = mmu_op30_ptest (pc, opcode, extra, extraa); ! 1152: } else if ((extra&0xE000)==0x2000 && (extra & 0x1C00)) { ! 1153: fline = mmu_op30_pflush (pc, opcode, extra, extraa); ! 1154: } else if ((extra&0xE000)==0x2000 && !(extra & 0x1C00)) { ! 1155: fline = mmu_op30_pload (pc, opcode, extra, extraa); ! 1156: } else { ! 1157: fline = mmu_op30_pmove (pc, opcode, extra, extraa); ! 1158: } ! 1159: ! 1160: if (fline) { ! 1161: m68k_setpc(pc); ! 1162: op_illg(opcode); ! 1163: } ! 1164: return fline; ! 1165: } ! 1166: ! 1167: void mmu_op (uae_u32 opcode, uae_u32 extra) ! 1168: { ! 1169: if (currprefs.cpu_model) { ! 1170: mmu_op_real (opcode, extra); ! 1171: return; ! 1172: } ! 1173: #if MMUOP_DEBUG > 1 ! 1174: write_log ("mmu_op %04X PC=%08X\n", opcode, m68k_getpc ()); ! 1175: #endif ! 1176: if ((opcode & 0xFE0) == 0x0500) { ! 1177: /* PFLUSH */ ! 1178: regs.mmusr = 0; ! 1179: #if MMUOP_DEBUG > 0 ! 1180: write_log ("PFLUSH\n"); ! 1181: #endif ! 1182: return; ! 1183: } else if ((opcode & 0x0FD8) == 0x548) { ! 1184: if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */ ! 1185: /* PTEST */ ! 1186: #if MMUOP_DEBUG > 0 ! 1187: write_log ("PTEST\n"); ! 1188: #endif ! 1189: return; ! 1190: } ! 1191: } ! 1192: #if MMUOP_DEBUG > 0 ! 1193: write_log ("Unknown MMU OP %04X\n", opcode); ! 1194: #endif ! 1195: m68k_setpc (m68k_getpc () - 2); ! 1196: op_illg (opcode); ! 1197: } ! 1198: ! 1199: #endif ! 1200: ! 1201: static void do_trace (void) ! 1202: { ! 1203: if (regs.t0 && currprefs.cpu_model >= 68020) { ! 1204: // this is obsolete ! 1205: return; ! 1206: } ! 1207: if (regs.t1) { ! 1208: activate_trace(); ! 1209: } ! 1210: } ! 1211: ! 1212: void doint (void) ! 1213: { ! 1214: if (currprefs.cpu_compatible) ! 1215: set_special (SPCFLAG_INT); ! 1216: else ! 1217: set_special (SPCFLAG_DOINT); ! 1218: } ! 1219: ! 1220: #define IDLETIME (currprefs.cpu_idle * sleep_resolution / 700) ! 1221: ! 1222: /* ! 1223: * Handle special flags ! 1224: */ ! 1225: ! 1226: static int vpos = 0; ! 1227: ! 1228: static int do_specialties (int cycles) ! 1229: { ! 1230: if (regs.spcflags & SPCFLAG_DOTRACE) ! 1231: Exception (9); ! 1232: ! 1233: /* Handle the STOP instruction */ ! 1234: if ( regs.spcflags & SPCFLAG_STOP ) { ! 1235: while (regs.spcflags & SPCFLAG_STOP) { ! 1236: ! 1237: /* Take care of quit event if needed */ ! 1238: if (regs.spcflags & SPCFLAG_BRK) ! 1239: return 1; ! 1240: ! 1241: M68000_AddCycles(cpu_cycles); ! 1242: ! 1243: /* It is possible one or more ints happen at the same time */ ! 1244: /* We must process them during the same cpu cycle until the special INT flag is set */ ! 1245: while (PendingInterrupt.time <=0 && PendingInterrupt.pFunction) { ! 1246: /* 1st, we call the interrupt handler */ ! 1247: CALL_VAR(PendingInterrupt.pFunction); ! 1248: ! 1249: if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) { ! 1250: unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); ! 1251: // SPCFLAG_BRK breaks STOP condition, need to prefetch ! 1252: m68k_resumestopped (); ! 1253: return 1; ! 1254: } ! 1255: ! 1256: if (currprefs.cpu_idle && ((regs.spcflags & SPCFLAG_STOP)) == SPCFLAG_STOP) { ! 1257: /* sleep 1ms if STOP-instruction is executed */ ! 1258: if (1) { ! 1259: static int sleepcnt, lvpos; ! 1260: if (vpos != lvpos) { ! 1261: sleepcnt--; ! 1262: lvpos = vpos; ! 1263: if (sleepcnt < 0) { ! 1264: /*sleepcnt = IDLETIME / 2; */ /* Laurent : badly removed for now */ ! 1265: host_sleep_ms(1); ! 1266: } ! 1267: } ! 1268: } ! 1269: } ! 1270: } ! 1271: } ! 1272: } ! 1273: ! 1274: if (regs.spcflags & SPCFLAG_TRACE) ! 1275: do_trace (); ! 1276: ! 1277: if (regs.spcflags & SPCFLAG_DOINT) { ! 1278: unset_special (SPCFLAG_DOINT); ! 1279: set_special (SPCFLAG_INT); ! 1280: } ! 1281: ! 1282: if (regs.spcflags & SPCFLAG_DEBUGGER) ! 1283: DebugCpu_Check(); ! 1284: ! 1285: if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) { ! 1286: unset_special(SPCFLAG_MODE_CHANGE); ! 1287: return 1; ! 1288: } ! 1289: ! 1290: return 0; ! 1291: } ! 1292: ! 1293: #ifndef CPUEMU_0 ! 1294: ! 1295: #else ! 1296: ! 1297: static int lastRegsS = 0; ! 1298: ! 1299: // Previous MMU 68030 ! 1300: static void m68k_run_mmu030 (void) ! 1301: { ! 1302: uae_u16 opcode; ! 1303: uaecptr pc; ! 1304: struct flag_struct f; ! 1305: f.cznv = 0; ! 1306: f.x = 0; ! 1307: int intr = 0; ! 1308: int lastintr = 0; ! 1309: mmu030_opcode_stageb = -1; ! 1310: retry: ! 1311: TRY (prb) { ! 1312: for (;;) { ! 1313: int cnt; ! 1314: insretry: ! 1315: pc = regs.instruction_pc = m68k_getpc (); ! 1316: f.cznv = regflags.cznv; ! 1317: f.x = regflags.x; ! 1318: ! 1319: mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0; ! 1320: mmu030_opcode = -1; ! 1321: if (mmu030_opcode_stageb < 0) { ! 1322: opcode = get_iword_mmu030 (0); ! 1323: } else { ! 1324: opcode = mmu030_opcode_stageb; ! 1325: mmu030_opcode_stageb = -1; ! 1326: } ! 1327: ! 1328: mmu030_opcode = opcode; ! 1329: mmu030_ad[0].done = false; ! 1330: ! 1331: Uint64 beforeCycles = nCyclesMainCounter; ! 1332: cnt = 50; ! 1333: for (;;) { ! 1334: opcode = mmu030_opcode; ! 1335: mmu030_idx = 0; ! 1336: mmu030_retry = false; ! 1337: cpu_cycles = (*cpufunctbl[opcode])(opcode); ! 1338: cnt--; // so that we don't get in infinite loop if things go horribly wrong ! 1339: if (!mmu030_retry) ! 1340: break; ! 1341: if (cnt < 0) { ! 1342: cpu_halt (9); ! 1343: break; ! 1344: } ! 1345: if (mmu030_retry && mmu030_opcode == -1) ! 1346: goto insretry; // urgh ! 1347: } ! 1348: ! 1349: mmu030_opcode = -1; ! 1350: ! 1351: M68000_AddCycles(cpu_cycles); ! 1352: cpu_cycles = nCyclesMainCounter - beforeCycles; ! 1353: ! 1354: DSP_Run(cpu_cycles); ! 1355: i860_Run(cpu_cycles); ! 1356: ! 1357: /* We can have several interrupts at the same time before the next CPU instruction */ ! 1358: /* We must check for pending interrupt and call do_specialties_interrupt() only */ ! 1359: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */ ! 1360: /* and prevent exiting the STOP state when calling do_specialties() after. */ ! 1361: /* For performance, we first test PendingInterruptCount, then regs.spcflags */ ! 1362: while ( ( PendingInterrupt.time <= 0 ) && ( PendingInterrupt.pFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) { ! 1363: CALL_VAR(PendingInterrupt.pFunction); /* call the interrupt handler */ ! 1364: } ! 1365: ! 1366: /* Previous: for now we poll the interrupt pins with every instruction. ! 1367: * TODO: only do this when an actual interrupt is active to not ! 1368: * unneccessarily slow down emulation. ! 1369: */ ! 1370: intr = intlev (); ! 1371: if (intr>regs.intmask || (intr==7 && intr>lastintr)) ! 1372: do_interrupt (intr, false); ! 1373: lastintr = intr; ! 1374: ! 1375: if(lastRegsS != regs.s) { ! 1376: host_realtime(!(regs.s)); ! 1377: lastRegsS = regs.s; ! 1378: } ! 1379: ! 1380: if (regs.spcflags & ~SPCFLAG_INT) { ! 1381: if (do_specialties (cpu_cycles)) ! 1382: return; ! 1383: } ! 1384: } ! 1385: } CATCH (prb) { ! 1386: ! 1387: regflags.cznv = f.cznv; ! 1388: regflags.x = f.x; ! 1389: ! 1390: m68k_setpci (regs.instruction_pc); ! 1391: ! 1392: if (mmufixup[0].reg >= 0) { ! 1393: m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value; ! 1394: mmufixup[0].reg = -1; ! 1395: } ! 1396: if (mmufixup[1].reg >= 0) { ! 1397: m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value; ! 1398: mmufixup[1].reg = -1; ! 1399: } ! 1400: ! 1401: TRY (prb2) { ! 1402: Exception (prb); ! 1403: } CATCH (prb2) { ! 1404: write_log("[FATAL] double fault\n"); ! 1405: m68k_reset (1); // auto-reset CPU ! 1406: //cpu_halt (1); ! 1407: return; ! 1408: } ENDTRY ! 1409: } ENDTRY ! 1410: goto retry; ! 1411: } ! 1412: ! 1413: /* Aranym MMU 68040 */ ! 1414: static void m68k_run_mmu040 (void) ! 1415: { ! 1416: uae_u16 opcode; ! 1417: struct flag_struct f; ! 1418: f.cznv = 0; ! 1419: f.x = 0; ! 1420: uaecptr pc; ! 1421: int intr = 0; ! 1422: int lastintr = 0; ! 1423: ! 1424: for (;;) { ! 1425: TRY (prb) { ! 1426: for (;;) { ! 1427: f.cznv = regflags.cznv; ! 1428: f.x = regflags.x; ! 1429: mmu_restart = true; ! 1430: pc = regs.instruction_pc = m68k_getpc (); ! 1431: ! 1432: Uint64 beforeCycles = nCyclesMainCounter; ! 1433: mmu_opcode = -1; ! 1434: mmu_opcode = opcode = x_prefetch (0); ! 1435: cpu_cycles = (*cpufunctbl[opcode])(opcode); ! 1436: M68000_AddCycles(cpu_cycles); ! 1437: ! 1438: cpu_cycles = nCyclesMainCounter - beforeCycles; ! 1439: ! 1440: DSP_Run(cpu_cycles); ! 1441: i860_Run(cpu_cycles); ! 1442: ! 1443: /* We can have several interrupts at the same time before the next CPU instruction */ ! 1444: /* We must check for pending interrupt and call do_specialties_interrupt() only */ ! 1445: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */ ! 1446: /* and prevent exiting the STOP state when calling do_specialties() after. */ ! 1447: /* For performance, we first test PendingInterruptCount, then regs.spcflags */ ! 1448: while ( ( PendingInterrupt.time <= 0 ) && ( PendingInterrupt.pFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) { ! 1449: CALL_VAR(PendingInterrupt.pFunction); /* call the interrupt handler */ ! 1450: } ! 1451: ! 1452: /* Previous: for now we poll the interrupt pins with every instruction. ! 1453: * TODO: only do this when an actual interrupt is active to not ! 1454: * unneccessarily slow down emulation. ! 1455: */ ! 1456: intr = intlev (); ! 1457: if (intr>regs.intmask || (intr==7 && intr>lastintr)) ! 1458: do_interrupt (intr, false); ! 1459: lastintr = intr; ! 1460: ! 1461: if(lastRegsS != regs.s) { ! 1462: host_realtime(!(regs.s)); ! 1463: lastRegsS = regs.s; ! 1464: } ! 1465: ! 1466: if (regs.spcflags & ~SPCFLAG_INT) { ! 1467: if (do_specialties (cpu_cycles)) ! 1468: return; ! 1469: } ! 1470: } // end of for(;;) ! 1471: } CATCH (prb) { ! 1472: ! 1473: if (mmu_restart) { ! 1474: /* restore state if instruction restart */ ! 1475: regflags.cznv = f.cznv; ! 1476: regflags.x = f.x; ! 1477: m68k_setpci (regs.instruction_pc); ! 1478: } ! 1479: ! 1480: if (mmufixup[0].reg >= 0) { ! 1481: m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value; ! 1482: mmufixup[0].reg = -1; ! 1483: } ! 1484: ! 1485: TRY (prb2) { ! 1486: Exception (prb); ! 1487: } CATCH (prb2) { ! 1488: write_log("[FATAL] double fault\n"); ! 1489: m68k_reset (1); // auto-reset CPU ! 1490: //cpu_halt (1); ! 1491: return; ! 1492: } ENDTRY ! 1493: ! 1494: } ENDTRY ! 1495: } ! 1496: } ! 1497: ! 1498: #endif /* CPUEMU_0 */ ! 1499: ! 1500: int in_m68k_go = 0; ! 1501: ! 1502: #if 0 ! 1503: static void exception2_handle (uaecptr addr, uaecptr fault) ! 1504: { ! 1505: last_addr_for_exception_3 = addr; ! 1506: last_fault_for_exception_3 = fault; ! 1507: last_writeaccess_for_exception_3 = 0; ! 1508: last_instructionaccess_for_exception_3 = 0; ! 1509: Exception (2); ! 1510: } ! 1511: #endif ! 1512: ! 1513: void m68k_go (int may_quit) ! 1514: { ! 1515: int hardboot = 1; ! 1516: ! 1517: if (in_m68k_go || !may_quit) { ! 1518: write_log ("Bug! m68k_go is not reentrant.\n"); ! 1519: DebugUI(); ! 1520: } ! 1521: ! 1522: in_m68k_go++; ! 1523: for (;;) { ! 1524: void (*run_func)(void); ! 1525: ! 1526: if (regs.spcflags & SPCFLAG_BRK) { ! 1527: unset_special(SPCFLAG_BRK); ! 1528: break; ! 1529: } ! 1530: ! 1531: hardboot = 0; ! 1532: ! 1533: #ifdef DEBUGGER ! 1534: if (debugging) ! 1535: debug (); ! 1536: #endif ! 1537: ! 1538: set_x_funcs (); ! 1539: run_func=currprefs.cpu_model == 68040 ? m68k_run_mmu040 : m68k_run_mmu030; ! 1540: run_func (); ! 1541: } ! 1542: in_m68k_go--; ! 1543: } ! 1544: ! 1545: ! 1546: #if 1 ! 1547: TCHAR* buf_out (TCHAR *buffer, int *bufsize, const TCHAR *format, ...) ! 1548: { ! 1549: va_list parms; ! 1550: ! 1551: if (buffer == NULL) ! 1552: { ! 1553: return NULL; ! 1554: } ! 1555: ! 1556: va_start (parms, format); ! 1557: vsnprintf (buffer, (*bufsize) - 1, format, parms); ! 1558: va_end (parms); ! 1559: *bufsize -= _tcslen (buffer); ! 1560: ! 1561: return buffer + _tcslen (buffer); ! 1562: } ! 1563: #endif ! 1564: ! 1565: static const TCHAR *ccnames[] = ! 1566: { ! 1567: _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"), ! 1568: _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE") ! 1569: }; ! 1570: static const TCHAR *fpccnames[] = ! 1571: { ! 1572: _T("F"), ! 1573: _T("EQ"), ! 1574: _T("OGT"), ! 1575: _T("OGE"), ! 1576: _T("OLT"), ! 1577: _T("OLE"), ! 1578: _T("OGL"), ! 1579: _T("OR"), ! 1580: _T("UN"), ! 1581: _T("UEQ"), ! 1582: _T("UGT"), ! 1583: _T("UGE"), ! 1584: _T("ULT"), ! 1585: _T("ULE"), ! 1586: _T("NE"), ! 1587: _T("T"), ! 1588: _T("SF"), ! 1589: _T("SEQ"), ! 1590: _T("GT"), ! 1591: _T("GE"), ! 1592: _T("LT"), ! 1593: _T("LE"), ! 1594: _T("GL"), ! 1595: _T("GLE"), ! 1596: _T("NGLE"), ! 1597: _T("NGL"), ! 1598: _T("NLE"), ! 1599: _T("NLT"), ! 1600: _T("NGE"), ! 1601: _T("NGT"), ! 1602: _T("SNE"), ! 1603: _T("ST") ! 1604: }; ! 1605: static const TCHAR *fpuopcodes[] = ! 1606: { ! 1607: _T("FMOVE"), ! 1608: _T("FINT"), ! 1609: _T("FSINH"), ! 1610: _T("FINTRZ"), ! 1611: _T("FSQRT"), ! 1612: NULL, ! 1613: _T("FLOGNP1"), ! 1614: NULL, ! 1615: _T("FETOXM1"), ! 1616: _T("FTANH"), ! 1617: _T("FATAN"), ! 1618: NULL, ! 1619: _T("FASIN"), ! 1620: _T("FATANH"), ! 1621: _T("FSIN"), ! 1622: _T("FTAN"), ! 1623: _T("FETOX"), // 0x10 ! 1624: _T("FTWOTOX"), ! 1625: _T("FTENTOX"), ! 1626: NULL, ! 1627: _T("FLOGN"), ! 1628: _T("FLOG10"), ! 1629: _T("FLOG2"), ! 1630: NULL, ! 1631: _T("FABS"), ! 1632: _T("FCOSH"), ! 1633: _T("FNEG"), ! 1634: NULL, ! 1635: _T("FACOS"), ! 1636: _T("FCOS"), ! 1637: _T("FGETEXP"), ! 1638: _T("FGETMAN"), ! 1639: _T("FDIV"), // 0x20 ! 1640: _T("FMOD"), ! 1641: _T("FADD"), ! 1642: _T("FMUL"), ! 1643: _T("FSGLDIV"), ! 1644: _T("FREM"), ! 1645: _T("FSCALE"), ! 1646: _T("FSGLMUL"), ! 1647: _T("FSUB"), ! 1648: NULL, ! 1649: NULL, ! 1650: NULL, ! 1651: NULL, ! 1652: NULL, ! 1653: NULL, ! 1654: NULL, ! 1655: _T("FSINCOS"), // 0x30 ! 1656: _T("FSINCOS"), ! 1657: _T("FSINCOS"), ! 1658: _T("FSINCOS"), ! 1659: _T("FSINCOS"), ! 1660: _T("FSINCOS"), ! 1661: _T("FSINCOS"), ! 1662: _T("FSINCOS"), ! 1663: _T("FCMP"), ! 1664: NULL, ! 1665: _T("FTST"), ! 1666: NULL, ! 1667: NULL, ! 1668: NULL, ! 1669: NULL, ! 1670: NULL ! 1671: }; ! 1672: ! 1673: static const TCHAR *movemregs[] = ! 1674: { ! 1675: _T("D0"), ! 1676: _T("D1"), ! 1677: _T("D2"), ! 1678: _T("D3"), ! 1679: _T("D4"), ! 1680: _T("D5"), ! 1681: _T("D6"), ! 1682: _T("D7"), ! 1683: _T("A0"), ! 1684: _T("A1"), ! 1685: _T("A2"), ! 1686: _T("A3"), ! 1687: _T("A4"), ! 1688: _T("A5"), ! 1689: _T("A6"), ! 1690: _T("A7"), ! 1691: _T("FP0"), ! 1692: _T("FP1"), ! 1693: _T("FP2"), ! 1694: _T("FP3"), ! 1695: _T("FP4"), ! 1696: _T("FP5"), ! 1697: _T("FP6"), ! 1698: _T("FP7"), ! 1699: _T("FPIAR"), ! 1700: _T("FPSR"), ! 1701: _T("FPCR") ! 1702: }; ! 1703: ! 1704: static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode) ! 1705: { ! 1706: TCHAR *p = out + _tcslen (out); ! 1707: if (*prevreg < 0) { ! 1708: *prevreg = reg; ! 1709: *lastreg = reg; ! 1710: return; ! 1711: } ! 1712: if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) { ! 1713: _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]); ! 1714: p = p + _tcslen (p); ! 1715: if (*lastreg != *prevreg) { ! 1716: if ((*lastreg) + 2 == reg) { ! 1717: _stprintf(p, _T("/%s"), movemregs[*prevreg]); ! 1718: } else if ((*lastreg) != (*prevreg)) { ! 1719: _stprintf(p, _T("-%s"), movemregs[*prevreg]); ! 1720: } ! 1721: } ! 1722: *lastreg = reg; ! 1723: *first = 0; ! 1724: } ! 1725: *prevreg = reg; ! 1726: } ! 1727: ! 1728: static void movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode) ! 1729: { ! 1730: unsigned int dmask, amask; ! 1731: int prevreg = -1, lastreg = -1, first = 1; ! 1732: int i; ! 1733: ! 1734: if (mode == Apdi && !fpmode) { ! 1735: uae_u8 dmask2; ! 1736: uae_u8 amask2; ! 1737: ! 1738: amask2 = mask & 0xff; ! 1739: dmask2 = (mask >> 8) & 0xff; ! 1740: dmask = 0; ! 1741: amask = 0; ! 1742: for (i = 0; i < 8; i++) { ! 1743: if (dmask2 & (1 << i)) ! 1744: dmask |= 1 << (7 - i); ! 1745: if (amask2 & (1 << i)) ! 1746: amask |= 1 << (7 - i); ! 1747: } ! 1748: } else { ! 1749: dmask = mask & 0xff; ! 1750: amask = (mask >> 8) & 0xff; ! 1751: if (fpmode == 1 && mode != Apdi) { ! 1752: uae_u8 dmask2 = dmask; ! 1753: dmask = 0; ! 1754: for (i = 0; i < 8; i++) { ! 1755: if (dmask2 & (1 << i)) ! 1756: dmask |= 1 << (7 - i); ! 1757: } ! 1758: } ! 1759: } ! 1760: if (fpmode) { ! 1761: while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; } ! 1762: } else { ! 1763: while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; } ! 1764: while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; } ! 1765: } ! 1766: addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode); ! 1767: } ! 1768: ! 1769: static const TCHAR *fpsizes[] = { ! 1770: _T("L"), ! 1771: _T("S"), ! 1772: _T("X"), ! 1773: _T("P"), ! 1774: _T("W"), ! 1775: _T("D"), ! 1776: _T("B"), ! 1777: _T("P") ! 1778: }; ! 1779: static const int fpsizeconv[] = { ! 1780: sz_long, ! 1781: sz_single, ! 1782: sz_extended, ! 1783: sz_packed, ! 1784: sz_word, ! 1785: sz_double, ! 1786: sz_byte, ! 1787: sz_packed ! 1788: }; ! 1789: ! 1790: static void disasm_size (TCHAR *instrname, struct instr *dp) ! 1791: { ! 1792: if (dp->unsized) { ! 1793: _tcscat(instrname, _T(" ")); ! 1794: return; ! 1795: } ! 1796: switch (dp->size) ! 1797: { ! 1798: case sz_byte: ! 1799: _tcscat (instrname, _T(".B ")); ! 1800: break; ! 1801: case sz_word: ! 1802: _tcscat (instrname, _T(".W ")); ! 1803: break; ! 1804: case sz_long: ! 1805: _tcscat (instrname, _T(".L ")); ! 1806: break; ! 1807: default: ! 1808: _tcscat (instrname, _T(" ")); ! 1809: break; ! 1810: } ! 1811: } ! 1812: ! 1813: void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode) ! 1814: { ! 1815: uae_u32 seaddr2; ! 1816: uae_u32 deaddr2; ! 1817: ! 1818: if (buf) ! 1819: memset (buf, 0, bufsize * sizeof (TCHAR)); ! 1820: if (!table68k) ! 1821: return; ! 1822: while (cnt-- > 0) { ! 1823: TCHAR instrname[100], *ccpt; ! 1824: int i; ! 1825: uae_u32 opcode; ! 1826: uae_u16 extra; ! 1827: struct mnemolookup *lookup; ! 1828: struct instr *dp; ! 1829: uaecptr oldpc; ! 1830: uaecptr m68kpc_illg = 0; ! 1831: bool illegal = false; ! 1832: ! 1833: seaddr2 = deaddr2 = 0; ! 1834: oldpc = pc; ! 1835: opcode = get_word_debug (pc); ! 1836: extra = get_word_debug (pc + 2); ! 1837: if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) { ! 1838: m68kpc_illg = pc + 2; ! 1839: illegal = true; ! 1840: } ! 1841: ! 1842: dp = table68k + opcode; ! 1843: if (dp->mnemo == i_ILLG) { ! 1844: illegal = false; ! 1845: opcode = 0x4AFC; ! 1846: dp = table68k + opcode; ! 1847: } ! 1848: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) ! 1849: ; ! 1850: ! 1851: buf = buf_out (buf, &bufsize, _T("%08X "), pc); ! 1852: ! 1853: pc += 2; ! 1854: ! 1855: if (lookup->friendlyname) ! 1856: _tcscpy (instrname, lookup->friendlyname); ! 1857: else ! 1858: _tcscpy (instrname, lookup->name); ! 1859: ccpt = _tcsstr (instrname, _T("cc")); ! 1860: if (ccpt != 0) { ! 1861: if ((opcode & 0xf000) == 0xf000) ! 1862: _tcscpy (ccpt, fpccnames[extra & 0x1f]); ! 1863: else ! 1864: _tcsncpy (ccpt, ccnames[dp->cc], 2); ! 1865: } ! 1866: disasm_size (instrname, dp); ! 1867: ! 1868: if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) { ! 1869: uae_u16 imm = extra; ! 1870: uae_u16 creg = imm & 0x0fff; ! 1871: uae_u16 r = imm >> 12; ! 1872: TCHAR regs[16]; ! 1873: const TCHAR *cname = _T("?"); ! 1874: int i; ! 1875: for (i = 0; m2cregs[i].regname; i++) { ! 1876: if (m2cregs[i].regno == creg) ! 1877: break; ! 1878: } ! 1879: _stprintf (regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r); ! 1880: if (m2cregs[i].regname) ! 1881: cname = m2cregs[i].regname; ! 1882: if (lookup->mnemo == i_MOVE2C) { ! 1883: _tcscat (instrname, regs); ! 1884: _tcscat (instrname, _T(",")); ! 1885: _tcscat (instrname, cname); ! 1886: } else { ! 1887: _tcscat (instrname, cname); ! 1888: _tcscat (instrname, _T(",")); ! 1889: _tcscat (instrname, regs); ! 1890: } ! 1891: pc += 2; ! 1892: } else if (lookup->mnemo == i_MVMEL) { ! 1893: uae_u16 mask = extra; ! 1894: pc += 2; ! 1895: pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); ! 1896: _tcscat (instrname, _T(",")); ! 1897: movemout (instrname, mask, dp->dmode, 0); ! 1898: } else if (lookup->mnemo == i_MVMLE) { ! 1899: uae_u16 mask = extra; ! 1900: pc += 2; ! 1901: movemout(instrname, mask, dp->dmode, 0); ! 1902: _tcscat(instrname, _T(",")); ! 1903: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); ! 1904: } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) { ! 1905: TCHAR *p; ! 1906: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); ! 1907: extra = get_word_debug(pc); ! 1908: pc += 2; ! 1909: p = instrname + _tcslen(instrname); ! 1910: if (extra & 0x0400) ! 1911: _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7); ! 1912: else ! 1913: _stprintf(p, _T(",D%d"), (extra >> 12) & 7); ! 1914: } else if (lookup->mnemo == i_MOVES) { ! 1915: TCHAR *p; ! 1916: pc += 2; ! 1917: if (!(extra & 0x1000)) { ! 1918: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); ! 1919: p = instrname + _tcslen(instrname); ! 1920: _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7); ! 1921: } else { ! 1922: p = instrname + _tcslen(instrname); ! 1923: _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7); ! 1924: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); ! 1925: } ! 1926: } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || ! 1927: lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR || ! 1928: lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS || ! 1929: lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) { ! 1930: TCHAR *p; ! 1931: int reg = -1; ! 1932: ! 1933: pc += 2; ! 1934: p = instrname + _tcslen(instrname); ! 1935: if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS) ! 1936: reg = (extra >> 12) & 7; ! 1937: if (lookup->mnemo == i_BFINS) ! 1938: _stprintf(p, _T("D%d,"), reg); ! 1939: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode); ! 1940: _tcscat(instrname, _T(" {")); ! 1941: p = instrname + _tcslen(instrname); ! 1942: if (extra & 0x0800) ! 1943: _stprintf(p, _T("D%d"), (extra >> 6) & 7); ! 1944: else ! 1945: _stprintf(p, _T("%d"), (extra >> 6) & 31); ! 1946: _tcscat(instrname, _T(":")); ! 1947: p = instrname + _tcslen(instrname); ! 1948: if (extra & 0x0020) ! 1949: _stprintf(p, _T("D%d"), extra & 7); ! 1950: else ! 1951: _stprintf(p, _T("%d"), extra & 31); ! 1952: _tcscat(instrname, _T("}")); ! 1953: p = instrname + _tcslen(instrname); ! 1954: if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU) ! 1955: _stprintf(p, _T(",D%d"), reg); ! 1956: } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || ! 1957: lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) { ! 1958: if ((opcode & 0xc0) == 0xc0) ! 1959: _tcscat(instrname, _T("BC")); ! 1960: else if (opcode & 0x80) ! 1961: _tcscat(instrname, _T("IC")); ! 1962: else if (opcode & 0x40) ! 1963: _tcscat(instrname, _T("DC")); ! 1964: else ! 1965: _tcscat(instrname, _T("?")); ! 1966: if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) { ! 1967: TCHAR *p = instrname + _tcslen(instrname); ! 1968: _stprintf(p, _T(",(A%d)"), opcode & 7); ! 1969: } ! 1970: } else if (lookup->mnemo == i_FPP) { ! 1971: TCHAR *p; ! 1972: int ins = extra & 0x3f; ! 1973: int size = (extra >> 10) & 7; ! 1974: ! 1975: pc += 2; ! 1976: if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7) ! 1977: fptype fp; ! 1978: if (fpu_get_constant(&fp, extra & 0x3f)) ! 1979: _stprintf(instrname, _T("FMOVECR.X #%s,FP%d"), fp_print(&fp), (extra >> 7) & 7); ! 1980: else ! 1981: _stprintf(instrname, _T("FMOVECR.X #?,FP%d"), (extra >> 7) & 7); ! 1982: } else if ((extra & 0x8000) == 0x8000) { // FMOVEM ! 1983: int dr = (extra >> 13) & 1; ! 1984: int mode; ! 1985: int dreg = (extra >> 4) & 7; ! 1986: int regmask, fpmode; ! 1987: ! 1988: if (extra & 0x4000) { ! 1989: mode = (extra >> 11) & 3; ! 1990: regmask = extra & 0xff; // FMOVEM FPx ! 1991: fpmode = 1; ! 1992: _tcscpy(instrname, _T("FMOVEM.X ")); ! 1993: } else { ! 1994: mode = 0; ! 1995: regmask = (extra >> 10) & 7; // FMOVEM control ! 1996: fpmode = 2; ! 1997: _tcscpy(instrname, _T("FMOVEM.L ")); ! 1998: if (regmask == 1 || regmask == 2 || regmask == 4) ! 1999: _tcscpy(instrname, _T("FMOVE.L ")); ! 2000: } ! 2001: p = instrname + _tcslen(instrname); ! 2002: if (dr) { ! 2003: if (mode & 1) ! 2004: _stprintf(instrname, _T("D%d"), dreg); ! 2005: else ! 2006: movemout(instrname, regmask, dp->dmode, fpmode); ! 2007: _tcscat(instrname, _T(",")); ! 2008: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); ! 2009: } else { ! 2010: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); ! 2011: _tcscat(instrname, _T(",")); ! 2012: p = instrname + _tcslen(instrname); ! 2013: if (mode & 1) ! 2014: _stprintf(p, _T("D%d"), dreg); ! 2015: else ! 2016: movemout(p, regmask, dp->dmode, fpmode); ! 2017: } ! 2018: } else { ! 2019: if (fpuopcodes[ins]) ! 2020: _tcscpy(instrname, fpuopcodes[ins]); ! 2021: else ! 2022: _tcscpy(instrname, _T("F?")); ! 2023: ! 2024: if ((extra & 0xe000) == 0x6000) { // FMOVE to memory ! 2025: int kfactor = extra & 0x7f; ! 2026: _tcscpy(instrname, _T("FMOVE.")); ! 2027: _tcscat(instrname, fpsizes[size]); ! 2028: _tcscat(instrname, _T(" ")); ! 2029: p = instrname + _tcslen(instrname); ! 2030: _stprintf(p, _T("FP%d,"), (extra >> 7) & 7); ! 2031: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode); ! 2032: p = instrname + _tcslen(instrname); ! 2033: if (size == 7) { ! 2034: _stprintf(p, _T(" {D%d}"), (kfactor >> 4)); ! 2035: } else if (kfactor) { ! 2036: if (kfactor & 0x40) ! 2037: kfactor |= ~0x3f; ! 2038: _stprintf(p, _T(" {%d}"), kfactor); ! 2039: } ! 2040: } else { ! 2041: if (extra & 0x4000) { // source is EA ! 2042: _tcscat(instrname, _T(".")); ! 2043: _tcscat(instrname, fpsizes[size]); ! 2044: _tcscat(instrname, _T(" ")); ! 2045: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode); ! 2046: } else { // source is FPx ! 2047: p = instrname + _tcslen(instrname); ! 2048: _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7); ! 2049: } ! 2050: p = instrname + _tcslen(instrname); ! 2051: if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7))) ! 2052: _stprintf(p, _T(",FP%d"), (extra >> 7) & 7); ! 2053: if (ins >= 0x30 && ins < 0x38) { // FSINCOS ! 2054: p = instrname + _tcslen(instrname); ! 2055: _stprintf(p, _T(",FP%d"), extra & 7); ! 2056: } ! 2057: } ! 2058: } ! 2059: } else if ((opcode & 0xf000) == 0xa000) { ! 2060: _tcscpy(instrname, _T("A-LINE")); ! 2061: } else { ! 2062: if (dp->suse) { ! 2063: pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode); ! 2064: } ! 2065: if (dp->suse && dp->duse) ! 2066: _tcscat (instrname, _T(",")); ! 2067: if (dp->duse) { ! 2068: pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode); ! 2069: } ! 2070: } ! 2071: ! 2072: for (i = 0; i < (int)(pc - oldpc) / 2 && i < 5; i++) { ! 2073: buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2)); ! 2074: } ! 2075: while (i++ < 5) ! 2076: buf = buf_out (buf, &bufsize, _T(" ")); ! 2077: ! 2078: if (illegal) ! 2079: buf = buf_out (buf, &bufsize, _T("[ ")); ! 2080: buf = buf_out (buf, &bufsize, instrname); ! 2081: if (illegal) ! 2082: buf = buf_out (buf, &bufsize, _T(" ]")); ! 2083: ! 2084: if (ccpt != 0) { ! 2085: uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2; ! 2086: if (deaddr) ! 2087: *deaddr = pc; ! 2088: if ((opcode & 0xf000) == 0xf000) { ! 2089: if (fpp_cond(dp->cc)) { ! 2090: buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2); ! 2091: } else { ! 2092: buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2); ! 2093: } ! 2094: } else { ! 2095: if (cctrue (dp->cc)) { ! 2096: buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), addr2); ! 2097: } else { ! 2098: buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), addr2); ! 2099: } ! 2100: } ! 2101: } else if ((opcode & 0xff00) == 0x6100) { /* BSR */ ! 2102: if (deaddr) ! 2103: *deaddr = pc; ! 2104: buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2); ! 2105: } ! 2106: buf = buf_out (buf, &bufsize, _T("\n")); ! 2107: ! 2108: if (illegal) ! 2109: pc = m68kpc_illg; ! 2110: } ! 2111: if (nextpc) ! 2112: *nextpc = pc; ! 2113: if (seaddr) ! 2114: *seaddr = seaddr2; ! 2115: if (deaddr) ! 2116: *deaddr = deaddr2; ! 2117: } ! 2118: ! 2119: void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr) ! 2120: { ! 2121: TCHAR *buf; ! 2122: ! 2123: buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt); ! 2124: if (!buf) ! 2125: return; ! 2126: m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, seaddr, deaddr, 1); ! 2127: xfree (buf); ! 2128: } ! 2129: void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt) ! 2130: { ! 2131: TCHAR *buf; ! 2132: ! 2133: buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt); ! 2134: if (!buf) ! 2135: return; ! 2136: m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0); ! 2137: printf (_T("%s"), buf); ! 2138: xfree (buf); ! 2139: } ! 2140: ! 2141: /************************************************************* ! 2142: Disasm the m68kcode at the given address into instrname ! 2143: and instrcode ! 2144: *************************************************************/ ! 2145: void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc) ! 2146: { ! 2147: TCHAR *ccpt; ! 2148: uae_u32 opcode; ! 2149: struct mnemolookup *lookup; ! 2150: struct instr *dp; ! 2151: uaecptr pc, oldpc; ! 2152: ! 2153: pc = oldpc = addr; ! 2154: opcode = get_word_debug (pc); ! 2155: if (cpufunctbl[opcode] == op_illg_1) { ! 2156: opcode = 0x4AFC; ! 2157: } ! 2158: dp = table68k + opcode; ! 2159: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++); ! 2160: ! 2161: pc += 2; ! 2162: ! 2163: _tcscpy (instrname, lookup->name); ! 2164: ccpt = _tcsstr (instrname, _T("cc")); ! 2165: if (ccpt != 0) { ! 2166: _tcsncpy (ccpt, ccnames[dp->cc], 2); ! 2167: } ! 2168: switch (dp->size){ ! 2169: case sz_byte: _tcscat (instrname, _T(".B ")); break; ! 2170: case sz_word: _tcscat (instrname, _T(".W ")); break; ! 2171: case sz_long: _tcscat (instrname, _T(".L ")); break; ! 2172: default: _tcscat (instrname, _T(" ")); break; ! 2173: } ! 2174: ! 2175: if (dp->suse) { ! 2176: pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0); ! 2177: } ! 2178: if (dp->suse && dp->duse) ! 2179: _tcscat (instrname, _T(",")); ! 2180: if (dp->duse) { ! 2181: pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0); ! 2182: } ! 2183: if (instrcode) ! 2184: { ! 2185: int i; ! 2186: for (i = 0; i < (int)(pc - oldpc) / 2; i++) ! 2187: { ! 2188: _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2)); ! 2189: instrcode += _tcslen (instrcode); ! 2190: } ! 2191: } ! 2192: if (nextpc) ! 2193: *nextpc = pc; ! 2194: } ! 2195: ! 2196: struct cpum2c m2cregs[] = { ! 2197: { 0, "SFC" }, ! 2198: { 1, "DFC" }, ! 2199: { 2, "CACR" }, ! 2200: { 3, "TC" }, ! 2201: { 4, "ITT0" }, ! 2202: { 5, "ITT1" }, ! 2203: { 6, "DTT0" }, ! 2204: { 7, "DTT1" }, ! 2205: { 8, "BUSC" }, ! 2206: { 0x800, "USP" }, ! 2207: { 0x801, "VBR" }, ! 2208: { 0x802, "CAAR" }, ! 2209: { 0x803, "MSP" }, ! 2210: { 0x804, "ISP" }, ! 2211: { 0x805, "MMUS" }, ! 2212: { 0x806, "URP" }, ! 2213: { 0x807, "SRP" }, ! 2214: { 0x808, "PCR" }, ! 2215: { -1, NULL } ! 2216: }; ! 2217: ! 2218: void m68k_dumpstate_2 (uaecptr pc, uaecptr *nextpc) ! 2219: { ! 2220: int i, j; ! 2221: ! 2222: for (i = 0; i < 8; i++){ ! 2223: printf (_T(" D%d %08X "), i, m68k_dreg (regs, i)); ! 2224: if ((i & 3) == 3) printf (_T("\n")); ! 2225: } ! 2226: for (i = 0; i < 8; i++){ ! 2227: printf (_T(" A%d %08X "), i, m68k_areg (regs, i)); ! 2228: if ((i & 3) == 3) printf (_T("\n")); ! 2229: } ! 2230: if (regs.s == 0) ! 2231: regs.usp = m68k_areg (regs, 7); ! 2232: if (regs.s && regs.m) ! 2233: regs.msp = m68k_areg (regs, 7); ! 2234: if (regs.s && regs.m == 0) ! 2235: regs.isp = m68k_areg (regs, 7); ! 2236: j = 2; ! 2237: printf (_T("USP %08X ISP %08X "), regs.usp, regs.isp); ! 2238: for (i = 0; m2cregs[i].regno>= 0; i++) { ! 2239: if (!movec_illg (m2cregs[i].regno)) { ! 2240: if (!_tcscmp (m2cregs[i].regname, _T("USP")) || !_tcscmp (m2cregs[i].regname, _T("ISP"))) ! 2241: continue; ! 2242: if (j > 0 && (j % 4) == 0) ! 2243: printf (_T("\n")); ! 2244: printf (_T("%-4s %08X "), m2cregs[i].regname, val_move2c (m2cregs[i].regno)); ! 2245: j++; ! 2246: } ! 2247: } ! 2248: if (j > 0) ! 2249: printf (_T("\n")); ! 2250: printf (_T("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d STP=%d\n"), ! 2251: regs.t1, regs.t0, regs.s, regs.m, ! 2252: GET_XFLG (), GET_NFLG (), GET_ZFLG (), ! 2253: GET_VFLG (), GET_CFLG (), ! 2254: regs.intmask, regs.stopped); ! 2255: #ifdef FPUEMU ! 2256: if (currprefs.fpu_model) { ! 2257: uae_u32 fpsr; ! 2258: for (i = 0; i < 8; i++){ ! 2259: printf (_T("FP%d: %s "), i, fp_print(®s.fp[i])); ! 2260: if ((i & 3) == 3) ! 2261: printf (_T("\n")); ! 2262: } ! 2263: fpsr = fpp_get_fpsr (); ! 2264: printf (_T("FPSR: %08X FPCR: %04x FPIAR: %08x N=%d Z=%d I=%d NAN=%d\n"), ! 2265: fpsr, regs.fpcr, regs.fpiar, ! 2266: (fpsr & 0x8000000) != 0, ! 2267: (fpsr & 0x4000000) != 0, ! 2268: (fpsr & 0x2000000) != 0, ! 2269: (fpsr & 0x1000000) != 0); ! 2270: } ! 2271: #endif ! 2272: if (currprefs.mmu_model == 68030) { ! 2273: printf (_T("SRP: %llX CRP: %llX\n"), srp_030, crp_030); ! 2274: printf (_T("TT0: %08X TT1: %08X TC: %08X\n"), tt0_030, tt1_030, tc_030); ! 2275: } ! 2276: if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) { ! 2277: struct instr *dp; ! 2278: struct mnemolookup *lookup1, *lookup2; ! 2279: dp = table68k + regs.irc; ! 2280: for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++); ! 2281: dp = table68k + regs.ir; ! 2282: for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++); ! 2283: printf (_T("Prefetch %04x (%s) %04x (%s) Chip latch %08X\n"), regs.irc, lookup1->name, regs.ir, lookup2->name, regs.chipset_latch_rw); ! 2284: } ! 2285: ! 2286: if (pc != 0xffffffff) { ! 2287: m68k_disasm (pc, nextpc, 1); ! 2288: if (nextpc) ! 2289: printf (_T("Next PC: %08x\n"), *nextpc); ! 2290: } ! 2291: } ! 2292: void m68k_dumpstate (uaecptr *nextpc) ! 2293: { ! 2294: m68k_dumpstate_2 (m68k_getpc (), nextpc); ! 2295: } ! 2296: ! 2297: static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, bool plus2) ! 2298: { ! 2299: if (currprefs.cpu_model >= 68040) ! 2300: addr &= ~1; ! 2301: if (currprefs.cpu_model >= 68020) { ! 2302: if (pc == 0xffffffff) ! 2303: last_addr_for_exception_3 = regs.instruction_pc; ! 2304: else ! 2305: last_addr_for_exception_3 = pc; ! 2306: } else if (pc == 0xffffffff) { ! 2307: last_addr_for_exception_3 = m68k_getpc (); ! 2308: if (plus2) ! 2309: last_addr_for_exception_3 += 2; ! 2310: } else { ! 2311: last_addr_for_exception_3 = pc; ! 2312: } ! 2313: last_fault_for_exception_3 = addr; ! 2314: last_op_for_exception_3 = opcode; ! 2315: last_writeaccess_for_exception_3 = writeaccess; ! 2316: last_instructionaccess_for_exception_3 = instructionaccess; ! 2317: Exception (3); ! 2318: } ! 2319: ! 2320: void exception3_read(uae_u32 opcode, uaecptr addr) ! 2321: { ! 2322: exception3f (opcode, addr, false, 0, false, 0xffffffff, false); ! 2323: } ! 2324: void exception3i (uae_u32 opcode, uaecptr addr) ! 2325: { ! 2326: exception3f (opcode, addr, 0, 1, false, 0xffffffff, true); ! 2327: } ! 2328: void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc) ! 2329: { ! 2330: exception3f (opcode, addr, w, i, false, pc, true); ! 2331: } ! 2332: ! 2333: void exception2 (uaecptr addr, bool read, int size, uae_u32 fc) ! 2334: { ! 2335: if (currprefs.mmu_model == 68030) { ! 2336: uae_u32 flags = size == 1 ? MMU030_SSW_SIZE_B : (size == 2 ? MMU030_SSW_SIZE_W : MMU030_SSW_SIZE_L); ! 2337: mmu030_page_fault (addr, read, flags, fc); ! 2338: } else { ! 2339: mmu_bus_error (addr, 0, fc, read == false, size, true); ! 2340: } ! 2341: } ! 2342: ! 2343: void cpureset (void) { ! 2344: uaecptr pc; ! 2345: uaecptr ksboot = 0xf80002 - 2; /* -2 = RESET hasn't increased PC yet */ ! 2346: uae_u16 ins; ! 2347: ! 2348: if (currprefs.cpu_compatible) { ! 2349: return; ! 2350: } ! 2351: ! 2352: pc = m68k_getpc (); ! 2353: /* panic, RAM is going to disappear under PC */ ! 2354: ins = get_word (pc + 2); ! 2355: if ((ins & ~7) == 0x4ed0) { ! 2356: int reg = ins & 7; ! 2357: uae_u32 addr = m68k_areg (regs, reg); ! 2358: write_log ("reset/jmp (ax) combination emulated -> %x\n", addr); ! 2359: if (addr < 0x80000) ! 2360: addr += 0xf80000; ! 2361: m68k_setpc (addr - 2); ! 2362: return; ! 2363: } ! 2364: write_log ("M68K RESET PC=%x, rebooting..\n", pc); ! 2365: m68k_setpc (ksboot); ! 2366: } ! 2367: ! 2368: ! 2369: void m68k_setstopped (void) ! 2370: { ! 2371: regs.stopped = 1; ! 2372: /* A traced STOP instruction drops through immediately without ! 2373: actually stopping. */ ! 2374: if ((regs.spcflags & SPCFLAG_DOTRACE) == 0) ! 2375: set_special (SPCFLAG_STOP); ! 2376: else ! 2377: m68k_resumestopped (); ! 2378: } ! 2379: ! 2380: void m68k_resumestopped (void) ! 2381: { ! 2382: if (!regs.stopped) ! 2383: return; ! 2384: regs.stopped = 0; ! 2385: unset_special (SPCFLAG_STOP); ! 2386: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.