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