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