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