|
|
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 MOVEC_DEBUG 0 ! 10: #define MMUOP_DEBUG 2 ! 11: #define DEBUG_CD32CDTVIO 0 ! 12: ! 13: /* ! 14: * #include "compat.h" ! 15: #include "sysconfig.h" ! 16: #include "sysdeps.h" ! 17: ! 18: #include "options_cpu.h" ! 19: #include "events.h" ! 20: //#include "uae.h" ! 21: #include "memory.h" ! 22: #include "custom.h" ! 23: #include "newcpu.h" ! 24: #include "cpummu.h" ! 25: #include "cpu_prefetch.h" ! 26: //#include "autoconf.h" ! 27: //#include "traps.h" ! 28: //#include "ersatz.h" ! 29: //#include "debug.h" ! 30: //#include "gui.h" ! 31: #include "savestate.h" ! 32: #include "blitter.h" ! 33: #include "ar.h" ! 34: //#include "gayle.h" ! 35: //#include "cia.h" ! 36: //#include "inputdevice.h" ! 37: */ ! 38: ! 39: #include "compat.h" ! 40: #include "sysconfig.h" ! 41: #include "sysdeps.h" ! 42: #include "hatari-glue.h" ! 43: #include "options_cpu.h" ! 44: #include "events.h" ! 45: #include "custom.h" ! 46: #include "maccess.h" ! 47: #include "memory.h" ! 48: #include "newcpu.h" ! 49: #include "main.h" ! 50: #include "cpummu.h" ! 51: #include "cpu_prefetch.h" ! 52: #include "main.h" ! 53: #include "m68000.h" ! 54: #include "reset.h" ! 55: #include "cycInt.h" ! 56: #include "mfp.h" ! 57: #include "cart.h" ! 58: #include "dialog.h" ! 59: #include "screen.h" ! 60: #include "video.h" ! 61: #include "options.h" ! 62: #include "log.h" ! 63: #include "debugui.h" ! 64: #include "debugcpu.h" ! 65: ! 66: ! 67: #ifdef JIT ! 68: #include "jit/compemu.h" ! 69: #include <signal.h> ! 70: #else ! 71: /* Need to have these somewhere */ ! 72: // static void build_comp (void) {} ! 73: // bool check_prefs_changed_comp (void) { return false; } ! 74: #endif ! 75: /* For faster JIT cycles handling */ ! 76: signed long pissoff = 0; ! 77: ! 78: uaecptr rtarea_base = RTAREA_DEFAULT; ! 79: ! 80: /* Opcode of faulting instruction */ ! 81: static uae_u16 last_op_for_exception_3; ! 82: /* PC at fault time */ ! 83: static uaecptr last_addr_for_exception_3; ! 84: /* Address that generated the exception */ ! 85: static uaecptr last_fault_for_exception_3; ! 86: /* read (0) or write (1) access */ ! 87: static int last_writeaccess_for_exception_3; ! 88: /* instruction (1) or data (0) access */ ! 89: static int last_instructionaccess_for_exception_3; ! 90: unsigned long irqcycles[15]; ! 91: int irqdelay[15]; ! 92: int mmu_enabled, mmu_triggered; ! 93: int cpu_cycles; ! 94: static int baseclock; ! 95: int cpucycleunit; ! 96: ! 97: const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 }; ! 98: const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 }; ! 99: ! 100: int movem_index1[256]; ! 101: int movem_index2[256]; ! 102: int movem_next[256]; ! 103: ! 104: cpuop_func *cpufunctbl[65536]; ! 105: ! 106: int OpcodeFamily; ! 107: struct mmufixup mmufixup[2]; ! 108: ! 109: extern uae_u32 get_fpsr (void); ! 110: ! 111: #define COUNT_INSTRS 0 ! 112: #define MC68060_PCR 0x04300000 ! 113: #define MC68EC060_PCR 0x04310000 ! 114: ! 115: static uae_u64 srp_030, crp_030; ! 116: static uae_u32 tt0_030, tt1_030, tc_030; ! 117: static uae_u16 mmusr_030; ! 118: ! 119: static struct cache020 caches020[CACHELINES020]; ! 120: static struct cache030 icaches030[CACHELINES030]; ! 121: static struct cache030 dcaches030[CACHELINES030]; ! 122: static struct cache040 caches040[CACHESETS040]; ! 123: static void InterruptAddJitter (int Level , int Pending); ! 124: ! 125: static void m68k_disasm_2 (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode); ! 126: ! 127: ! 128: #if COUNT_INSTRS ! 129: static unsigned long int instrcount[65536]; ! 130: static uae_u16 opcodenums[65536]; ! 131: ! 132: static int compfn (const void *el1, const void *el2) ! 133: { ! 134: return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2]; ! 135: } ! 136: ! 137: static TCHAR *icountfilename (void) ! 138: { ! 139: TCHAR *name = getenv ("INSNCOUNT"); ! 140: if (name) ! 141: return name; ! 142: return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount"; ! 143: } ! 144: ! 145: void dump_counts (void) ! 146: { ! 147: FILE *f = fopen (icountfilename (), "w"); ! 148: unsigned long int total; ! 149: int i; ! 150: ! 151: write_log ("Writing instruction count file...\n"); ! 152: for (i = 0; i < 65536; i++) { ! 153: opcodenums[i] = i; ! 154: total += instrcount[i]; ! 155: } ! 156: qsort (opcodenums, 65536, sizeof (uae_u16), compfn); ! 157: ! 158: fprintf (f, "Total: %lu\n", total); ! 159: for (i=0; i < 65536; i++) { ! 160: unsigned long int cnt = instrcount[opcodenums[i]]; ! 161: struct instr *dp; ! 162: struct mnemolookup *lookup; ! 163: if (!cnt) ! 164: break; ! 165: dp = table68k + opcodenums[i]; ! 166: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) ! 167: ; ! 168: fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name); ! 169: } ! 170: fclose (f); ! 171: } ! 172: #else ! 173: void dump_counts (void) ! 174: { ! 175: } ! 176: #endif ! 177: ! 178: ! 179: uae_u32 (*x_prefetch)(int); ! 180: uae_u32 (*x_next_iword)(void); ! 181: uae_u32 (*x_next_ilong)(void); ! 182: uae_u32 (*x_get_long)(uaecptr); ! 183: uae_u32 (*x_get_word)(uaecptr); ! 184: uae_u32 (*x_get_byte)(uaecptr); ! 185: void (*x_put_long)(uaecptr,uae_u32); ! 186: void (*x_put_word)(uaecptr,uae_u32); ! 187: void (*x_put_byte)(uaecptr,uae_u32); ! 188: ! 189: // shared memory access functions ! 190: static void set_x_funcs (void) ! 191: { ! 192: if (currprefs.mmu_model) { ! 193: x_prefetch = get_iword_mmu; ! 194: x_next_iword = next_iword_mmu; ! 195: x_next_ilong = next_ilong_mmu; ! 196: x_put_long = put_long_mmu; ! 197: x_put_word = put_word_mmu; ! 198: x_put_byte = put_byte_mmu; ! 199: x_get_long = get_long_mmu; ! 200: x_get_word = get_word_mmu; ! 201: x_get_byte = get_byte_mmu; ! 202: } else if (!currprefs.cpu_cycle_exact) { ! 203: x_prefetch = get_iword; ! 204: x_next_iword = next_iword; ! 205: x_next_ilong = next_ilong; ! 206: x_put_long = put_long; ! 207: x_put_word = put_word; ! 208: x_put_byte = put_byte; ! 209: x_get_long = get_long; ! 210: x_get_word = get_word; ! 211: x_get_byte = get_byte; ! 212: } else if (currprefs.cpu_model < 68020) { ! 213: x_prefetch = NULL; ! 214: x_next_iword = NULL; ! 215: x_next_ilong = NULL; ! 216: x_put_long = put_long_ce; ! 217: x_put_word = put_word_ce; ! 218: x_put_byte = put_byte_ce; ! 219: x_get_long = get_long_ce; ! 220: x_get_word = get_word_ce; ! 221: x_get_byte = get_byte_ce; ! 222: } else if (currprefs.cpu_model == 68020) { ! 223: x_prefetch = get_word_ce020_prefetch; ! 224: x_next_iword = next_iword_020ce; ! 225: x_next_ilong = next_ilong_020ce; ! 226: x_put_long = put_long_ce020; ! 227: x_put_word = put_word_ce020; ! 228: x_put_byte = put_byte_ce020; ! 229: x_get_long = get_long_ce020; ! 230: x_get_word = get_word_ce020; ! 231: x_get_byte = get_byte_ce020; ! 232: } else { ! 233: x_prefetch = get_word_ce030_prefetch; ! 234: x_next_iword = next_iword_030ce; ! 235: x_next_ilong = next_ilong_030ce; ! 236: x_put_long = put_long_ce030; ! 237: x_put_word = put_word_ce030; ! 238: x_put_byte = put_byte_ce030; ! 239: x_get_long = get_long_ce030; ! 240: x_get_word = get_word_ce030; ! 241: x_get_byte = get_byte_ce030; ! 242: } ! 243: ! 244: } ! 245: ! 246: static void set_cpu_caches (void) ! 247: { ! 248: int i; ! 249: ! 250: for (i = 0; i < CPU_PIPELINE_MAX; i++) ! 251: regs.prefetch020addr[i] = 0xffffffff; ! 252: ! 253: #ifdef JIT ! 254: if (currprefs.cachesize) { ! 255: if (currprefs.cpu_model < 68040) { ! 256: set_cache_state (regs.cacr & 1); ! 257: if (regs.cacr & 0x08) { ! 258: flush_icache (0, 3); ! 259: } ! 260: } else { ! 261: set_cache_state ((regs.cacr & 0x8000) ? 1 : 0); ! 262: } ! 263: } ! 264: #endif ! 265: if (currprefs.cpu_model == 68020) { ! 266: if (regs.cacr & 0x08) { // clear instr cache ! 267: for (i = 0; i < CACHELINES020; i++) ! 268: caches020[i].valid = 0; ! 269: } ! 270: if (regs.cacr & 0x04) { // clear entry in instr cache ! 271: caches020[(regs.caar >> 2) & (CACHELINES020 - 1)].valid = 0; ! 272: regs.cacr &= ~0x04; ! 273: } ! 274: } else if (currprefs.cpu_model == 68030) { ! 275: //regs.cacr |= 0x100; ! 276: if (regs.cacr & 0x08) { // clear instr cache ! 277: for (i = 0; i < CACHELINES030; i++) { ! 278: icaches030[i].valid[0] = 0; ! 279: icaches030[i].valid[1] = 0; ! 280: icaches030[i].valid[2] = 0; ! 281: icaches030[i].valid[3] = 0; ! 282: } ! 283: } ! 284: if (regs.cacr & 0x04) { // clear entry in instr cache ! 285: icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0; ! 286: regs.cacr &= ~0x04; ! 287: } ! 288: if (regs.cacr & 0x800) { // clear data cache ! 289: for (i = 0; i < CACHELINES030; i++) { ! 290: dcaches030[i].valid[0] = 0; ! 291: dcaches030[i].valid[1] = 0; ! 292: dcaches030[i].valid[2] = 0; ! 293: dcaches030[i].valid[3] = 0; ! 294: } ! 295: regs.cacr &= ~0x800; ! 296: } ! 297: if (regs.cacr & 0x400) { // clear entry in data cache ! 298: dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0; ! 299: regs.cacr &= ~0x400; ! 300: } ! 301: } else if (currprefs.cpu_model == 68040) { ! 302: if (!(regs.cacr & 0x8000)) { ! 303: for (i = 0; i < CACHESETS040; i++) { ! 304: caches040[i].valid[0] = 0; ! 305: caches040[i].valid[1] = 0; ! 306: caches040[i].valid[2] = 0; ! 307: caches040[i].valid[3] = 0; ! 308: } ! 309: } ! 310: } ! 311: } ! 312: ! 313: STATIC_INLINE void count_instr (unsigned int opcode) ! 314: { ! 315: } ! 316: ! 317: static unsigned long REGPARAM3 op_illg_1 (uae_u32 opcode) REGPARAM; ! 318: ! 319: static unsigned long REGPARAM2 op_illg_1 (uae_u32 opcode) ! 320: { ! 321: op_illg (opcode); ! 322: return 4; ! 323: } ! 324: ! 325: void build_cpufunctbl (void) ! 326: { ! 327: int i, opcnt; ! 328: unsigned long opcode; ! 329: const struct cputbl *tbl = 0; ! 330: int lvl; ! 331: ! 332: switch (currprefs.cpu_model) ! 333: { ! 334: #ifdef CPUEMU_0 ! 335: #ifndef CPUEMU_68000_ONLY ! 336: case 68060: ! 337: lvl = 5; ! 338: tbl = op_smalltbl_0_ff; ! 339: if (currprefs.cpu_cycle_exact) ! 340: tbl = op_smalltbl_21_ff; ! 341: if (currprefs.mmu_model) ! 342: tbl = op_smalltbl_31_ff; ! 343: break; ! 344: case 68040: ! 345: lvl = 4; ! 346: tbl = op_smalltbl_1_ff; ! 347: if (currprefs.cpu_cycle_exact) ! 348: tbl = op_smalltbl_22_ff; ! 349: if (currprefs.mmu_model) ! 350: tbl = op_smalltbl_31_ff; ! 351: break; ! 352: case 68030: ! 353: lvl = 3; ! 354: tbl = op_smalltbl_2_ff; ! 355: if (currprefs.cpu_cycle_exact) ! 356: tbl = op_smalltbl_23_ff; ! 357: break; ! 358: case 68020: ! 359: lvl = 2; ! 360: tbl = op_smalltbl_3_ff; ! 361: if (currprefs.cpu_cycle_exact) ! 362: tbl = op_smalltbl_20_ff; ! 363: break; ! 364: case 68010: ! 365: lvl = 1; ! 366: tbl = op_smalltbl_4_ff; ! 367: break; ! 368: #endif ! 369: #endif ! 370: default: ! 371: changed_prefs.cpu_model = currprefs.cpu_model = 68000; ! 372: case 68000: ! 373: lvl = 0; ! 374: tbl = op_smalltbl_5_ff; ! 375: #ifdef CPUEMU_11 ! 376: if (currprefs.cpu_compatible) ! 377: tbl = op_smalltbl_11_ff; /* prefetch */ ! 378: #endif ! 379: #ifdef CPUEMU_12 ! 380: if (currprefs.cpu_cycle_exact) ! 381: tbl = op_smalltbl_12_ff; /* prefetch and cycle-exact */ ! 382: #endif ! 383: break; ! 384: } ! 385: ! 386: if (tbl == 0) { ! 387: write_log ("no CPU emulation cores available CPU=%d!", currprefs.cpu_model); ! 388: abort (); ! 389: } ! 390: ! 391: for (opcode = 0; opcode < 65536; opcode++) ! 392: cpufunctbl[opcode] = op_illg_1; ! 393: for (i = 0; tbl[i].handler != NULL; i++) { ! 394: opcode = tbl[i].opcode; ! 395: cpufunctbl[opcode] = tbl[i].handler; ! 396: } ! 397: ! 398: /* hack fpu to 68000/68010 mode */ ! 399: if (currprefs.fpu_model && currprefs.cpu_model < 68020) { ! 400: tbl = op_smalltbl_3_ff; ! 401: for (i = 0; tbl[i].handler != NULL; i++) { ! 402: if ((tbl[i].opcode & 0xfe00) == 0xf200) ! 403: cpufunctbl[tbl[i].opcode] = tbl[i].handler; ! 404: } ! 405: } ! 406: opcnt = 0; ! 407: for (opcode = 0; opcode < 65536; opcode++) { ! 408: cpuop_func *f; ! 409: ! 410: if (table68k[opcode].mnemo == i_ILLG) ! 411: continue; ! 412: if (currprefs.fpu_model && currprefs.cpu_model < 68020) { ! 413: /* more hack fpu to 68000/68010 mode */ ! 414: if (table68k[opcode].clev > lvl && (opcode & 0xfe00) != 0xf200) ! 415: continue; ! 416: } else if (table68k[opcode].clev > lvl) { ! 417: continue; ! 418: } ! 419: ! 420: if (table68k[opcode].handler != -1) { ! 421: int idx = table68k[opcode].handler; ! 422: f = cpufunctbl[idx]; ! 423: if (f == op_illg_1) ! 424: abort (); ! 425: cpufunctbl[opcode] = f; ! 426: opcnt++; ! 427: } ! 428: } ! 429: write_log ("Building CPU, %d opcodes (%d %d %d)\n", ! 430: opcnt, lvl, ! 431: currprefs.cpu_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0, currprefs.address_space_24); ! 432: write_log ("CPU=%d, FPU=%d, MMU=%d, JIT%s=%d.\n", ! 433: currprefs.cpu_model, currprefs.fpu_model, ! 434: currprefs.mmu_model, ! 435: currprefs.cachesize ? (currprefs.compfpu ? "=CPU/FPU" : "=CPU") : "", ! 436: currprefs.cachesize); ! 437: #ifdef JIT ! 438: build_comp (); ! 439: #endif ! 440: set_cpu_caches (); ! 441: if (currprefs.mmu_model) { ! 442: mmu_reset (); ! 443: mmu_set_tc (regs.tcr); ! 444: mmu_set_super (regs.s != 0); ! 445: } ! 446: } ! 447: ! 448: void fill_prefetch_slow (void) ! 449: { ! 450: if (currprefs.mmu_model) ! 451: return; ! 452: regs.ir = x_get_word (m68k_getpc ()); ! 453: regs.irc = x_get_word (m68k_getpc () + 2); ! 454: } ! 455: ! 456: unsigned long cycles_mask, cycles_val; ! 457: ! 458: static void update_68k_cycles (void) ! 459: { ! 460: cycles_mask = 0; ! 461: cycles_val = currprefs.m68k_speed; ! 462: if (currprefs.m68k_speed < 1) { ! 463: cycles_mask = 0xFFFFFFFF; ! 464: cycles_val = 0; ! 465: } ! 466: currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier; ! 467: currprefs.cpu_frequency = changed_prefs.cpu_frequency; ! 468: ! 469: baseclock = currprefs.ntscmode ? 28636360 : 28375160; ! 470: cpucycleunit = CYCLE_UNIT / 2; ! 471: if (currprefs.cpu_clock_multiplier) { ! 472: if (currprefs.cpu_clock_multiplier >= 256) { ! 473: cpucycleunit = CYCLE_UNIT / (currprefs.cpu_clock_multiplier >> 8); ! 474: } else { ! 475: cpucycleunit = CYCLE_UNIT * currprefs.cpu_clock_multiplier; ! 476: } ! 477: } else if (currprefs.cpu_frequency) { ! 478: cpucycleunit = CYCLE_UNIT * baseclock / currprefs.cpu_frequency; ! 479: } ! 480: if (cpucycleunit < 1) ! 481: cpucycleunit = 1; ! 482: if (currprefs.cpu_cycle_exact) ! 483: write_log ("CPU cycleunit: %d (%.3f)\n", cpucycleunit, (float)cpucycleunit / CYCLE_UNIT); ! 484: config_changed = 1; ! 485: } ! 486: ! 487: static void prefs_changed_cpu (void) ! 488: { ! 489: fixup_cpu (&changed_prefs); ! 490: currprefs.cpu_model = changed_prefs.cpu_model; ! 491: currprefs.fpu_model = changed_prefs.fpu_model; ! 492: currprefs.mmu_model = changed_prefs.mmu_model; ! 493: currprefs.cpu_compatible = changed_prefs.cpu_compatible; ! 494: currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact; ! 495: currprefs.blitter_cycle_exact = changed_prefs.cpu_cycle_exact; ! 496: } ! 497: ! 498: void check_prefs_changed_cpu (void) ! 499: { ! 500: bool changed = 0; ! 501: ! 502: if (!config_changed) ! 503: return; ! 504: #ifdef JIT ! 505: changed = check_prefs_changed_comp (); ! 506: #endif ! 507: if (changed ! 508: || currprefs.cpu_model != changed_prefs.cpu_model ! 509: || currprefs.fpu_model != changed_prefs.fpu_model ! 510: || currprefs.mmu_model != changed_prefs.mmu_model ! 511: || currprefs.cpu_compatible != changed_prefs.cpu_compatible ! 512: || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact) { ! 513: ! 514: prefs_changed_cpu (); ! 515: if (!currprefs.cpu_compatible && changed_prefs.cpu_compatible) ! 516: fill_prefetch_slow (); ! 517: build_cpufunctbl (); ! 518: changed = 1; ! 519: } ! 520: if (changed ! 521: || currprefs.m68k_speed != changed_prefs.m68k_speed ! 522: || currprefs.cpu_clock_multiplier != changed_prefs.cpu_clock_multiplier ! 523: || currprefs.cpu_frequency != changed_prefs.cpu_frequency) { ! 524: currprefs.m68k_speed = changed_prefs.m68k_speed; ! 525: reset_frame_rate_hack (); ! 526: update_68k_cycles (); ! 527: changed = 1; ! 528: } ! 529: ! 530: if (currprefs.cpu_idle != changed_prefs.cpu_idle) { ! 531: currprefs.cpu_idle = changed_prefs.cpu_idle; ! 532: } ! 533: if (changed) ! 534: set_special (SPCFLAG_BRK); ! 535: ! 536: } ! 537: ! 538: void init_m68k (void) ! 539: { ! 540: int i; ! 541: ! 542: prefs_changed_cpu (); ! 543: update_68k_cycles (); ! 544: ! 545: for (i = 0 ; i < 256 ; i++) { ! 546: int j; ! 547: for (j = 0 ; j < 8 ; j++) { ! 548: if (i & (1 << j)) break; ! 549: } ! 550: movem_index1[i] = j; ! 551: movem_index2[i] = 7-j; ! 552: movem_next[i] = i & (~(1 << j)); ! 553: } ! 554: ! 555: #if COUNT_INSTRS ! 556: { ! 557: FILE *f = fopen (icountfilename (), "r"); ! 558: memset (instrcount, 0, sizeof instrcount); ! 559: if (f) { ! 560: uae_u32 opcode, count, total; ! 561: TCHAR name[20]; ! 562: write_log ("Reading instruction count file...\n"); ! 563: fscanf (f, "Total: %lu\n", &total); ! 564: while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) { ! 565: instrcount[opcode] = count; ! 566: } ! 567: fclose (f); ! 568: } ! 569: } ! 570: #endif ! 571: write_log ("Building CPU table for configuration: %d", currprefs.cpu_model); ! 572: regs.address_space_mask = 0xffffffff; ! 573: // if (currprefs.cpu_compatible) { ! 574: // if (currprefs.address_space_24 && currprefs.cpu_model >= 68030) ! 575: // currprefs.address_space_24 = false; ! 576: // } ! 577: if (currprefs.fpu_model > 0) ! 578: write_log ("/%d", currprefs.fpu_model); ! 579: if (currprefs.cpu_cycle_exact) { ! 580: if (currprefs.cpu_model == 68000) ! 581: write_log (" prefetch and cycle-exact"); ! 582: else ! 583: write_log (" ~cycle-exact"); ! 584: } else if (currprefs.cpu_compatible) ! 585: write_log (" prefetch"); ! 586: if (currprefs.address_space_24) { ! 587: regs.address_space_mask = 0x00ffffff; ! 588: write_log (" 24-bit"); ! 589: } ! 590: write_log ("\n"); ! 591: ! 592: read_table68k (); ! 593: do_merges (); ! 594: ! 595: write_log ("%d CPU functions\n", nr_cpuop_funcs); ! 596: ! 597: build_cpufunctbl (); ! 598: set_x_funcs (); ! 599: ! 600: #ifdef JIT ! 601: /* We need to check whether NATMEM settings have changed ! 602: * before starting the CPU */ ! 603: check_prefs_changed_comp (); ! 604: #endif ! 605: } ! 606: ! 607: struct regstruct regs, mmu_backup_regs; ! 608: struct flag_struct regflags; ! 609: static struct regstruct regs_backup[16]; ! 610: static int backup_pointer = 0; ! 611: static long int m68kpc_offset; ! 612: ! 613: #define get_ibyte_1(o) get_byte (regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1) ! 614: #define get_iword_1(o) get_word (regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) ! 615: #define get_ilong_1(o) get_long (regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) ! 616: ! 617: static uae_s32 ShowEA (FILE *f, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode) ! 618: { ! 619: uae_u16 dp; ! 620: uae_s8 disp8; ! 621: uae_s16 disp16; ! 622: int r; ! 623: uae_u32 dispreg; ! 624: uaecptr addr = 0; ! 625: uae_s32 offset = 0; ! 626: TCHAR buffer[80]; ! 627: ! 628: switch (mode){ ! 629: case Dreg: ! 630: _stprintf (buffer, "D%d", reg); ! 631: break; ! 632: case Areg: ! 633: _stprintf (buffer, "A%d", reg); ! 634: break; ! 635: case Aind: ! 636: _stprintf (buffer, "(A%d)", reg); ! 637: addr = regs.regs[reg + 8]; ! 638: break; ! 639: case Aipi: ! 640: _stprintf (buffer, "(A%d)+", reg); ! 641: addr = regs.regs[reg + 8]; ! 642: break; ! 643: case Apdi: ! 644: _stprintf (buffer, "-(A%d)", reg); ! 645: addr = regs.regs[reg + 8]; ! 646: break; ! 647: case Ad16: ! 648: { ! 649: TCHAR offtxt[80]; ! 650: disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; ! 651: if (disp16 < 0) ! 652: _stprintf (offtxt, "-$%04x", -disp16); ! 653: else ! 654: _stprintf (offtxt, "$%04x", disp16); ! 655: addr = m68k_areg (regs, reg) + disp16; ! 656: _stprintf (buffer, "(A%d, %s) == $%08lx", reg, offtxt, (unsigned long)addr); ! 657: } ! 658: break; ! 659: case Ad8r: ! 660: dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; ! 661: disp8 = dp & 0xFF; ! 662: r = (dp & 0x7000) >> 12; ! 663: dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r); ! 664: if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); ! 665: dispreg <<= (dp >> 9) & 3; ! 666: ! 667: if (dp & 0x100) { ! 668: uae_s32 outer = 0, disp = 0; ! 669: uae_s32 base = m68k_areg (regs, reg); ! 670: TCHAR name[10]; ! 671: _stprintf (name, "A%d, ", reg); ! 672: if (dp & 0x80) { base = 0; name[0] = 0; } ! 673: if (dp & 0x40) dispreg = 0; ! 674: if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } ! 675: if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } ! 676: base += disp; ! 677: ! 678: if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } ! 679: if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } ! 680: ! 681: if (!(dp & 4)) base += dispreg; ! 682: if ((dp & 3) && !safemode) base = get_long (base); ! 683: if (dp & 4) base += dispreg; ! 684: ! 685: addr = base + outer; ! 686: _stprintf (buffer, "(%s%c%d.%c*%d+%d)+%d == $%08lx", name, ! 687: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', ! 688: 1 << ((dp >> 9) & 3), ! 689: disp, outer, ! 690: (unsigned long)addr); ! 691: } else { ! 692: addr = m68k_areg (regs, reg) + (uae_s32)((uae_s8)disp8) + dispreg; ! 693: _stprintf (buffer, "(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg, ! 694: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', ! 695: 1 << ((dp >> 9) & 3), disp8, ! 696: (unsigned long)addr); ! 697: } ! 698: break; ! 699: case PC16: ! 700: addr = m68k_getpc () + m68kpc_offset; ! 701: disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; ! 702: addr += (uae_s16)disp16; ! 703: _stprintf (buffer, "(PC,$%04x) == $%08lx", disp16 & 0xffff, (unsigned long)addr); ! 704: break; ! 705: case PC8r: ! 706: addr = m68k_getpc () + m68kpc_offset; ! 707: dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; ! 708: disp8 = dp & 0xFF; ! 709: r = (dp & 0x7000) >> 12; ! 710: dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r); ! 711: if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); ! 712: dispreg <<= (dp >> 9) & 3; ! 713: ! 714: if (dp & 0x100) { ! 715: uae_s32 outer = 0, disp = 0; ! 716: uae_s32 base = addr; ! 717: TCHAR name[10]; ! 718: _stprintf (name, "PC, "); ! 719: if (dp & 0x80) { base = 0; name[0] = 0; } ! 720: if (dp & 0x40) dispreg = 0; ! 721: if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } ! 722: if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } ! 723: base += disp; ! 724: ! 725: if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } ! 726: if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } ! 727: ! 728: if (!(dp & 4)) base += dispreg; ! 729: if ((dp & 3) && !safemode) base = get_long (base); ! 730: if (dp & 4) base += dispreg; ! 731: ! 732: addr = base + outer; ! 733: _stprintf (buffer, "(%s%c%d.%c*%d+%d)+%d == $%08lx", name, ! 734: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', ! 735: 1 << ((dp >> 9) & 3), ! 736: disp, outer, ! 737: (unsigned long)addr); ! 738: } else { ! 739: addr += (uae_s32)((uae_s8)disp8) + dispreg; ! 740: _stprintf (buffer, "(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D', ! 741: (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3), ! 742: disp8, (unsigned long)addr); ! 743: } ! 744: break; ! 745: case absw: ! 746: addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); ! 747: _stprintf (buffer, "$%08lx", (unsigned long)addr); ! 748: m68kpc_offset += 2; ! 749: break; ! 750: case absl: ! 751: addr = get_ilong_1 (m68kpc_offset); ! 752: _stprintf (buffer, "$%08lx", (unsigned long)addr); ! 753: m68kpc_offset += 4; ! 754: break; ! 755: case imm: ! 756: switch (size){ ! 757: case sz_byte: ! 758: _stprintf (buffer, "#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff)); ! 759: m68kpc_offset += 2; ! 760: break; ! 761: case sz_word: ! 762: _stprintf (buffer, "#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff)); ! 763: m68kpc_offset += 2; ! 764: break; ! 765: case sz_long: ! 766: _stprintf (buffer, "#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset))); ! 767: m68kpc_offset += 4; ! 768: break; ! 769: default: ! 770: break; ! 771: } ! 772: break; ! 773: case imm0: ! 774: offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); ! 775: m68kpc_offset += 2; ! 776: _stprintf (buffer, "#$%02x", (unsigned int)(offset & 0xff)); ! 777: break; ! 778: case imm1: ! 779: offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); ! 780: m68kpc_offset += 2; ! 781: buffer[0] = 0; ! 782: _stprintf (buffer, "#$%04x", (unsigned int)(offset & 0xffff)); ! 783: break; ! 784: case imm2: ! 785: offset = (uae_s32)get_ilong_1 (m68kpc_offset); ! 786: m68kpc_offset += 4; ! 787: _stprintf (buffer, "#$%08lx", (unsigned long)offset); ! 788: break; ! 789: case immi: ! 790: offset = (uae_s32)(uae_s8)(reg & 0xff); ! 791: _stprintf (buffer, "#$%08lx", (unsigned long)offset); ! 792: break; ! 793: default: ! 794: break; ! 795: } ! 796: if (buf == 0) ! 797: f_out (f, "%s", buffer); ! 798: else ! 799: _tcscat (buf, buffer); ! 800: if (eaddr) ! 801: *eaddr = addr; ! 802: return offset; ! 803: } ! 804: ! 805: #if 0 ! 806: /* The plan is that this will take over the job of exception 3 handling - ! 807: * the CPU emulation functions will just do a longjmp to m68k_go whenever ! 808: * they hit an odd address. */ ! 809: static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val) ! 810: { ! 811: uae_u16 dp; ! 812: uae_s8 disp8; ! 813: uae_s16 disp16; ! 814: int r; ! 815: uae_u32 dispreg; ! 816: uaecptr addr; ! 817: uae_s32 offset = 0; ! 818: ! 819: switch (mode){ ! 820: case Dreg: ! 821: *val = m68k_dreg (regs, reg); ! 822: return 1; ! 823: case Areg: ! 824: *val = m68k_areg (regs, reg); ! 825: return 1; ! 826: ! 827: case Aind: ! 828: case Aipi: ! 829: addr = m68k_areg (regs, reg); ! 830: break; ! 831: case Apdi: ! 832: addr = m68k_areg (regs, reg); ! 833: break; ! 834: case Ad16: ! 835: disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; ! 836: addr = m68k_areg (regs, reg) + (uae_s16)disp16; ! 837: break; ! 838: case Ad8r: ! 839: addr = m68k_areg (regs, reg); ! 840: d8r_common: ! 841: dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; ! 842: disp8 = dp & 0xFF; ! 843: r = (dp & 0x7000) >> 12; ! 844: dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r); ! 845: if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); ! 846: dispreg <<= (dp >> 9) & 3; ! 847: ! 848: if (dp & 0x100) { ! 849: uae_s32 outer = 0, disp = 0; ! 850: uae_s32 base = addr; ! 851: if (dp & 0x80) base = 0; ! 852: if (dp & 0x40) dispreg = 0; ! 853: if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } ! 854: if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } ! 855: base += disp; ! 856: ! 857: if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } ! 858: if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } ! 859: ! 860: if (!(dp & 4)) base += dispreg; ! 861: if (dp & 3) base = get_long (base); ! 862: if (dp & 4) base += dispreg; ! 863: ! 864: addr = base + outer; ! 865: } else { ! 866: addr += (uae_s32)((uae_s8)disp8) + dispreg; ! 867: } ! 868: break; ! 869: case PC16: ! 870: addr = m68k_getpc () + m68kpc_offset; ! 871: disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; ! 872: addr += (uae_s16)disp16; ! 873: break; ! 874: case PC8r: ! 875: addr = m68k_getpc () + m68kpc_offset; ! 876: goto d8r_common; ! 877: case absw: ! 878: addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); ! 879: m68kpc_offset += 2; ! 880: break; ! 881: case absl: ! 882: addr = get_ilong_1 (m68kpc_offset); ! 883: m68kpc_offset += 4; ! 884: break; ! 885: case imm: ! 886: switch (size){ ! 887: case sz_byte: ! 888: *val = get_iword_1 (m68kpc_offset) & 0xff; ! 889: m68kpc_offset += 2; ! 890: break; ! 891: case sz_word: ! 892: *val = get_iword_1 (m68kpc_offset) & 0xffff; ! 893: m68kpc_offset += 2; ! 894: break; ! 895: case sz_long: ! 896: *val = get_ilong_1 (m68kpc_offset); ! 897: m68kpc_offset += 4; ! 898: break; ! 899: default: ! 900: break; ! 901: } ! 902: return 1; ! 903: case imm0: ! 904: *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); ! 905: m68kpc_offset += 2; ! 906: return 1; ! 907: case imm1: ! 908: *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); ! 909: m68kpc_offset += 2; ! 910: return 1; ! 911: case imm2: ! 912: *val = get_ilong_1 (m68kpc_offset); ! 913: m68kpc_offset += 4; ! 914: return 1; ! 915: case immi: ! 916: *val = (uae_s32)(uae_s8)(reg & 0xff); ! 917: return 1; ! 918: default: ! 919: addr = 0; ! 920: break; ! 921: } ! 922: if ((addr & 1) == 0) ! 923: return 1; ! 924: ! 925: last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset; ! 926: last_fault_for_exception_3 = addr; ! 927: last_writeaccess_for_exception_3 = 0; ! 928: last_instructionaccess_for_exception_3 = 0; ! 929: return 0; ! 930: } ! 931: #endif ! 932: ! 933: int get_cpu_model (void) ! 934: { ! 935: return currprefs.cpu_model; ! 936: } ! 937: ! 938: /* ! 939: * extract bitfield data from memory and return it in the MSBs ! 940: * bdata caches the unmodified data for put_bitfield() ! 941: */ ! 942: uae_u32 REGPARAM2 get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) ! 943: { ! 944: uae_u32 tmp, res, mask; ! 945: ! 946: offset &= 7; ! 947: mask = 0xffffffffu << (32 - width); ! 948: switch ((offset + width + 7) >> 3) { ! 949: case 1: ! 950: tmp = get_byte (src); ! 951: res = tmp << (24 + offset); ! 952: bdata[0] = tmp & ~(mask >> (24 + offset)); ! 953: break; ! 954: case 2: ! 955: tmp = get_word (src); ! 956: res = tmp << (16 + offset); ! 957: bdata[0] = tmp & ~(mask >> (16 + offset)); ! 958: break; ! 959: case 3: ! 960: tmp = get_word (src); ! 961: res = tmp << (16 + offset); ! 962: bdata[0] = tmp & ~(mask >> (16 + offset)); ! 963: tmp = get_byte (src + 2); ! 964: res |= tmp << (8 + offset); ! 965: bdata[1] = tmp & ~(mask >> (8 + offset)); ! 966: break; ! 967: case 4: ! 968: tmp = get_long (src); ! 969: res = tmp << offset; ! 970: bdata[0] = tmp & ~(mask >> offset); ! 971: break; ! 972: case 5: ! 973: tmp = get_long (src); ! 974: res = tmp << offset; ! 975: bdata[0] = tmp & ~(mask >> offset); ! 976: tmp = get_byte (src + 4); ! 977: res |= tmp >> (8 - offset); ! 978: bdata[1] = tmp & ~(mask << (8 - offset)); ! 979: break; ! 980: default: ! 981: /* Panic? */ ! 982: res = 0; ! 983: break; ! 984: } ! 985: return res; ! 986: } ! 987: /* ! 988: * write bitfield data (in the LSBs) back to memory, upper bits ! 989: * must be cleared already. ! 990: */ ! 991: void REGPARAM2 put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) ! 992: { ! 993: offset = (offset & 7) + width; ! 994: switch ((offset + 7) >> 3) { ! 995: case 1: ! 996: put_byte (dst, bdata[0] | (val << (8 - offset))); ! 997: break; ! 998: case 2: ! 999: put_word (dst, bdata[0] | (val << (16 - offset))); ! 1000: break; ! 1001: case 3: ! 1002: put_word (dst, bdata[0] | (val >> (offset - 16))); ! 1003: put_byte (dst + 2, bdata[1] | (val << (24 - offset))); ! 1004: break; ! 1005: case 4: ! 1006: put_long (dst, bdata[0] | (val << (32 - offset))); ! 1007: break; ! 1008: case 5: ! 1009: put_long (dst, bdata[0] | (val >> (offset - 32))); ! 1010: put_byte (dst + 4, bdata[1] | (val << (40 - offset))); ! 1011: break; ! 1012: } ! 1013: } ! 1014: ! 1015: uae_u32 REGPARAM2 x_get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) ! 1016: { ! 1017: uae_u32 tmp, res, mask; ! 1018: ! 1019: offset &= 7; ! 1020: mask = 0xffffffffu << (32 - width); ! 1021: switch ((offset + width + 7) >> 3) { ! 1022: case 1: ! 1023: tmp = x_get_byte (src); ! 1024: res = tmp << (24 + offset); ! 1025: bdata[0] = tmp & ~(mask >> (24 + offset)); ! 1026: break; ! 1027: case 2: ! 1028: tmp = x_get_word (src); ! 1029: res = tmp << (16 + offset); ! 1030: bdata[0] = tmp & ~(mask >> (16 + offset)); ! 1031: break; ! 1032: case 3: ! 1033: tmp = x_get_word (src); ! 1034: res = tmp << (16 + offset); ! 1035: bdata[0] = tmp & ~(mask >> (16 + offset)); ! 1036: tmp = x_get_byte (src + 2); ! 1037: res |= tmp << (8 + offset); ! 1038: bdata[1] = tmp & ~(mask >> (8 + offset)); ! 1039: break; ! 1040: case 4: ! 1041: tmp = x_get_long (src); ! 1042: res = tmp << offset; ! 1043: bdata[0] = tmp & ~(mask >> offset); ! 1044: break; ! 1045: case 5: ! 1046: tmp = x_get_long (src); ! 1047: res = tmp << offset; ! 1048: bdata[0] = tmp & ~(mask >> offset); ! 1049: tmp = x_get_byte (src + 4); ! 1050: res |= tmp >> (8 - offset); ! 1051: bdata[1] = tmp & ~(mask << (8 - offset)); ! 1052: break; ! 1053: default: ! 1054: /* Panic? */ ! 1055: res = 0; ! 1056: break; ! 1057: } ! 1058: return res; ! 1059: } ! 1060: ! 1061: void REGPARAM2 x_put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) ! 1062: { ! 1063: offset = (offset & 7) + width; ! 1064: switch ((offset + 7) >> 3) { ! 1065: case 1: ! 1066: x_put_byte (dst, bdata[0] | (val << (8 - offset))); ! 1067: break; ! 1068: case 2: ! 1069: x_put_word (dst, bdata[0] | (val << (16 - offset))); ! 1070: break; ! 1071: case 3: ! 1072: x_put_word (dst, bdata[0] | (val >> (offset - 16))); ! 1073: x_put_byte (dst + 2, bdata[1] | (val << (24 - offset))); ! 1074: break; ! 1075: case 4: ! 1076: x_put_long (dst, bdata[0] | (val << (32 - offset))); ! 1077: break; ! 1078: case 5: ! 1079: x_put_long (dst, bdata[0] | (val >> (offset - 32))); ! 1080: x_put_byte (dst + 4, bdata[1] | (val << (40 - offset))); ! 1081: break; ! 1082: } ! 1083: } ! 1084: ! 1085: uae_u32 REGPARAM2 get_disp_ea_020 (uae_u32 base, uae_u32 dp) ! 1086: { ! 1087: int reg = (dp >> 12) & 15; ! 1088: uae_s32 regd = regs.regs[reg]; ! 1089: if ((dp & 0x800) == 0) ! 1090: regd = (uae_s32)(uae_s16)regd; ! 1091: regd <<= (dp >> 9) & 3; ! 1092: if (dp & 0x100) { ! 1093: uae_s32 outer = 0; ! 1094: if (dp & 0x80) base = 0; ! 1095: if (dp & 0x40) regd = 0; ! 1096: ! 1097: if ((dp & 0x30) == 0x20) ! 1098: base += (uae_s32)(uae_s16) next_iword (); ! 1099: if ((dp & 0x30) == 0x30) ! 1100: base += next_ilong (); ! 1101: ! 1102: if ((dp & 0x3) == 0x2) ! 1103: outer = (uae_s32)(uae_s16) next_iword (); ! 1104: if ((dp & 0x3) == 0x3) ! 1105: outer = next_ilong (); ! 1106: ! 1107: if ((dp & 0x4) == 0) ! 1108: base += regd; ! 1109: if (dp & 0x3) ! 1110: base = get_long (base); ! 1111: if (dp & 0x4) ! 1112: base += regd; ! 1113: ! 1114: return base + outer; ! 1115: } else { ! 1116: return base + (uae_s32)((uae_s8)dp) + regd; ! 1117: } ! 1118: } ! 1119: ! 1120: uae_u32 REGPARAM2 x_get_disp_ea_020 (uae_u32 base, uae_u32 dp) ! 1121: { ! 1122: int reg = (dp >> 12) & 15; ! 1123: int cycles = 0; ! 1124: uae_u32 v; ! 1125: ! 1126: uae_s32 regd = regs.regs[reg]; ! 1127: if ((dp & 0x800) == 0) ! 1128: regd = (uae_s32)(uae_s16)regd; ! 1129: regd <<= (dp >> 9) & 3; ! 1130: if (dp & 0x100) { ! 1131: uae_s32 outer = 0; ! 1132: if (dp & 0x80) ! 1133: base = 0; ! 1134: if (dp & 0x40) ! 1135: regd = 0; ! 1136: ! 1137: if ((dp & 0x30) == 0x20) { ! 1138: base += (uae_s32)(uae_s16) x_next_iword (); ! 1139: cycles++; ! 1140: } ! 1141: if ((dp & 0x30) == 0x30) { ! 1142: base += x_next_ilong (); ! 1143: cycles++; ! 1144: } ! 1145: ! 1146: if ((dp & 0x3) == 0x2) { ! 1147: outer = (uae_s32)(uae_s16) x_next_iword (); ! 1148: cycles++; ! 1149: } ! 1150: if ((dp & 0x3) == 0x3) { ! 1151: outer = x_next_ilong (); ! 1152: cycles++; ! 1153: } ! 1154: ! 1155: if ((dp & 0x4) == 0) { ! 1156: base += regd; ! 1157: cycles++; ! 1158: } ! 1159: if (dp & 0x3) { ! 1160: base = x_get_long (base); ! 1161: cycles++; ! 1162: } ! 1163: if (dp & 0x4) { ! 1164: base += regd; ! 1165: cycles++; ! 1166: } ! 1167: v = base + outer; ! 1168: } else { ! 1169: v = base + (uae_s32)((uae_s8)dp) + regd; ! 1170: } ! 1171: if (cycles) ! 1172: do_cycles_ce020 (cycles); ! 1173: return v; ! 1174: } ! 1175: ! 1176: ! 1177: uae_u32 REGPARAM3 get_disp_ea_000 (uae_u32 base, uae_u32 dp) REGPARAM ! 1178: { ! 1179: int reg = (dp >> 12) & 15; ! 1180: uae_s32 regd = regs.regs[reg]; ! 1181: #if 1 ! 1182: if ((dp & 0x800) == 0) ! 1183: regd = (uae_s32)(uae_s16)regd; ! 1184: return base + (uae_s8)dp + regd; ! 1185: #else ! 1186: /* Branch-free code... benchmark this again now that ! 1187: * things are no longer inline. */ ! 1188: uae_s32 regd16; ! 1189: uae_u32 mask; ! 1190: mask = ((dp & 0x800) >> 11) - 1; ! 1191: regd16 = (uae_s32)(uae_s16)regd; ! 1192: regd16 &= mask; ! 1193: mask = ~mask; ! 1194: base += (uae_s8)dp; ! 1195: regd &= mask; ! 1196: regd |= regd16; ! 1197: return base + regd; ! 1198: #endif ! 1199: } ! 1200: ! 1201: STATIC_INLINE int in_rom (uaecptr pc) ! 1202: { ! 1203: return (munge24 (pc) & 0xFFF80000) == 0xF80000; ! 1204: } ! 1205: ! 1206: #if AMIGA_ONLY ! 1207: STATIC_INLINE int in_rtarea (uaecptr pc) ! 1208: { ! 1209: return (munge24 (pc) & 0xFFFF0000) == rtarea_base && uae_boot_rom; ! 1210: } ! 1211: #endif ! 1212: ! 1213: void REGPARAM2 MakeSR (void) ! 1214: { ! 1215: regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) ! 1216: | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8) ! 1217: | (GET_XFLG () << 4) | (GET_NFLG () << 3) ! 1218: | (GET_ZFLG () << 2) | (GET_VFLG () << 1) ! 1219: | GET_CFLG ()); ! 1220: } ! 1221: ! 1222: void REGPARAM2 MakeFromSR (void) ! 1223: { ! 1224: int oldm = regs.m; ! 1225: int olds = regs.s; ! 1226: ! 1227: if (currprefs.cpu_cycle_exact && currprefs.cpu_model >= 68020) { ! 1228: do_cycles_ce (6 * CYCLE_UNIT); ! 1229: regs.ce020memcycles = 0; ! 1230: } ! 1231: ! 1232: SET_XFLG ((regs.sr >> 4) & 1); ! 1233: SET_NFLG ((regs.sr >> 3) & 1); ! 1234: SET_ZFLG ((regs.sr >> 2) & 1); ! 1235: SET_VFLG ((regs.sr >> 1) & 1); ! 1236: SET_CFLG (regs.sr & 1); ! 1237: if (regs.t1 == ((regs.sr >> 15) & 1) && ! 1238: regs.t0 == ((regs.sr >> 14) & 1) && ! 1239: regs.s == ((regs.sr >> 13) & 1) && ! 1240: regs.m == ((regs.sr >> 12) & 1) && ! 1241: regs.intmask == ((regs.sr >> 8) & 7)) ! 1242: return; ! 1243: regs.t1 = (regs.sr >> 15) & 1; ! 1244: regs.t0 = (regs.sr >> 14) & 1; ! 1245: regs.s = (regs.sr >> 13) & 1; ! 1246: regs.m = (regs.sr >> 12) & 1; ! 1247: regs.intmask = (regs.sr >> 8) & 7; ! 1248: if (currprefs.cpu_model >= 68020) { ! 1249: /* 68060 does not have MSP but does have M-bit.. */ ! 1250: if (currprefs.cpu_model >= 68060) ! 1251: regs.msp = regs.isp; ! 1252: if (olds != regs.s) { ! 1253: if (olds) { ! 1254: if (oldm) ! 1255: regs.msp = m68k_areg (regs, 7); ! 1256: else ! 1257: regs.isp = m68k_areg (regs, 7); ! 1258: m68k_areg (regs, 7) = regs.usp; ! 1259: } else { ! 1260: regs.usp = m68k_areg (regs, 7); ! 1261: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp; ! 1262: } ! 1263: } else if (olds && oldm != regs.m) { ! 1264: if (oldm) { ! 1265: regs.msp = m68k_areg (regs, 7); ! 1266: m68k_areg (regs, 7) = regs.isp; ! 1267: } else { ! 1268: regs.isp = m68k_areg (regs, 7); ! 1269: m68k_areg (regs, 7) = regs.msp; ! 1270: } ! 1271: } ! 1272: if (currprefs.cpu_model >= 68060) ! 1273: regs.t0 = 0; ! 1274: } else { ! 1275: regs.t0 = regs.m = 0; ! 1276: if (olds != regs.s) { ! 1277: if (olds) { ! 1278: regs.isp = m68k_areg (regs, 7); ! 1279: m68k_areg (regs, 7) = regs.usp; ! 1280: } else { ! 1281: regs.usp = m68k_areg (regs, 7); ! 1282: m68k_areg (regs, 7) = regs.isp; ! 1283: } ! 1284: } ! 1285: } ! 1286: if (currprefs.mmu_model) ! 1287: mmu_set_super (regs.s != 0); ! 1288: ! 1289: doint (); ! 1290: if (regs.t1 || regs.t0) ! 1291: set_special (SPCFLAG_TRACE); ! 1292: else ! 1293: /* Keep SPCFLAG_DOTRACE, we still want a trace exception for ! 1294: SR-modifying instructions (including STOP). */ ! 1295: unset_special (SPCFLAG_TRACE); ! 1296: } ! 1297: ! 1298: static void exception_trace (int nr) ! 1299: { ! 1300: unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE); ! 1301: if (regs.t1 && !regs.t0) { ! 1302: /* trace stays pending if exception is div by zero, chk, ! 1303: * trapv or trap #x ! 1304: */ ! 1305: if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47)) ! 1306: set_special (SPCFLAG_DOTRACE); ! 1307: } ! 1308: regs.t1 = regs.t0 = regs.m = 0; ! 1309: } ! 1310: ! 1311: static void exception_debug (int nr) ! 1312: { ! 1313: #ifdef DEBUGGER ! 1314: if (!exception_debugging) ! 1315: return; ! 1316: console_out_f ("Exception %d, PC=%08X\n", nr, M68K_GETPC); ! 1317: #endif ! 1318: } ! 1319: ! 1320: #ifdef CPUEMU_12 ! 1321: ! 1322: /* cycle-exact exception handler, 68000 only */ ! 1323: ! 1324: /* ! 1325: ! 1326: Address/Bus Error: ! 1327: ! 1328: - 6 idle cycles ! 1329: - write PC low word ! 1330: - write SR ! 1331: - write PC high word ! 1332: - write instruction word ! 1333: - write fault address low word ! 1334: - write status code ! 1335: - write fault address high word ! 1336: - 2 idle cycles ! 1337: - read exception address high word ! 1338: - read exception address low word ! 1339: - prefetch ! 1340: - 2 idle cycles ! 1341: - prefetch ! 1342: ! 1343: Division by Zero: ! 1344: ! 1345: - 6 idle cycles ! 1346: - write PC low word ! 1347: - write SR ! 1348: - write PC high word ! 1349: - read exception address high word ! 1350: - read exception address low word ! 1351: - prefetch ! 1352: - 2 idle cycles ! 1353: - prefetch ! 1354: ! 1355: Traps: ! 1356: ! 1357: - 2 idle cycles ! 1358: - write PC low word ! 1359: - write SR ! 1360: - write PC high word ! 1361: - read exception address high word ! 1362: - read exception address low word ! 1363: - prefetch ! 1364: - 2 idle cycles ! 1365: - prefetch ! 1366: ! 1367: TrapV: ! 1368: ! 1369: - write PC low word ! 1370: - write SR ! 1371: - write PC high word ! 1372: - read exception address high word ! 1373: - read exception address low word ! 1374: - prefetch ! 1375: - 2 idle cycles ! 1376: - prefetch ! 1377: ! 1378: CHK: ! 1379: ! 1380: - 6 idle cycles ! 1381: - write PC low word ! 1382: - write SR ! 1383: - write PC high word ! 1384: - read exception address high word ! 1385: - read exception address low word ! 1386: - prefetch ! 1387: - 2 idle cycles ! 1388: - prefetch ! 1389: ! 1390: Illegal Instruction: ! 1391: ! 1392: - 2 idle cycles ! 1393: - write PC low word ! 1394: - write SR ! 1395: - write PC high word ! 1396: - read exception address high word ! 1397: - read exception address low word ! 1398: - prefetch ! 1399: - 2 idle cycles ! 1400: - prefetch ! 1401: ! 1402: Interrupt cycle diagram: ! 1403: ! 1404: - 6 idle cycles ! 1405: - write PC low word ! 1406: - read exception number byte from (0xfffff1 | (interrupt number << 1)) ! 1407: - 4 idle cycles ! 1408: - write SR ! 1409: - write PC high word ! 1410: - read exception address high word ! 1411: - read exception address low word ! 1412: - prefetch ! 1413: - 2 idle cycles ! 1414: - prefetch ! 1415: ! 1416: */ ! 1417: ! 1418: static void Exception_ce000 (int nr, uaecptr oldpc) ! 1419: { ! 1420: uae_u32 currpc = m68k_getpc (), newpc; ! 1421: int sv = regs.s; ! 1422: int start, interrupt; ! 1423: ! 1424: start = 6; ! 1425: if (nr == 7) // TRAPV ! 1426: start = 0; ! 1427: else if (nr >= 32 && nr < 32 + 16) // TRAP #x ! 1428: start = 2; ! 1429: else if (nr == 4 || nr == 8) // ILLG & PRIVIL VIOL ! 1430: start = 2; ! 1431: interrupt = nr >= 24 && nr < 24 + 8; ! 1432: ! 1433: if (start) ! 1434: do_cycles_ce000 (start); ! 1435: ! 1436: exception_debug (nr); ! 1437: MakeSR (); ! 1438: ! 1439: if (!regs.s) { ! 1440: regs.usp = m68k_areg (regs, 7); ! 1441: m68k_areg (regs, 7) = regs.isp; ! 1442: regs.s = 1; ! 1443: } ! 1444: if (nr == 2 || nr == 3) { /* 2=bus error, 3=address error */ ! 1445: uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); ! 1446: mode |= last_writeaccess_for_exception_3 ? 0 : 16; ! 1447: m68k_areg (regs, 7) -= 14; ! 1448: /* fixme: bit3=I/N */ ! 1449: put_word_ce (m68k_areg (regs, 7) + 12, last_addr_for_exception_3); ! 1450: put_word_ce (m68k_areg (regs, 7) + 8, regs.sr); ! 1451: put_word_ce (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16); ! 1452: put_word_ce (m68k_areg (regs, 7) + 6, last_op_for_exception_3); ! 1453: put_word_ce (m68k_areg (regs, 7) + 4, last_fault_for_exception_3); ! 1454: put_word_ce (m68k_areg (regs, 7) + 0, mode); ! 1455: put_word_ce (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16); ! 1456: do_cycles_ce000 (2); ! 1457: write_log ("Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, get_long (4 * nr)); ! 1458: goto kludge_me_do; ! 1459: } ! 1460: m68k_areg (regs, 7) -= 6; ! 1461: put_word_ce (m68k_areg (regs, 7) + 4, currpc); // write low address ! 1462: if (interrupt) { ! 1463: // fetch interrupt vector number ! 1464: nr = get_byte_ce (0x00fffff1 | ((nr - 24) << 1)); ! 1465: do_cycles_ce000 (4); ! 1466: } ! 1467: put_word_ce (m68k_areg (regs, 7) + 0, regs.sr); // write SR ! 1468: put_word_ce (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address ! 1469: kludge_me_do: ! 1470: newpc = get_word_ce (4 * nr) << 16; // read high address ! 1471: newpc |= get_word_ce (4 * nr + 2); // read low address ! 1472: if (newpc & 1) { ! 1473: if (nr == 2 || nr == 3) ! 1474: Reset_Cold(); /* there is nothing else we can do.. */ ! 1475: else ! 1476: exception3 (regs.ir, m68k_getpc (), newpc); ! 1477: return; ! 1478: } ! 1479: m68k_setpc (newpc); ! 1480: regs.ir = get_word_ce (m68k_getpc ()); // prefetch 1 ! 1481: do_cycles_ce000 (2); ! 1482: regs.irc = get_word_ce (m68k_getpc () + 2); // prefetch 2 ! 1483: #ifdef JIT ! 1484: set_special (SPCFLAG_END_COMPILE); ! 1485: #endif ! 1486: exception_trace (nr); ! 1487: } ! 1488: #endif ! 1489: ! 1490: static void Exception_mmu (int nr, uaecptr oldpc) ! 1491: { ! 1492: uae_u32 currpc = m68k_getpc (), newpc; ! 1493: int sv = regs.s; ! 1494: int i; ! 1495: ! 1496: exception_debug (nr); ! 1497: MakeSR (); ! 1498: ! 1499: if (!regs.s) { ! 1500: regs.usp = m68k_areg (regs, 7); ! 1501: if (currprefs.cpu_model >= 68020) ! 1502: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp; ! 1503: else ! 1504: m68k_areg (regs, 7) = regs.isp; ! 1505: regs.s = 1; ! 1506: mmu_set_super (1); ! 1507: } ! 1508: if (nr == 2) { ! 1509: // write_log ("%08x %08x %08x\n", currpc, oldpc, regs.mmu_fault_addr); ! 1510: // if (currpc == 0x0013b5e2) ! 1511: // activate_debugger (); ! 1512: // bus error ! 1513: for (i = 0 ; i < 7 ; i++) { ! 1514: m68k_areg (regs, 7) -= 4; ! 1515: put_long_mmu (m68k_areg (regs, 7), 0); ! 1516: } ! 1517: m68k_areg (regs, 7) -= 4; ! 1518: put_long_mmu (m68k_areg (regs, 7), regs.wb3_data); ! 1519: m68k_areg (regs, 7) -= 4; ! 1520: put_long_mmu (m68k_areg (regs, 7), regs.mmu_fault_addr); ! 1521: m68k_areg (regs, 7) -= 4; ! 1522: put_long_mmu (m68k_areg (regs, 7), regs.mmu_fault_addr); ! 1523: m68k_areg (regs, 7) -= 2; ! 1524: put_word_mmu (m68k_areg (regs, 7), 0); ! 1525: m68k_areg (regs, 7) -= 2; ! 1526: put_word_mmu (m68k_areg (regs, 7), 0); ! 1527: m68k_areg (regs, 7) -= 2; ! 1528: put_word_mmu (m68k_areg (regs, 7), regs.wb3_status); ! 1529: regs.wb3_status = 0; ! 1530: m68k_areg (regs, 7) -= 2; ! 1531: put_word_mmu (m68k_areg (regs, 7), regs.mmu_ssw); ! 1532: m68k_areg (regs, 7) -= 4; ! 1533: put_long_mmu (m68k_areg (regs, 7), regs.mmu_fault_addr); ! 1534: ! 1535: m68k_areg (regs, 7) -= 2; ! 1536: put_word_mmu (m68k_areg (regs, 7), 0x7000 + nr * 4); ! 1537: m68k_areg (regs, 7) -= 4; ! 1538: put_long_mmu (m68k_areg (regs, 7), oldpc); ! 1539: m68k_areg (regs, 7) -= 2; ! 1540: put_word_mmu (m68k_areg (regs, 7), regs.sr); ! 1541: goto kludge_me_do; ! 1542: ! 1543: } else if (nr == 3) { ! 1544: ! 1545: // address error ! 1546: uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); ! 1547: ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40; ! 1548: ssw |= 0x20; ! 1549: for (i = 0 ; i < 36; i++) { ! 1550: m68k_areg (regs, 7) -= 2; ! 1551: put_word_mmu (m68k_areg (regs, 7), 0); ! 1552: } ! 1553: m68k_areg (regs, 7) -= 4; ! 1554: put_long_mmu (m68k_areg (regs, 7), last_fault_for_exception_3); ! 1555: m68k_areg (regs, 7) -= 2; ! 1556: put_word_mmu (m68k_areg (regs, 7), 0); ! 1557: m68k_areg (regs, 7) -= 2; ! 1558: put_word_mmu (m68k_areg (regs, 7), 0); ! 1559: m68k_areg (regs, 7) -= 2; ! 1560: put_word_mmu (m68k_areg (regs, 7), 0); ! 1561: m68k_areg (regs, 7) -= 2; ! 1562: put_word_mmu (m68k_areg (regs, 7), ssw); ! 1563: m68k_areg (regs, 7) -= 2; ! 1564: put_word_mmu (m68k_areg (regs, 7), 0xb000 + nr * 4); ! 1565: write_log ("Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, get_long (regs.vbr + 4*nr)); ! 1566: ! 1567: } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { ! 1568: ! 1569: m68k_areg (regs, 7) -= 4; ! 1570: put_long_mmu (m68k_areg (regs, 7), oldpc); ! 1571: m68k_areg (regs, 7) -= 2; ! 1572: put_word_mmu (m68k_areg (regs, 7), 0x2000 + nr * 4); ! 1573: ! 1574: } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */ ! 1575: ! 1576: m68k_areg (regs, 7) -= 2; ! 1577: put_word_mmu (m68k_areg (regs, 7), nr * 4); ! 1578: m68k_areg (regs, 7) -= 4; ! 1579: put_long_mmu (m68k_areg (regs, 7), currpc); ! 1580: m68k_areg (regs, 7) -= 2; ! 1581: put_word_mmu (m68k_areg (regs, 7), regs.sr); ! 1582: regs.sr |= (1 << 13); ! 1583: regs.msp = m68k_areg (regs, 7); ! 1584: m68k_areg (regs, 7) = regs.isp; ! 1585: m68k_areg (regs, 7) -= 2; ! 1586: put_word_mmu (m68k_areg (regs, 7), 0x1000 + nr * 4); ! 1587: ! 1588: } else { ! 1589: ! 1590: m68k_areg (regs, 7) -= 2; ! 1591: put_word_mmu (m68k_areg (regs, 7), nr * 4); ! 1592: ! 1593: } ! 1594: m68k_areg (regs, 7) -= 4; ! 1595: put_long_mmu (m68k_areg (regs, 7), currpc); ! 1596: m68k_areg (regs, 7) -= 2; ! 1597: put_word_mmu (m68k_areg (regs, 7), regs.sr); ! 1598: kludge_me_do: ! 1599: newpc = get_long_mmu (regs.vbr + 4 * nr); ! 1600: if (newpc & 1) { ! 1601: if (nr == 2 || nr == 3) ! 1602: Reset_Cold(); /* there is nothing else we can do.. */ ! 1603: else ! 1604: exception3 (regs.ir, m68k_getpc (), newpc); ! 1605: return; ! 1606: } ! 1607: m68k_setpc (newpc); ! 1608: #ifdef JIT ! 1609: set_special (SPCFLAG_END_COMPILE); ! 1610: #endif ! 1611: fill_prefetch_slow (); ! 1612: exception_trace (nr); ! 1613: } ! 1614: ! 1615: /* Handle exceptions. We need a special case to handle MFP exceptions */ ! 1616: /* on Atari ST, because it's possible to change the MFP's vector base */ ! 1617: /* and get a conflict with 'normal' cpu exceptions. */ ! 1618: static void Exception_normal (int nr, uaecptr oldpc, int ExceptionSource) ! 1619: { ! 1620: uae_u32 currpc = m68k_getpc (), newpc; ! 1621: int sv = regs.s; ! 1622: ! 1623: ! 1624: #if AMIGA_ONLY ! 1625: if (nr >= 24 && nr < 24 + 8 && currprefs.cpu_model <= 68010) ! 1626: nr = x_get_byte (0x00fffff1 | (nr << 1)); ! 1627: #endif ! 1628: ! 1629: exception_debug (nr); ! 1630: MakeSR (); ! 1631: ! 1632: /* Change to supervisor mode if necessary */ ! 1633: if (!regs.s) { ! 1634: regs.usp = m68k_areg (regs, 7); ! 1635: if (currprefs.cpu_model >= 68020) ! 1636: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp; ! 1637: else ! 1638: m68k_areg (regs, 7) = regs.isp; ! 1639: regs.s = 1; ! 1640: if (currprefs.mmu_model) ! 1641: mmu_set_super (regs.s != 0); ! 1642: } ! 1643: if (currprefs.cpu_model > 68000) { ! 1644: /* Build additional exception stack frame for 68010 and higher */ ! 1645: /* (special case for MFP) */ ! 1646: ! 1647: if (nr == 2 || nr == 3) { ! 1648: int i; ! 1649: if (currprefs.cpu_model >= 68040) { ! 1650: if (nr == 2) { ! 1651: // bus error ! 1652: if (currprefs.mmu_model) { ! 1653: ! 1654: for (i = 0 ; i < 7 ; i++) { ! 1655: m68k_areg (regs, 7) -= 4; ! 1656: x_put_long (m68k_areg (regs, 7), 0); ! 1657: } ! 1658: m68k_areg (regs, 7) -= 4; ! 1659: x_put_long (m68k_areg (regs, 7), regs.wb3_data); ! 1660: m68k_areg (regs, 7) -= 4; ! 1661: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); ! 1662: m68k_areg (regs, 7) -= 4; ! 1663: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); ! 1664: m68k_areg (regs, 7) -= 2; ! 1665: x_put_word (m68k_areg (regs, 7), 0); ! 1666: m68k_areg (regs, 7) -= 2; ! 1667: x_put_word (m68k_areg (regs, 7), 0); ! 1668: m68k_areg (regs, 7) -= 2; ! 1669: x_put_word (m68k_areg (regs, 7), regs.wb3_status); ! 1670: regs.wb3_status = 0; ! 1671: m68k_areg (regs, 7) -= 2; ! 1672: x_put_word (m68k_areg (regs, 7), regs.mmu_ssw); ! 1673: m68k_areg (regs, 7) -= 4; ! 1674: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); ! 1675: ! 1676: m68k_areg (regs, 7) -= 2; ! 1677: x_put_word (m68k_areg (regs, 7), 0x7000 + nr * 4); ! 1678: m68k_areg (regs, 7) -= 4; ! 1679: x_put_long (m68k_areg (regs, 7), oldpc); ! 1680: m68k_areg (regs, 7) -= 2; ! 1681: x_put_word (m68k_areg (regs, 7), regs.sr); ! 1682: newpc = x_get_long (regs.vbr + 4 * nr); ! 1683: if (newpc & 1) { ! 1684: if (nr == 2 || nr == 3) ! 1685: uae_reset (1); /* there is nothing else we can do.. */ ! 1686: else ! 1687: exception3 (regs.ir, m68k_getpc (), newpc); ! 1688: return; ! 1689: } ! 1690: m68k_setpc (newpc); ! 1691: #ifdef JIT ! 1692: set_special (SPCFLAG_END_COMPILE); ! 1693: #endif ! 1694: exception_trace (nr); ! 1695: return; ! 1696: ! 1697: } else { ! 1698: ! 1699: for (i = 0 ; i < 18 ; i++) { ! 1700: m68k_areg (regs, 7) -= 2; ! 1701: x_put_word (m68k_areg (regs, 7), 0); ! 1702: } ! 1703: m68k_areg (regs, 7) -= 4; ! 1704: x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3); ! 1705: m68k_areg (regs, 7) -= 2; ! 1706: x_put_word (m68k_areg (regs, 7), 0); ! 1707: m68k_areg (regs, 7) -= 2; ! 1708: x_put_word (m68k_areg (regs, 7), 0); ! 1709: m68k_areg (regs, 7) -= 2; ! 1710: x_put_word (m68k_areg (regs, 7), 0); ! 1711: m68k_areg (regs, 7) -= 2; ! 1712: x_put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */ ! 1713: m68k_areg (regs, 7) -= 4; ! 1714: x_put_long (m68k_areg (regs, 7), last_addr_for_exception_3); ! 1715: m68k_areg (regs, 7) -= 2; ! 1716: x_put_word (m68k_areg (regs, 7), 0x7000 + nr * 4); ! 1717: m68k_areg (regs, 7) -= 4; ! 1718: x_put_long (m68k_areg (regs, 7), oldpc); ! 1719: m68k_areg (regs, 7) -= 2; ! 1720: x_put_word (m68k_areg (regs, 7), regs.sr); ! 1721: goto kludge_me_do; ! 1722: ! 1723: } ! 1724: ! 1725: } else { ! 1726: m68k_areg (regs, 7) -= 4; ! 1727: x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3); ! 1728: m68k_areg (regs, 7) -= 2; ! 1729: x_put_word (m68k_areg (regs, 7), 0x2000 + nr * 4); ! 1730: } ! 1731: } else { ! 1732: // address error ! 1733: uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); ! 1734: ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40; ! 1735: ssw |= 0x20; ! 1736: for (i = 0 ; i < 36; i++) { ! 1737: m68k_areg (regs, 7) -= 2; ! 1738: x_put_word (m68k_areg (regs, 7), 0); ! 1739: } ! 1740: m68k_areg (regs, 7) -= 4; ! 1741: x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3); ! 1742: m68k_areg (regs, 7) -= 2; ! 1743: x_put_word (m68k_areg (regs, 7), 0); ! 1744: m68k_areg (regs, 7) -= 2; ! 1745: x_put_word (m68k_areg (regs, 7), 0); ! 1746: m68k_areg (regs, 7) -= 2; ! 1747: x_put_word (m68k_areg (regs, 7), 0); ! 1748: m68k_areg (regs, 7) -= 2; ! 1749: x_put_word (m68k_areg (regs, 7), ssw); ! 1750: m68k_areg (regs, 7) -= 2; ! 1751: x_put_word (m68k_areg (regs, 7), 0xb000 + nr * 4); ! 1752: } ! 1753: write_log ("Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, x_get_long (regs.vbr + 4*nr)); ! 1754: } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { ! 1755: m68k_areg (regs, 7) -= 4; ! 1756: x_put_long (m68k_areg (regs, 7), oldpc); ! 1757: m68k_areg (regs, 7) -= 2; ! 1758: x_put_word (m68k_areg (regs, 7), 0x2000 + nr * 4); ! 1759: } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */ ! 1760: m68k_areg (regs, 7) -= 2; ! 1761: x_put_word (m68k_areg (regs, 7), nr * 4); ! 1762: m68k_areg (regs, 7) -= 4; ! 1763: x_put_long (m68k_areg (regs, 7), currpc); ! 1764: m68k_areg (regs, 7) -= 2; ! 1765: x_put_word (m68k_areg (regs, 7), regs.sr); ! 1766: regs.sr |= (1 << 13); ! 1767: regs.msp = m68k_areg (regs, 7); ! 1768: m68k_areg (regs, 7) = regs.isp; ! 1769: m68k_areg (regs, 7) -= 2; ! 1770: x_put_word (m68k_areg (regs, 7), 0x1000 + nr * 4); ! 1771: } else { ! 1772: m68k_areg (regs, 7) -= 2; ! 1773: x_put_word (m68k_areg (regs, 7), nr * 4); ! 1774: } ! 1775: } else if (nr == 2 || nr == 3) { ! 1776: uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); ! 1777: mode |= last_writeaccess_for_exception_3 ? 0 : 16; ! 1778: m68k_areg (regs, 7) -= 14; ! 1779: /* fixme: bit3=I/N */ ! 1780: x_put_word (m68k_areg (regs, 7) + 0, mode); ! 1781: x_put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3); ! 1782: x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3); ! 1783: x_put_word (m68k_areg (regs, 7) + 8, regs.sr); ! 1784: x_put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3); ! 1785: write_log ("Exception %d (%x) at %x -> %x!\n", nr, oldpc, currpc, x_get_long (regs.vbr + 4*nr)); ! 1786: goto kludge_me_do; ! 1787: } ! 1788: ! 1789: /* Push PC on stack: */ ! 1790: m68k_areg (regs, 7) -= 4; ! 1791: x_put_long (m68k_areg (regs, 7), currpc); ! 1792: /* Push SR on stack: */ ! 1793: m68k_areg (regs, 7) -= 2; ! 1794: x_put_word (m68k_areg (regs, 7), regs.sr); ! 1795: kludge_me_do: ! 1796: newpc = x_get_long (regs.vbr + 4 * nr); ! 1797: if (newpc & 1) { ! 1798: if (nr == 2 || nr == 3) ! 1799: uae_reset (1); /* there is nothing else we can do.. */ ! 1800: else ! 1801: exception3 (regs.ir, m68k_getpc (), newpc); ! 1802: return; ! 1803: } ! 1804: m68k_setpc (newpc); ! 1805: #ifdef JIT ! 1806: set_special (SPCFLAG_END_COMPILE); ! 1807: #endif ! 1808: fill_prefetch_slow (); ! 1809: exception_trace (nr); ! 1810: ! 1811: /* Handle exception cycles (special case for MFP) */ ! 1812: if (ExceptionSource == M68000_EXC_SRC_INT_MFP) ! 1813: { ! 1814: M68000_AddCycles(44+12); /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */ ! 1815: } ! 1816: else if (nr >= 24 && nr <= 31) ! 1817: { ! 1818: if ( nr == 26 ) /* HBL */ ! 1819: { ! 1820: /* store current cycle pos when then interrupt was received (see video.c) */ ! 1821: // LastCycleHblException = Cycles_GetCounter(CYCLES_COUNTER_VIDEO); ! 1822: M68000_AddCycles(44+12); /* Video Interrupt */ ! 1823: } ! 1824: else if ( nr == 28 ) /* VBL */ ! 1825: M68000_AddCycles(44+12); /* Video Interrupt */ ! 1826: else ! 1827: M68000_AddCycles(44+4); /* Other Interrupts */ ! 1828: } ! 1829: else if(nr >= 32 && nr <= 47) ! 1830: { ! 1831: M68000_AddCycles(34-4); /* Trap (total is 34, but cpuemu.c already adds 4) */ ! 1832: } ! 1833: else switch(nr) ! 1834: { ! 1835: case 2: M68000_AddCycles(50); break; /* Bus error */ ! 1836: case 3: M68000_AddCycles(50); break; /* Address error */ ! 1837: case 4: M68000_AddCycles(34); break; /* Illegal instruction */ ! 1838: case 5: M68000_AddCycles(38); break; /* Div by zero */ ! 1839: case 6: M68000_AddCycles(40); break; /* CHK */ ! 1840: case 7: M68000_AddCycles(34); break; /* TRAPV */ ! 1841: case 8: M68000_AddCycles(34); break; /* Privilege violation */ ! 1842: case 9: M68000_AddCycles(34); break; /* Trace */ ! 1843: case 10: M68000_AddCycles(34); break; /* Line-A - probably wrong */ ! 1844: case 11: M68000_AddCycles(34); break; /* Line-F - probably wrong */ ! 1845: default: ! 1846: /* FIXME: Add right cycles value for MFP interrupts and copro exceptions ... */ ! 1847: if(nr < 64) ! 1848: M68000_AddCycles(4); /* Coprocessor and unassigned exceptions (???) */ ! 1849: else ! 1850: M68000_AddCycles(44+12); /* Must be a MFP or DSP interrupt */ ! 1851: break; ! 1852: } ! 1853: ! 1854: } ! 1855: ! 1856: /* Handle exceptions. We need a special case to handle MFP exceptions */ ! 1857: /* on Atari ST, because it's possible to change the MFP's vector base */ ! 1858: /* and get a conflict with 'normal' cpu exceptions. */ ! 1859: void REGPARAM2 Exception (int nr, uaecptr oldpc, int ExceptionSource) ! 1860: { ! 1861: #ifdef CPUEMU_12 ! 1862: if (currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000) ! 1863: Exception_ce000 (nr, oldpc); ! 1864: else ! 1865: #endif ! 1866: if (currprefs.mmu_model) ! 1867: Exception_mmu (nr, oldpc); // Todo: add ExceptionSource ! 1868: else ! 1869: Exception_normal (nr, oldpc, ExceptionSource); ! 1870: ! 1871: #if AMIGA_ONLY ! 1872: if (debug_illegal && !in_rom (M68K_GETPC)) { ! 1873: int v = nr; ! 1874: if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) { ! 1875: write_log ("Exception %d breakpoint\n", nr); ! 1876: activate_debugger (); ! 1877: } ! 1878: } ! 1879: #endif ! 1880: } ! 1881: ! 1882: STATIC_INLINE void do_interrupt (int nr, int Pending) ! 1883: { ! 1884: #if AMIGA_ONLY ! 1885: if (debug_dma) ! 1886: record_dma_event (DMA_EVENT_CPUIRQ, current_hpos (), vpos); ! 1887: #endif ! 1888: ! 1889: regs.stopped = 0; ! 1890: unset_special (SPCFLAG_STOP); ! 1891: assert (nr < 8 && nr >= 0); ! 1892: ! 1893: /* On Hatari, only video ints are using SPCFLAG_INT (see m68000.c) */ ! 1894: Exception (nr + 24, 0, M68000_EXC_SRC_AUTOVEC); ! 1895: ! 1896: regs.intmask = nr; ! 1897: doint (); ! 1898: ! 1899: set_special (SPCFLAG_INT); ! 1900: /* Handle Atari ST's specific jitter for hbl/vbl */ ! 1901: InterruptAddJitter (nr , Pending); ! 1902: } ! 1903: ! 1904: ! 1905: void NMI (void) ! 1906: { ! 1907: do_interrupt (7, false); ! 1908: } ! 1909: ! 1910: #ifndef CPUEMU_68000_ONLY ! 1911: ! 1912: int movec_illg (int regno) ! 1913: { ! 1914: int regno2 = regno & 0x7ff; ! 1915: ! 1916: if (currprefs.cpu_model == 68060) { ! 1917: if (regno <= 8) ! 1918: return 0; ! 1919: if (regno == 0x800 || regno == 0x801 || ! 1920: regno == 0x806 || regno == 0x807 || regno == 0x808) ! 1921: return 0; ! 1922: return 1; ! 1923: } else if (currprefs.cpu_model == 68010) { ! 1924: if (regno2 < 2) ! 1925: return 0; ! 1926: return 1; ! 1927: } else if (currprefs.cpu_model == 68020) { ! 1928: if (regno == 3) ! 1929: return 1; /* 68040/060 only */ ! 1930: /* 4 is >=68040, but 0x804 is in 68020 */ ! 1931: if (regno2 < 4 || regno == 0x804) ! 1932: return 0; ! 1933: return 1; ! 1934: } else if (currprefs.cpu_model == 68030) { ! 1935: if (regno2 <= 2) ! 1936: return 0; ! 1937: if (regno == 0x803 || regno == 0x804) ! 1938: return 0; ! 1939: return 1; ! 1940: } else if (currprefs.cpu_model == 68040) { ! 1941: if (regno == 0x802) ! 1942: return 1; /* 68020 only */ ! 1943: if (regno2 < 8) return 0; ! 1944: return 1; ! 1945: } ! 1946: return 1; ! 1947: } ! 1948: ! 1949: int m68k_move2c (int regno, uae_u32 *regp) ! 1950: { ! 1951: #if MOVEC_DEBUG > 0 ! 1952: write_log ("move2c %04X <- %08X PC=%x\n", regno, *regp, M68K_GETPC); ! 1953: #endif ! 1954: if (movec_illg (regno)) { ! 1955: op_illg (0x4E7B); ! 1956: return 0; ! 1957: } else { ! 1958: switch (regno) { ! 1959: case 0: regs.sfc = *regp & 7; break; ! 1960: case 1: regs.dfc = *regp & 7; break; ! 1961: case 2: ! 1962: { ! 1963: uae_u32 cacr_mask = 0; ! 1964: if (currprefs.cpu_model == 68020) ! 1965: cacr_mask = 0x0000000f; ! 1966: else if (currprefs.cpu_model == 68030) ! 1967: cacr_mask = 0x00003f1f; ! 1968: else if (currprefs.cpu_model == 68040) ! 1969: cacr_mask = 0x80008000; ! 1970: else if (currprefs.cpu_model == 68060) ! 1971: cacr_mask = 0xf8e0e000; ! 1972: regs.cacr = *regp & cacr_mask; ! 1973: set_cpu_caches (); ! 1974: } ! 1975: break; ! 1976: /* 68040/060 only */ ! 1977: case 3: ! 1978: regs.tcr = *regp & (currprefs.cpu_model == 68060 ? 0xfffe : 0xc000); ! 1979: if (currprefs.mmu_model) ! 1980: mmu_set_tc (regs.tcr); ! 1981: break; ! 1982: ! 1983: /* no differences between 68040 and 68060 */ ! 1984: case 4: regs.itt0 = *regp & 0xffffe364; break; ! 1985: case 5: regs.itt1 = *regp & 0xffffe364; break; ! 1986: case 6: regs.dtt0 = *regp & 0xffffe364; break; ! 1987: case 7: regs.dtt1 = *regp & 0xffffe364; break; ! 1988: /* 68060 only */ ! 1989: case 8: regs.buscr = *regp & 0xf0000000; break; ! 1990: ! 1991: case 0x800: regs.usp = *regp; break; ! 1992: case 0x801: regs.vbr = *regp; break; ! 1993: case 0x802: regs.caar = *regp & 0xfc; break; ! 1994: case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg (regs, 7) = regs.msp; break; ! 1995: case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg (regs, 7) = regs.isp; break; ! 1996: /* 68040 only */ ! 1997: case 0x805: regs.mmusr = *regp; break; ! 1998: /* 68040/060 */ ! 1999: case 0x806: regs.urp = *regp & 0xfffffe00; break; ! 2000: case 0x807: regs.srp = *regp & 0xfffffe00; break; ! 2001: /* 68060 only */ ! 2002: case 0x808: ! 2003: { ! 2004: uae_u32 opcr = regs.pcr; ! 2005: regs.pcr &= ~(0x40 | 2 | 1); ! 2006: regs.pcr |= (*regp) & (0x40 | 2 | 1); ! 2007: if (((opcr ^ regs.pcr) & 2) == 2) { ! 2008: write_log ("68060 FPU state: %s\n", regs.pcr & 2 ? "disabled" : "enabled"); ! 2009: /* flush possible already translated FPU instructions */ ! 2010: flush_icache (0, 3); ! 2011: } ! 2012: } ! 2013: break; ! 2014: default: ! 2015: op_illg (0x4E7B); ! 2016: return 0; ! 2017: } ! 2018: } ! 2019: return 1; ! 2020: } ! 2021: ! 2022: int m68k_movec2 (int regno, uae_u32 *regp) ! 2023: { ! 2024: #if MOVEC_DEBUG > 0 ! 2025: write_log ("movec2 %04X PC=%x\n", regno, M68K_GETPC); ! 2026: #endif ! 2027: if (movec_illg (regno)) { ! 2028: op_illg (0x4E7A); ! 2029: return 0; ! 2030: } else { ! 2031: switch (regno) { ! 2032: case 0: *regp = regs.sfc; break; ! 2033: case 1: *regp = regs.dfc; break; ! 2034: case 2: ! 2035: { ! 2036: uae_u32 v = regs.cacr; ! 2037: uae_u32 cacr_mask = 0; ! 2038: if (currprefs.cpu_model == 68020) ! 2039: cacr_mask = 0x00000003; ! 2040: else if (currprefs.cpu_model == 68030) ! 2041: cacr_mask = 0x00003313; ! 2042: else if (currprefs.cpu_model == 68040) ! 2043: cacr_mask = 0x80008000; ! 2044: else if (currprefs.cpu_model == 68060) ! 2045: cacr_mask = 0xf880e000; ! 2046: *regp = v & cacr_mask; ! 2047: } ! 2048: break; ! 2049: case 3: *regp = regs.tcr; break; ! 2050: case 4: *regp = regs.itt0; break; ! 2051: case 5: *regp = regs.itt1; break; ! 2052: case 6: *regp = regs.dtt0; break; ! 2053: case 7: *regp = regs.dtt1; break; ! 2054: case 8: *regp = regs.buscr; break; ! 2055: ! 2056: case 0x800: *regp = regs.usp; break; ! 2057: case 0x801: *regp = regs.vbr; break; ! 2058: case 0x802: *regp = regs.caar; break; ! 2059: case 0x803: *regp = regs.m == 1 ? m68k_areg (regs, 7) : regs.msp; break; ! 2060: case 0x804: *regp = regs.m == 0 ? m68k_areg (regs, 7) : regs.isp; break; ! 2061: case 0x805: *regp = regs.mmusr; break; ! 2062: case 0x806: *regp = regs.urp; break; ! 2063: case 0x807: *regp = regs.srp; break; ! 2064: case 0x808: *regp = regs.pcr; break; ! 2065: ! 2066: default: ! 2067: op_illg (0x4E7A); ! 2068: return 0; ! 2069: } ! 2070: } ! 2071: #if MOVEC_DEBUG > 0 ! 2072: write_log ("-> %08X\n", *regp); ! 2073: #endif ! 2074: return 1; ! 2075: } ! 2076: ! 2077: STATIC_INLINE int div_unsigned (uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem) ! 2078: { ! 2079: uae_u32 q = 0, cbit = 0; ! 2080: int i; ! 2081: ! 2082: if (div <= src_hi) { ! 2083: return 1; ! 2084: } ! 2085: for (i = 0 ; i < 32 ; i++) { ! 2086: cbit = src_hi & 0x80000000ul; ! 2087: src_hi <<= 1; ! 2088: if (src_lo & 0x80000000ul) src_hi++; ! 2089: src_lo <<= 1; ! 2090: q = q << 1; ! 2091: if (cbit || div <= src_hi) { ! 2092: q |= 1; ! 2093: src_hi -= div; ! 2094: } ! 2095: } ! 2096: *quot = q; ! 2097: *rem = src_hi; ! 2098: return 0; ! 2099: } ! 2100: ! 2101: void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc) ! 2102: { ! 2103: #if defined (uae_s64) ! 2104: if (src == 0) { ! 2105: Exception (5, oldpc, M68000_EXC_SRC_CPU); ! 2106: return; ! 2107: } ! 2108: if (extra & 0x800) { ! 2109: /* signed variant */ ! 2110: uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7); ! 2111: uae_s64 quot, rem; ! 2112: ! 2113: if (extra & 0x400) { ! 2114: a &= 0xffffffffu; ! 2115: a |= (uae_s64)m68k_dreg (regs, extra & 7) << 32; ! 2116: } ! 2117: rem = a % (uae_s64)(uae_s32)src; ! 2118: quot = a / (uae_s64)(uae_s32)src; ! 2119: if ((quot & UVAL64 (0xffffffff80000000)) != 0 ! 2120: && (quot & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000)) ! 2121: { ! 2122: SET_VFLG (1); ! 2123: SET_NFLG (1); ! 2124: SET_CFLG (0); ! 2125: } else { ! 2126: if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem; ! 2127: SET_VFLG (0); ! 2128: SET_CFLG (0); ! 2129: SET_ZFLG (((uae_s32)quot) == 0); ! 2130: SET_NFLG (((uae_s32)quot) < 0); ! 2131: m68k_dreg (regs, extra & 7) = (uae_u32)rem; ! 2132: m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)quot; ! 2133: } ! 2134: } else { ! 2135: /* unsigned */ ! 2136: uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7); ! 2137: uae_u64 quot, rem; ! 2138: ! 2139: if (extra & 0x400) { ! 2140: a &= 0xffffffffu; ! 2141: a |= (uae_u64)m68k_dreg (regs, extra & 7) << 32; ! 2142: } ! 2143: rem = a % (uae_u64)src; ! 2144: quot = a / (uae_u64)src; ! 2145: if (quot > 0xffffffffu) { ! 2146: SET_VFLG (1); ! 2147: SET_NFLG (1); ! 2148: SET_CFLG (0); ! 2149: } else { ! 2150: SET_VFLG (0); ! 2151: SET_CFLG (0); ! 2152: SET_ZFLG (((uae_s32)quot) == 0); ! 2153: SET_NFLG (((uae_s32)quot) < 0); ! 2154: m68k_dreg (regs, extra & 7) = (uae_u32)rem; ! 2155: m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)quot; ! 2156: } ! 2157: } ! 2158: #else ! 2159: if (src == 0) { ! 2160: Exception (5, oldpc, M68000_EXC_SRC_CPU); ! 2161: return; ! 2162: } ! 2163: if (extra & 0x800) { ! 2164: /* signed variant */ ! 2165: uae_s32 lo = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7); ! 2166: uae_s32 hi = lo < 0 ? -1 : 0; ! 2167: uae_s32 save_high; ! 2168: uae_u32 quot, rem; ! 2169: uae_u32 sign; ! 2170: ! 2171: if (extra & 0x400) { ! 2172: hi = (uae_s32)m68k_dreg (regs, extra & 7); ! 2173: } ! 2174: save_high = hi; ! 2175: sign = (hi ^ src); ! 2176: if (hi < 0) { ! 2177: hi = ~hi; ! 2178: lo = -lo; ! 2179: if (lo == 0) hi++; ! 2180: } ! 2181: if ((uae_s32)src < 0) src = -src; ! 2182: if (div_unsigned (hi, lo, src, ", &rem) || ! 2183: (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) { ! 2184: SET_VFLG (1); ! 2185: SET_NFLG (1); ! 2186: SET_CFLG (0); ! 2187: } else { ! 2188: if (sign & 0x80000000) quot = -quot; ! 2189: if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem; ! 2190: SET_VFLG (0); ! 2191: SET_CFLG (0); ! 2192: SET_ZFLG (((uae_s32)quot) == 0); ! 2193: SET_NFLG (((uae_s32)quot) < 0); ! 2194: m68k_dreg (regs, extra & 7) = rem; ! 2195: m68k_dreg (regs, (extra >> 12) & 7) = quot; ! 2196: } ! 2197: } else { ! 2198: /* unsigned */ ! 2199: uae_u32 lo = (uae_u32)m68k_dreg (regs, (extra >> 12) & 7); ! 2200: uae_u32 hi = 0; ! 2201: uae_u32 quot, rem; ! 2202: ! 2203: if (extra & 0x400) { ! 2204: hi = (uae_u32)m68k_dreg (regs, extra & 7); ! 2205: } ! 2206: if (div_unsigned (hi, lo, src, ", &rem)) { ! 2207: SET_VFLG (1); ! 2208: SET_NFLG (1); ! 2209: SET_CFLG (0); ! 2210: } else { ! 2211: SET_VFLG (0); ! 2212: SET_CFLG (0); ! 2213: SET_ZFLG (((uae_s32)quot) == 0); ! 2214: SET_NFLG (((uae_s32)quot) < 0); ! 2215: m68k_dreg (regs, extra & 7) = rem; ! 2216: m68k_dreg (regs, (extra >> 12) & 7) = quot; ! 2217: } ! 2218: } ! 2219: #endif ! 2220: } ! 2221: ! 2222: STATIC_INLINE void mul_unsigned (uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo) ! 2223: { ! 2224: uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff); ! 2225: uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff); ! 2226: uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff); ! 2227: uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff); ! 2228: uae_u32 lo; ! 2229: ! 2230: lo = r0 + ((r1 << 16) & 0xffff0000ul); ! 2231: if (lo < r0) r3++; ! 2232: r0 = lo; ! 2233: lo = r0 + ((r2 << 16) & 0xffff0000ul); ! 2234: if (lo < r0) r3++; ! 2235: r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff); ! 2236: *dst_lo = lo; ! 2237: *dst_hi = r3; ! 2238: } ! 2239: ! 2240: void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra) ! 2241: { ! 2242: #if defined (uae_s64) ! 2243: if (extra & 0x800) { ! 2244: /* signed variant */ ! 2245: uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7); ! 2246: ! 2247: a *= (uae_s64)(uae_s32)src; ! 2248: SET_VFLG (0); ! 2249: SET_CFLG (0); ! 2250: SET_ZFLG (a == 0); ! 2251: SET_NFLG (a < 0); ! 2252: if (extra & 0x400) ! 2253: m68k_dreg (regs, extra & 7) = (uae_u32)(a >> 32); ! 2254: else if ((a & UVAL64 (0xffffffff80000000)) != 0 ! 2255: && (a & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000)) ! 2256: { ! 2257: SET_VFLG (1); ! 2258: } ! 2259: m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a; ! 2260: } else { ! 2261: /* unsigned */ ! 2262: uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7); ! 2263: ! 2264: a *= (uae_u64)src; ! 2265: SET_VFLG (0); ! 2266: SET_CFLG (0); ! 2267: SET_ZFLG (a == 0); ! 2268: SET_NFLG (((uae_s64)a) < 0); ! 2269: if (extra & 0x400) ! 2270: m68k_dreg (regs, extra & 7) = (uae_u32)(a >> 32); ! 2271: else if ((a & UVAL64 (0xffffffff00000000)) != 0) { ! 2272: SET_VFLG (1); ! 2273: } ! 2274: m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a; ! 2275: } ! 2276: #else ! 2277: if (extra & 0x800) { ! 2278: /* signed variant */ ! 2279: uae_s32 src1, src2; ! 2280: uae_u32 dst_lo, dst_hi; ! 2281: uae_u32 sign; ! 2282: ! 2283: src1 = (uae_s32)src; ! 2284: src2 = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7); ! 2285: sign = (src1 ^ src2); ! 2286: if (src1 < 0) src1 = -src1; ! 2287: if (src2 < 0) src2 = -src2; ! 2288: mul_unsigned ((uae_u32)src1, (uae_u32)src2, &dst_hi, &dst_lo); ! 2289: if (sign & 0x80000000) { ! 2290: dst_hi = ~dst_hi; ! 2291: dst_lo = -dst_lo; ! 2292: if (dst_lo == 0) dst_hi++; ! 2293: } ! 2294: SET_VFLG (0); ! 2295: SET_CFLG (0); ! 2296: SET_ZFLG (dst_hi == 0 && dst_lo == 0); ! 2297: SET_NFLG (((uae_s32)dst_hi) < 0); ! 2298: if (extra & 0x400) ! 2299: m68k_dreg (regs, extra & 7) = dst_hi; ! 2300: else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0) ! 2301: && ((dst_hi & 0xffffffff) != 0xffffffff ! 2302: || (dst_lo & 0x80000000) != 0x80000000)) ! 2303: { ! 2304: SET_VFLG (1); ! 2305: } ! 2306: m68k_dreg (regs, (extra >> 12) & 7) = dst_lo; ! 2307: } else { ! 2308: /* unsigned */ ! 2309: uae_u32 dst_lo, dst_hi; ! 2310: ! 2311: mul_unsigned (src, (uae_u32)m68k_dreg (regs, (extra >> 12) & 7), &dst_hi, &dst_lo); ! 2312: ! 2313: SET_VFLG (0); ! 2314: SET_CFLG (0); ! 2315: SET_ZFLG (dst_hi == 0 && dst_lo == 0); ! 2316: SET_NFLG (((uae_s32)dst_hi) < 0); ! 2317: if (extra & 0x400) ! 2318: m68k_dreg (regs, extra & 7) = dst_hi; ! 2319: else if (dst_hi != 0) { ! 2320: SET_VFLG (1); ! 2321: } ! 2322: m68k_dreg (regs, (extra >> 12) & 7) = dst_lo; ! 2323: } ! 2324: #endif ! 2325: } ! 2326: ! 2327: #endif ! 2328: ! 2329: void m68k_reset (int hardreset) ! 2330: { ! 2331: regs.spcflags = 0; ! 2332: regs.ipl = regs.ipl_pin = 0; ! 2333: #ifdef SAVESTATE ! 2334: if (savestate_state == STATE_RESTORE || savestate_state == STATE_REWIND) { ! 2335: m68k_setpc (regs.pc); ! 2336: SET_XFLG ((regs.sr >> 4) & 1); ! 2337: SET_NFLG ((regs.sr >> 3) & 1); ! 2338: SET_ZFLG ((regs.sr >> 2) & 1); ! 2339: SET_VFLG ((regs.sr >> 1) & 1); ! 2340: SET_CFLG (regs.sr & 1); ! 2341: regs.t1 = (regs.sr >> 15) & 1; ! 2342: regs.t0 = (regs.sr >> 14) & 1; ! 2343: regs.s = (regs.sr >> 13) & 1; ! 2344: regs.m = (regs.sr >> 12) & 1; ! 2345: regs.intmask = (regs.sr >> 8) & 7; ! 2346: /* set stack pointer */ ! 2347: if (regs.s) ! 2348: m68k_areg (regs, 7) = regs.isp; ! 2349: else ! 2350: m68k_areg (regs, 7) = regs.usp; ! 2351: return; ! 2352: } ! 2353: #endif ! 2354: regs.s = 1; ! 2355: regs.m = 0; ! 2356: regs.stopped = 0; ! 2357: regs.t1 = 0; ! 2358: regs.t0 = 0; ! 2359: SET_ZFLG (0); ! 2360: SET_XFLG (0); ! 2361: SET_CFLG (0); ! 2362: SET_VFLG (0); ! 2363: SET_NFLG (0); ! 2364: regs.intmask = 7; ! 2365: regs.vbr = regs.sfc = regs.dfc = 0; ! 2366: regs.irc = 0xffff; ! 2367: ! 2368: m68k_areg (regs, 7) = get_long (0); ! 2369: m68k_setpc (get_long (4)); ! 2370: ! 2371: #ifdef FPUEMU ! 2372: fpu_reset (); ! 2373: #endif ! 2374: regs.caar = regs.cacr = 0; ! 2375: regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0; ! 2376: regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0; ! 2377: if (currprefs.cpu_model == 68020) { ! 2378: regs.cacr |= 8; ! 2379: set_cpu_caches (); ! 2380: } ! 2381: ! 2382: mmufixup[0].reg = -1; ! 2383: mmufixup[1].reg = -1; ! 2384: if (currprefs.mmu_model) { ! 2385: mmu_reset (); ! 2386: mmu_set_tc (regs.tcr); ! 2387: mmu_set_super (regs.s != 0); ! 2388: } ! 2389: ! 2390: #if AMIGA_ONLY ! 2391: a3000_fakekick (0); ! 2392: #endif ! 2393: /* only (E)nable bit is zeroed when CPU is reset, A3000 SuperKickstart expects this */ ! 2394: tc_030 &= ~0x80000000; ! 2395: tt0_030 &= ~0x80000000; ! 2396: tt1_030 &= ~0x80000000; ! 2397: if (hardreset) { ! 2398: srp_030 = crp_030 = 0; ! 2399: tt0_030 = tt1_030 = tc_030 = 0; ! 2400: } ! 2401: mmusr_030 = 0; ! 2402: ! 2403: /* 68060 FPU is not compatible with 68040, ! 2404: * 68060 accelerators' boot ROM disables the FPU ! 2405: */ ! 2406: regs.pcr = 0; ! 2407: if (currprefs.cpu_model == 68060) { ! 2408: regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR; ! 2409: regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8; ! 2410: if (kickstart_rom) ! 2411: regs.pcr |= 2; /* disable FPU */ ! 2412: } ! 2413: fill_prefetch_slow (); ! 2414: } ! 2415: ! 2416: unsigned long REGPARAM2 op_illg (uae_u32 opcode) ! 2417: { ! 2418: uaecptr pc = m68k_getpc (); ! 2419: static int warned; ! 2420: ! 2421: #if AMIGA_ONLY ! 2422: int inrom = in_rom (pc); ! 2423: int inrt = in_rtarea (pc); ! 2424: ! 2425: if (cloanto_rom && (opcode & 0xF100) == 0x7100) { ! 2426: m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF); ! 2427: m68k_incpc (2); ! 2428: fill_prefetch_slow (); ! 2429: return 4; ! 2430: } ! 2431: ! 2432: if (opcode == 0x4E7B && inrom && get_long (0x10) == 0) { ! 2433: notify_user (NUMSG_KS68020); ! 2434: uae_restart (-1, NULL); ! 2435: } ! 2436: #endif ! 2437: ! 2438: #ifdef AUTOCONFIG ! 2439: if (opcode == 0xFF0D) { ! 2440: if (inrom) { ! 2441: /* This is from the dummy Kickstart replacement */ ! 2442: uae_u16 arg = get_iword (2); ! 2443: m68k_incpc (4); ! 2444: ersatz_perform (arg); ! 2445: fill_prefetch_slow (); ! 2446: return 4; ! 2447: } else if (inrt) { ! 2448: /* User-mode STOP replacement */ ! 2449: m68k_setstopped (); ! 2450: return 4; ! 2451: } ! 2452: } ! 2453: ! 2454: if ((opcode & 0xF000) == 0xA000 && inrt) { ! 2455: /* Calltrap. */ ! 2456: m68k_incpc (2); ! 2457: m68k_handle_trap (opcode & 0xFFF); ! 2458: fill_prefetch_slow (); ! 2459: return 4; ! 2460: } ! 2461: #endif ! 2462: ! 2463: if ((opcode & 0xF000) == 0xF000) { ! 2464: if (warned < 20) { ! 2465: write_log ("B-Trap %x at %x (%p)\n", opcode, pc, regs.pc_p); ! 2466: warned++; ! 2467: } ! 2468: Exception (0xB, 0, M68000_EXC_SRC_CPU); ! 2469: //activate_debugger (); ! 2470: return 4; ! 2471: } ! 2472: if ((opcode & 0xF000) == 0xA000) { ! 2473: if (warned < 20) { ! 2474: write_log ("A-Trap %x at %x (%p)\n", opcode, pc, regs.pc_p); ! 2475: warned++; ! 2476: } ! 2477: Exception (0xA, 0, M68000_EXC_SRC_CPU); ! 2478: //activate_debugger(); ! 2479: return 4; ! 2480: } ! 2481: if (warned < 20) { ! 2482: write_log ("Illegal instruction: %04x at %08X -> %08X\n", opcode, pc, get_long (regs.vbr + 0x10)); ! 2483: warned++; ! 2484: //activate_debugger(); ! 2485: } ! 2486: ! 2487: Exception (4, 0, M68000_EXC_SRC_CPU); ! 2488: return 4; ! 2489: } ! 2490: ! 2491: #ifdef CPUEMU_0 ! 2492: ! 2493: static const TCHAR *mmu30regs[] = { "TCR", "", "SRP", "CRP", "", "", "", "" }; ! 2494: ! 2495: static void mmu_op30_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra) ! 2496: { ! 2497: int preg = (next >> 10) & 31; ! 2498: int rw = (next >> 9) & 1; ! 2499: int fd = (next >> 8) & 1; ! 2500: const TCHAR *reg = NULL; ! 2501: uae_u32 otc = tc_030; ! 2502: int siz; ! 2503: ! 2504: switch (preg) ! 2505: { ! 2506: case 0x10: // TC ! 2507: reg = "TC"; ! 2508: siz = 4; ! 2509: if (rw) ! 2510: x_put_long (extra, tc_030); ! 2511: else ! 2512: tc_030 = x_get_long (extra); ! 2513: break; ! 2514: case 0x12: // SRP ! 2515: reg = "SRP"; ! 2516: siz = 8; ! 2517: if (rw) { ! 2518: x_put_long (extra, srp_030 >> 32); ! 2519: x_put_long (extra + 4, srp_030); ! 2520: } else { ! 2521: srp_030 = (uae_u64)x_get_long (extra) << 32; ! 2522: srp_030 |= x_get_long (extra + 4); ! 2523: } ! 2524: break; ! 2525: case 0x13: // CRP ! 2526: reg = "CRP"; ! 2527: siz = 8; ! 2528: if (rw) { ! 2529: x_put_long (extra, crp_030 >> 32); ! 2530: x_put_long (extra + 4, crp_030); ! 2531: } else { ! 2532: crp_030 = (uae_u64)x_get_long (extra) << 32; ! 2533: crp_030 |= x_get_long (extra + 4); ! 2534: } ! 2535: break; ! 2536: case 0x18: // MMUSR ! 2537: reg = "MMUSR"; ! 2538: siz = 2; ! 2539: if (rw) ! 2540: x_put_word (extra, mmusr_030); ! 2541: else ! 2542: mmusr_030 = x_get_word (extra); ! 2543: break; ! 2544: case 0x02: // TT0 ! 2545: reg = "TT0"; ! 2546: siz = 4; ! 2547: if (rw) ! 2548: x_put_long (extra, tt0_030); ! 2549: else ! 2550: tt0_030 = x_get_long (extra); ! 2551: break; ! 2552: case 0x03: // TT1 ! 2553: reg = "TT1"; ! 2554: siz = 4; ! 2555: if (rw) ! 2556: x_put_long (extra, tt1_030); ! 2557: else ! 2558: tt1_030 = x_get_long (extra); ! 2559: break; ! 2560: } ! 2561: ! 2562: if (!reg) { ! 2563: op_illg (opcode); ! 2564: return; ! 2565: } ! 2566: #if MMUOP_DEBUG > 0 ! 2567: { ! 2568: uae_u32 val; ! 2569: if (siz == 8) { ! 2570: uae_u32 val2 = x_get_long (extra); ! 2571: val = x_get_long (extra + 4); ! 2572: if (rw) ! 2573: write_log ("PMOVE %s,%08X%08X", reg, val2, val); ! 2574: else ! 2575: write_log ("PMOVE %08X%08X,%s", val2, val, reg); ! 2576: } else { ! 2577: if (siz == 4) ! 2578: val = x_get_long (extra); ! 2579: else ! 2580: val = x_get_word (extra); ! 2581: if (rw) ! 2582: write_log ("PMOVE %s,%08X", reg, val); ! 2583: else ! 2584: write_log ("PMOVE %08X,%s", val, reg); ! 2585: } ! 2586: write_log (" PC=%08X\n", pc); ! 2587: } ! 2588: #endif ! 2589: if (currprefs.cs_mbdmac == 1 && currprefs.mbresmem_low_size > 0) { ! 2590: if (otc != tc_030) { ! 2591: #if AMIGA_ONLY ! 2592: a3000_fakekick (tc_030 & 0x80000000); ! 2593: #endif ! 2594: } ! 2595: } ! 2596: } ! 2597: ! 2598: static void mmu_op30_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra) ! 2599: { ! 2600: #if MMUOP_DEBUG > 0 ! 2601: TCHAR tmp[10]; ! 2602: ! 2603: tmp[0] = 0; ! 2604: if ((next >> 8) & 1) ! 2605: _stprintf (tmp, ",A%d", (next >> 4) & 15); ! 2606: write_log ("PTEST%c %02X,%08X,#%X%s PC=%08X\n", ! 2607: ((next >> 9) & 1) ? 'W' : 'R', (next & 15), extra, (next >> 10) & 7, tmp, pc); ! 2608: #endif ! 2609: mmusr_030 = 0; ! 2610: } ! 2611: ! 2612: static void mmu_op30_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra) ! 2613: { ! 2614: #if MMUOP_DEBUG > 0 ! 2615: write_log ("PFLUSH PC=%08X\n", pc); ! 2616: #endif ! 2617: } ! 2618: ! 2619: void mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa) ! 2620: { ! 2621: if (currprefs.cpu_model != 68030) { ! 2622: m68k_setpc (pc); ! 2623: op_illg (opcode); ! 2624: return; ! 2625: } ! 2626: if (extra & 0x8000) ! 2627: mmu_op30_ptest (pc, opcode, extra, extraa); ! 2628: else if (extra & 0x2000) ! 2629: mmu_op30_pflush (pc, opcode, extra, extraa); ! 2630: else ! 2631: mmu_op30_pmove (pc, opcode, extra, extraa); ! 2632: } ! 2633: ! 2634: void mmu_op (uae_u32 opcode, uae_u32 extra) ! 2635: { ! 2636: if (currprefs.cpu_model) { ! 2637: mmu_op_real (opcode, extra); ! 2638: return; ! 2639: } ! 2640: #if MMUOP_DEBUG > 1 ! 2641: write_log ("mmu_op %04X PC=%08X\n", opcode, m68k_getpc ()); ! 2642: #endif ! 2643: if ((opcode & 0xFE0) == 0x0500) { ! 2644: /* PFLUSH */ ! 2645: regs.mmusr = 0; ! 2646: #if MMUOP_DEBUG > 0 ! 2647: write_log ("PFLUSH\n"); ! 2648: #endif ! 2649: return; ! 2650: } else if ((opcode & 0x0FD8) == 0x548) { ! 2651: if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */ ! 2652: /* PTEST */ ! 2653: #if MMUOP_DEBUG > 0 ! 2654: write_log ("PTEST\n"); ! 2655: #endif ! 2656: return; ! 2657: } ! 2658: } else if ((opcode & 0x0FB8) == 0x588) { ! 2659: /* PLPA */ ! 2660: if (currprefs.cpu_model == 68060) { ! 2661: #if MMUOP_DEBUG > 0 ! 2662: write_log ("PLPA\n"); ! 2663: #endif ! 2664: return; ! 2665: } ! 2666: } ! 2667: #if MMUOP_DEBUG > 0 ! 2668: write_log ("Unknown MMU OP %04X\n", opcode); ! 2669: #endif ! 2670: m68k_setpc (m68k_getpc () - 2); ! 2671: op_illg (opcode); ! 2672: } ! 2673: ! 2674: #endif ! 2675: ! 2676: static uaecptr last_trace_ad = 0; ! 2677: ! 2678: static void do_trace (void) ! 2679: { ! 2680: if (regs.t0 && currprefs.cpu_model >= 68020) { ! 2681: uae_u16 opcode; ! 2682: /* should also include TRAP, CHK, SR modification FPcc */ ! 2683: /* probably never used so why bother */ ! 2684: /* We can afford this to be inefficient... */ ! 2685: m68k_setpc (m68k_getpc ()); ! 2686: fill_prefetch_slow (); ! 2687: opcode = x_get_word (regs.pc); ! 2688: if (opcode == 0x4e73 /* RTE */ ! 2689: || opcode == 0x4e74 /* RTD */ ! 2690: || opcode == 0x4e75 /* RTS */ ! 2691: || opcode == 0x4e77 /* RTR */ ! 2692: || opcode == 0x4e76 /* TRAPV */ ! 2693: || (opcode & 0xffc0) == 0x4e80 /* JSR */ ! 2694: || (opcode & 0xffc0) == 0x4ec0 /* JMP */ ! 2695: || (opcode & 0xff00) == 0x6100 /* BSR */ ! 2696: || ((opcode & 0xf000) == 0x6000 /* Bcc */ ! 2697: && cctrue ((opcode >> 8) & 0xf)) ! 2698: || ((opcode & 0xf0f0) == 0x5050 /* DBcc */ ! 2699: && !cctrue ((opcode >> 8) & 0xf) ! 2700: && (uae_s16)m68k_dreg (regs, opcode & 7) != 0)) ! 2701: { ! 2702: last_trace_ad = m68k_getpc (); ! 2703: unset_special (SPCFLAG_TRACE); ! 2704: set_special (SPCFLAG_DOTRACE); ! 2705: } ! 2706: } else if (regs.t1) { ! 2707: last_trace_ad = m68k_getpc (); ! 2708: unset_special (SPCFLAG_TRACE); ! 2709: set_special (SPCFLAG_DOTRACE); ! 2710: } ! 2711: } ! 2712: ! 2713: ! 2714: // handle interrupt delay (few cycles) ! 2715: STATIC_INLINE int time_for_interrupt (void) ! 2716: { ! 2717: if (regs.ipl > regs.intmask || regs.ipl == 7) { ! 2718: #if 0 ! 2719: if (regs.ipl == 3 && current_hpos () < 11) { ! 2720: write_log ("%d\n", current_hpos ()); ! 2721: activate_debugger (); ! 2722: } ! 2723: #endif ! 2724: return 1; ! 2725: } ! 2726: return 0; ! 2727: } ! 2728: ! 2729: void doint (void) ! 2730: { ! 2731: if (currprefs.cpu_cycle_exact) { ! 2732: regs.ipl_pin = intlev (); ! 2733: set_special (SPCFLAG_INT); ! 2734: return; ! 2735: } ! 2736: if (currprefs.cpu_compatible) ! 2737: set_special (SPCFLAG_INT); ! 2738: else ! 2739: set_special (SPCFLAG_DOINT); ! 2740: } ! 2741: ! 2742: #define IDLETIME (currprefs.cpu_idle * sleep_resolution / 700) ! 2743: ! 2744: /* ! 2745: * Compute the number of jitter cycles to add when a video interrupt occurs ! 2746: * (this is specific to the Atari ST) ! 2747: */ ! 2748: STATIC_INLINE void InterruptAddJitter (int Level , int Pending) ! 2749: { ! 2750: } ! 2751: ! 2752: ! 2753: /* ! 2754: * Handle special flags ! 2755: */ ! 2756: ! 2757: static bool do_specialties_interrupt (int Pending) ! 2758: { ! 2759: return false; /* no interrupt was found */ ! 2760: } ! 2761: ! 2762: STATIC_INLINE int do_specialties (int cycles) ! 2763: { ! 2764: #ifdef JIT ! 2765: unset_special (SPCFLAG_END_COMPILE); /* has done its job */ ! 2766: #endif ! 2767: ! 2768: #if AMIGA_ONLY ! 2769: while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && !currprefs.blitter_cycle_exact) { ! 2770: /* Laurent : I don't know if our blitter code should be called here ! */ ! 2771: int c = blitnasty (); ! 2772: if (c > 0) { ! 2773: cycles -= c * CYCLE_UNIT * 2; ! 2774: if (cycles < CYCLE_UNIT) ! 2775: cycles = 0; ! 2776: } else ! 2777: c = 4; ! 2778: do_cycles (c * CYCLE_UNIT); ! 2779: if (regs.spcflags & SPCFLAG_COPPER) ! 2780: do_copper (); ! 2781: } ! 2782: #endif ! 2783: ! 2784: if (regs.spcflags & SPCFLAG_BUSERROR) { ! 2785: /* We can not execute bus errors directly in the memory handler ! 2786: * functions since the PC should point to the address of the next ! 2787: * instruction, so we're executing the bus errors here: */ ! 2788: unset_special(SPCFLAG_BUSERROR); ! 2789: Exception(2, 0, M68000_EXC_SRC_CPU); ! 2790: } ! 2791: ! 2792: if(regs.spcflags & SPCFLAG_EXTRA_CYCLES) { ! 2793: /* Add some extra cycles to simulate a wait state */ ! 2794: unset_special(SPCFLAG_EXTRA_CYCLES); ! 2795: M68000_AddCycles(nWaitStateCycles); ! 2796: nWaitStateCycles = 0; ! 2797: } ! 2798: ! 2799: if (regs.spcflags & SPCFLAG_DOTRACE) ! 2800: Exception (9, last_trace_ad, M68000_EXC_SRC_CPU); ! 2801: ! 2802: if (regs.spcflags & SPCFLAG_TRAP) { ! 2803: unset_special (SPCFLAG_TRAP); ! 2804: Exception (3, 0, M68000_EXC_SRC_CPU); ! 2805: } ! 2806: ! 2807: /* Handle the STOP instruction */ ! 2808: if ( regs.spcflags & SPCFLAG_STOP ) { ! 2809: /* We first test if there's a pending interrupt that would */ ! 2810: /* allow to immediatly leave the STOP state */ ! 2811: if ( do_specialties_interrupt(true) ) { /* test if there's an interrupt and add pending jitter */ ! 2812: regs.stopped = 0; ! 2813: unset_special (SPCFLAG_STOP); ! 2814: } ! 2815: ! 2816: while (regs.spcflags & SPCFLAG_STOP) { ! 2817: ! 2818: /* Take care of quit event if needed */ ! 2819: if (regs.spcflags & SPCFLAG_BRK) ! 2820: return 1; ! 2821: ! 2822: do_cycles (currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT); ! 2823: M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT); ! 2824: ! 2825: /* It is possible one or more ints happen at the same time */ ! 2826: /* We must process them during the same cpu cycle until the special INT flag is set */ ! 2827: while (PendingInterruptCount<=0 && PendingInterruptFunction) { ! 2828: /* 1st, we call the interrupt handler */ ! 2829: CALL_VAR(PendingInterruptFunction); ! 2830: ! 2831: /* Then we check if this handler triggered an interrupt to process */ ! 2832: if ( do_specialties_interrupt(false) ) { /* test if there's an interrupt and add non pending jitter */ ! 2833: regs.stopped = 0; ! 2834: unset_special (SPCFLAG_STOP); ! 2835: break; ! 2836: } ! 2837: ! 2838: #if AMIGA_ONLY ! 2839: if (regs.spcflags & SPCFLAG_COPPER) ! 2840: do_copper (); ! 2841: #endif ! 2842: ! 2843: if (currprefs.cpu_cycle_exact) { ! 2844: ipl_fetch (); ! 2845: if (time_for_interrupt ()) { ! 2846: do_interrupt (regs.ipl, true); ! 2847: } ! 2848: } else { ! 2849: #if 0 ! 2850: if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) { ! 2851: int intr = intlev (); ! 2852: unset_special (SPCFLAG_INT | SPCFLAG_DOINT); ! 2853: if (intr > 0 && intr > regs.intmask) ! 2854: do_interrupt (intr, true); ! 2855: } ! 2856: #endif ! 2857: } ! 2858: if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) { ! 2859: unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); ! 2860: // SPCFLAG_BRK breaks STOP condition, need to prefetch ! 2861: m68k_resumestopped (); ! 2862: return 1; ! 2863: } ! 2864: ! 2865: if (currprefs.cpu_idle && currprefs.m68k_speed != 0 && ((regs.spcflags & SPCFLAG_STOP)) == SPCFLAG_STOP) { ! 2866: /* sleep 1ms if STOP-instruction is executed */ ! 2867: if (1) { ! 2868: static int sleepcnt, lvpos, zerocnt; ! 2869: if (vpos != lvpos) { ! 2870: sleepcnt--; ! 2871: #ifdef JIT ! 2872: if (pissoff == 0 && currprefs.cachesize && --zerocnt < 0) { ! 2873: sleepcnt = -1; ! 2874: zerocnt = IDLETIME / 4; ! 2875: } ! 2876: #endif ! 2877: lvpos = vpos; ! 2878: if (sleepcnt < 0) { ! 2879: /*sleepcnt = IDLETIME / 2; */ /* Laurent : badly removed for now */ ! 2880: sleep_millis (1); ! 2881: } ! 2882: } ! 2883: } ! 2884: } ! 2885: } ! 2886: } ! 2887: } ! 2888: ! 2889: if (regs.spcflags & SPCFLAG_TRACE) ! 2890: do_trace (); ! 2891: ! 2892: if (currprefs.cpu_cycle_exact) { ! 2893: if (time_for_interrupt ()) { ! 2894: do_interrupt (regs.ipl, true); ! 2895: } ! 2896: } else { ! 2897: if (regs.spcflags & SPCFLAG_INT) { ! 2898: int intr = intlev (); ! 2899: unset_special (SPCFLAG_INT | SPCFLAG_DOINT); ! 2900: if (intr > 0 && (intr > regs.intmask || intr == 7)) ! 2901: do_interrupt (intr, false); /* call do_interrupt() with Pending=false, not necessarily true but harmless */ ! 2902: } ! 2903: } ! 2904: ! 2905: if (regs.spcflags & SPCFLAG_DOINT) { ! 2906: unset_special (SPCFLAG_DOINT); ! 2907: set_special (SPCFLAG_INT); ! 2908: } ! 2909: ! 2910: if ( do_specialties_interrupt(false) ) { /* test if there's an interrupt and add non pending jitter */ ! 2911: /* TODO: Always do do_specialties_interrupt() in m68k_run_x instead? */ ! 2912: regs.stopped = 0; ! 2913: } ! 2914: ! 2915: if (regs.spcflags & SPCFLAG_DEBUGGER) ! 2916: DebugCpu_Check(); ! 2917: ! 2918: if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) { ! 2919: unset_special(SPCFLAG_MODE_CHANGE); ! 2920: return 1; ! 2921: } ! 2922: return 0; ! 2923: } ! 2924: ! 2925: //static uae_u32 pcs[1000]; ! 2926: ! 2927: #if DEBUG_CD32CDTVIO ! 2928: ! 2929: static uae_u32 cd32nextpc, cd32request; ! 2930: ! 2931: static void out_cd32io2 (void) ! 2932: { ! 2933: uae_u32 request = cd32request; ! 2934: write_log ("%08x returned\n", request); ! 2935: //write_log ("ACTUAL=%d ERROR=%d\n", get_long (request + 32), get_byte (request + 31)); ! 2936: cd32nextpc = 0; ! 2937: cd32request = 0; ! 2938: } ! 2939: ! 2940: static void out_cd32io (uae_u32 pc) ! 2941: { ! 2942: TCHAR out[100]; ! 2943: int ioreq = 0; ! 2944: uae_u32 request = m68k_areg (regs, 1); ! 2945: ! 2946: if (pc == cd32nextpc) { ! 2947: out_cd32io2 (); ! 2948: return; ! 2949: } ! 2950: out[0] = 0; ! 2951: switch (pc) ! 2952: { ! 2953: case 0xe57cc0: ! 2954: case 0xf04c34: ! 2955: _stprintf (out, "opendevice"); ! 2956: break; ! 2957: case 0xe57ce6: ! 2958: case 0xf04c56: ! 2959: _stprintf (out, "closedevice"); ! 2960: break; ! 2961: case 0xe57e44: ! 2962: case 0xf04f2c: ! 2963: _stprintf (out, "beginio"); ! 2964: ioreq = 1; ! 2965: break; ! 2966: case 0xe57ef2: ! 2967: case 0xf0500e: ! 2968: _stprintf (out, "abortio"); ! 2969: ioreq = -1; ! 2970: break; ! 2971: } ! 2972: if (out[0] == 0) ! 2973: return; ! 2974: if (cd32request) ! 2975: write_log ("old request still not returned!\n"); ! 2976: cd32request = request; ! 2977: cd32nextpc = get_long (m68k_areg (regs, 7)); ! 2978: write_log ("%s A1=%08X\n", out, request); ! 2979: if (ioreq) { ! 2980: static int cnt = 0; ! 2981: int cmd = get_word (request + 28); ! 2982: #if 0 ! 2983: if (cmd == 37) { ! 2984: cnt--; ! 2985: if (cnt <= 0) ! 2986: activate_debugger (); ! 2987: } ! 2988: #endif ! 2989: write_log ("CMD=%d DATA=%08X LEN=%d %OFF=%d PC=%x\n", ! 2990: cmd, get_long (request + 40), ! 2991: get_long (request + 36), get_long (request + 44), M68K_GETPC); ! 2992: } ! 2993: if (ioreq < 0) ! 2994: ;//activate_debugger (); ! 2995: } ! 2996: ! 2997: #endif /* DEBUG_CD32CDTVIO */ ! 2998: ! 2999: #ifndef CPUEMU_11 ! 3000: ! 3001: static void m68k_run_1 (void) ! 3002: { ! 3003: } ! 3004: ! 3005: #else ! 3006: ! 3007: /* It's really sad to have two almost identical functions for this, but we ! 3008: do it all for performance... :( ! 3009: This version emulates 68000's prefetch "cache" */ ! 3010: static void m68k_run_1 (void) ! 3011: { ! 3012: struct regstruct *r = ®s; ! 3013: ! 3014: for (;;) { ! 3015: uae_u32 opcode = r->ir; ! 3016: ! 3017: count_instr (opcode); ! 3018: ! 3019: /*m68k_dumpstate(stderr, NULL);*/ ! 3020: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM)) ! 3021: { ! 3022: int FrameCycles, HblCounterVideo, LineCycles; ! 3023: ! 3024: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles ); ! 3025: ! 3026: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo ); ! 3027: m68k_disasm(stderr, m68k_getpc (), NULL, 1); ! 3028: } ! 3029: ! 3030: #if DEBUG_CD32CDTVIO ! 3031: out_cd32io (m68k_getpc ()); ! 3032: #endif ! 3033: ! 3034: #if 0 ! 3035: int pc = m68k_getpc (); ! 3036: if (pc == 0xdff002) ! 3037: write_log ("hip\n"); ! 3038: if (pc != pcs[0] && (pc < 0xd00000 || pc > 0x1000000)) { ! 3039: memmove (pcs + 1, pcs, 998 * 4); ! 3040: pcs[0] = pc; ! 3041: //write_log ("%08X-%04X ", pc, opcode); ! 3042: } ! 3043: #endif ! 3044: do_cycles (cpu_cycles); ! 3045: cpu_cycles = (*cpufunctbl[opcode])(opcode); ! 3046: cpu_cycles &= cycles_mask; ! 3047: cpu_cycles |= cycles_val; ! 3048: ! 3049: /* We can have several interrupts at the same time before the next CPU instruction */ ! 3050: /* We must check for pending interrupt and call do_specialties_interrupt() only */ ! 3051: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */ ! 3052: /* and prevent exiting the STOP state when calling do_specialties() after. */ ! 3053: /* For performance, we first test PendingInterruptCount, then regs.spcflags */ ! 3054: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) { ! 3055: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */ ! 3056: do_specialties_interrupt(false); /* test if there's an mfp/video interrupt and add non pending jitter */ ! 3057: } ! 3058: ! 3059: if (r->spcflags) { ! 3060: if (do_specialties (cpu_cycles)) ! 3061: return; ! 3062: } ! 3063: regs.ipl = regs.ipl_pin; ! 3064: if (!currprefs.cpu_compatible || (currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000)) ! 3065: return; ! 3066: } ! 3067: } ! 3068: ! 3069: #endif /* CPUEMU_11 */ ! 3070: ! 3071: #ifndef CPUEMU_12 ! 3072: ! 3073: static void m68k_run_1_ce (void) ! 3074: { ! 3075: } ! 3076: ! 3077: #else ! 3078: ! 3079: /* cycle-exact m68k_run () */ ! 3080: ! 3081: static void m68k_run_1_ce (void) ! 3082: { ! 3083: struct regstruct *r = ®s; ! 3084: ! 3085: ipl_fetch (); ! 3086: for (;;) { ! 3087: uae_u32 opcode = r->ir; ! 3088: ! 3089: /*m68k_dumpstate(stderr, NULL);*/ ! 3090: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM)) ! 3091: { ! 3092: int FrameCycles, HblCounterVideo, LineCycles; ! 3093: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles ); ! 3094: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo ); ! 3095: m68k_disasm(stderr, m68k_getpc (), NULL, 1); ! 3096: } ! 3097: ! 3098: #if DEBUG_CD32CDTVIO ! 3099: out_cd32io (m68k_getpc ()); ! 3100: #endif ! 3101: (*cpufunctbl[opcode])(opcode); ! 3102: if (r->spcflags) { ! 3103: if (do_specialties (0)) ! 3104: return; ! 3105: } ! 3106: if (!currprefs.cpu_cycle_exact || currprefs.cpu_model > 68000) ! 3107: return; ! 3108: } ! 3109: } ! 3110: #endif ! 3111: ! 3112: #ifdef JIT /* Completely different run_2 replacement */ ! 3113: ! 3114: void do_nothing (void) ! 3115: { ! 3116: /* What did you expect this to do? */ ! 3117: do_cycles (0); ! 3118: /* I bet you didn't expect *that* ;-) */ ! 3119: } ! 3120: ! 3121: void exec_nostats (void) ! 3122: { ! 3123: struct regstruct *r = ®s; ! 3124: ! 3125: for (;;) ! 3126: { ! 3127: uae_u16 opcode = get_iword (0); ! 3128: ! 3129: cpu_cycles = (*cpufunctbl[opcode])(opcode); ! 3130: ! 3131: cpu_cycles &= cycles_mask; ! 3132: cpu_cycles |= cycles_val; ! 3133: ! 3134: do_cycles (cpu_cycles); ! 3135: ! 3136: if (end_block (opcode) || r->spcflags || uae_int_requested) ! 3137: return; /* We will deal with the spcflags in the caller */ ! 3138: } ! 3139: } ! 3140: ! 3141: static int triggered; ! 3142: ! 3143: void execute_normal (void) ! 3144: { ! 3145: struct regstruct *r = ®s; ! 3146: int blocklen; ! 3147: cpu_history pc_hist[MAXRUN]; ! 3148: int total_cycles; ! 3149: ! 3150: if (check_for_cache_miss ()) ! 3151: return; ! 3152: ! 3153: total_cycles = 0; ! 3154: blocklen = 0; ! 3155: start_pc_p = r->pc_oldp; ! 3156: start_pc = r->pc; ! 3157: for (;;) { ! 3158: /* Take note: This is the do-it-normal loop */ ! 3159: uae_u16 opcode = get_iword (0); ! 3160: ! 3161: special_mem = DISTRUST_CONSISTENT_MEM; ! 3162: pc_hist[blocklen].location = (uae_u16*)r->pc_p; ! 3163: ! 3164: cpu_cycles = (*cpufunctbl[opcode])(opcode); ! 3165: ! 3166: cpu_cycles &= cycles_mask; ! 3167: cpu_cycles |= cycles_val; ! 3168: do_cycles (cpu_cycles); ! 3169: total_cycles += cpu_cycles; ! 3170: pc_hist[blocklen].specmem = special_mem; ! 3171: blocklen++; ! 3172: if (end_block (opcode) || blocklen >= MAXRUN || r->spcflags || uae_int_requested) { ! 3173: compile_block (pc_hist, blocklen, total_cycles); ! 3174: return; /* We will deal with the spcflags in the caller */ ! 3175: } ! 3176: /* No need to check regs.spcflags, because if they were set, ! 3177: we'd have ended up inside that "if" */ ! 3178: } ! 3179: } ! 3180: ! 3181: typedef void compiled_handler (void); ! 3182: ! 3183: static void m68k_run_jit (void) ! 3184: { ! 3185: for (;;) { ! 3186: ! 3187: /*m68k_dumpstate(stderr, NULL);*/ ! 3188: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM)) ! 3189: { ! 3190: int FrameCycles, HblCounterVideo, LineCycles; ! 3191: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles ); ! 3192: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo ); ! 3193: m68k_disasm(stderr, m68k_getpc (), NULL, 1); ! 3194: } ! 3195: ! 3196: ((compiled_handler*)(pushall_call_handler))(); ! 3197: /* Whenever we return from that, we should check spcflags */ ! 3198: if (uae_int_requested) { ! 3199: INTREQ_f (0x8008); ! 3200: set_special (SPCFLAG_INT); ! 3201: } ! 3202: if (regs.spcflags) { ! 3203: if (do_specialties (0)) { ! 3204: return; ! 3205: } ! 3206: } ! 3207: } ! 3208: } ! 3209: #endif /* JIT */ ! 3210: ! 3211: #ifndef CPUEMU_0 ! 3212: ! 3213: static void m68k_run_2 (void) ! 3214: { ! 3215: } ! 3216: ! 3217: #else ! 3218: ! 3219: #if 0 ! 3220: static void opcodedebug (uae_u32 pc, uae_u16 opcode) ! 3221: { ! 3222: struct mnemolookup *lookup; ! 3223: struct instr *dp; ! 3224: uae_u32 addr; ! 3225: int fault; ! 3226: ! 3227: if (cpufunctbl[opcode] == op_illg_1) ! 3228: opcode = 0x4AFC; ! 3229: dp = table68k + opcode; ! 3230: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) ! 3231: ; ! 3232: fault = 0; ! 3233: // TRY(prb) { ! 3234: except = 0; ! 3235: addr = mmu_translate (pc, (regs.mmu_ssw & 4) ? 1 : 0, 0, 0); ! 3236: // } CATCH (prb) { ! 3237: if (except != 0) { ! 3238: fault = 1; ! 3239: } ! 3240: if (!fault) { ! 3241: write_log ("mmufixup=%d %04x %04x\n", mmufixup[0].reg, regs.wb3_status, regs.mmu_ssw); ! 3242: m68k_disasm_2 (stdout, addr, NULL, 1, NULL, NULL, 0); ! 3243: write_log ("%s\n", buf); ! 3244: m68k_dumpstate (stdout, NULL); ! 3245: } ! 3246: } ! 3247: #endif ! 3248: ! 3249: /* Aranym MMU 68040 */ ! 3250: static void m68k_run_mmu040 (void) ! 3251: { ! 3252: uae_u32 opcode; ! 3253: uaecptr pc; ! 3254: m68k_exception save_except; ! 3255: ! 3256: retry: ! 3257: // TRY (prb) { ! 3258: except = 0; ! 3259: for (;;) { ! 3260: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM)) ! 3261: { ! 3262: int FrameCycles, HblCounterVideo, LineCycles; ! 3263: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles ); ! 3264: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo ); ! 3265: m68k_disasm(stderr, m68k_getpc (), NULL, 1); ! 3266: } ! 3267: ! 3268: pc = regs.fault_pc = m68k_getpc (); ! 3269: #if 0 ! 3270: static int done; ! 3271: if (pc == 0x16AF94) { ! 3272: // write_log ("D0=%d A7=%08x\n", regs.regs[0], regs.regs[15]); ! 3273: if (regs.regs[0] == 360) { ! 3274: done = 1; ! 3275: activate_debugger (); ! 3276: } ! 3277: } ! 3278: /* ! 3279: if (pc == 0x16B01A) { ! 3280: write_log ("-> ERR\n"); ! 3281: } ! 3282: if (pc == 0x16B018) { ! 3283: write_log ("->\n"); ! 3284: } ! 3285: */ ! 3286: if (pc == 0x17967C || pc == 0x13b5e2 - 4) { ! 3287: if (done) { ! 3288: write_log ("*\n"); ! 3289: mmu_dump_tables (); ! 3290: activate_debugger (); ! 3291: } ! 3292: } ! 3293: #endif ! 3294: opcode = x_prefetch (0); ! 3295: count_instr (opcode); ! 3296: do_cycles (cpu_cycles); ! 3297: cpu_cycles = (*cpufunctbl[opcode])(opcode); ! 3298: cpu_cycles &= cycles_mask; ! 3299: cpu_cycles |= cycles_val; ! 3300: ! 3301: ! 3302: M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT); ! 3303: ! 3304: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) { ! 3305: /* Add some extra cycles to simulate a wait state */ ! 3306: unset_special(SPCFLAG_EXTRA_CYCLES); ! 3307: M68000_AddCycles(nWaitStateCycles); ! 3308: nWaitStateCycles = 0; ! 3309: } ! 3310: ! 3311: /* We can have several interrupts at the same time before the next CPU instruction */ ! 3312: /* We must check for pending interrupt and call do_specialties_interrupt() only */ ! 3313: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */ ! 3314: /* and prevent exiting the STOP state when calling do_specialties() after. */ ! 3315: /* For performance, we first test PendingInterruptCount, then regs.spcflags */ ! 3316: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) { ! 3317: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */ ! 3318: do_specialties_interrupt(false); /* test if there's an mfp/video interrupt and add non pending jitter */ ! 3319: } ! 3320: ! 3321: if (regs.spcflags) { ! 3322: if (do_specialties (cpu_cycles* 2 / CYCLE_UNIT)) ! 3323: return; ! 3324: } ! 3325: } ! 3326: ! 3327: // } CATCH (prb) { ! 3328: if (except != 0) { ! 3329: save_except = except; ! 3330: if (currprefs.mmu_model == 68060) { ! 3331: regs.fault_pc = pc; ! 3332: if (mmufixup[1].reg >= 0) { ! 3333: m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value; ! 3334: mmufixup[1].reg = -1; ! 3335: } ! 3336: } else { ! 3337: if (regs.wb3_status & 0x80) { ! 3338: // movem to memory? ! 3339: if ((opcode & 0xff80) == 0x4880) { ! 3340: regs.mmu_ssw |= MMU_SSW_CM; ! 3341: //write_log ("MMU_SSW_CM\n"); ! 3342: } ! 3343: } ! 3344: } ! 3345: ! 3346: //opcodedebug (regs.fault_pc, opcode); ! 3347: ! 3348: if (mmufixup[0].reg >= 0) { ! 3349: m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value; ! 3350: mmufixup[0].reg = -1; ! 3351: } ! 3352: //activate_debugger (); ! 3353: // TRY (prb2) { ! 3354: except = 0; ! 3355: Exception (save_except, regs.fault_pc, true); ! 3356: // } CATCH (prb2) { ! 3357: if (except != 0) { ! 3358: write_log ("MMU: double bus error, rebooting..\n"); ! 3359: regs.tcr = 0; ! 3360: m68k_reset (0); ! 3361: m68k_setpc (0xf80002); ! 3362: mmu_reset (); ! 3363: uae_reset (1); ! 3364: return; ! 3365: } ! 3366: goto retry; ! 3367: } ! 3368: ! 3369: } ! 3370: ! 3371: /* "cycle exact" 68020/030 */ ! 3372: #define MAX68020CYCLES 4 ! 3373: static void m68k_run_2ce (void) ! 3374: { ! 3375: struct regstruct *r = ®s; ! 3376: int tmpcycles = MAX68020CYCLES; ! 3377: ! 3378: ipl_fetch (); ! 3379: for (;;) { ! 3380: /*m68k_dumpstate(stderr, NULL);*/ ! 3381: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM)) ! 3382: { ! 3383: int FrameCycles, HblCounterVideo, LineCycles; ! 3384: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles ); ! 3385: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo ); ! 3386: m68k_disasm(stderr, m68k_getpc (), NULL, 1); ! 3387: } ! 3388: ! 3389: uae_u32 opcode = x_prefetch (0); ! 3390: (*cpufunctbl[opcode])(opcode); ! 3391: if (r->ce020memcycles > 0) { ! 3392: tmpcycles = CYCLE_UNIT * MAX68020CYCLES; ! 3393: do_cycles_ce (r->ce020memcycles); ! 3394: r->ce020memcycles = 0; ! 3395: } ! 3396: if (r->spcflags) { ! 3397: if (do_specialties (0)) ! 3398: return; ! 3399: } ! 3400: tmpcycles -= cpucycleunit; ! 3401: if (tmpcycles <= 0) { ! 3402: do_cycles_ce (1 * CYCLE_UNIT); ! 3403: tmpcycles = CYCLE_UNIT * MAX68020CYCLES;; ! 3404: } ! 3405: regs.ipl = regs.ipl_pin; ! 3406: } ! 3407: } ! 3408: ! 3409: /* emulate simple prefetch */ ! 3410: static void m68k_run_2p (void) ! 3411: { ! 3412: uae_u32 prefetch, prefetch_pc; ! 3413: struct regstruct *r = ®s; ! 3414: ! 3415: prefetch_pc = m68k_getpc (); ! 3416: prefetch = get_longi (prefetch_pc); ! 3417: for (;;) { ! 3418: uae_u32 opcode; ! 3419: uae_u32 pc = m68k_getpc (); ! 3420: ! 3421: /*m68k_dumpstate(stderr, NULL);*/ ! 3422: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM)) ! 3423: { ! 3424: int FrameCycles, HblCounterVideo, LineCycles; ! 3425: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles ); ! 3426: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo ); ! 3427: m68k_disasm(stderr, m68k_getpc (), NULL, 1); ! 3428: } ! 3429: ! 3430: #if DEBUG_CD32CDTVIO ! 3431: out_cd32io (m68k_getpc ()); ! 3432: #endif ! 3433: ! 3434: do_cycles (cpu_cycles); ! 3435: ! 3436: if (pc == prefetch_pc) ! 3437: opcode = prefetch >> 16; ! 3438: else if (pc == prefetch_pc + 2) ! 3439: opcode = prefetch & 0xffff; ! 3440: else ! 3441: opcode = get_wordi (pc); ! 3442: ! 3443: count_instr (opcode); ! 3444: ! 3445: prefetch_pc = m68k_getpc () + 2; ! 3446: prefetch = get_longi (prefetch_pc); ! 3447: cpu_cycles = (*cpufunctbl[opcode])(opcode); ! 3448: cpu_cycles &= cycles_mask; ! 3449: cpu_cycles |= cycles_val; ! 3450: ! 3451: M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT); ! 3452: ! 3453: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) { ! 3454: /* Add some extra cycles to simulate a wait state */ ! 3455: unset_special(SPCFLAG_EXTRA_CYCLES); ! 3456: M68000_AddCycles(nWaitStateCycles); ! 3457: nWaitStateCycles = 0; ! 3458: } ! 3459: ! 3460: /* We can have several interrupts at the same time before the next CPU instruction */ ! 3461: /* We must check for pending interrupt and call do_specialties_interrupt() only */ ! 3462: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */ ! 3463: /* and prevent exiting the STOP state when calling do_specialties() after. */ ! 3464: /* For performance, we first test PendingInterruptCount, then regs.spcflags */ ! 3465: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) { ! 3466: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */ ! 3467: do_specialties_interrupt(false); /* test if there's an mfp/video interrupt and add non pending jitter */ ! 3468: } ! 3469: ! 3470: if (r->spcflags) { ! 3471: if (do_specialties (cpu_cycles* 2 / CYCLE_UNIT)) ! 3472: return; ! 3473: } ! 3474: } ! 3475: } ! 3476: ! 3477: ! 3478: //static int used[65536]; ! 3479: ! 3480: /* Same thing, but don't use prefetch to get opcode. */ ! 3481: static void m68k_run_2 (void) ! 3482: { ! 3483: struct regstruct *r = ®s; ! 3484: ! 3485: for (;;) { ! 3486: uae_u32 opcode = get_iword (0); ! 3487: count_instr (opcode); ! 3488: ! 3489: /*m68k_dumpstate(stderr, NULL);*/ ! 3490: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM)) ! 3491: { ! 3492: int FrameCycles, HblCounterVideo, LineCycles; ! 3493: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles ); ! 3494: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo ); ! 3495: m68k_disasm(stderr, m68k_getpc (), NULL, 1); ! 3496: } ! 3497: ! 3498: #if 0 ! 3499: if (!used[opcode]) { ! 3500: write_log ("%04X ", opcode); ! 3501: used[opcode] = 1; ! 3502: } ! 3503: #endif ! 3504: do_cycles (cpu_cycles); ! 3505: cpu_cycles = (*cpufunctbl[opcode])(opcode); ! 3506: cpu_cycles &= cycles_mask; ! 3507: cpu_cycles |= cycles_val; ! 3508: ! 3509: M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT); ! 3510: ! 3511: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) { ! 3512: /* Add some extra cycles to simulate a wait state */ ! 3513: unset_special(SPCFLAG_EXTRA_CYCLES); ! 3514: M68000_AddCycles(nWaitStateCycles); ! 3515: nWaitStateCycles = 0; ! 3516: } ! 3517: ! 3518: /* We can have several interrupts at the same time before the next CPU instruction */ ! 3519: /* We must check for pending interrupt and call do_specialties_interrupt() only */ ! 3520: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */ ! 3521: /* and prevent exiting the STOP state when calling do_specialties() after. */ ! 3522: /* For performance, we first test PendingInterruptCount, then regs.spcflags */ ! 3523: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) { ! 3524: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */ ! 3525: do_specialties_interrupt(false); /* test if there's an mfp/video interrupt and add non pending jitter */ ! 3526: } ! 3527: ! 3528: ! 3529: if (r->spcflags) { ! 3530: if (do_specialties (cpu_cycles* 2 / CYCLE_UNIT)) ! 3531: return; ! 3532: } ! 3533: } ! 3534: } ! 3535: ! 3536: ! 3537: /* fake MMU 68k */ ! 3538: static void m68k_run_mmu (void) ! 3539: { ! 3540: for (;;) { ! 3541: ! 3542: /*m68k_dumpstate(stderr, NULL);*/ ! 3543: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM)) ! 3544: { ! 3545: int FrameCycles, HblCounterVideo, LineCycles; ! 3546: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles ); ! 3547: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo ); ! 3548: m68k_disasm(stderr, m68k_getpc (), NULL, 1); ! 3549: } ! 3550: ! 3551: uae_u32 opcode = get_iword (0); ! 3552: do_cycles (cpu_cycles); ! 3553: mmu_backup_regs = regs; ! 3554: cpu_cycles = (*cpufunctbl[opcode])(opcode); ! 3555: cpu_cycles &= cycles_mask; ! 3556: cpu_cycles |= cycles_val; ! 3557: if (mmu_triggered) ! 3558: mmu_do_hit (); ! 3559: if (regs.spcflags) { ! 3560: if (do_specialties (cpu_cycles)) ! 3561: return; ! 3562: } ! 3563: } ! 3564: } ! 3565: ! 3566: #endif /* CPUEMU_0 */ ! 3567: ! 3568: int in_m68k_go = 0; ! 3569: ! 3570: static void exception2_handle (uaecptr addr, uaecptr fault) ! 3571: { ! 3572: last_addr_for_exception_3 = addr; ! 3573: last_fault_for_exception_3 = fault; ! 3574: last_writeaccess_for_exception_3 = 0; ! 3575: last_instructionaccess_for_exception_3 = 0; ! 3576: Exception (2, m68k_getpc (), true); ! 3577: } ! 3578: ! 3579: void m68k_go (int may_quit) ! 3580: { ! 3581: int hardboot = 1; ! 3582: ! 3583: if (in_m68k_go || !may_quit) { ! 3584: write_log ("Bug! m68k_go is not reentrant.\n"); ! 3585: abort (); ! 3586: } ! 3587: ! 3588: reset_frame_rate_hack (); ! 3589: update_68k_cycles (); ! 3590: ! 3591: in_m68k_go++; ! 3592: for (;;) { ! 3593: void (*run_func)(void); ! 3594: ! 3595: if (regs.spcflags & SPCFLAG_BRK) { ! 3596: unset_special(SPCFLAG_BRK); ! 3597: break; ! 3598: } ! 3599: ! 3600: quit_program = 0; ! 3601: hardboot = 0; ! 3602: ! 3603: #ifdef DEBUGGER ! 3604: if (debugging) ! 3605: debug (); ! 3606: #endif ! 3607: if (regs.panic) { ! 3608: regs.panic = 0; ! 3609: /* program jumped to non-existing memory and cpu was >= 68020 */ ! 3610: get_real_address (regs.isp); /* stack in no one's land? -> reboot */ ! 3611: if (regs.isp & 1) ! 3612: regs.panic = 1; ! 3613: if (!regs.panic) ! 3614: exception2_handle (regs.panic_pc, regs.panic_addr); ! 3615: if (regs.panic) { ! 3616: /* system is very badly confused */ ! 3617: write_log ("double bus error or corrupted stack, forcing reboot..\n"); ! 3618: regs.panic = 0; ! 3619: uae_reset (1); ! 3620: } ! 3621: } ! 3622: ! 3623: #if 0 /* what was the meaning of this? this breaks trace emulation if debugger is used */ ! 3624: if (regs.spcflags) { ! 3625: uae_u32 of = regs.spcflags; ! 3626: regs.spcflags &= ~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); ! 3627: do_specialties (0); ! 3628: regs.spcflags |= of & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); ! 3629: } ! 3630: #endif ! 3631: ! 3632: set_x_funcs (); ! 3633: if (mmu_enabled && !currprefs.cachesize) { ! 3634: run_func = m68k_run_mmu; ! 3635: } else { ! 3636: run_func = currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000 ? m68k_run_1_ce : ! 3637: currprefs.cpu_compatible && currprefs.cpu_model == 68000 ? m68k_run_1 : ! 3638: #ifdef JIT ! 3639: currprefs.cpu_model >= 68020 && currprefs.cachesize ? m68k_run_jit : ! 3640: #endif ! 3641: (currprefs.cpu_model == 68040 || currprefs.cpu_model == 68060) && currprefs.mmu_model ? m68k_run_mmu040 : ! 3642: currprefs.cpu_model >= 68020 && currprefs.cpu_cycle_exact ? m68k_run_2ce : ! 3643: currprefs.cpu_compatible ? m68k_run_2p : m68k_run_2; ! 3644: } ! 3645: run_func (); ! 3646: } ! 3647: in_m68k_go--; ! 3648: } ! 3649: ! 3650: #if 0 ! 3651: static void m68k_verify (uaecptr addr, uaecptr *nextpc) ! 3652: { ! 3653: uae_u32 opcode, val; ! 3654: struct instr *dp; ! 3655: ! 3656: opcode = get_iword_1 (0); ! 3657: last_op_for_exception_3 = opcode; ! 3658: m68kpc_offset = 2; ! 3659: ! 3660: if (cpufunctbl[opcode] == op_illg_1) { ! 3661: opcode = 0x4AFC; ! 3662: } ! 3663: dp = table68k + opcode; ! 3664: ! 3665: if (dp->suse) { ! 3666: if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) { ! 3667: Exception (3, 0); ! 3668: return; ! 3669: } ! 3670: } ! 3671: if (dp->duse) { ! 3672: if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) { ! 3673: Exception (3, 0); ! 3674: return; ! 3675: } ! 3676: } ! 3677: } ! 3678: #endif ! 3679: ! 3680: static const TCHAR *ccnames[] = ! 3681: { "T ","F ","HI","LS","CC","CS","NE","EQ", ! 3682: "VC","VS","PL","MI","GE","LT","GT","LE" }; ! 3683: ! 3684: static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg) ! 3685: { ! 3686: TCHAR *p = out + _tcslen (out); ! 3687: if (*prevreg < 0) { ! 3688: *prevreg = reg; ! 3689: *lastreg = reg; ! 3690: return; ! 3691: } ! 3692: if ((*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) { ! 3693: _stprintf (p, "%s%c%d", (*first) ? "" : "/", (*lastreg) < 8 ? 'D' : 'A', (*lastreg) & 7); ! 3694: p = p + _tcslen (p); ! 3695: if ((*lastreg) + 2 == reg) { ! 3696: _stprintf (p, "/%c%d", (*prevreg) < 8 ? 'D' : 'A', (*prevreg) & 7); ! 3697: } else if ((*lastreg) != (*prevreg)) { ! 3698: _stprintf (p, "-%c%d", (*prevreg) < 8 ? 'D' : 'A', (*prevreg) & 7); ! 3699: } ! 3700: *lastreg = reg; ! 3701: *first = 0; ! 3702: } ! 3703: *prevreg = reg; ! 3704: } ! 3705: ! 3706: static void movemout (TCHAR *out, uae_u16 mask, int mode) ! 3707: { ! 3708: unsigned int dmask, amask; ! 3709: int prevreg = -1, lastreg = -1, first = 1; ! 3710: ! 3711: if (mode == Apdi) { ! 3712: int i; ! 3713: uae_u8 dmask2 = (mask >> 8) & 0xff; ! 3714: uae_u8 amask2 = mask & 0xff; ! 3715: dmask = 0; ! 3716: amask = 0; ! 3717: for (i = 0; i < 8; i++) { ! 3718: if (dmask2 & (1 << i)) ! 3719: dmask |= 1 << (7 - i); ! 3720: if (amask2 & (1 << i)) ! 3721: amask |= 1 << (7 - i); ! 3722: } ! 3723: } else { ! 3724: dmask = mask & 0xff; ! 3725: amask = (mask >> 8) & 0xff; ! 3726: } ! 3727: while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask]); dmask = movem_next[dmask]; } ! 3728: while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8); amask = movem_next[amask]; } ! 3729: addmovemreg (out, &prevreg, &lastreg, &first, -1); ! 3730: } ! 3731: ! 3732: static void disasm_size (TCHAR *instrname, struct instr *dp) ! 3733: { ! 3734: #if 0 ! 3735: int i, size; ! 3736: uae_u16 mnemo = dp->mnemo; ! 3737: ! 3738: size = dp->size; ! 3739: for (i = 0; i < 65536; i++) { ! 3740: struct instr *in = &table68k[i]; ! 3741: if (in->mnemo == mnemo && in != dp) { ! 3742: if (size != in->size) ! 3743: break; ! 3744: } ! 3745: } ! 3746: if (i == 65536) ! 3747: size = -1; ! 3748: #endif ! 3749: switch (dp->size) ! 3750: { ! 3751: case sz_byte: ! 3752: _tcscat (instrname, ".B "); ! 3753: break; ! 3754: case sz_word: ! 3755: _tcscat (instrname, ".W "); ! 3756: break; ! 3757: case sz_long: ! 3758: _tcscat (instrname, ".L "); ! 3759: break; ! 3760: default: ! 3761: _tcscat (instrname, " "); ! 3762: break; ! 3763: } ! 3764: } ! 3765: ! 3766: static void m68k_disasm_2 (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode) ! 3767: { ! 3768: uaecptr newpc = 0; ! 3769: m68kpc_offset = addr - m68k_getpc (); ! 3770: ! 3771: if (!table68k) ! 3772: return; ! 3773: while (cnt-- > 0) { ! 3774: TCHAR instrname[100], *ccpt; ! 3775: int i; ! 3776: uae_u32 opcode; ! 3777: struct mnemolookup *lookup; ! 3778: struct instr *dp; ! 3779: int oldpc; ! 3780: ! 3781: oldpc = m68kpc_offset; ! 3782: opcode = get_iword_1 (m68kpc_offset); ! 3783: if (cpufunctbl[opcode] == op_illg_1) { ! 3784: opcode = 0x4AFC; ! 3785: } ! 3786: dp = table68k + opcode; ! 3787: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) ! 3788: ; ! 3789: ! 3790: fprintf(f, "%08lX ", m68k_getpc () + m68kpc_offset); ! 3791: m68kpc_offset += 2; ! 3792: ! 3793: if (strcmp(lookup->friendlyname, "")) ! 3794: _tcscpy (instrname, lookup->friendlyname); ! 3795: else ! 3796: _tcscpy (instrname, lookup->name); ! 3797: ccpt = _tcsstr (instrname, "cc"); ! 3798: if (ccpt != 0) { ! 3799: _tcsncpy (ccpt, ccnames[dp->cc], 2); ! 3800: } ! 3801: disasm_size (instrname, dp); ! 3802: ! 3803: if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) { ! 3804: uae_u16 imm = get_iword_1 (m68kpc_offset); ! 3805: uae_u16 creg = imm & 0x0fff; ! 3806: uae_u16 r = imm >> 12; ! 3807: TCHAR regs[16]; ! 3808: const TCHAR *cname = "?"; ! 3809: int i; ! 3810: for (i = 0; m2cregs[i].regname; i++) { ! 3811: if (m2cregs[i].regno == creg) ! 3812: break; ! 3813: } ! 3814: _stprintf (regs, "%c%d", r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r); ! 3815: if (m2cregs[i].regname) ! 3816: cname = m2cregs[i].regname; ! 3817: if (lookup->mnemo == i_MOVE2C) { ! 3818: _tcscat (instrname, regs); ! 3819: _tcscat (instrname, ","); ! 3820: _tcscat (instrname, cname); ! 3821: } else { ! 3822: _tcscat (instrname, cname); ! 3823: _tcscat (instrname, ","); ! 3824: _tcscat (instrname, regs); ! 3825: } ! 3826: m68kpc_offset += 2; ! 3827: } else if (lookup->mnemo == i_MVMEL) { ! 3828: newpc = m68k_getpc () + m68kpc_offset; ! 3829: m68kpc_offset += 2; ! 3830: newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); ! 3831: _tcscat (instrname, ","); ! 3832: movemout (instrname, get_iword_1 (oldpc + 2), dp->dmode); ! 3833: } else if (lookup->mnemo == i_MVMLE) { ! 3834: m68kpc_offset += 2; ! 3835: movemout (instrname, get_iword_1 (oldpc + 2), dp->dmode); ! 3836: _tcscat (instrname, ","); ! 3837: newpc = m68k_getpc () + m68kpc_offset; ! 3838: newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); ! 3839: } else { ! 3840: if (dp->suse) { ! 3841: newpc = m68k_getpc () + m68kpc_offset; ! 3842: newpc += ShowEA (0, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr, safemode); ! 3843: } ! 3844: if (dp->suse && dp->duse) ! 3845: _tcscat (instrname, ","); ! 3846: if (dp->duse) { ! 3847: newpc = m68k_getpc () + m68kpc_offset; ! 3848: newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode); ! 3849: } ! 3850: } ! 3851: ! 3852: for (i = 0; i < (m68kpc_offset - oldpc) / 2; i++) { ! 3853: fprintf(f, "%04x ", get_iword_1 (oldpc + i * 2)); ! 3854: } ! 3855: ! 3856: while (i++ < 5) ! 3857: fprintf(f, "%s", " "); ! 3858: ! 3859: fprintf(f, "%s", instrname); ! 3860: ! 3861: if (ccpt != 0) { ! 3862: if (deaddr) ! 3863: *deaddr = newpc; ! 3864: if (cctrue (dp->cc)) ! 3865: fprintf(f, " == $%08X (T)", newpc); ! 3866: else ! 3867: fprintf(f, " == $%08X (F)", newpc); ! 3868: } else if ((opcode & 0xff00) == 0x6100) { /* BSR */ ! 3869: if (deaddr) ! 3870: *deaddr = newpc; ! 3871: fprintf(f, " == $%08X", newpc); ! 3872: } ! 3873: fprintf(f, "%s", "\n"); ! 3874: } ! 3875: if (nextpc) ! 3876: *nextpc = m68k_getpc () + m68kpc_offset; ! 3877: } ! 3878: ! 3879: void m68k_disasm_ea (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr) ! 3880: { ! 3881: m68k_disasm_2 (f, addr, nextpc, cnt, seaddr, deaddr, 1); ! 3882: } ! 3883: void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt) ! 3884: { ! 3885: m68k_disasm_2 (f, addr, nextpc, cnt, NULL, NULL, 0); ! 3886: } ! 3887: ! 3888: /************************************************************* ! 3889: Disasm the m68kcode at the given address into instrname ! 3890: and instrcode ! 3891: *************************************************************/ ! 3892: void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc) ! 3893: { ! 3894: TCHAR *ccpt; ! 3895: uae_u32 opcode; ! 3896: struct mnemolookup *lookup; ! 3897: struct instr *dp; ! 3898: int oldpc; ! 3899: ! 3900: uaecptr newpc = 0; ! 3901: ! 3902: m68kpc_offset = addr - m68k_getpc (); ! 3903: ! 3904: oldpc = m68kpc_offset; ! 3905: opcode = get_iword_1 (m68kpc_offset); ! 3906: if (cpufunctbl[opcode] == op_illg_1) { ! 3907: opcode = 0x4AFC; ! 3908: } ! 3909: dp = table68k + opcode; ! 3910: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++); ! 3911: ! 3912: m68kpc_offset += 2; ! 3913: ! 3914: _tcscpy (instrname, lookup->name); ! 3915: ccpt = _tcsstr (instrname, "cc"); ! 3916: if (ccpt != 0) { ! 3917: _tcsncpy (ccpt, ccnames[dp->cc], 2); ! 3918: } ! 3919: switch (dp->size){ ! 3920: case sz_byte: _tcscat (instrname, ".B "); break; ! 3921: case sz_word: _tcscat (instrname, ".W "); break; ! 3922: case sz_long: _tcscat (instrname, ".L "); break; ! 3923: default: _tcscat (instrname, " "); break; ! 3924: } ! 3925: ! 3926: if (dp->suse) { ! 3927: newpc = m68k_getpc () + m68kpc_offset; ! 3928: newpc += ShowEA (0, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0); ! 3929: } ! 3930: if (dp->suse && dp->duse) ! 3931: _tcscat (instrname, ","); ! 3932: if (dp->duse) { ! 3933: newpc = m68k_getpc () + m68kpc_offset; ! 3934: newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0); ! 3935: } ! 3936: ! 3937: if (instrcode) ! 3938: { ! 3939: int i; ! 3940: for (i = 0; i < (m68kpc_offset - oldpc) / 2; i++) ! 3941: { ! 3942: _stprintf (instrcode, "%04x ", get_iword_1 (oldpc + i * 2)); ! 3943: instrcode += _tcslen (instrcode); ! 3944: } ! 3945: } ! 3946: ! 3947: if (nextpc) ! 3948: *nextpc = m68k_getpc () + m68kpc_offset; ! 3949: } ! 3950: ! 3951: struct cpum2c m2cregs[] = { ! 3952: { 0, "SFC" }, ! 3953: { 1, "DFC" }, ! 3954: { 2, "CACR" }, ! 3955: { 3, "TC" }, ! 3956: { 4, "ITT0" }, ! 3957: { 5, "ITT1" }, ! 3958: { 6, "DTT0" }, ! 3959: { 7, "DTT1" }, ! 3960: { 8, "BUSC" }, ! 3961: { 0x800, "USP" }, ! 3962: { 0x801, "VBR" }, ! 3963: { 0x802, "CAAR" }, ! 3964: { 0x803, "MSP" }, ! 3965: { 0x804, "ISP" }, ! 3966: { 0x805, "MMUS" }, ! 3967: { 0x806, "URP" }, ! 3968: { 0x807, "SRP" }, ! 3969: { 0x808, "PCR" }, ! 3970: { -1, NULL } ! 3971: }; ! 3972: ! 3973: void val_move2c2 (int regno, uae_u32 val) ! 3974: { ! 3975: switch (regno) { ! 3976: case 0: regs.sfc = val; break; ! 3977: case 1: regs.dfc = val; break; ! 3978: case 2: regs.cacr = val; break; ! 3979: case 3: regs.tcr = val; break; ! 3980: case 4: regs.itt0 = val; break; ! 3981: case 5: regs.itt1 = val; break; ! 3982: case 6: regs.dtt0 = val; break; ! 3983: case 7: regs.dtt1 = val; break; ! 3984: case 8: regs.buscr = val; break; ! 3985: case 0x800: regs.usp = val; break; ! 3986: case 0x801: regs.vbr = val; break; ! 3987: case 0x802: regs.caar = val; break; ! 3988: case 0x803: regs.msp = val; break; ! 3989: case 0x804: regs.isp = val; break; ! 3990: case 0x805: regs.mmusr = val; break; ! 3991: case 0x806: regs.urp = val; break; ! 3992: case 0x807: regs.srp = val; break; ! 3993: case 0x808: regs.pcr = val; break; ! 3994: } ! 3995: } ! 3996: ! 3997: uae_u32 val_move2c (int regno) ! 3998: { ! 3999: switch (regno) { ! 4000: case 0: return regs.sfc; ! 4001: case 1: return regs.dfc; ! 4002: case 2: return regs.cacr; ! 4003: case 3: return regs.tcr; ! 4004: case 4: return regs.itt0; ! 4005: case 5: return regs.itt1; ! 4006: case 6: return regs.dtt0; ! 4007: case 7: return regs.dtt1; ! 4008: case 8: return regs.buscr; ! 4009: case 0x800: return regs.usp; ! 4010: case 0x801: return regs.vbr; ! 4011: case 0x802: return regs.caar; ! 4012: case 0x803: return regs.msp; ! 4013: case 0x804: return regs.isp; ! 4014: case 0x805: return regs.mmusr; ! 4015: case 0x806: return regs.urp; ! 4016: case 0x807: return regs.srp; ! 4017: case 0x808: return regs.pcr; ! 4018: default: return 0; ! 4019: } ! 4020: } ! 4021: ! 4022: void m68k_dumpstate (FILE *f, uaecptr *nextpc) ! 4023: { ! 4024: int i, j; ! 4025: ! 4026: for (i = 0; i < 8; i++){ ! 4027: f_out (f, " D%d %08lX ", i, m68k_dreg (regs, i)); ! 4028: if ((i & 3) == 3) f_out (f, "\n"); ! 4029: } ! 4030: for (i = 0; i < 8; i++){ ! 4031: f_out (f, " A%d %08lX ", i, m68k_areg (regs, i)); ! 4032: if ((i & 3) == 3) f_out (f, "\n"); ! 4033: } ! 4034: if (regs.s == 0) ! 4035: regs.usp = m68k_areg (regs, 7); ! 4036: if (regs.s && regs.m) ! 4037: regs.msp = m68k_areg (regs, 7); ! 4038: if (regs.s && regs.m == 0) ! 4039: regs.isp = m68k_areg (regs, 7); ! 4040: j = 2; ! 4041: f_out (f, "USP %08X ISP %08X ", regs.usp, regs.isp); ! 4042: for (i = 0; m2cregs[i].regno>= 0; i++) { ! 4043: if (!movec_illg (m2cregs[i].regno)) { ! 4044: if (!_tcscmp (m2cregs[i].regname, "USP") || !_tcscmp (m2cregs[i].regname, "ISP")) ! 4045: continue; ! 4046: if (j > 0 && (j % 4) == 0) ! 4047: f_out (f, "\n"); ! 4048: f_out (f, "%-4s %08X ", m2cregs[i].regname, val_move2c (m2cregs[i].regno)); ! 4049: j++; ! 4050: } ! 4051: } ! 4052: if (j > 0) ! 4053: f_out (f, "\n"); ! 4054: f_out (f, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d STP=%d\n", ! 4055: regs.t1, regs.t0, regs.s, regs.m, ! 4056: GET_XFLG (), GET_NFLG (), GET_ZFLG (), ! 4057: GET_VFLG (), GET_CFLG (), ! 4058: regs.intmask, regs.stopped); ! 4059: #ifdef FPUEMU ! 4060: if (currprefs.fpu_model) { ! 4061: uae_u32 fpsr; ! 4062: for (i = 0; i < 8; i++){ ! 4063: f_out (f, "FP%d: %g ", i, regs.fp[i]); ! 4064: if ((i & 3) == 3) ! 4065: f_out (f, "\n"); ! 4066: } ! 4067: fpsr = get_fpsr (); ! 4068: f_out (f, "N=%d Z=%d I=%d NAN=%d\n", ! 4069: (fpsr & 0x8000000) != 0, ! 4070: (fpsr & 0x4000000) != 0, ! 4071: (fpsr & 0x2000000) != 0, ! 4072: (fpsr & 0x1000000) != 0); ! 4073: } ! 4074: #endif ! 4075: if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) { ! 4076: struct instr *dp; ! 4077: struct mnemolookup *lookup1, *lookup2; ! 4078: dp = table68k + regs.irc; ! 4079: for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++); ! 4080: dp = table68k + regs.ir; ! 4081: for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++); ! 4082: f_out (f, "Prefetch %04x (%s) %04x (%s)\n", regs.irc, lookup1->name, regs.ir, lookup2->name); ! 4083: } ! 4084: ! 4085: m68k_disasm (f, m68k_getpc (), nextpc, 1); ! 4086: if (nextpc) ! 4087: f_out (f, "Next PC: %08lx\n", *nextpc); ! 4088: } ! 4089: ! 4090: #ifdef SAVESTATE ! 4091: ! 4092: /* CPU save/restore code */ ! 4093: ! 4094: #define CPUTYPE_EC 1 ! 4095: #define CPUMODE_HALT 1 ! 4096: ! 4097: ! 4098: ! 4099: uae_u8 *restore_cpu (uae_u8 *src) ! 4100: { ! 4101: int i, flags, model; ! 4102: uae_u32 l; ! 4103: ! 4104: changed_prefs.cpu_model = model = restore_u32 (); ! 4105: flags = restore_u32 (); ! 4106: changed_prefs.address_space_24 = 0; ! 4107: if (flags & CPUTYPE_EC) ! 4108: changed_prefs.address_space_24 = 1; ! 4109: if (model > 68020) ! 4110: changed_prefs.cpu_compatible = 0; ! 4111: currprefs.address_space_24 = changed_prefs.address_space_24; ! 4112: currprefs.cpu_compatible = changed_prefs.cpu_compatible; ! 4113: currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact; ! 4114: currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact; ! 4115: currprefs.cpu_frequency = changed_prefs.cpu_frequency = 0; ! 4116: currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 0; ! 4117: for (i = 0; i < 15; i++) ! 4118: regs.regs[i] = restore_u32 (); ! 4119: regs.pc = restore_u32 (); ! 4120: regs.irc = restore_u16 (); ! 4121: regs.ir = restore_u16 (); ! 4122: regs.usp = restore_u32 (); ! 4123: regs.isp = restore_u32 (); ! 4124: regs.sr = restore_u16 (); ! 4125: l = restore_u32 (); ! 4126: if (l & CPUMODE_HALT) { ! 4127: regs.stopped = 1; ! 4128: } else { ! 4129: regs.stopped = 0; ! 4130: } ! 4131: if (model >= 68010) { ! 4132: regs.dfc = restore_u32 (); ! 4133: regs.sfc = restore_u32 (); ! 4134: regs.vbr = restore_u32 (); ! 4135: } ! 4136: if (model >= 68020) { ! 4137: regs.caar = restore_u32 (); ! 4138: regs.cacr = restore_u32 (); ! 4139: regs.msp = restore_u32 (); ! 4140: /* A500 speed in 68020 mode isn't too logical.. */ ! 4141: if (changed_prefs.m68k_speed == 0 && !(currprefs.cpu_cycle_exact)) ! 4142: currprefs.m68k_speed = changed_prefs.m68k_speed = -1; ! 4143: } ! 4144: if (model >= 68030) { ! 4145: crp_030 = restore_u64 (); ! 4146: srp_030 = restore_u64 (); ! 4147: tt0_030 =restore_u32 (); ! 4148: tt1_030 = restore_u32 (); ! 4149: tc_030 = restore_u32 (); ! 4150: mmusr_030 = restore_u16 (); ! 4151: } ! 4152: if (model >= 68040) { ! 4153: regs.itt0 = restore_u32 (); ! 4154: regs.itt1 = restore_u32 (); ! 4155: regs.dtt0 = restore_u32 (); ! 4156: regs.dtt1 = restore_u32 (); ! 4157: regs.tcr = restore_u32 (); ! 4158: regs.urp = restore_u32 (); ! 4159: regs.srp = restore_u32 (); ! 4160: } ! 4161: if (model >= 68060) { ! 4162: regs.buscr = restore_u32 (); ! 4163: regs.pcr = restore_u32 (); ! 4164: } ! 4165: if (flags & 0x80000000) { ! 4166: int khz = restore_u32 (); ! 4167: restore_u32 (); ! 4168: if (khz > 0 && khz < 800000) ! 4169: currprefs.m68k_speed = changed_prefs.m68k_speed = 0; ! 4170: } ! 4171: write_log ("CPU: %d%s%03d, PC=%08X\n", ! 4172: model / 1000, flags & 1 ? "EC" : "", model % 1000, regs.pc); ! 4173: ! 4174: return src; ! 4175: } ! 4176: ! 4177: void restore_cpu_finish (void) ! 4178: { ! 4179: init_m68k (); ! 4180: m68k_setpc (regs.pc); ! 4181: set_cpu_caches (); ! 4182: doint (); ! 4183: if (regs.stopped) ! 4184: set_special (SPCFLAG_STOP); ! 4185: //activate_debugger (); ! 4186: } ! 4187: ! 4188: uae_u8 *restore_cpu_extra (uae_u8 *src) ! 4189: { ! 4190: restore_u32 (); ! 4191: uae_u32 flags = restore_u32 (); ! 4192: ! 4193: ! 4194: currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact = (flags & 1) ? true : false; ! 4195: currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact = currprefs.cpu_cycle_exact; ! 4196: currprefs.cpu_compatible = changed_prefs.cpu_compatible = (flags & 2) ? true : false; ! 4197: currprefs.cpu_frequency = changed_prefs.cpu_frequency = restore_u32 (); ! 4198: currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = restore_u32 (); ! 4199: currprefs.cachesize = changed_prefs.cachesize = (flags & 8) ? 8192 : 0; ! 4200: ! 4201: currprefs.m68k_speed = changed_prefs.m68k_speed = 0; ! 4202: if (flags & 4) ! 4203: currprefs.m68k_speed = changed_prefs.m68k_speed = -1; ! 4204: ! 4205: currprefs.cpu060_revision = changed_prefs.cpu060_revision = restore_u8 (); ! 4206: currprefs.fpu_revision = changed_prefs.fpu_revision = restore_u8 (); ! 4207: ! 4208: return src; ! 4209: } ! 4210: ! 4211: uae_u8 *save_cpu_extra (int *len, uae_u8 *dstptr) ! 4212: { ! 4213: uae_u8 *dstbak, *dst; ! 4214: uae_u32 flags; ! 4215: ! 4216: if (dstptr) ! 4217: dstbak = dst = dstptr; ! 4218: else ! 4219: dstbak = dst = xmalloc (uae_u8, 1000); ! 4220: save_u32 (0); // version ! 4221: flags = 0; ! 4222: flags |= currprefs.cpu_cycle_exact ? 1 : 0; ! 4223: flags |= currprefs.cpu_compatible ? 2 : 0; ! 4224: flags |= currprefs.m68k_speed < 0 ? 4 : 0; ! 4225: flags |= currprefs.cachesize > 0 ? 8 : 0; ! 4226: save_u32 (flags); ! 4227: save_u32 (currprefs.cpu_frequency); ! 4228: save_u32 (currprefs.cpu_clock_multiplier); ! 4229: save_u8 (currprefs.cpu060_revision); ! 4230: save_u8 (currprefs.fpu_revision); ! 4231: *len = dst - dstbak; ! 4232: return dstbak; ! 4233: } ! 4234: ! 4235: uae_u8 *save_cpu (int *len, uae_u8 *dstptr) ! 4236: { ! 4237: uae_u8 *dstbak, *dst; ! 4238: int model, i, khz; ! 4239: ! 4240: if (dstptr) ! 4241: dstbak = dst = dstptr; ! 4242: else ! 4243: dstbak = dst = xmalloc (uae_u8, 1000); ! 4244: model = currprefs.cpu_model; ! 4245: save_u32 (model); /* MODEL */ ! 4246: save_u32 (0x80000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */ ! 4247: for (i = 0;i < 15; i++) ! 4248: save_u32 (regs.regs[i]); /* D0-D7 A0-A6 */ ! 4249: save_u32 (m68k_getpc ()); /* PC */ ! 4250: save_u16 (regs.irc); /* prefetch */ ! 4251: save_u16 (regs.ir); /* instruction prefetch */ ! 4252: MakeSR (); ! 4253: save_u32 (!regs.s ? regs.regs[15] : regs.usp); /* USP */ ! 4254: save_u32 (regs.s ? regs.regs[15] : regs.isp); /* ISP */ ! 4255: save_u16 (regs.sr); /* SR/CCR */ ! 4256: save_u32 (regs.stopped ? CPUMODE_HALT : 0); /* flags */ ! 4257: if (model >= 68010) { ! 4258: save_u32 (regs.dfc); /* DFC */ ! 4259: save_u32 (regs.sfc); /* SFC */ ! 4260: save_u32 (regs.vbr); /* VBR */ ! 4261: } ! 4262: if (model >= 68020) { ! 4263: save_u32 (regs.caar); /* CAAR */ ! 4264: save_u32 (regs.cacr); /* CACR */ ! 4265: save_u32 (regs.msp); /* MSP */ ! 4266: } ! 4267: if (model >= 68030) { ! 4268: save_u64 (crp_030); /* CRP */ ! 4269: save_u64 (srp_030); /* SRP */ ! 4270: save_u32 (tt0_030); /* TT0/AC0 */ ! 4271: save_u32 (tt1_030); /* TT1/AC1 */ ! 4272: save_u32 (tc_030); /* TCR */ ! 4273: save_u16 (mmusr_030); /* MMUSR/ACUSR */ ! 4274: } ! 4275: if (model >= 68040) { ! 4276: save_u32 (regs.itt0); /* ITT0 */ ! 4277: save_u32 (regs.itt1); /* ITT1 */ ! 4278: save_u32 (regs.dtt0); /* DTT0 */ ! 4279: save_u32 (regs.dtt1); /* DTT1 */ ! 4280: save_u32 (regs.tcr); /* TCR */ ! 4281: save_u32 (regs.urp); /* URP */ ! 4282: save_u32 (regs.srp); /* SRP */ ! 4283: } ! 4284: if (model >= 68060) { ! 4285: save_u32 (regs.buscr); /* BUSCR */ ! 4286: save_u32 (regs.pcr); /* PCR */ ! 4287: } ! 4288: khz = -1; ! 4289: if (currprefs.m68k_speed == 0) { ! 4290: khz = currprefs.ntscmode ? 715909 : 709379; ! 4291: if (currprefs.cpu_model >= 68020) ! 4292: khz *= 2; ! 4293: } ! 4294: save_u32 (khz); // clock rate in KHz: -1 = fastest possible ! 4295: save_u32 (0); // spare ! 4296: *len = dst - dstbak; ! 4297: return dstbak; ! 4298: } ! 4299: ! 4300: uae_u8 *save_mmu (int *len, uae_u8 *dstptr) ! 4301: { ! 4302: uae_u8 *dstbak, *dst; ! 4303: int model; ! 4304: ! 4305: model = currprefs.mmu_model; ! 4306: if (model != 68040 && model != 68060) ! 4307: return NULL; ! 4308: if (dstptr) ! 4309: dstbak = dst = dstptr; ! 4310: else ! 4311: dstbak = dst = xmalloc (uae_u8, 1000); ! 4312: save_u32 (model); /* MODEL */ ! 4313: save_u32 (0); /* FLAGS */ ! 4314: *len = dst - dstbak; ! 4315: return dstbak; ! 4316: } ! 4317: ! 4318: uae_u8 *restore_mmu (uae_u8 *src) ! 4319: { ! 4320: int flags, model; ! 4321: ! 4322: changed_prefs.mmu_model = model = restore_u32 (); ! 4323: flags = restore_u32 (); ! 4324: write_log ("MMU: %d\n", model); ! 4325: return src; ! 4326: } ! 4327: ! 4328: #endif /* SAVESTATE */ ! 4329: ! 4330: static void exception3f (uae_u32 opcode, uaecptr addr, uaecptr fault, int writeaccess, int instructionaccess) ! 4331: { ! 4332: if (currprefs.cpu_model >= 68040) ! 4333: addr &= ~1; ! 4334: last_addr_for_exception_3 = addr; ! 4335: last_fault_for_exception_3 = fault; ! 4336: last_op_for_exception_3 = opcode; ! 4337: last_writeaccess_for_exception_3 = writeaccess; ! 4338: last_instructionaccess_for_exception_3 = instructionaccess; ! 4339: Exception (3, fault, true); ! 4340: } ! 4341: ! 4342: void exception3 (uae_u32 opcode, uaecptr addr, uaecptr fault) ! 4343: { ! 4344: exception3f (opcode, addr, fault, 0, 0); ! 4345: } ! 4346: ! 4347: void exception3i (uae_u32 opcode, uaecptr addr, uaecptr fault) ! 4348: { ! 4349: exception3f (opcode, addr, fault, 0, 1); ! 4350: } ! 4351: ! 4352: void exception2 (uaecptr addr, uaecptr fault) ! 4353: { ! 4354: write_log ("delayed exception2!\n"); ! 4355: regs.panic_pc = m68k_getpc (); ! 4356: regs.panic_addr = addr; ! 4357: regs.panic = 2; ! 4358: set_special (SPCFLAG_BRK); ! 4359: m68k_setpc (0xf80000); ! 4360: #ifdef JIT ! 4361: set_special (SPCFLAG_END_COMPILE); ! 4362: #endif ! 4363: fill_prefetch_slow (); ! 4364: } ! 4365: ! 4366: void cpureset (void) ! 4367: { ! 4368: uaecptr pc; ! 4369: uaecptr ksboot = 0xf80002 - 2; /* -2 = RESET hasn't increased PC yet */ ! 4370: uae_u16 ins; ! 4371: ! 4372: if (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) { ! 4373: // customreset (0); ! 4374: customreset (); ! 4375: return; ! 4376: } ! 4377: pc = m68k_getpc (); ! 4378: if (pc >= currprefs.chipmem_size) { ! 4379: addrbank *b = &get_mem_bank (pc); ! 4380: if (b->check (pc, 2 + 2)) { ! 4381: /* We have memory, hope for the best.. */ ! 4382: // customreset (0); ! 4383: customreset (); ! 4384: return; ! 4385: } ! 4386: write_log ("M68K RESET PC=%x, rebooting..\n", pc); ! 4387: // customreset (0); ! 4388: customreset (); ! 4389: m68k_setpc (ksboot); ! 4390: return; ! 4391: } ! 4392: /* panic, RAM is going to disappear under PC */ ! 4393: ins = get_word (pc + 2); ! 4394: if ((ins & ~7) == 0x4ed0) { ! 4395: int reg = ins & 7; ! 4396: uae_u32 addr = m68k_areg (regs, reg); ! 4397: write_log ("reset/jmp (ax) combination emulated -> %x\n", addr); ! 4398: // customreset (0); ! 4399: customreset (); ! 4400: if (addr < 0x80000) ! 4401: addr += 0xf80000; ! 4402: m68k_setpc (addr - 2); ! 4403: return; ! 4404: } ! 4405: write_log ("M68K RESET PC=%x, rebooting..\n", pc); ! 4406: // customreset (0); ! 4407: customreset (); ! 4408: m68k_setpc (ksboot); ! 4409: } ! 4410: ! 4411: ! 4412: void m68k_setstopped (void) ! 4413: { ! 4414: regs.stopped = 1; ! 4415: /* A traced STOP instruction drops through immediately without ! 4416: actually stopping. */ ! 4417: if ((regs.spcflags & SPCFLAG_DOTRACE) == 0) ! 4418: set_special (SPCFLAG_STOP); ! 4419: else ! 4420: m68k_resumestopped (); ! 4421: } ! 4422: ! 4423: void m68k_resumestopped (void) ! 4424: { ! 4425: if (!regs.stopped) ! 4426: return; ! 4427: regs.stopped = 0; ! 4428: if (currprefs.cpu_cycle_exact) { ! 4429: if (currprefs.cpu_model == 68000) ! 4430: do_cycles_ce000 (6); ! 4431: } ! 4432: fill_prefetch_slow (); ! 4433: unset_special (SPCFLAG_STOP); ! 4434: } ! 4435: ! 4436: /* ! 4437: * Compute exact number of CPU cycles taken ! 4438: * by DIVU and DIVS on a 68000 processor. ! 4439: * ! 4440: * Copyright (c) 2005 by Jorge Cwik, [email protected] ! 4441: * ! 4442: * This is free software; you can redistribute it and/or modify ! 4443: * it under the terms of the GNU General Public License as published by ! 4444: * the Free Software Foundation; either version 2 of the License, or ! 4445: * (at your option) any later version. ! 4446: * ! 4447: * This software is distributed in the hope that it will be useful, ! 4448: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 4449: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 4450: * GNU General Public License for more details. ! 4451: * ! 4452: * You should have received a copy of the GNU General Public License ! 4453: * along with this software; if not, write to the Free Software ! 4454: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! 4455: * ! 4456: */ ! 4457: ! 4458: ! 4459: /* ! 4460: ! 4461: The routines below take dividend and divisor as parameters. ! 4462: They return 0 if division by zero, or exact number of cycles otherwise. ! 4463: ! 4464: The number of cycles returned assumes a register operand. ! 4465: Effective address time must be added if memory operand. ! 4466: ! 4467: For 68000 only (not 68010, 68012, 68020, etc). ! 4468: Probably valid for 68008 after adding the extra prefetch cycle. ! 4469: ! 4470: ! 4471: Best and worst cases for register operand: ! 4472: (Note the difference with the documented range.) ! 4473: ! 4474: ! 4475: DIVU: ! 4476: ! 4477: Overflow (always): 10 cycles. ! 4478: Worst case: 136 cycles. ! 4479: Best case: 76 cycles. ! 4480: ! 4481: ! 4482: DIVS: ! 4483: ! 4484: Absolute overflow: 16-18 cycles. ! 4485: Signed overflow is not detected prematurely. ! 4486: ! 4487: Worst case: 156 cycles. ! 4488: Best case without signed overflow: 122 cycles. ! 4489: Best case with signed overflow: 120 cycles ! 4490: ! 4491: ! 4492: */ ! 4493: ! 4494: int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor) ! 4495: { ! 4496: int mcycles; ! 4497: uae_u32 hdivisor; ! 4498: int i; ! 4499: ! 4500: if (divisor == 0) ! 4501: return 0; ! 4502: ! 4503: // Overflow ! 4504: if ((dividend >> 16) >= divisor) ! 4505: return (mcycles = 5) * 2; ! 4506: ! 4507: mcycles = 38; ! 4508: hdivisor = divisor << 16; ! 4509: ! 4510: for (i = 0; i < 15; i++) { ! 4511: uae_u32 temp; ! 4512: temp = dividend; ! 4513: ! 4514: dividend <<= 1; ! 4515: ! 4516: // If carry from shift ! 4517: if ((uae_s32)temp < 0) ! 4518: dividend -= hdivisor; ! 4519: else { ! 4520: mcycles += 2; ! 4521: if (dividend >= hdivisor) { ! 4522: dividend -= hdivisor; ! 4523: mcycles--; ! 4524: } ! 4525: } ! 4526: } ! 4527: return mcycles * 2; ! 4528: } ! 4529: ! 4530: int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor) ! 4531: { ! 4532: int mcycles; ! 4533: uae_u32 aquot; ! 4534: int i; ! 4535: ! 4536: if (divisor == 0) ! 4537: return 0; ! 4538: ! 4539: mcycles = 6; ! 4540: ! 4541: if (dividend < 0) ! 4542: mcycles++; ! 4543: ! 4544: // Check for absolute overflow ! 4545: if (((uae_u32)abs (dividend) >> 16) >= (uae_u16)abs (divisor)) ! 4546: return (mcycles + 2) * 2; ! 4547: ! 4548: // Absolute quotient ! 4549: aquot = (uae_u32) abs (dividend) / (uae_u16)abs (divisor); ! 4550: ! 4551: mcycles += 55; ! 4552: ! 4553: if (divisor >= 0) { ! 4554: if (dividend >= 0) ! 4555: mcycles--; ! 4556: else ! 4557: mcycles++; ! 4558: } ! 4559: ! 4560: // Count 15 msbits in absolute of quotient ! 4561: ! 4562: for (i = 0; i < 15; i++) { ! 4563: if ((uae_s16)aquot >= 0) ! 4564: mcycles++; ! 4565: aquot <<= 1; ! 4566: } ! 4567: ! 4568: return mcycles * 2; ! 4569: } ! 4570: ! 4571: STATIC_INLINE void fill_cache040 (uae_u32 addr) ! 4572: { ! 4573: int index, i, lws; ! 4574: uae_u32 tag; ! 4575: uae_u32 data; ! 4576: struct cache040 *c; ! 4577: static int linecnt; ! 4578: ! 4579: addr &= ~15; ! 4580: index = (addr >> 4) & (CACHESETS040 - 1); ! 4581: tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1)); ! 4582: lws = (addr >> 2) & 3; ! 4583: c = &caches040[index]; ! 4584: for (i = 0; i < CACHELINES040; i++) { ! 4585: if (c->valid[i] && c->tag[i] == tag) { ! 4586: // cache hit ! 4587: regs.prefetch020addr[0] = addr; ! 4588: regs.prefetch020data[0] = c->data[i][lws]; ! 4589: return; ! 4590: } ! 4591: } ! 4592: // cache miss ! 4593: data = mem_access_delay_longi_read_ce020 (addr); ! 4594: int line = linecnt; ! 4595: for (i = 0; i < CACHELINES040; i++) { ! 4596: int line = (linecnt + i) & (CACHELINES040 - 1); ! 4597: if (c->tag[i] != tag || c->valid[i] == false) { ! 4598: c->tag[i] = tag; ! 4599: c->valid[i] = true; ! 4600: c->data[i][0] = data; ! 4601: } ! 4602: } ! 4603: regs.prefetch020addr[0] = addr; ! 4604: regs.prefetch020data[0] = data; ! 4605: } ! 4606: ! 4607: // this one is really simple and easy ! 4608: STATIC_INLINE void fill_icache020 (uae_u32 addr, int idx) ! 4609: { ! 4610: int index; ! 4611: uae_u32 tag; ! 4612: uae_u32 data; ! 4613: struct cache020 *c; ! 4614: ! 4615: addr &= ~3; ! 4616: index = (addr >> 2) & (CACHELINES020 - 1); ! 4617: tag = regs.s | (addr & ~((CACHELINES020 << 2) - 1)); ! 4618: c = &caches020[index]; ! 4619: if (c->valid && c->tag == tag) { ! 4620: // cache hit ! 4621: regs.prefetch020addr[idx] = addr; ! 4622: regs.prefetch020data[idx] = c->data; ! 4623: return; ! 4624: } ! 4625: // cache miss ! 4626: data = mem_access_delay_longi_read_ce020 (addr); ! 4627: if (!(regs.cacr & 2)) { ! 4628: c->tag = tag; ! 4629: c->valid = !!(regs.cacr & 1); ! 4630: c->data = data; ! 4631: } ! 4632: regs.prefetch020addr[idx] = addr; ! 4633: regs.prefetch020data[idx] = data; ! 4634: } ! 4635: ! 4636: uae_u32 get_word_ce020_prefetch (int o) ! 4637: { ! 4638: int i; ! 4639: uae_u32 pc = m68k_getpc () + o; ! 4640: ! 4641: for (;;) { ! 4642: for (i = 0; i < 2; i++) { ! 4643: if (pc == regs.prefetch020addr[0]) { ! 4644: uae_u32 v = regs.prefetch020data[0] >> 16; ! 4645: fill_icache020 (regs.prefetch020addr[0] + 4, 1); ! 4646: return v; ! 4647: } ! 4648: if (pc == regs.prefetch020addr[0] + 2) { ! 4649: uae_u32 v = regs.prefetch020data[0] & 0xffff; ! 4650: if (regs.prefetch020addr[1] == regs.prefetch020addr[0] + 4) { ! 4651: regs.prefetch020addr[0] = regs.prefetch020addr[1]; ! 4652: regs.prefetch020data[0] = regs.prefetch020data[1]; ! 4653: fill_icache020 (regs.prefetch020addr[0] + 4, 1); ! 4654: } else { ! 4655: fill_icache020 (pc + 4, 0); ! 4656: fill_icache020 (regs.prefetch020addr[0] + 4, 1); ! 4657: } ! 4658: return v; ! 4659: } ! 4660: regs.prefetch020addr[0] = regs.prefetch020addr[1]; ! 4661: regs.prefetch020data[0] = regs.prefetch020data[1]; ! 4662: } ! 4663: fill_icache020 (pc + 0, 0); ! 4664: fill_icache020 (pc + 4, 1); ! 4665: } ! 4666: } ! 4667: ! 4668: // 68030 caches aren't so simple as 68020 cache.. ! 4669: STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp) ! 4670: { ! 4671: int index, lws; ! 4672: uae_u32 tag; ! 4673: struct cache030 *c; ! 4674: ! 4675: addr &= ~3; ! 4676: index = (addr >> 4) & (CACHELINES030 - 1); ! 4677: tag = regs.s | (addr & ~((CACHELINES030 << 4) - 1)); ! 4678: lws = (addr >> 2) & 3; ! 4679: c = &cp[index]; ! 4680: *tagp = tag; ! 4681: *lwsp = lws; ! 4682: return c; ! 4683: } ! 4684: ! 4685: STATIC_INLINE void update_cache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, int lws) ! 4686: { ! 4687: if (c->tag != tag) ! 4688: c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false; ! 4689: c->tag = tag; ! 4690: c->valid[lws] = true; ! 4691: c->data[lws] = val; ! 4692: } ! 4693: ! 4694: STATIC_INLINE void fill_icache030 (uae_u32 addr, int idx) ! 4695: { ! 4696: int lws; ! 4697: uae_u32 tag; ! 4698: uae_u32 data; ! 4699: struct cache030 *c; ! 4700: ! 4701: addr &= ~3; ! 4702: c = getcache030 (icaches030, addr, &tag, &lws); ! 4703: if (c->valid[lws] && c->tag == tag) { ! 4704: // cache hit ! 4705: regs.prefetch020addr[idx] = addr; ! 4706: regs.prefetch020data[idx] = c->data[lws]; ! 4707: return; ! 4708: } ! 4709: // cache miss ! 4710: data = mem_access_delay_longi_read_ce020 (addr); ! 4711: if ((regs.cacr & 3) == 1) { // not frozen and enabled ! 4712: update_cache030 (c, data, tag, lws); ! 4713: #if 0 ! 4714: if ((regs.cacr & 0x11) == 0x11 && lws == 0 && !c->valid[0] && !c->valid[1] && !c->valid[2] && !c->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST) { ! 4715: // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram ! 4716: c->data[1] = mem_access_delay_long_read_ce020 (addr + 4); ! 4717: c->data[2] = mem_access_delay_long_read_ce020 (addr + 8); ! 4718: c->data[3] = mem_access_delay_long_read_ce020 (addr + 12); ! 4719: c->valid[1] = c->valid[2] = c->valid[3] = true; ! 4720: } ! 4721: #endif ! 4722: } ! 4723: regs.prefetch020addr[idx] = addr; ! 4724: regs.prefetch020data[idx] = data; ! 4725: } ! 4726: ! 4727: STATIC_INLINE bool cancache030 (uaecptr addr) ! 4728: { ! 4729: return ce_cachable[addr >> 16] != 0; ! 4730: } ! 4731: ! 4732: // and finally the worst part, 68030 data cache.. ! 4733: void write_dcache030 (uaecptr addr, uae_u32 val, int size) ! 4734: { ! 4735: struct cache030 *c1, *c2; ! 4736: int lws1, lws2; ! 4737: uae_u32 tag1, tag2; ! 4738: int aligned = addr & 3; ! 4739: ! 4740: if (!(regs.cacr & 0x100) || currprefs.cpu_model == 68040) // data cache disabled? 68040 shares this too. ! 4741: return; ! 4742: if (!cancache030 (addr)) ! 4743: return; ! 4744: ! 4745: c1 = getcache030 (dcaches030, addr, &tag1, &lws1); ! 4746: if (!(regs.cacr & 0x2000)) { // write allocate ! 4747: if (c1->tag != tag1 || c1->valid[lws1] == false) ! 4748: return; ! 4749: } ! 4750: ! 4751: #if 0 ! 4752: uaecptr a = 0x1db0c; ! 4753: if (addr - (1 << size) + 1 <= a && addr + (1 << size) >= a) { ! 4754: write_log ("%08x %d %d %08x %08x %d\n", addr, aligned, size, val, tag1, lws1); ! 4755: if (aligned == 2) ! 4756: write_log ("*\n"); ! 4757: } ! 4758: #endif ! 4759: ! 4760: // easy one ! 4761: if (size == 2 && aligned == 0) { ! 4762: update_cache030 (c1, val, tag1, lws1); ! 4763: #if 0 ! 4764: if ((regs.cacr & 0x1100) == 0x1100 && lws1 == 0 && !c1->valid[0] && !c1->valid[1] && !c1->valid[2] && !c1->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST) { ! 4765: // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram ! 4766: c1->data[1] = mem_access_delay_long_read_ce020 (addr + 4); ! 4767: c1->data[2] = mem_access_delay_long_read_ce020 (addr + 8); ! 4768: c1->data[3] = mem_access_delay_long_read_ce020 (addr + 12); ! 4769: c1->valid[1] = c1->valid[2] = c1->valid[3] = true; ! 4770: } ! 4771: #endif ! 4772: return; ! 4773: } ! 4774: // argh!! merge partial write ! 4775: c2 = getcache030 (dcaches030, addr + 4, &tag2, &lws2); ! 4776: if (size == 2) { ! 4777: if (c1->valid[lws1] && c1->tag == tag1) { ! 4778: c1->data[lws1] &= ~(0xffffffff >> (aligned * 8)); ! 4779: c1->data[lws1] |= val >> (aligned * 8); ! 4780: } ! 4781: if (c2->valid[lws2] && c2->tag == tag2) { ! 4782: c2->data[lws2] &= 0xffffffff >> ((4 - aligned) * 8); ! 4783: c2->data[lws2] |= val << ((4 - aligned) * 8); ! 4784: } ! 4785: } else if (size == 1) { ! 4786: val <<= 16; ! 4787: if (c1->valid[lws1] && c1->tag == tag1) { ! 4788: c1->data[lws1] &= ~(0xffff0000 >> (aligned * 8)); ! 4789: c1->data[lws1] |= val >> (aligned * 8); ! 4790: } ! 4791: if (c2->valid[lws2] && c2->tag == tag2 && aligned == 3) { ! 4792: c2->data[lws2] &= 0x00ffffff; ! 4793: c2->data[lws2] |= val << 8; ! 4794: } ! 4795: } else if (size == 0) { ! 4796: val <<= 24; ! 4797: if (c1->valid[lws1] && c1->tag == tag1) { ! 4798: c1->data[lws1] &= ~(0xff000000 >> (aligned * 8)); ! 4799: c1->data[lws1] |= val >> (aligned * 8); ! 4800: } ! 4801: } ! 4802: } ! 4803: ! 4804: uae_u32 read_dcache030 (uaecptr addr, int size) ! 4805: { ! 4806: struct cache030 *c1, *c2; ! 4807: int lws1, lws2; ! 4808: uae_u32 tag1, tag2; ! 4809: int aligned = addr & 3; ! 4810: int len = (1 << size) * 8; ! 4811: uae_u32 v1, v2; ! 4812: ! 4813: if (!(regs.cacr & 0x100) || currprefs.cpu_model == 68040 || !cancache030 (addr)) { // data cache disabled? shared with 68040 "ce" ! 4814: if (size == 2) ! 4815: return mem_access_delay_long_read_ce020 (addr); ! 4816: else if (size == 1) ! 4817: return mem_access_delay_word_read_ce020 (addr); ! 4818: else ! 4819: return mem_access_delay_byte_read_ce020 (addr); ! 4820: } ! 4821: ! 4822: c1 = getcache030 (dcaches030, addr, &tag1, &lws1); ! 4823: addr &= ~3; ! 4824: if (!c1->valid[lws1] || c1->tag != tag1) { ! 4825: v1 = mem_access_delay_long_read_ce020 (addr); ! 4826: update_cache030 (c1, v1, tag1, lws1); ! 4827: } else { ! 4828: v1 = c1->data[lws1]; ! 4829: if (get_long (addr) != v1) { ! 4830: write_log ("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n", ! 4831: size, aligned, addr, get_long (addr), v1, tag1, lws1, M68K_GETPC); ! 4832: v1 = get_long (addr); ! 4833: } ! 4834: } ! 4835: // only one long fetch needed? ! 4836: if (size == 0) { ! 4837: v1 >>= (3 - aligned) * 8; ! 4838: return v1; ! 4839: } else if (size == 1 && aligned <= 2) { ! 4840: v1 >>= (2 - aligned) * 8; ! 4841: return v1; ! 4842: } else if (size == 2 && aligned == 0) { ! 4843: return v1; ! 4844: } ! 4845: // need two longs ! 4846: addr += 4; ! 4847: c2 = getcache030 (dcaches030, addr, &tag2, &lws2); ! 4848: if (!c2->valid[lws2] || c2->tag != tag2) { ! 4849: v2 = mem_access_delay_long_read_ce020 (addr); ! 4850: update_cache030 (c2, v2, tag2, lws2); ! 4851: } else { ! 4852: v2 = c2->data[lws2]; ! 4853: if (get_long (addr) != v2) { ! 4854: write_log ("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n", ! 4855: size, aligned, addr, get_long (addr), v2, tag2, lws2, M68K_GETPC); ! 4856: v2 = get_long (addr); ! 4857: } ! 4858: } ! 4859: if (size == 1 && aligned == 3) ! 4860: return (v1 << 8) | (v2 >> 24); ! 4861: else if (size == 2 && aligned == 1) ! 4862: return (v1 << 8) | (v2 >> 24); ! 4863: else if (size == 2 && aligned == 2) ! 4864: return (v1 << 16) | (v2 >> 16); ! 4865: else if (size == 2 && aligned == 3) ! 4866: return (v1 << 24) | (v2 >> 8); ! 4867: ! 4868: write_log ("dcache030 weirdness!?\n"); ! 4869: return 0; ! 4870: } ! 4871: ! 4872: uae_u32 get_word_ce030_prefetch (int o) ! 4873: { ! 4874: int i; ! 4875: uae_u32 pc = m68k_getpc () + o; ! 4876: ! 4877: for (;;) { ! 4878: for (i = 0; i < 2; i++) { ! 4879: if (pc == regs.prefetch020addr[0]) { ! 4880: uae_u32 v = regs.prefetch020data[0] >> 16; ! 4881: fill_icache030 (regs.prefetch020addr[0] + 4, 1); ! 4882: return v; ! 4883: } ! 4884: if (pc == regs.prefetch020addr[0] + 2) { ! 4885: uae_u32 v = regs.prefetch020data[0] & 0xffff; ! 4886: if (regs.prefetch020addr[1] == regs.prefetch020addr[0] + 4) { ! 4887: regs.prefetch020addr[0] = regs.prefetch020addr[1]; ! 4888: regs.prefetch020data[0] = regs.prefetch020data[1]; ! 4889: fill_icache030 (regs.prefetch020addr[0] + 4, 1); ! 4890: } else { ! 4891: fill_icache030 (pc + 4, 0); ! 4892: fill_icache030 (regs.prefetch020addr[0] + 4, 1); ! 4893: } ! 4894: return v; ! 4895: } ! 4896: regs.prefetch020addr[0] = regs.prefetch020addr[1]; ! 4897: regs.prefetch020data[0] = regs.prefetch020data[1]; ! 4898: } ! 4899: fill_icache030 (pc + 0, 0); ! 4900: fill_icache030 (pc + 4, 1); ! 4901: } ! 4902: } ! 4903: ! 4904: ! 4905: void flush_dcache (uaecptr addr, int size) ! 4906: { ! 4907: int i; ! 4908: if (!currprefs.cpu_cycle_exact) ! 4909: return; ! 4910: if (currprefs.cpu_model >= 68030) { ! 4911: for (i = 0; i < CACHELINES030; i++) { ! 4912: dcaches030[i].valid[0] = 0; ! 4913: dcaches030[i].valid[1] = 0; ! 4914: dcaches030[i].valid[2] = 0; ! 4915: dcaches030[i].valid[3] = 0; ! 4916: } ! 4917: } ! 4918: } ! 4919: ! 4920: void do_cycles_ce020 (int clocks) ! 4921: { ! 4922: do_cycles_ce (clocks * cpucycleunit); ! 4923: } ! 4924: void do_cycles_ce020_mem (int clocks) ! 4925: { ! 4926: regs.ce020memcycles -= clocks * cpucycleunit; ! 4927: do_cycles_ce (clocks * cpucycleunit); ! 4928: } ! 4929: ! 4930: void do_cycles_ce000 (int clocks) ! 4931: { ! 4932: do_cycles_ce (clocks * cpucycleunit); ! 4933: } ! 4934: ! 4935: void m68k_do_rte_mmu (uaecptr a7) ! 4936: { ! 4937: uae_u16 ssr = get_word_mmu (a7 + 8 + 4); ! 4938: if (ssr & MMU_SSW_CT) { ! 4939: uaecptr src_a7 = a7 + 8 - 8; ! 4940: uaecptr dst_a7 = a7 + 8 + 52; ! 4941: put_word_mmu (dst_a7 + 0, get_word_mmu (src_a7 + 0)); ! 4942: put_long_mmu (dst_a7 + 2, get_long_mmu (src_a7 + 2)); ! 4943: // skip this word ! 4944: put_long_mmu (dst_a7 + 8, get_long_mmu (src_a7 + 8)); ! 4945: } ! 4946: } ! 4947: ! 4948: void flush_mmu (uaecptr addr, int n) ! 4949: { ! 4950: } ! 4951: ! 4952: void m68k_do_rts_mmu (void) ! 4953: { ! 4954: m68k_setpc (get_long_mmu (m68k_areg (regs, 7))); ! 4955: m68k_areg (regs, 7) += 4; ! 4956: } ! 4957: ! 4958: void m68k_do_bsr_mmu (uaecptr oldpc, uae_s32 offset) ! 4959: { ! 4960: put_long_mmu (m68k_areg (regs, 7) - 4, oldpc); ! 4961: m68k_areg (regs, 7) -= 4; ! 4962: m68k_incpci (offset); ! 4963: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.