|
|
1.1.1.4 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * MC68000 emulation
5: *
6: * (c) 1995 Bernd Schmidt
7: */
8:
9: #define MMUOP_DEBUG 2
10: #define DEBUG_CD32CDTVIO 0
1.1.1.7 ! root 11: #define EXCEPTION3_DEBUGGER 0
! 12: #define CPUTRACE_DEBUG 0
! 13:
! 14: #define MORE_ACCURATE_68020_PIPELINE 1
1.1.1.4 root 15:
1.1.1.5 root 16: #include "main.h"
1.1.1.4 root 17: #include "compat.h"
1.1.1.7 ! root 18:
1.1.1.4 root 19: #include "sysconfig.h"
20: #include "sysdeps.h"
1.1.1.7 ! root 21:
1.1.1.4 root 22: #include "hatari-glue.h"
1.1.1.7 ! root 23:
1.1.1.4 root 24: #include "options_cpu.h"
25: #include "events.h"
26: #include "memory.h"
1.1.1.7 ! root 27: #include "custom.h"
1.1.1.4 root 28: #include "newcpu.h"
29: #include "cpummu.h"
1.1.1.5 root 30: #include "cpummu030.h"
1.1.1.4 root 31: #include "cpu_prefetch.h"
1.1.1.7 ! root 32: #include "savestate.h"
! 33: #include "md-fpp.h"
! 34: #ifdef WINUAE_FOR_HATARI
! 35: #include "debug.h"
! 36: #endif
! 37:
! 38: #include "m68000.h"
1.1.1.4 root 39: #include "reset.h"
40: #include "cycInt.h"
41: #include "mfp.h"
42: #include "tos.h"
43: #include "vdi.h"
44: #include "cart.h"
45: #include "dialog.h"
46: #include "bios.h"
47: #include "xbios.h"
48: #include "screen.h"
49: #include "video.h"
50: #include "options.h"
51: #include "dsp.h"
52: #include "log.h"
53: #include "debugui.h"
54: #include "debugcpu.h"
1.1.1.5 root 55: #include "stMemory.h"
1.1.1.4 root 56:
57:
58: #ifdef JIT
59: #include "jit/compemu.h"
60: #include <signal.h>
61: #else
62: /* Need to have these somewhere */
1.1.1.7 ! root 63: #ifndef WINUAE_FOR_HATARI
! 64: bool check_prefs_changed_comp (void) { return false; }
! 65: #endif
1.1.1.4 root 66: #endif
67: /* For faster JIT cycles handling */
68: signed long pissoff = 0;
69:
70: /* Opcode of faulting instruction */
71: static uae_u16 last_op_for_exception_3;
72: /* PC at fault time */
73: static uaecptr last_addr_for_exception_3;
74: /* Address that generated the exception */
75: static uaecptr last_fault_for_exception_3;
76: /* read (0) or write (1) access */
1.1.1.7 ! root 77: static bool last_writeaccess_for_exception_3;
1.1.1.4 root 78: /* instruction (1) or data (0) access */
1.1.1.7 ! root 79: static bool last_instructionaccess_for_exception_3;
! 80: /* not instruction */
! 81: static bool last_notinstruction_for_exception_3;
! 82: /* set when writing exception stack frame */
! 83: static int exception_in_exception;
! 84:
1.1.1.4 root 85: int mmu_enabled, mmu_triggered;
86: int cpu_cycles;
1.1.1.7 ! root 87: int bus_error_offset;
! 88: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 89: static int baseclock;
1.1.1.7 ! root 90: #endif
! 91: int m68k_pc_indirect;
! 92: bool m68k_interrupt_delay;
! 93: static bool m68k_reset_delay;
! 94: static int cpu_prefs_changed_flag;
! 95:
1.1.1.4 root 96: int cpucycleunit;
1.1.1.7 ! root 97: int cpu_tracer;
1.1.1.4 root 98:
99: const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };
100: const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
101:
102: int movem_index1[256];
103: int movem_index2[256];
104: int movem_next[256];
105:
106: cpuop_func *cpufunctbl[65536];
107:
1.1.1.7 ! root 108: struct cputbl_data
! 109: {
! 110: uae_s16 length;
! 111: uae_s8 disp020[2];
! 112: uae_u8 branch;
! 113: };
! 114: static struct cputbl_data cpudatatbl[65536];
1.1.1.5 root 115:
1.1.1.4 root 116: struct mmufixup mmufixup[2];
117:
118: #define COUNT_INSTRS 0
119: #define MC68060_PCR 0x04300000
120: #define MC68EC060_PCR 0x04310000
121:
1.1.1.7 ! root 122: static uae_u64 fake_srp_030, fake_crp_030;
! 123: static uae_u32 fake_tt0_030, fake_tt1_030, fake_tc_030;
! 124: static uae_u16 fake_mmusr_030;
1.1.1.4 root 125:
126: static struct cache020 caches020[CACHELINES020];
127: static struct cache030 icaches030[CACHELINES030];
128: static struct cache030 dcaches030[CACHELINES030];
1.1.1.7 ! root 129: static int icachelinecnt, dcachelinecnt;
! 130: static struct cache040 icaches040[CACHESETS040];
! 131: static struct cache040 dcaches040[CACHESETS040];
! 132:
! 133:
! 134: #ifdef WINUAE_FOR_HATARI
! 135: int OpcodeFamily;
! 136: int BusCyclePenalty = 0;
1.1.1.4 root 137:
1.1.1.7 ! root 138: FILE *console_out_FILE = NULL;
! 139: #endif
1.1.1.4 root 140:
141:
142: #if COUNT_INSTRS
143: static unsigned long int instrcount[65536];
144: static uae_u16 opcodenums[65536];
145:
146: static int compfn (const void *el1, const void *el2)
147: {
148: return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
149: }
150:
151: static TCHAR *icountfilename (void)
152: {
153: TCHAR *name = getenv ("INSNCOUNT");
154: if (name)
155: return name;
156: return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
157: }
158:
159: void dump_counts (void)
160: {
161: FILE *f = fopen (icountfilename (), "w");
162: unsigned long int total;
163: int i;
164:
1.1.1.7 ! root 165: write_log (_T("Writing instruction count file...\n"));
1.1.1.4 root 166: for (i = 0; i < 65536; i++) {
167: opcodenums[i] = i;
168: total += instrcount[i];
169: }
170: qsort (opcodenums, 65536, sizeof (uae_u16), compfn);
171:
172: fprintf (f, "Total: %lu\n", total);
173: for (i=0; i < 65536; i++) {
174: unsigned long int cnt = instrcount[opcodenums[i]];
175: struct instr *dp;
176: struct mnemolookup *lookup;
177: if (!cnt)
178: break;
179: dp = table68k + opcodenums[i];
180: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
181: ;
182: fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
183: }
184: fclose (f);
185: }
186: #else
187: void dump_counts (void)
188: {
189: }
190: #endif
191:
1.1.1.7 ! root 192: /*
! 193:
! 194: ok, all this to "record" current instruction state
! 195: for later 100% cycle-exact restoring
! 196:
! 197: */
! 198:
! 199: static uae_u32 (*x2_prefetch)(int);
! 200: static uae_u32 (*x2_prefetch_long)(int);
! 201: static uae_u32 (*x2_next_iword)(void);
! 202: static uae_u32 (*x2_next_ilong)(void);
! 203: static uae_u32 (*x2_get_ilong)(int);
! 204: static uae_u32 (*x2_get_iword)(int);
! 205: static uae_u32 (*x2_get_ibyte)(int);
! 206: static uae_u32 (*x2_get_long)(uaecptr);
! 207: static uae_u32 (*x2_get_word)(uaecptr);
! 208: static uae_u32 (*x2_get_byte)(uaecptr);
! 209: static void (*x2_put_long)(uaecptr,uae_u32);
! 210: static void (*x2_put_word)(uaecptr,uae_u32);
! 211: static void (*x2_put_byte)(uaecptr,uae_u32);
! 212: static void (*x2_do_cycles)(unsigned long);
! 213: static void (*x2_do_cycles_pre)(unsigned long);
! 214: static void (*x2_do_cycles_post)(unsigned long, uae_u32);
1.1.1.4 root 215:
216: uae_u32 (*x_prefetch)(int);
217: uae_u32 (*x_next_iword)(void);
218: uae_u32 (*x_next_ilong)(void);
1.1.1.7 ! root 219: uae_u32 (*x_get_ilong)(int);
! 220: uae_u32 (*x_get_iword)(int);
! 221: uae_u32 (*x_get_ibyte)(int);
1.1.1.4 root 222: uae_u32 (*x_get_long)(uaecptr);
223: uae_u32 (*x_get_word)(uaecptr);
224: uae_u32 (*x_get_byte)(uaecptr);
225: void (*x_put_long)(uaecptr,uae_u32);
226: void (*x_put_word)(uaecptr,uae_u32);
227: void (*x_put_byte)(uaecptr,uae_u32);
228:
1.1.1.7 ! root 229: uae_u32 (*x_cp_next_iword)(void);
! 230: uae_u32 (*x_cp_next_ilong)(void);
! 231: uae_u32 (*x_cp_get_long)(uaecptr);
! 232: uae_u32 (*x_cp_get_word)(uaecptr);
! 233: uae_u32 (*x_cp_get_byte)(uaecptr);
! 234: void (*x_cp_put_long)(uaecptr,uae_u32);
! 235: void (*x_cp_put_word)(uaecptr,uae_u32);
! 236: void (*x_cp_put_byte)(uaecptr,uae_u32);
! 237: uae_u32 (REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
! 238:
! 239: void (*x_do_cycles)(unsigned long);
! 240: void (*x_do_cycles_pre)(unsigned long);
! 241: void (*x_do_cycles_post)(unsigned long, uae_u32);
! 242:
! 243: uae_u32(*x_phys_get_iword)(uaecptr);
! 244: uae_u32(*x_phys_get_ilong)(uaecptr);
! 245: uae_u32(*x_phys_get_byte)(uaecptr);
! 246: uae_u32(*x_phys_get_word)(uaecptr);
! 247: uae_u32(*x_phys_get_long)(uaecptr);
! 248: void(*x_phys_put_byte)(uaecptr, uae_u32);
! 249: void(*x_phys_put_word)(uaecptr, uae_u32);
! 250: void(*x_phys_put_long)(uaecptr, uae_u32);
! 251:
! 252: static void set_x_cp_funcs(void)
! 253: {
! 254: x_cp_put_long = x_put_long;
! 255: x_cp_put_word = x_put_word;
! 256: x_cp_put_byte = x_put_byte;
! 257: x_cp_get_long = x_get_long;
! 258: x_cp_get_word = x_get_word;
! 259: x_cp_get_byte = x_get_byte;
! 260: x_cp_next_iword = x_next_iword;
! 261: x_cp_next_ilong = x_next_ilong;
! 262: x_cp_get_disp_ea_020 = x_get_disp_ea_020;
! 263:
! 264: if (currprefs.mmu_model == 68030) {
! 265: x_cp_put_long = put_long_mmu030_state;
! 266: x_cp_put_word = put_word_mmu030_state;
! 267: x_cp_put_byte = put_byte_mmu030_state;
! 268: x_cp_get_long = get_long_mmu030_state;
! 269: x_cp_get_word = get_word_mmu030_state;
! 270: x_cp_get_byte = get_byte_mmu030_state;
! 271: x_cp_next_iword = next_iword_mmu030_state;
! 272: x_cp_next_ilong = next_ilong_mmu030_state;
! 273: x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030;
! 274: }
! 275: }
! 276:
! 277: static struct cputracestruct cputrace;
! 278:
! 279: #if CPUTRACE_DEBUG
! 280: static void validate_trace (void)
! 281: {
! 282: for (int i = 0; i < cputrace.memoryoffset; i++) {
! 283: struct cputracememory *ctm = &cputrace.ctm[i];
! 284: if (ctm->data == 0xdeadf00d) {
! 285: write_log (_T("unfinished write operation %d %08x\n"), i, ctm->addr);
! 286: }
! 287: }
! 288: }
! 289: #endif
! 290:
! 291: static void debug_trace (void)
! 292: {
! 293: if (cputrace.writecounter > 10000 || cputrace.readcounter > 10000)
! 294: write_log (_T("cputrace.readcounter=%d cputrace.writecounter=%d\n"), cputrace.readcounter, cputrace.writecounter);
! 295: }
! 296:
! 297: STATIC_INLINE void clear_trace (void)
! 298: {
! 299: #if CPUTRACE_DEBUG
! 300: validate_trace ();
! 301: #endif
! 302: struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
! 303: ctm->mode = 0;
! 304: cputrace.cyclecounter = 0;
! 305: cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
! 306: }
! 307: static void set_trace (uaecptr addr, int accessmode, int size)
! 308: {
! 309: #if CPUTRACE_DEBUG
! 310: validate_trace ();
! 311: #endif
! 312: struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
! 313: ctm->addr = addr;
! 314: ctm->data = 0xdeadf00d;
! 315: ctm->mode = accessmode | (size << 4);
! 316: cputrace.cyclecounter_pre = -1;
! 317: if (accessmode == 1)
! 318: cputrace.writecounter++;
! 319: else
! 320: cputrace.readcounter++;
! 321: debug_trace ();
! 322: }
! 323: static void add_trace (uaecptr addr, uae_u32 val, int accessmode, int size)
! 324: {
! 325: if (cputrace.memoryoffset < 1) {
! 326: #if CPUTRACE_DEBUG
! 327: write_log (_T("add_trace memoryoffset=%d!\n"), cputrace.memoryoffset);
! 328: #endif
! 329: return;
! 330: }
! 331: int mode = accessmode | (size << 4);
! 332: struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
! 333: ctm->addr = addr;
! 334: ctm->data = val;
! 335: if (!ctm->mode) {
! 336: ctm->mode = mode;
! 337: if (accessmode == 1)
! 338: cputrace.writecounter++;
! 339: else
! 340: cputrace.readcounter++;
! 341: }
! 342: debug_trace ();
! 343: cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
! 344: }
! 345:
! 346:
! 347: static void check_trace2 (void)
! 348: {
! 349: if (cputrace.readcounter || cputrace.writecounter ||
! 350: cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
! 351: write_log (_T("CPU tracer invalid state during playback!\n"));
! 352: }
! 353:
! 354: static bool check_trace (void)
! 355: {
! 356: if (!cpu_tracer)
! 357: return true;
! 358: if (!cputrace.readcounter && !cputrace.writecounter && !cputrace.cyclecounter) {
! 359: if (cpu_tracer != -2) {
! 360: write_log (_T("CPU trace: dma_cycle() enabled. %08x %08x NOW=%08lx\n"),
! 361: cputrace.cyclecounter_pre, cputrace.cyclecounter_post, get_cycles ());
! 362: cpu_tracer = -2; // dma_cycle() allowed to work now
! 363: }
! 364: }
! 365: if (cputrace.readcounter || cputrace.writecounter ||
! 366: cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
! 367: return false;
! 368: x_prefetch = x2_prefetch;
! 369: x_get_ilong = x2_get_ilong;
! 370: x_get_iword = x2_get_iword;
! 371: x_get_ibyte = x2_get_ibyte;
! 372: x_next_iword = x2_next_iword;
! 373: x_next_ilong = x2_next_ilong;
! 374: x_put_long = x2_put_long;
! 375: x_put_word = x2_put_word;
! 376: x_put_byte = x2_put_byte;
! 377: x_get_long = x2_get_long;
! 378: x_get_word = x2_get_word;
! 379: x_get_byte = x2_get_byte;
! 380: x_do_cycles = x2_do_cycles;
! 381: x_do_cycles_pre = x2_do_cycles_pre;
! 382: x_do_cycles_post = x2_do_cycles_post;
! 383: set_x_cp_funcs();
! 384: write_log (_T("CPU tracer playback complete. STARTCYCLES=%08x NOWCYCLES=%08lx\n"), cputrace.startcycles, get_cycles ());
! 385: cputrace.needendcycles = 1;
! 386: cpu_tracer = 0;
! 387: return true;
! 388: }
! 389:
! 390: static bool get_trace (uaecptr addr, int accessmode, int size, uae_u32 *data)
! 391: {
! 392: int mode = accessmode | (size << 4);
! 393: int i;
! 394: for (i = 0; i < cputrace.memoryoffset; i++) {
! 395: struct cputracememory *ctm = &cputrace.ctm[i];
! 396: if (ctm->addr == addr && ctm->mode == mode) {
! 397: ctm->mode = 0;
! 398: write_log (_T("CPU trace: GET %d: PC=%08x %08x=%08x %d %d %08x/%08x/%08x %d/%d (%08lx)\n"),
! 399: i, cputrace.pc, addr, ctm->data, accessmode, size,
! 400: cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
! 401: cputrace.readcounter, cputrace.writecounter, get_cycles ());
! 402: if (accessmode == 1)
! 403: cputrace.writecounter--;
! 404: else
! 405: cputrace.readcounter--;
! 406: if (cputrace.writecounter == 0 && cputrace.readcounter == 0) {
! 407: if (cputrace.cyclecounter_post) {
! 408: int c = cputrace.cyclecounter_post;
! 409: cputrace.cyclecounter_post = 0;
! 410: x_do_cycles (c);
! 411: } else if (cputrace.cyclecounter_pre) {
! 412: check_trace ();
! 413: *data = ctm->data;
! 414: return true; // argh, need to rerun the memory access..
! 415: }
! 416: }
! 417: check_trace ();
! 418: *data = ctm->data;
! 419: return false;
! 420: }
! 421: }
! 422: if (cputrace.cyclecounter_post) {
! 423: int c = cputrace.cyclecounter_post;
! 424: cputrace.cyclecounter_post = 0;
! 425: check_trace ();
! 426: check_trace2 ();
! 427: x_do_cycles (c);
! 428: return false;
! 429: }
! 430: gui_message (_T("CPU trace: GET %08x %d %d NOT FOUND!\n"), addr, accessmode, size);
! 431: check_trace ();
! 432: *data = 0;
! 433: return false;
! 434: }
! 435:
! 436: static uae_u32 cputracefunc_x_prefetch (int o)
! 437: {
! 438: uae_u32 pc = m68k_getpc ();
! 439: set_trace (pc + o, 2, 2);
! 440: uae_u32 v = x2_prefetch (o);
! 441: add_trace (pc + o, v, 2, 2);
! 442: return v;
! 443: }
! 444: static uae_u32 cputracefunc2_x_prefetch (int o)
! 445: {
! 446: uae_u32 v;
! 447: if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
! 448: v = x2_prefetch (o);
! 449: check_trace2 ();
! 450: }
! 451: return v;
! 452: }
! 453:
! 454: static uae_u32 cputracefunc_x_next_iword (void)
! 455: {
! 456: uae_u32 pc = m68k_getpc ();
! 457: set_trace (pc, 2, 2);
! 458: uae_u32 v = x2_next_iword ();
! 459: add_trace (pc, v, 2, 2);
! 460: return v;
! 461: }
! 462: static uae_u32 cputracefunc_x_next_ilong (void)
! 463: {
! 464: uae_u32 pc = m68k_getpc ();
! 465: set_trace (pc, 2, 4);
! 466: uae_u32 v = x2_next_ilong ();
! 467: add_trace (pc, v, 2, 4);
! 468: return v;
! 469: }
! 470: static uae_u32 cputracefunc2_x_next_iword (void)
! 471: {
! 472: uae_u32 v;
! 473: if (get_trace (m68k_getpc (), 2, 2, &v)) {
! 474: v = x2_next_iword ();
! 475: check_trace2 ();
! 476: }
! 477: return v;
! 478: }
! 479: static uae_u32 cputracefunc2_x_next_ilong (void)
! 480: {
! 481: uae_u32 v;
! 482: if (get_trace (m68k_getpc (), 2, 4, &v)) {
! 483: v = x2_next_ilong ();
! 484: check_trace2 ();
! 485: }
! 486: return v;
! 487: }
! 488:
! 489: static uae_u32 cputracefunc_x_get_ilong (int o)
! 490: {
! 491: uae_u32 pc = m68k_getpc ();
! 492: set_trace (pc + o, 2, 4);
! 493: uae_u32 v = x2_get_ilong (o);
! 494: add_trace (pc + o, v, 2, 4);
! 495: return v;
! 496: }
! 497: static uae_u32 cputracefunc_x_get_iword (int o)
! 498: {
! 499: uae_u32 pc = m68k_getpc ();
! 500: set_trace (pc + o, 2, 2);
! 501: uae_u32 v = x2_get_iword (o);
! 502: add_trace (pc + o, v, 2, 2);
! 503: return v;
! 504: }
! 505: static uae_u32 cputracefunc_x_get_ibyte (int o)
! 506: {
! 507: uae_u32 pc = m68k_getpc ();
! 508: set_trace (pc + o, 2, 1);
! 509: uae_u32 v = x2_get_ibyte (o);
! 510: add_trace (pc + o, v, 2, 1);
! 511: return v;
! 512: }
! 513: static uae_u32 cputracefunc2_x_get_ilong (int o)
! 514: {
! 515: uae_u32 v;
! 516: if (get_trace (m68k_getpc () + o, 2, 4, &v)) {
! 517: v = x2_get_ilong (o);
! 518: check_trace2 ();
! 519: }
! 520: return v;
! 521: }
! 522: static uae_u32 cputracefunc2_x_get_iword (int o)
! 523: {
! 524: uae_u32 v;
! 525: if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
! 526: v = x2_get_iword (o);
! 527: check_trace2 ();
! 528: }
! 529: return v;
! 530: }
! 531: static uae_u32 cputracefunc2_x_get_ibyte (int o)
! 532: {
! 533: uae_u32 v;
! 534: if (get_trace (m68k_getpc () + o, 2, 1, &v)) {
! 535: v = x2_get_ibyte (o);
! 536: check_trace2 ();
! 537: }
! 538: return v;
! 539: }
! 540:
! 541: static uae_u32 cputracefunc_x_get_long (uaecptr o)
! 542: {
! 543: set_trace (o, 0, 4);
! 544: uae_u32 v = x2_get_long (o);
! 545: add_trace (o, v, 0, 4);
! 546: return v;
! 547: }
! 548: static uae_u32 cputracefunc_x_get_word (uaecptr o)
! 549: {
! 550: set_trace (o, 0, 2);
! 551: uae_u32 v = x2_get_word (o);
! 552: add_trace (o, v, 0, 2);
! 553: return v;
! 554: }
! 555: static uae_u32 cputracefunc_x_get_byte (uaecptr o)
! 556: {
! 557: set_trace (o, 0, 1);
! 558: uae_u32 v = x2_get_byte (o);
! 559: add_trace (o, v, 0, 1);
! 560: return v;
! 561: }
! 562: static uae_u32 cputracefunc2_x_get_long (uaecptr o)
! 563: {
! 564: uae_u32 v;
! 565: if (get_trace (o, 0, 4, &v)) {
! 566: v = x2_get_long (o);
! 567: check_trace2 ();
! 568: }
! 569: return v;
! 570: }
! 571: static uae_u32 cputracefunc2_x_get_word (uaecptr o)
! 572: {
! 573: uae_u32 v;
! 574: if (get_trace (o, 0, 2, &v)) {
! 575: v = x2_get_word (o);
! 576: check_trace2 ();
! 577: }
! 578: return v;
! 579: }
! 580: static uae_u32 cputracefunc2_x_get_byte (uaecptr o)
! 581: {
! 582: uae_u32 v;
! 583: if (get_trace (o, 0, 1, &v)) {
! 584: v = x2_get_byte (o);
! 585: check_trace2 ();
! 586: }
! 587: return v;
! 588: }
! 589:
! 590: static void cputracefunc_x_put_long (uaecptr o, uae_u32 val)
! 591: {
! 592: clear_trace ();
! 593: add_trace (o, val, 1, 4);
! 594: x2_put_long (o, val);
! 595: }
! 596: static void cputracefunc_x_put_word (uaecptr o, uae_u32 val)
! 597: {
! 598: clear_trace ();
! 599: add_trace (o, val, 1, 2);
! 600: x2_put_word (o, val);
! 601: }
! 602: static void cputracefunc_x_put_byte (uaecptr o, uae_u32 val)
! 603: {
! 604: clear_trace ();
! 605: add_trace (o, val, 1, 1);
! 606: x2_put_byte (o, val);
! 607: }
! 608: static void cputracefunc2_x_put_long (uaecptr o, uae_u32 val)
! 609: {
! 610: uae_u32 v;
! 611: if (get_trace (o, 1, 4, &v)) {
! 612: x2_put_long (o, val);
! 613: check_trace2 ();
! 614: }
! 615: if (v != val)
! 616: write_log (_T("cputracefunc2_x_put_long %d <> %d\n"), v, val);
! 617: }
! 618: static void cputracefunc2_x_put_word (uaecptr o, uae_u32 val)
! 619: {
! 620: uae_u32 v;
! 621: if (get_trace (o, 1, 2, &v)) {
! 622: x2_put_word (o, val);
! 623: check_trace2 ();
! 624: }
! 625: if (v != val)
! 626: write_log (_T("cputracefunc2_x_put_word %d <> %d\n"), v, val);
! 627: }
! 628: static void cputracefunc2_x_put_byte (uaecptr o, uae_u32 val)
! 629: {
! 630: uae_u32 v;
! 631: if (get_trace (o, 1, 1, &v)) {
! 632: x2_put_byte (o, val);
! 633: check_trace2 ();
! 634: }
! 635: if (v != val)
! 636: write_log (_T("cputracefunc2_x_put_byte %d <> %d\n"), v, val);
! 637: }
! 638:
! 639: static void cputracefunc_x_do_cycles (unsigned long cycles)
! 640: {
! 641: while (cycles >= CYCLE_UNIT) {
! 642: cputrace.cyclecounter += CYCLE_UNIT;
! 643: cycles -= CYCLE_UNIT;
! 644: x2_do_cycles (CYCLE_UNIT);
! 645: }
! 646: if (cycles > 0) {
! 647: cputrace.cyclecounter += cycles;
! 648: x2_do_cycles (cycles);
! 649: }
! 650: }
! 651:
! 652: static void cputracefunc2_x_do_cycles (unsigned long cycles)
! 653: {
! 654: if (cputrace.cyclecounter > (long)cycles) {
! 655: cputrace.cyclecounter -= cycles;
! 656: return;
! 657: }
! 658: cycles -= cputrace.cyclecounter;
! 659: cputrace.cyclecounter = 0;
! 660: check_trace ();
! 661: x_do_cycles = x2_do_cycles;
! 662: if (cycles > 0)
! 663: x_do_cycles (cycles);
! 664: }
! 665:
! 666: static void cputracefunc_x_do_cycles_pre (unsigned long cycles)
! 667: {
! 668: cputrace.cyclecounter_post = 0;
! 669: cputrace.cyclecounter_pre = 0;
! 670: while (cycles >= CYCLE_UNIT) {
! 671: cycles -= CYCLE_UNIT;
! 672: cputrace.cyclecounter_pre += CYCLE_UNIT;
! 673: x2_do_cycles (CYCLE_UNIT);
! 674: }
! 675: if (cycles > 0) {
! 676: x2_do_cycles (cycles);
! 677: cputrace.cyclecounter_pre += cycles;
! 678: }
! 679: cputrace.cyclecounter_pre = 0;
! 680: }
! 681: // cyclecounter_pre = how many cycles we need to SWALLOW
! 682: // -1 = rerun whole access
! 683: static void cputracefunc2_x_do_cycles_pre (unsigned long cycles)
! 684: {
! 685: if (cputrace.cyclecounter_pre == -1) {
! 686: cputrace.cyclecounter_pre = 0;
! 687: check_trace ();
! 688: check_trace2 ();
! 689: x_do_cycles (cycles);
! 690: return;
! 691: }
! 692: if (cputrace.cyclecounter_pre > (long)cycles) {
! 693: cputrace.cyclecounter_pre -= cycles;
! 694: return;
! 695: }
! 696: cycles -= cputrace.cyclecounter_pre;
! 697: cputrace.cyclecounter_pre = 0;
! 698: check_trace ();
! 699: if (cycles > 0)
! 700: x_do_cycles (cycles);
! 701: }
! 702:
! 703: static void cputracefunc_x_do_cycles_post (unsigned long cycles, uae_u32 v)
! 704: {
! 705: if (cputrace.memoryoffset < 1) {
! 706: #if CPUTRACE_DEBUG
! 707: write_log (_T("cputracefunc_x_do_cycles_post memoryoffset=%d!\n"), cputrace.memoryoffset);
! 708: #endif
! 709: return;
! 710: }
! 711: struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
! 712: ctm->data = v;
! 713: cputrace.cyclecounter_post = cycles;
! 714: cputrace.cyclecounter_pre = 0;
! 715: while (cycles >= CYCLE_UNIT) {
! 716: cycles -= CYCLE_UNIT;
! 717: cputrace.cyclecounter_post -= CYCLE_UNIT;
! 718: x2_do_cycles (CYCLE_UNIT);
! 719: }
! 720: if (cycles > 0) {
! 721: cputrace.cyclecounter_post -= cycles;
! 722: x2_do_cycles (cycles);
! 723: }
! 724: cputrace.cyclecounter_post = 0;
! 725: }
! 726: // cyclecounter_post = how many cycles we need to WAIT
! 727: static void cputracefunc2_x_do_cycles_post (unsigned long cycles, uae_u32 v)
! 728: {
! 729: uae_u32 c;
! 730: if (cputrace.cyclecounter_post) {
! 731: c = cputrace.cyclecounter_post;
! 732: cputrace.cyclecounter_post = 0;
! 733: } else {
! 734: c = cycles;
! 735: }
! 736: check_trace ();
! 737: if (c > 0)
! 738: x_do_cycles (c);
! 739: }
! 740:
! 741: static void do_cycles_post (unsigned long cycles, uae_u32 v)
! 742: {
! 743: do_cycles (cycles);
! 744: }
! 745: static void do_cycles_ce_post (unsigned long cycles, uae_u32 v)
! 746: {
! 747: do_cycles_ce (cycles);
! 748: }
! 749: static void do_cycles_ce020_post (unsigned long cycles, uae_u32 v)
! 750: {
! 751: #ifndef WINUAE_FOR_HATARI
! 752: do_cycles_ce020 (cycles);
! 753: #else
! 754: do_cycles_ce020_long (cycles);
! 755: #endif
! 756: }
! 757:
! 758: static void set_x_ifetches(void)
! 759: {
! 760: if (m68k_pc_indirect) {
! 761: if (currprefs.cachesize) {
! 762: // indirect via addrbank
! 763: x_get_ilong = get_iilong_jit;
! 764: x_get_iword = get_iiword_jit;
! 765: x_get_ibyte = get_iibyte_jit;
! 766: x_next_iword = next_iiword_jit;
! 767: x_next_ilong = next_iilong_jit;
! 768: } else {
! 769: // indirect via addrbank
! 770: x_get_ilong = get_iilong;
! 771: x_get_iword = get_iiword;
! 772: x_get_ibyte = get_iibyte;
! 773: x_next_iword = next_iiword;
! 774: x_next_ilong = next_iilong;
! 775: }
! 776: } else {
! 777: // direct to memory
! 778: x_get_ilong = get_dilong;
! 779: x_get_iword = get_diword;
! 780: x_get_ibyte = get_dibyte;
! 781: x_next_iword = next_diword;
! 782: x_next_ilong = next_dilong;
! 783: }
! 784: }
! 785:
! 786: // indirect memory access functions
1.1.1.4 root 787: static void set_x_funcs (void)
788: {
1.1.1.7 ! root 789: if (currprefs.mmu_model) {
! 790: if (currprefs.cpu_model == 68060) {
! 791: x_prefetch = get_iword_mmu060;
! 792: x_get_ilong = get_ilong_mmu060;
! 793: x_get_iword = get_iword_mmu060;
! 794: x_get_ibyte = get_ibyte_mmu060;
! 795: x_next_iword = next_iword_mmu060;
! 796: x_next_ilong = next_ilong_mmu060;
! 797: x_put_long = put_long_mmu060;
! 798: x_put_word = put_word_mmu060;
! 799: x_put_byte = put_byte_mmu060;
! 800: x_get_long = get_long_mmu060;
! 801: x_get_word = get_word_mmu060;
! 802: x_get_byte = get_byte_mmu060;
! 803: } else if (currprefs.cpu_model == 68040) {
! 804: x_prefetch = get_iword_mmu040;
! 805: x_get_ilong = get_ilong_mmu040;
! 806: x_get_iword = get_iword_mmu040;
! 807: x_get_ibyte = get_ibyte_mmu040;
! 808: x_next_iword = next_iword_mmu040;
! 809: x_next_ilong = next_ilong_mmu040;
! 810: x_put_long = put_long_mmu040;
! 811: x_put_word = put_word_mmu040;
! 812: x_put_byte = put_byte_mmu040;
! 813: x_get_long = get_long_mmu040;
! 814: x_get_word = get_word_mmu040;
! 815: x_get_byte = get_byte_mmu040;
! 816: } else {
! 817: x_prefetch = get_iword_mmu030;
! 818: x_get_ilong = get_ilong_mmu030;
! 819: x_get_iword = get_iword_mmu030;
! 820: x_get_ibyte = get_ibyte_mmu030;
! 821: x_next_iword = next_iword_mmu030;
! 822: x_next_ilong = next_ilong_mmu030;
! 823: x_put_long = put_long_mmu030;
! 824: x_put_word = put_word_mmu030;
! 825: x_put_byte = put_byte_mmu030;
! 826: x_get_long = get_long_mmu030;
! 827: x_get_word = get_word_mmu030;
! 828: x_get_byte = get_byte_mmu030;
! 829: }
! 830: x_do_cycles = do_cycles;
! 831: x_do_cycles_pre = do_cycles;
! 832: x_do_cycles_post = do_cycles_post;
1.1.1.4 root 833: } else if (currprefs.cpu_model < 68020) {
1.1.1.7 ! root 834: // 68000/010
! 835: if (currprefs.cpu_cycle_exact) {
! 836: x_prefetch = get_word_ce000_prefetch;
! 837: x_get_ilong = NULL;
! 838: x_get_iword = get_wordi_ce000;
! 839: x_get_ibyte = NULL;
! 840: x_next_iword = NULL;
! 841: x_next_ilong = NULL;
! 842: x_put_long = put_long_ce000;
! 843: x_put_word = put_word_ce000;
! 844: x_put_byte = put_byte_ce000;
! 845: x_get_long = get_long_ce000;
! 846: x_get_word = get_word_ce000;
! 847: x_get_byte = get_byte_ce000;
! 848: x_do_cycles = do_cycles_ce;
! 849: x_do_cycles_pre = do_cycles_ce;
! 850: x_do_cycles_post = do_cycles_ce_post;
! 851: } else if (currprefs.cpu_compatible) {
! 852: x_prefetch = get_word_prefetch;
! 853: x_get_ilong = NULL;
! 854: x_get_iword = get_iiword;
! 855: x_get_ibyte = get_iibyte;
! 856: x_next_iword = NULL;
! 857: x_next_ilong = NULL;
! 858: x_put_long = put_long;
! 859: x_put_word = put_word;
! 860: x_put_byte = put_byte;
! 861: x_get_long = get_long;
! 862: x_get_word = get_word;
! 863: x_get_byte = get_byte;
! 864: x_do_cycles = do_cycles;
! 865: x_do_cycles_pre = do_cycles;
! 866: x_do_cycles_post = do_cycles_post;
! 867: } else {
! 868: x_prefetch = NULL;
! 869: x_get_ilong = get_dilong;
! 870: x_get_iword = get_diword;
! 871: x_get_ibyte = get_dibyte;
! 872: x_next_iword = next_diword;
! 873: x_next_ilong = next_dilong;
! 874: x_put_long = put_long;
! 875: x_put_word = put_word;
! 876: x_put_byte = put_byte;
! 877: x_get_long = get_long;
! 878: x_get_word = get_word;
! 879: x_get_byte = get_byte;
! 880: x_do_cycles = do_cycles;
! 881: x_do_cycles_pre = do_cycles;
! 882: x_do_cycles_post = do_cycles_post;
! 883: }
! 884: } else if (!currprefs.cpu_cycle_exact) {
! 885: // 68020+ no ce
! 886: if (currprefs.cpu_compatible) {
! 887: if (currprefs.cpu_model == 68020 && !currprefs.cachesize) {
! 888: x_prefetch = get_word_prefetch;
! 889: x_get_ilong = get_long_020_prefetch;
! 890: x_get_iword = get_word_020_prefetch;
! 891: x_get_ibyte = NULL;
! 892: x_next_iword = next_iword_020_prefetch;
! 893: x_next_ilong = next_ilong_020_prefetch;
! 894: x_put_long = put_long;
! 895: x_put_word = put_word;
! 896: x_put_byte = put_byte;
! 897: x_get_long = get_long;
! 898: x_get_word = get_word;
! 899: x_get_byte = get_byte;
! 900: x_do_cycles = do_cycles;
! 901: x_do_cycles_pre = do_cycles;
! 902: x_do_cycles_post = do_cycles_post;
! 903: } else if (currprefs.cpu_model == 68030 && !currprefs.cachesize) {
! 904: x_prefetch = get_word_prefetch;
! 905: x_get_ilong = get_long_030_prefetch;
! 906: x_get_iword = get_word_030_prefetch;
! 907: x_get_ibyte = NULL;
! 908: x_next_iword = next_iword_030_prefetch;
! 909: x_next_ilong = next_ilong_030_prefetch;
! 910: x_put_long = put_long;
! 911: x_put_word = put_word;
! 912: x_put_byte = put_byte;
! 913: x_get_long = get_long;
! 914: x_get_word = get_word;
! 915: x_get_byte = get_byte;
! 916: x_do_cycles = do_cycles;
! 917: x_do_cycles_pre = do_cycles;
! 918: x_do_cycles_post = do_cycles_post;
! 919: } else if (currprefs.cpu_model < 68040) {
! 920: // JIT or 68030+ does not have real prefetch only emulation
! 921: x_prefetch = NULL;
! 922: set_x_ifetches();
! 923: x_put_long = put_long;
! 924: x_put_word = put_word;
! 925: x_put_byte = put_byte;
! 926: x_get_long = get_long;
! 927: x_get_word = get_word;
! 928: x_get_byte = get_byte;
! 929: x_do_cycles = do_cycles;
! 930: x_do_cycles_pre = do_cycles;
! 931: x_do_cycles_post = do_cycles_post;
! 932: } else {
! 933: x_prefetch = NULL;
! 934: x_get_ilong = get_ilong_cache_040;
! 935: x_get_iword = get_iword_cache_040;
! 936: x_get_ibyte = NULL;
! 937: x_next_iword = next_iword_cache040;
! 938: x_next_ilong = next_ilong_cache040;
! 939: x_put_long = put_long_cache_040;
! 940: x_put_word = put_word_cache_040;
! 941: x_put_byte = put_byte_cache_040;
! 942: x_get_long = get_long_cache_040;
! 943: x_get_word = get_word_cache_040;
! 944: x_get_byte = get_byte_cache_040;
! 945: x_do_cycles = do_cycles;
! 946: x_do_cycles_pre = do_cycles;
! 947: x_do_cycles_post = do_cycles_post;
! 948: }
! 949: } else {
! 950: x_prefetch = NULL;
! 951: set_x_ifetches();
! 952: x_put_long = put_long;
! 953: x_put_word = put_word;
! 954: x_put_byte = put_byte;
! 955: x_get_long = get_long;
! 956: x_get_word = get_word;
! 957: x_get_byte = get_byte;
! 958: x_do_cycles = do_cycles;
! 959: x_do_cycles_pre = do_cycles;
! 960: x_do_cycles_post = do_cycles_post;
! 961: }
! 962: // 68020+ cycle exact
1.1.1.4 root 963: } else if (currprefs.cpu_model == 68020) {
964: x_prefetch = get_word_ce020_prefetch;
1.1.1.7 ! root 965: x_get_ilong = get_long_ce020_prefetch;
! 966: x_get_iword = get_word_ce020_prefetch;
! 967: x_get_ibyte = NULL;
1.1.1.4 root 968: x_next_iword = next_iword_020ce;
969: x_next_ilong = next_ilong_020ce;
970: x_put_long = put_long_ce020;
971: x_put_word = put_word_ce020;
972: x_put_byte = put_byte_ce020;
973: x_get_long = get_long_ce020;
974: x_get_word = get_word_ce020;
975: x_get_byte = get_byte_ce020;
1.1.1.7 ! root 976: #ifndef WINUAE_FOR_HATARI
! 977: x_do_cycles = do_cycles_ce020;
! 978: x_do_cycles_pre = do_cycles_ce020;
! 979: x_do_cycles_post = do_cycles_ce020_post;
! 980: #else
! 981: x_do_cycles = do_cycles_ce020_long;
! 982: x_do_cycles_pre = do_cycles_ce020_long;
! 983: x_do_cycles_post = do_cycles_ce020_post;
! 984: #endif
! 985: } else if (currprefs.cpu_model == 68030) {
1.1.1.4 root 986: x_prefetch = get_word_ce030_prefetch;
1.1.1.7 ! root 987: x_get_ilong = get_long_ce030_prefetch;
! 988: x_get_iword = get_word_ce030_prefetch;
! 989: x_get_ibyte = NULL;
1.1.1.4 root 990: x_next_iword = next_iword_030ce;
991: x_next_ilong = next_ilong_030ce;
992: x_put_long = put_long_ce030;
993: x_put_word = put_word_ce030;
994: x_put_byte = put_byte_ce030;
995: x_get_long = get_long_ce030;
996: x_get_word = get_word_ce030;
997: x_get_byte = get_byte_ce030;
1.1.1.7 ! root 998: #ifndef WINUAE_FOR_HATARI
! 999: x_do_cycles = do_cycles_ce020;
! 1000: x_do_cycles_pre = do_cycles_ce020;
! 1001: x_do_cycles_post = do_cycles_ce020_post;
! 1002: #else
! 1003: x_do_cycles = do_cycles_ce020_long;
! 1004: x_do_cycles_pre = do_cycles_ce020_long;
! 1005: x_do_cycles_post = do_cycles_ce020_post;
! 1006: #endif
! 1007: } else if (currprefs.cpu_model >= 68040) {
! 1008: x_prefetch = NULL;
! 1009: x_get_ilong = get_ilong_cache_040;
! 1010: x_get_iword = get_iword_cache_040;
! 1011: x_get_ibyte = NULL;
! 1012: x_next_iword = next_iword_cache040;
! 1013: x_next_ilong = next_ilong_cache040;
! 1014: x_put_long = put_long_cache_040;
! 1015: x_put_word = put_word_cache_040;
! 1016: x_put_byte = put_byte_cache_040;
! 1017: x_get_long = get_long_cache_040;
! 1018: x_get_word = get_word_cache_040;
! 1019: x_get_byte = get_byte_cache_040;
! 1020: #ifndef WINUAE_FOR_HATARI
! 1021: x_do_cycles = do_cycles_ce020;
! 1022: x_do_cycles_pre = do_cycles_ce020;
! 1023: x_do_cycles_post = do_cycles_ce020_post;
! 1024: #else
! 1025: x_do_cycles = do_cycles_ce020_long;
! 1026: x_do_cycles_pre = do_cycles_ce020_long;
! 1027: x_do_cycles_post = do_cycles_ce020_post;
! 1028: #endif
! 1029: }
! 1030: x2_prefetch = x_prefetch;
! 1031: x2_get_ilong = x_get_ilong;
! 1032: x2_get_iword = x_get_iword;
! 1033: x2_get_ibyte = x_get_ibyte;
! 1034: x2_next_iword = x_next_iword;
! 1035: x2_next_ilong = x_next_ilong;
! 1036: x2_put_long = x_put_long;
! 1037: x2_put_word = x_put_word;
! 1038: x2_put_byte = x_put_byte;
! 1039: x2_get_long = x_get_long;
! 1040: x2_get_word = x_get_word;
! 1041: x2_get_byte = x_get_byte;
! 1042: x2_do_cycles = x_do_cycles;
! 1043: x2_do_cycles_pre = x_do_cycles_pre;
! 1044: x2_do_cycles_post = x_do_cycles_post;
! 1045:
! 1046: if (cpu_tracer > 0) {
! 1047: x_prefetch = cputracefunc_x_prefetch;
! 1048: x_get_ilong = cputracefunc_x_get_ilong;
! 1049: x_get_iword = cputracefunc_x_get_iword;
! 1050: x_get_ibyte = cputracefunc_x_get_ibyte;
! 1051: x_next_iword = cputracefunc_x_next_iword;
! 1052: x_next_ilong = cputracefunc_x_next_ilong;
! 1053: x_put_long = cputracefunc_x_put_long;
! 1054: x_put_word = cputracefunc_x_put_word;
! 1055: x_put_byte = cputracefunc_x_put_byte;
! 1056: x_get_long = cputracefunc_x_get_long;
! 1057: x_get_word = cputracefunc_x_get_word;
! 1058: x_get_byte = cputracefunc_x_get_byte;
! 1059: x_do_cycles = cputracefunc_x_do_cycles;
! 1060: x_do_cycles_pre = cputracefunc_x_do_cycles_pre;
! 1061: x_do_cycles_post = cputracefunc_x_do_cycles_post;
! 1062: } else if (cpu_tracer < 0) {
! 1063: if (!check_trace ()) {
! 1064: x_prefetch = cputracefunc2_x_prefetch;
! 1065: x_get_ilong = cputracefunc2_x_get_ilong;
! 1066: x_get_iword = cputracefunc2_x_get_iword;
! 1067: x_get_ibyte = cputracefunc2_x_get_ibyte;
! 1068: x_next_iword = cputracefunc2_x_next_iword;
! 1069: x_next_ilong = cputracefunc2_x_next_ilong;
! 1070: x_put_long = cputracefunc2_x_put_long;
! 1071: x_put_word = cputracefunc2_x_put_word;
! 1072: x_put_byte = cputracefunc2_x_put_byte;
! 1073: x_get_long = cputracefunc2_x_get_long;
! 1074: x_get_word = cputracefunc2_x_get_word;
! 1075: x_get_byte = cputracefunc2_x_get_byte;
! 1076: x_do_cycles = cputracefunc2_x_do_cycles;
! 1077: x_do_cycles_pre = cputracefunc2_x_do_cycles_pre;
! 1078: x_do_cycles_post = cputracefunc2_x_do_cycles_post;
! 1079: }
! 1080: }
! 1081:
! 1082: set_x_cp_funcs();
! 1083: mmu_set_funcs();
! 1084: mmu030_set_funcs();
! 1085:
! 1086: }
! 1087:
! 1088: bool can_cpu_tracer (void)
! 1089: {
! 1090: return (currprefs.cpu_model == 68000 || currprefs.cpu_model == 68020) && currprefs.cpu_cycle_exact;
! 1091: }
! 1092:
! 1093: bool is_cpu_tracer (void)
! 1094: {
! 1095: return cpu_tracer > 0;
! 1096: }
! 1097: bool set_cpu_tracer (bool state)
! 1098: {
! 1099: if (cpu_tracer < 0)
! 1100: return false;
! 1101: int old = cpu_tracer;
! 1102: #ifndef WINUAE_FOR_HATARI
! 1103: if (input_record)
! 1104: state = true;
! 1105: #endif
! 1106: cpu_tracer = 0;
! 1107: if (state && can_cpu_tracer ()) {
! 1108: cpu_tracer = 1;
! 1109: set_x_funcs ();
! 1110: if (old != cpu_tracer)
! 1111: write_log (_T("CPU tracer enabled\n"));
1.1.1.4 root 1112: }
1.1.1.7 ! root 1113: if (old > 0 && state == false) {
! 1114: set_x_funcs ();
! 1115: write_log (_T("CPU tracer disabled\n"));
! 1116: }
! 1117: return is_cpu_tracer ();
1.1.1.4 root 1118: }
1119:
1.1.1.7 ! root 1120: void flush_cpu_caches(bool force)
1.1.1.4 root 1121: {
1.1.1.7 ! root 1122: bool doflush = currprefs.cpu_compatible || currprefs.cpu_cycle_exact;
1.1.1.4 root 1123: int i;
1124:
1125: if (currprefs.cpu_model == 68020) {
1126: if (regs.cacr & 0x08) { // clear instr cache
1127: for (i = 0; i < CACHELINES020; i++)
1128: caches020[i].valid = 0;
1.1.1.7 ! root 1129: regs.cacr &= ~0x08;
1.1.1.4 root 1130: }
1131: if (regs.cacr & 0x04) { // clear entry in instr cache
1.1.1.7 ! root 1132: caches020[(regs.caar >> 2) & (CACHELINES020 - 1)].valid = 0;
1.1.1.4 root 1133: regs.cacr &= ~0x04;
1134: }
1135: } else if (currprefs.cpu_model == 68030) {
1136: if (regs.cacr & 0x08) { // clear instr cache
1.1.1.7 ! root 1137: if (doflush) {
! 1138: for (i = 0; i < CACHELINES030; i++) {
! 1139: icaches030[i].valid[0] = 0;
! 1140: icaches030[i].valid[1] = 0;
! 1141: icaches030[i].valid[2] = 0;
! 1142: icaches030[i].valid[3] = 0;
! 1143: }
1.1.1.4 root 1144: }
1.1.1.7 ! root 1145: regs.cacr &= ~0x08;
1.1.1.4 root 1146: }
1147: if (regs.cacr & 0x04) { // clear entry in instr cache
1.1.1.7 ! root 1148: icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1.1.1.4 root 1149: regs.cacr &= ~0x04;
1150: }
1151: if (regs.cacr & 0x800) { // clear data cache
1.1.1.7 ! root 1152: if (doflush) {
! 1153: for (i = 0; i < CACHELINES030; i++) {
! 1154: dcaches030[i].valid[0] = 0;
! 1155: dcaches030[i].valid[1] = 0;
! 1156: dcaches030[i].valid[2] = 0;
! 1157: dcaches030[i].valid[3] = 0;
! 1158: }
1.1.1.4 root 1159: }
1160: regs.cacr &= ~0x800;
1161: }
1162: if (regs.cacr & 0x400) { // clear entry in data cache
1.1.1.7 ! root 1163: dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1.1.1.4 root 1164: regs.cacr &= ~0x400;
1165: }
1.1.1.7 ! root 1166: } else if (currprefs.cpu_model >= 68040) {
! 1167: icachelinecnt = 0;
! 1168: dcachelinecnt = 0;
! 1169: if (doflush) {
1.1.1.4 root 1170: for (i = 0; i < CACHESETS040; i++) {
1.1.1.7 ! root 1171: icaches040[i].valid[0] = 0;
! 1172: icaches040[i].valid[1] = 0;
! 1173: icaches040[i].valid[2] = 0;
! 1174: icaches040[i].valid[3] = 0;
1.1.1.4 root 1175: }
1176: }
1177: }
1178: }
1179:
1.1.1.7 ! root 1180: void flush_cpu_caches_040(uae_u16 opcode)
1.1.1.4 root 1181: {
1.1.1.7 ! root 1182: int cache = (opcode >> 6) & 3;
! 1183: if (!(cache & 2))
! 1184: return;
! 1185: flush_cpu_caches(true);
1.1.1.4 root 1186: }
1187:
1.1.1.7 ! root 1188: void set_cpu_caches (bool flush)
1.1.1.4 root 1189: {
1.1.1.7 ! root 1190: regs.prefetch020addr = 0xffffffff;
! 1191: regs.cacheholdingaddr020 = 0xffffffff;
1.1.1.4 root 1192:
1.1.1.7 ! root 1193: #ifdef JIT
! 1194: if (currprefs.cachesize) {
! 1195: if (currprefs.cpu_model < 68040) {
! 1196: set_cache_state (regs.cacr & 1);
! 1197: if (regs.cacr & 0x08) {
! 1198: flush_icache (0, 3);
! 1199: }
! 1200: } else {
! 1201: set_cache_state ((regs.cacr & 0x8000) ? 1 : 0);
! 1202: }
! 1203: }
! 1204: #endif
! 1205: flush_cpu_caches(flush);
! 1206: }
! 1207:
! 1208: STATIC_INLINE void count_instr (unsigned int opcode)
! 1209: {
! 1210: }
! 1211:
! 1212: static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode)
! 1213: {
! 1214: op_illg (opcode);
! 1215: return 4;
! 1216: }
! 1217: static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
! 1218: {
! 1219: if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060)
! 1220: op_illg (opcode);
! 1221: else
! 1222: op_unimpl (opcode);
! 1223: return 4;
! 1224: }
! 1225:
! 1226: // generic+direct, generic+indirect, more compatible, cycle-exact, mmu
! 1227: static const struct cputbl *cputbls[6][5] =
! 1228: {
! 1229: // 68000
! 1230: { op_smalltbl_5_ff, op_smalltbl_45_ff, op_smalltbl_12_ff, op_smalltbl_14_ff, NULL },
! 1231: // 68010
! 1232: { op_smalltbl_4_ff, op_smalltbl_44_ff, op_smalltbl_11_ff, op_smalltbl_13_ff, NULL },
! 1233: // 68020
! 1234: { op_smalltbl_3_ff, op_smalltbl_43_ff, op_smalltbl_20_ff, op_smalltbl_21_ff, NULL },
! 1235: // 68030
! 1236: { op_smalltbl_2_ff, op_smalltbl_42_ff, op_smalltbl_22_ff, op_smalltbl_23_ff, op_smalltbl_32_ff },
! 1237: // 68040
! 1238: { op_smalltbl_1_ff, op_smalltbl_41_ff, op_smalltbl_25_ff, op_smalltbl_25_ff, op_smalltbl_31_ff },
! 1239: // 68060
! 1240: { op_smalltbl_0_ff, op_smalltbl_40_ff, op_smalltbl_24_ff, op_smalltbl_24_ff, op_smalltbl_33_ff }
! 1241: };
! 1242:
! 1243: static void build_cpufunctbl (void)
1.1.1.4 root 1244: {
1245: int i, opcnt;
1246: unsigned long opcode;
1247: const struct cputbl *tbl = 0;
1.1.1.7 ! root 1248: int lvl, mode;
1.1.1.4 root 1249:
1.1.1.7 ! root 1250: if (!currprefs.cachesize) {
1.1.1.5 root 1251: if (currprefs.mmu_model)
1.1.1.7 ! root 1252: mode = 4;
! 1253: else if (currprefs.cpu_cycle_exact)
! 1254: mode = 3;
! 1255: else if (currprefs.cpu_compatible)
! 1256: mode = 2;
! 1257: else
! 1258: mode = 0;
! 1259: m68k_pc_indirect = mode != 0 ? 1 : 0;
! 1260: } else {
! 1261: mode = 0;
! 1262: m68k_pc_indirect = 0;
! 1263: if (currprefs.comptrustbyte) {
! 1264: mode = 1;
! 1265: m68k_pc_indirect = -1;
! 1266: }
1.1.1.4 root 1267: }
1.1.1.7 ! root 1268: lvl = (currprefs.cpu_model - 68000) / 10;
! 1269: if (lvl == 6)
! 1270: lvl = 5;
! 1271: tbl = cputbls[lvl][mode];
1.1.1.4 root 1272:
1.1.1.7 ! root 1273: if (tbl == NULL) {
! 1274: write_log (_T("no CPU emulation cores available CPU=%d!"), currprefs.cpu_model);
1.1.1.4 root 1275: abort ();
1276: }
1277:
1278: for (opcode = 0; opcode < 65536; opcode++)
1279: cpufunctbl[opcode] = op_illg_1;
1280: for (i = 0; tbl[i].handler != NULL; i++) {
1281: opcode = tbl[i].opcode;
1282: cpufunctbl[opcode] = tbl[i].handler;
1.1.1.7 ! root 1283: cpudatatbl[opcode].length = tbl[i].length;
! 1284: cpudatatbl[opcode].disp020[0] = tbl[i].disp020[0];
! 1285: cpudatatbl[opcode].disp020[1] = tbl[i].disp020[1];
! 1286: cpudatatbl[opcode].branch = tbl[i].branch;
1.1.1.4 root 1287: }
1288:
1289: /* hack fpu to 68000/68010 mode */
1290: if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
1291: tbl = op_smalltbl_3_ff;
1292: for (i = 0; tbl[i].handler != NULL; i++) {
1.1.1.7 ! root 1293: if ((tbl[i].opcode & 0xfe00) == 0xf200) {
1.1.1.4 root 1294: cpufunctbl[tbl[i].opcode] = tbl[i].handler;
1.1.1.7 ! root 1295: cpudatatbl[tbl[i].opcode].length = tbl[i].length;
! 1296: cpudatatbl[tbl[i].opcode].disp020[0] = tbl[i].disp020[0];
! 1297: cpudatatbl[tbl[i].opcode].disp020[1] = tbl[i].disp020[1];
! 1298: cpudatatbl[tbl[i].opcode].branch = tbl[i].branch;
! 1299: }
1.1.1.4 root 1300: }
1301: }
1.1.1.7 ! root 1302:
1.1.1.4 root 1303: opcnt = 0;
1304: for (opcode = 0; opcode < 65536; opcode++) {
1305: cpuop_func *f;
1.1.1.7 ! root 1306: struct instr *table = &table68k[opcode];
! 1307:
! 1308: if (table->mnemo == i_ILLG)
! 1309: continue;
! 1310:
! 1311: /* unimplemented opcode? */
! 1312: if (table->unimpclev > 0 && lvl >= table->unimpclev) {
! 1313: if (currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
! 1314: cpufunctbl[opcode] = op_unimpl_1;
! 1315: continue;
! 1316: } else {
! 1317: // emulate 68060 unimplemented instructions if int_no_unimplemented=false
! 1318: if (currprefs.cpu_model != 68060 && table->unimpclev != 5) {
! 1319: cpufunctbl[opcode] = op_illg_1;
! 1320: continue;
! 1321: }
! 1322: }
! 1323: }
1.1.1.4 root 1324:
1325: if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
1326: /* more hack fpu to 68000/68010 mode */
1.1.1.7 ! root 1327: if (table->clev > lvl && (opcode & 0xfe00) != 0xf200)
1.1.1.4 root 1328: continue;
1.1.1.7 ! root 1329: } else if (table->clev > lvl) {
1.1.1.4 root 1330: continue;
1331: }
1332:
1.1.1.7 ! root 1333: if (table->handler != -1) {
! 1334: int idx = table->handler;
1.1.1.4 root 1335: f = cpufunctbl[idx];
1336: if (f == op_illg_1)
1337: abort ();
1338: cpufunctbl[opcode] = f;
1.1.1.7 ! root 1339: memcpy(&cpudatatbl[opcode], &cpudatatbl[idx], sizeof(struct cputbl_data));
1.1.1.4 root 1340: opcnt++;
1341: }
1342: }
1.1.1.7 ! root 1343: write_log (_T("Building CPU, %d opcodes (%d %d %d)\n"),
1.1.1.4 root 1344: opcnt, lvl,
1345: currprefs.cpu_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0, currprefs.address_space_24);
1346: #ifdef JIT
1347: build_comp ();
1348: #endif
1.1.1.7 ! root 1349:
! 1350: write_log(_T("CPU=%d, FPU=%d, MMU=%d, JIT%s=%d."),
! 1351: currprefs.cpu_model, currprefs.fpu_model,
! 1352: currprefs.mmu_model,
! 1353: currprefs.cachesize ? (currprefs.compfpu ? _T("=CPU/FPU") : _T("=CPU")) : _T(""),
! 1354: currprefs.cachesize);
! 1355:
! 1356: regs.address_space_mask = 0xffffffff;
! 1357: #ifndef WINUAE_FOR_HATARI
! 1358: if (currprefs.cpu_compatible) {
! 1359: if (currprefs.address_space_24 && currprefs.cpu_model >= 68040)
! 1360: currprefs.address_space_24 = false;
! 1361: }
! 1362: #else
! 1363: /* Hatari : don't force address_space_24=0 for 68030, as the Falcon has a 68030 LC with only 24 bits */
! 1364: /* TODO ? Force address_space_24=0 for 68040 ? */
! 1365: #endif
! 1366: m68k_interrupt_delay = false;
! 1367: if (currprefs.cpu_cycle_exact) {
! 1368: if (tbl == op_smalltbl_14_ff || tbl == op_smalltbl_13_ff || tbl == op_smalltbl_21_ff || tbl == op_smalltbl_23_ff)
! 1369: m68k_interrupt_delay = true;
! 1370: }
! 1371:
! 1372: if (currprefs.cpu_cycle_exact) {
! 1373: if (currprefs.cpu_model == 68000)
! 1374: write_log(_T(" prefetch and cycle-exact"));
! 1375: else
! 1376: write_log(_T(" ~cycle-exact"));
! 1377: } else if (currprefs.cpu_compatible) {
! 1378: if (currprefs.cpu_model <= 68020) {
! 1379: write_log(_T(" prefetch"));
! 1380: } else {
! 1381: write_log(_T(" fake prefetch"));
1.1.1.5 root 1382: }
1.1.1.4 root 1383: }
1.1.1.7 ! root 1384: if (currprefs.m68k_speed < 0)
! 1385: write_log(_T(" fast"));
! 1386: if (currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
! 1387: write_log(_T(" no unimplemented integer instructions"));
! 1388: }
! 1389: if (currprefs.fpu_no_unimplemented && currprefs.fpu_model) {
! 1390: write_log(_T(" no unimplemented floating point instructions"));
! 1391: }
! 1392: if (currprefs.address_space_24) {
! 1393: regs.address_space_mask = 0x00ffffff;
! 1394: write_log(_T(" 24-bit"));
! 1395: }
! 1396: write_log(_T("\n"));
1.1.1.4 root 1397:
1.1.1.7 ! root 1398: set_cpu_caches (true);
1.1.1.4 root 1399: }
1400:
1.1.1.7 ! root 1401: #define CYCLES_DIV 8192
! 1402: static unsigned long cycles_mult;
1.1.1.4 root 1403:
1404: static void update_68k_cycles (void)
1405: {
1.1.1.7 ! root 1406: fprintf ( stderr , "update cyc speed %d throttle %f clock_mult %d\n", currprefs.m68k_speed, currprefs.m68k_speed_throttle, changed_prefs.cpu_clock_multiplier );
! 1407: cycles_mult = 0;
! 1408: #ifndef WINUAE_FOR_HATARI
! 1409: /* [NP] Don't adjust cycles_mult in Hatari and ignore m68k_speed (forced to 0) */
! 1410: if (currprefs.m68k_speed >= 0 && !currprefs.cpu_cycle_exact) {
! 1411: if (currprefs.m68k_speed_throttle < 0) {
! 1412: cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
! 1413: } else if (currprefs.m68k_speed_throttle > 0) {
! 1414: cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
! 1415: }
! 1416: }
! 1417: if (currprefs.m68k_speed == 0) {
! 1418: if (currprefs.cpu_model >= 68040) {
! 1419: if (!cycles_mult)
! 1420: cycles_mult = CYCLES_DIV / 8;
! 1421: else
! 1422: cycles_mult /= 8;
! 1423: } else if (currprefs.cpu_model >= 68020) {
! 1424: if (!cycles_mult)
! 1425: cycles_mult = CYCLES_DIV / 4;
! 1426: else
! 1427: cycles_mult /= 4;
! 1428: }
1.1.1.4 root 1429: }
1.1.1.7 ! root 1430: #endif
! 1431:
1.1.1.4 root 1432: currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier;
1433: currprefs.cpu_frequency = changed_prefs.cpu_frequency;
1434:
1.1.1.7 ! root 1435: #ifndef WINUAE_FOR_HATARI
! 1436: baseclock = (currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) * 8;
! 1437: #endif
1.1.1.4 root 1438: cpucycleunit = CYCLE_UNIT / 2;
1439: if (currprefs.cpu_clock_multiplier) {
1440: if (currprefs.cpu_clock_multiplier >= 256) {
1441: cpucycleunit = CYCLE_UNIT / (currprefs.cpu_clock_multiplier >> 8);
1442: } else {
1443: cpucycleunit = CYCLE_UNIT * currprefs.cpu_clock_multiplier;
1444: }
1.1.1.7 ! root 1445: if (currprefs.cpu_model >= 68040)
! 1446: cpucycleunit /= 2;
! 1447: #ifndef WINUAE_FOR_HATARI /* [NP] TODO : handle any cpu frequency, not just mulltiplier ? */
1.1.1.4 root 1448: } else if (currprefs.cpu_frequency) {
1449: cpucycleunit = CYCLE_UNIT * baseclock / currprefs.cpu_frequency;
1.1.1.7 ! root 1450: #endif
! 1451: } else if (currprefs.cpu_cycle_exact && currprefs.cpu_clock_multiplier == 0) {
! 1452: if (currprefs.cpu_model >= 68040) {
! 1453: cpucycleunit = CYCLE_UNIT / 16;
! 1454: } if (currprefs.cpu_model == 68030) {
! 1455: cpucycleunit = CYCLE_UNIT / 8;
! 1456: } else if (currprefs.cpu_model == 68020) {
! 1457: cpucycleunit = CYCLE_UNIT / 4;
! 1458: } else {
! 1459: cpucycleunit = CYCLE_UNIT / 2;
! 1460: }
1.1.1.4 root 1461: }
1462: if (cpucycleunit < 1)
1463: cpucycleunit = 1;
1464: if (currprefs.cpu_cycle_exact)
1.1.1.7 ! root 1465: write_log (_T("CPU cycleunit: %d (%.3f)\n"), cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
! 1466: write_log (_T("CPU cycleunit: %d (%.3f)\n"), cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
! 1467: #ifndef WINUAE_FOR_HATARI
! 1468: set_config_changed ();
! 1469: #endif
1.1.1.4 root 1470: }
1471:
1472: static void prefs_changed_cpu (void)
1473: {
1474: fixup_cpu (&changed_prefs);
1475: currprefs.cpu_model = changed_prefs.cpu_model;
1476: currprefs.fpu_model = changed_prefs.fpu_model;
1477: currprefs.mmu_model = changed_prefs.mmu_model;
1478: currprefs.cpu_compatible = changed_prefs.cpu_compatible;
1479: currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
1.1.1.7 ! root 1480: currprefs.int_no_unimplemented = changed_prefs.int_no_unimplemented;
! 1481: currprefs.fpu_no_unimplemented = changed_prefs.fpu_no_unimplemented;
! 1482: currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
1.1.1.4 root 1483: }
1484:
1.1.1.7 ! root 1485: static int check_prefs_changed_cpu2(void)
1.1.1.4 root 1486: {
1.1.1.7 ! root 1487: int changed = 0;
1.1.1.4 root 1488:
1489: #ifdef JIT
1.1.1.7 ! root 1490: changed = check_prefs_changed_comp() ? 1 : 0;
1.1.1.4 root 1491: #endif
1492: if (changed
1493: || currprefs.cpu_model != changed_prefs.cpu_model
1494: || currprefs.fpu_model != changed_prefs.fpu_model
1495: || currprefs.mmu_model != changed_prefs.mmu_model
1.1.1.7 ! root 1496: || currprefs.int_no_unimplemented != changed_prefs.int_no_unimplemented
! 1497: || currprefs.fpu_no_unimplemented != changed_prefs.fpu_no_unimplemented
1.1.1.4 root 1498: || currprefs.cpu_compatible != changed_prefs.cpu_compatible
1499: || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact) {
1.1.1.7 ! root 1500: cpu_prefs_changed_flag |= 1;
! 1501: #ifdef WINUAE_FOR_HATARI
! 1502: /* When changing CPU prefs in Hatari we reset the emulation, */
! 1503: /* so new cpu table should be built now, not in m68k_go() */
! 1504: // uaecptr pc = m68k_getpc();
! 1505: prefs_changed_cpu();
! 1506: build_cpufunctbl();
! 1507: // done in m68k_go :
! 1508: // m68k_setpc_normal(pc);
! 1509: // fill_prefetch();
! 1510: #endif
1.1.1.4 root 1511: }
1512: if (changed
1513: || currprefs.m68k_speed != changed_prefs.m68k_speed
1.1.1.7 ! root 1514: || currprefs.m68k_speed_throttle != changed_prefs.m68k_speed_throttle
1.1.1.4 root 1515: || currprefs.cpu_clock_multiplier != changed_prefs.cpu_clock_multiplier
1.1.1.7 ! root 1516: || currprefs.reset_delay != changed_prefs.reset_delay
1.1.1.4 root 1517: || currprefs.cpu_frequency != changed_prefs.cpu_frequency) {
1.1.1.7 ! root 1518: cpu_prefs_changed_flag |= 2;
1.1.1.4 root 1519: }
1.1.1.7 ! root 1520: return cpu_prefs_changed_flag;
! 1521: }
1.1.1.4 root 1522:
1.1.1.7 ! root 1523: void check_prefs_changed_cpu(void)
! 1524: {
! 1525: #ifndef WINUAE_FOR_HATARI
! 1526: return; /* [NP] TODO : handle cpu change on the fly ? */
! 1527: if (!config_changed)
! 1528: return;
! 1529: #else
1.1.1.4 root 1530:
1.1.1.7 ! root 1531: currprefs.cpu_idle = changed_prefs.cpu_idle;
! 1532: currprefs.ppc_cpu_idle = changed_prefs.ppc_cpu_idle;
! 1533: currprefs.reset_delay = changed_prefs.reset_delay;
! 1534:
! 1535: if (check_prefs_changed_cpu2()) {
! 1536: set_special(SPCFLAG_MODE_CHANGE);
! 1537: reset_frame_rate_hack();
! 1538: }
! 1539: #endif
1.1.1.4 root 1540: }
1541:
1542: void init_m68k (void)
1543: {
1544: int i;
1545:
1546: prefs_changed_cpu ();
1547: update_68k_cycles ();
1548:
1549: for (i = 0 ; i < 256 ; i++) {
1550: int j;
1551: for (j = 0 ; j < 8 ; j++) {
1552: if (i & (1 << j)) break;
1553: }
1554: movem_index1[i] = j;
1.1.1.7 ! root 1555: movem_index2[i] = 7 - j;
1.1.1.4 root 1556: movem_next[i] = i & (~(1 << j));
1557: }
1558:
1559: #if COUNT_INSTRS
1560: {
1561: FILE *f = fopen (icountfilename (), "r");
1562: memset (instrcount, 0, sizeof instrcount);
1563: if (f) {
1564: uae_u32 opcode, count, total;
1565: TCHAR name[20];
1.1.1.7 ! root 1566: write_log (_T("Reading instruction count file...\n"));
1.1.1.4 root 1567: fscanf (f, "Total: %lu\n", &total);
1.1.1.7 ! root 1568: while (fscanf (f, "%x: %lu %s\n", &opcode, &count, name) == 3) {
1.1.1.4 root 1569: instrcount[opcode] = count;
1570: }
1571: fclose (f);
1572: }
1573: }
1574: #endif
1575:
1576: read_table68k ();
1577: do_merges ();
1578:
1.1.1.7 ! root 1579: write_log (_T("%d CPU functions\n"), nr_cpuop_funcs);
1.1.1.4 root 1580:
1581: build_cpufunctbl ();
1582: set_x_funcs ();
1583:
1584: #ifdef JIT
1585: /* We need to check whether NATMEM settings have changed
1586: * before starting the CPU */
1587: check_prefs_changed_comp ();
1588: #endif
1589: }
1590:
1591: struct regstruct regs, mmu_backup_regs;
1592: struct flag_struct regflags;
1.1.1.7 ! root 1593: static int m68kpc_offset;
1.1.1.4 root 1594:
1.1.1.7 ! root 1595: #if 0
1.1.1.4 root 1596: #define get_ibyte_1(o) get_byte (regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
1597: #define get_iword_1(o) get_word (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
1598: #define get_ilong_1(o) get_long (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
1.1.1.7 ! root 1599: #endif
1.1.1.4 root 1600:
1.1.1.7 ! root 1601: static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
1.1.1.4 root 1602: {
1603: uae_u16 dp;
1604: uae_s8 disp8;
1605: uae_s16 disp16;
1606: int r;
1607: uae_u32 dispreg;
1.1.1.7 ! root 1608: uaecptr addr = pc;
1.1.1.4 root 1609: uae_s32 offset = 0;
1610: TCHAR buffer[80];
1611:
1612: switch (mode){
1613: case Dreg:
1.1.1.7 ! root 1614: _stprintf (buffer, _T("D%d"), reg);
1.1.1.4 root 1615: break;
1616: case Areg:
1.1.1.7 ! root 1617: _stprintf (buffer, _T("A%d"), reg);
1.1.1.4 root 1618: break;
1619: case Aind:
1.1.1.7 ! root 1620: _stprintf (buffer, _T("(A%d)"), reg);
1.1.1.4 root 1621: addr = regs.regs[reg + 8];
1622: break;
1623: case Aipi:
1.1.1.7 ! root 1624: _stprintf (buffer, _T("(A%d)+"), reg);
1.1.1.4 root 1625: addr = regs.regs[reg + 8];
1626: break;
1627: case Apdi:
1.1.1.7 ! root 1628: _stprintf (buffer, _T("-(A%d)"), reg);
1.1.1.4 root 1629: addr = regs.regs[reg + 8];
1630: break;
1631: case Ad16:
1632: {
1633: TCHAR offtxt[80];
1.1.1.7 ! root 1634: disp16 = get_iword_debug (pc); pc += 2;
1.1.1.4 root 1635: if (disp16 < 0)
1.1.1.7 ! root 1636: _stprintf (offtxt, _T("-$%04x"), -disp16);
1.1.1.4 root 1637: else
1.1.1.7 ! root 1638: _stprintf (offtxt, _T("$%04x"), disp16);
1.1.1.4 root 1639: addr = m68k_areg (regs, reg) + disp16;
1.1.1.7 ! root 1640: _stprintf (buffer, _T("(A%d, %s) == $%08x"), reg, offtxt, addr);
1.1.1.4 root 1641: }
1642: break;
1643: case Ad8r:
1.1.1.7 ! root 1644: dp = get_iword_debug (pc); pc += 2;
1.1.1.4 root 1645: disp8 = dp & 0xFF;
1646: r = (dp & 0x7000) >> 12;
1647: dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
1648: if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1649: dispreg <<= (dp >> 9) & 3;
1650:
1651: if (dp & 0x100) {
1652: uae_s32 outer = 0, disp = 0;
1653: uae_s32 base = m68k_areg (regs, reg);
1654: TCHAR name[10];
1.1.1.7 ! root 1655: _stprintf (name, _T("A%d, "), reg);
1.1.1.4 root 1656: if (dp & 0x80) { base = 0; name[0] = 0; }
1657: if (dp & 0x40) dispreg = 0;
1.1.1.7 ! root 1658: if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
! 1659: if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
1.1.1.4 root 1660: base += disp;
1661:
1.1.1.7 ! root 1662: if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
! 1663: if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
1.1.1.4 root 1664:
1665: if (!(dp & 4)) base += dispreg;
1.1.1.7 ! root 1666: if ((dp & 3) && !safemode) base = get_ilong_debug (base);
1.1.1.4 root 1667: if (dp & 4) base += dispreg;
1668:
1669: addr = base + outer;
1.1.1.7 ! root 1670: _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
1.1.1.4 root 1671: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1672: 1 << ((dp >> 9) & 3),
1.1.1.7 ! root 1673: disp, outer, addr);
1.1.1.4 root 1674: } else {
1675: addr = m68k_areg (regs, reg) + (uae_s32)((uae_s8)disp8) + dispreg;
1.1.1.7 ! root 1676: _stprintf (buffer, _T("(A%d, %c%d.%c*%d, $%02x) == $%08x"), reg,
1.1.1.4 root 1677: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1.1.1.7 ! root 1678: 1 << ((dp >> 9) & 3), disp8, addr);
1.1.1.4 root 1679: }
1680: break;
1681: case PC16:
1.1.1.7 ! root 1682: disp16 = get_iword_debug (pc); pc += 2;
1.1.1.4 root 1683: addr += (uae_s16)disp16;
1.1.1.7 ! root 1684: _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr);
1.1.1.4 root 1685: break;
1686: case PC8r:
1.1.1.7 ! root 1687: dp = get_iword_debug (pc); pc += 2;
1.1.1.4 root 1688: disp8 = dp & 0xFF;
1689: r = (dp & 0x7000) >> 12;
1690: dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
1691: if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1692: dispreg <<= (dp >> 9) & 3;
1693:
1694: if (dp & 0x100) {
1695: uae_s32 outer = 0, disp = 0;
1696: uae_s32 base = addr;
1697: TCHAR name[10];
1.1.1.7 ! root 1698: _stprintf (name, _T("PC, "));
1.1.1.4 root 1699: if (dp & 0x80) { base = 0; name[0] = 0; }
1700: if (dp & 0x40) dispreg = 0;
1.1.1.7 ! root 1701: if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
! 1702: if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
1.1.1.4 root 1703: base += disp;
1704:
1.1.1.7 ! root 1705: if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
! 1706: if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
1.1.1.4 root 1707:
1708: if (!(dp & 4)) base += dispreg;
1.1.1.7 ! root 1709: if ((dp & 3) && !safemode) base = get_ilong_debug (base);
1.1.1.4 root 1710: if (dp & 4) base += dispreg;
1711:
1712: addr = base + outer;
1.1.1.7 ! root 1713: _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
1.1.1.4 root 1714: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1715: 1 << ((dp >> 9) & 3),
1.1.1.7 ! root 1716: disp, outer, addr);
1.1.1.4 root 1717: } else {
1718: addr += (uae_s32)((uae_s8)disp8) + dispreg;
1.1.1.7 ! root 1719: _stprintf (buffer, _T("(PC, %c%d.%c*%d, $%02x) == $%08x"), dp & 0x8000 ? 'A' : 'D',
1.1.1.4 root 1720: (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3),
1.1.1.7 ! root 1721: disp8, addr);
1.1.1.4 root 1722: }
1723: break;
1724: case absw:
1.1.1.7 ! root 1725: addr = (uae_s32)(uae_s16)get_iword_debug (pc);
! 1726: _stprintf (buffer, _T("$%08x"), addr);
! 1727: pc += 2;
1.1.1.4 root 1728: break;
1729: case absl:
1.1.1.7 ! root 1730: addr = get_ilong_debug (pc);
! 1731: _stprintf (buffer, _T("$%08x"), addr);
! 1732: pc += 4;
1.1.1.4 root 1733: break;
1734: case imm:
1735: switch (size){
1736: case sz_byte:
1.1.1.7 ! root 1737: _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff));
! 1738: pc += 2;
1.1.1.4 root 1739: break;
1740: case sz_word:
1.1.1.7 ! root 1741: _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff));
! 1742: pc += 2;
1.1.1.4 root 1743: break;
1744: case sz_long:
1.1.1.7 ! root 1745: _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc)));
! 1746: pc += 4;
! 1747: break;
! 1748: case sz_single:
! 1749: {
! 1750: fpdata fp;
! 1751: to_single(&fp, get_ilong_debug(pc));
! 1752: _stprintf(buffer, _T("#%e"), fp.fp);
! 1753: pc += 4;
! 1754: }
! 1755: break;
! 1756: case sz_double:
! 1757: {
! 1758: fpdata fp;
! 1759: to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
! 1760: _stprintf(buffer, _T("#%e"), fp.fp);
! 1761: pc += 8;
! 1762: }
! 1763: break;
! 1764: case sz_extended:
! 1765: {
! 1766: fpdata fp;
! 1767: to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
! 1768: #if USE_LONG_DOUBLE
! 1769: _stprintf(buffer, _T("#%Le"), fp.fp);
! 1770: #else
! 1771: _stprintf(buffer, _T("#%e"), fp.fp);
! 1772: #endif
! 1773: pc += 12;
! 1774: break;
! 1775: }
! 1776: case sz_packed:
! 1777: _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
! 1778: pc += 12;
1.1.1.4 root 1779: break;
1780: default:
1781: break;
1782: }
1783: break;
1784: case imm0:
1.1.1.7 ! root 1785: offset = (uae_s32)(uae_s8)get_iword_debug (pc);
! 1786: _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff));
! 1787: addr = pc + 2 + offset;
! 1788: pc += 2;
1.1.1.4 root 1789: break;
1790: case imm1:
1.1.1.7 ! root 1791: offset = (uae_s32)(uae_s16)get_iword_debug (pc);
1.1.1.4 root 1792: buffer[0] = 0;
1.1.1.7 ! root 1793: _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff));
! 1794: addr = pc + offset;
! 1795: pc += 2;
1.1.1.4 root 1796: break;
1797: case imm2:
1.1.1.7 ! root 1798: offset = (uae_s32)get_ilong_debug (pc);
! 1799: _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
! 1800: addr = pc + offset;
! 1801: pc += 4;
1.1.1.4 root 1802: break;
1803: case immi:
1804: offset = (uae_s32)(uae_s8)(reg & 0xff);
1.1.1.7 ! root 1805: _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
! 1806: addr = pc + offset;
1.1.1.4 root 1807: break;
1808: default:
1809: break;
1810: }
1811: if (buf == 0)
1.1.1.7 ! root 1812: f_out (f, _T("%s"), buffer);
1.1.1.4 root 1813: else
1814: _tcscat (buf, buffer);
1815: if (eaddr)
1816: *eaddr = addr;
1.1.1.7 ! root 1817: return pc;
1.1.1.4 root 1818: }
1819:
1820: #if 0
1821: /* The plan is that this will take over the job of exception 3 handling -
1822: * the CPU emulation functions will just do a longjmp to m68k_go whenever
1823: * they hit an odd address. */
1824: static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
1825: {
1826: uae_u16 dp;
1827: uae_s8 disp8;
1828: uae_s16 disp16;
1829: int r;
1830: uae_u32 dispreg;
1831: uaecptr addr;
1832: uae_s32 offset = 0;
1833:
1834: switch (mode){
1835: case Dreg:
1836: *val = m68k_dreg (regs, reg);
1837: return 1;
1838: case Areg:
1839: *val = m68k_areg (regs, reg);
1840: return 1;
1841:
1842: case Aind:
1843: case Aipi:
1844: addr = m68k_areg (regs, reg);
1845: break;
1846: case Apdi:
1847: addr = m68k_areg (regs, reg);
1848: break;
1849: case Ad16:
1850: disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1851: addr = m68k_areg (regs, reg) + (uae_s16)disp16;
1852: break;
1853: case Ad8r:
1854: addr = m68k_areg (regs, reg);
1855: d8r_common:
1856: dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1857: disp8 = dp & 0xFF;
1858: r = (dp & 0x7000) >> 12;
1859: dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
1860: if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1861: dispreg <<= (dp >> 9) & 3;
1862:
1863: if (dp & 0x100) {
1864: uae_s32 outer = 0, disp = 0;
1865: uae_s32 base = addr;
1866: if (dp & 0x80) base = 0;
1867: if (dp & 0x40) dispreg = 0;
1868: if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
1869: if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1870: base += disp;
1871:
1872: if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
1873: if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1874:
1875: if (!(dp & 4)) base += dispreg;
1876: if (dp & 3) base = get_long (base);
1877: if (dp & 4) base += dispreg;
1878:
1879: addr = base + outer;
1880: } else {
1881: addr += (uae_s32)((uae_s8)disp8) + dispreg;
1882: }
1883: break;
1884: case PC16:
1885: addr = m68k_getpc () + m68kpc_offset;
1886: disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1887: addr += (uae_s16)disp16;
1888: break;
1889: case PC8r:
1890: addr = m68k_getpc () + m68kpc_offset;
1891: goto d8r_common;
1892: case absw:
1893: addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
1894: m68kpc_offset += 2;
1895: break;
1896: case absl:
1897: addr = get_ilong_1 (m68kpc_offset);
1898: m68kpc_offset += 4;
1899: break;
1900: case imm:
1901: switch (size){
1902: case sz_byte:
1903: *val = get_iword_1 (m68kpc_offset) & 0xff;
1904: m68kpc_offset += 2;
1905: break;
1906: case sz_word:
1907: *val = get_iword_1 (m68kpc_offset) & 0xffff;
1908: m68kpc_offset += 2;
1909: break;
1910: case sz_long:
1911: *val = get_ilong_1 (m68kpc_offset);
1912: m68kpc_offset += 4;
1913: break;
1914: default:
1915: break;
1916: }
1917: return 1;
1918: case imm0:
1919: *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
1920: m68kpc_offset += 2;
1921: return 1;
1922: case imm1:
1923: *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
1924: m68kpc_offset += 2;
1925: return 1;
1926: case imm2:
1927: *val = get_ilong_1 (m68kpc_offset);
1928: m68kpc_offset += 4;
1929: return 1;
1930: case immi:
1931: *val = (uae_s32)(uae_s8)(reg & 0xff);
1932: return 1;
1933: default:
1934: addr = 0;
1935: break;
1936: }
1937: if ((addr & 1) == 0)
1938: return 1;
1939:
1940: last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
1941: last_fault_for_exception_3 = addr;
1942: last_writeaccess_for_exception_3 = 0;
1943: last_instructionaccess_for_exception_3 = 0;
1944: return 0;
1945: }
1946: #endif
1947:
1948: int get_cpu_model (void)
1949: {
1950: return currprefs.cpu_model;
1951: }
1952:
1.1.1.7 ! root 1953: #ifndef WINUAE_FOR_HATARI
! 1954: STATIC_INLINE int in_rom (uaecptr pc)
1.1.1.4 root 1955: {
1.1.1.7 ! root 1956: return (munge24 (pc) & 0xFFF80000) == 0xF80000;
1.1.1.4 root 1957: }
1958:
1.1.1.7 ! root 1959: STATIC_INLINE int in_rtarea (uaecptr pc)
1.1.1.4 root 1960: {
1.1.1.7 ! root 1961: return (munge24 (pc) & 0xFFFF0000) == rtarea_base && uae_boot_rom_type;
1.1.1.4 root 1962: }
1.1.1.7 ! root 1963: #endif
1.1.1.4 root 1964:
1.1.1.7 ! root 1965: STATIC_INLINE void wait_memory_cycles (void)
1.1.1.4 root 1966: {
1.1.1.7 ! root 1967: if (regs.memory_waitstate_cycles) {
! 1968: x_do_cycles(regs.memory_waitstate_cycles);
! 1969: regs.memory_waitstate_cycles = 0;
1.1.1.4 root 1970: }
1.1.1.7 ! root 1971: if (regs.ce020extracycles >= 16) {
! 1972: regs.ce020extracycles = 0;
! 1973: x_do_cycles(4 * CYCLE_UNIT);
1.1.1.4 root 1974: }
1975: }
1976:
1.1.1.7 ! root 1977: STATIC_INLINE int adjust_cycles (int cycles)
1.1.1.4 root 1978: {
1.1.1.7 ! root 1979: int mc = regs.memory_waitstate_cycles;
! 1980: regs.memory_waitstate_cycles = 0;
! 1981: if (currprefs.m68k_speed < 0 || cycles_mult == 0)
! 1982: return cycles + mc;
! 1983: cycles *= cycles_mult;
! 1984: cycles /= CYCLES_DIV;
! 1985: return cycles + mc;
1.1.1.4 root 1986: }
1987:
1988: void REGPARAM2 MakeSR (void)
1989: {
1990: regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
1991: | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
1992: | (GET_XFLG () << 4) | (GET_NFLG () << 3)
1993: | (GET_ZFLG () << 2) | (GET_VFLG () << 1)
1994: | GET_CFLG ());
1995: }
1996:
1.1.1.7 ! root 1997: void SetSR (uae_u16 sr)
1.1.1.4 root 1998: {
1.1.1.7 ! root 1999: regs.sr &= 0xff00;
! 2000: regs.sr |= sr;
1.1.1.4 root 2001:
2002: SET_XFLG ((regs.sr >> 4) & 1);
2003: SET_NFLG ((regs.sr >> 3) & 1);
2004: SET_ZFLG ((regs.sr >> 2) & 1);
2005: SET_VFLG ((regs.sr >> 1) & 1);
2006: SET_CFLG (regs.sr & 1);
1.1.1.7 ! root 2007: }
! 2008:
! 2009: void REGPARAM2 MakeFromSR (void)
! 2010: {
! 2011: int oldm = regs.m;
! 2012: int olds = regs.s;
! 2013:
! 2014: SET_XFLG ((regs.sr >> 4) & 1);
! 2015: SET_NFLG ((regs.sr >> 3) & 1);
! 2016: SET_ZFLG ((regs.sr >> 2) & 1);
! 2017: SET_VFLG ((regs.sr >> 1) & 1);
! 2018: SET_CFLG (regs.sr & 1);
! 2019: if (regs.t1 == ((regs.sr >> 15) & 1) &&
! 2020: regs.t0 == ((regs.sr >> 14) & 1) &&
! 2021: regs.s == ((regs.sr >> 13) & 1) &&
1.1.1.4 root 2022: regs.m == ((regs.sr >> 12) & 1) &&
2023: regs.intmask == ((regs.sr >> 8) & 7))
2024: return;
2025: regs.t1 = (regs.sr >> 15) & 1;
2026: regs.t0 = (regs.sr >> 14) & 1;
2027: regs.s = (regs.sr >> 13) & 1;
2028: regs.m = (regs.sr >> 12) & 1;
2029: regs.intmask = (regs.sr >> 8) & 7;
2030: if (currprefs.cpu_model >= 68020) {
2031: /* 68060 does not have MSP but does have M-bit.. */
2032: if (currprefs.cpu_model >= 68060)
2033: regs.msp = regs.isp;
2034: if (olds != regs.s) {
2035: if (olds) {
2036: if (oldm)
2037: regs.msp = m68k_areg (regs, 7);
2038: else
2039: regs.isp = m68k_areg (regs, 7);
2040: m68k_areg (regs, 7) = regs.usp;
2041: } else {
2042: regs.usp = m68k_areg (regs, 7);
2043: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
2044: }
2045: } else if (olds && oldm != regs.m) {
2046: if (oldm) {
2047: regs.msp = m68k_areg (regs, 7);
2048: m68k_areg (regs, 7) = regs.isp;
2049: } else {
2050: regs.isp = m68k_areg (regs, 7);
2051: m68k_areg (regs, 7) = regs.msp;
2052: }
2053: }
2054: if (currprefs.cpu_model >= 68060)
2055: regs.t0 = 0;
2056: } else {
2057: regs.t0 = regs.m = 0;
2058: if (olds != regs.s) {
2059: if (olds) {
2060: regs.isp = m68k_areg (regs, 7);
2061: m68k_areg (regs, 7) = regs.usp;
2062: } else {
2063: regs.usp = m68k_areg (regs, 7);
2064: m68k_areg (regs, 7) = regs.isp;
2065: }
2066: }
2067: }
2068: if (currprefs.mmu_model)
2069: mmu_set_super (regs.s != 0);
2070:
2071: doint ();
2072: if (regs.t1 || regs.t0)
2073: set_special (SPCFLAG_TRACE);
2074: else
2075: /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
2076: SR-modifying instructions (including STOP). */
2077: unset_special (SPCFLAG_TRACE);
2078: }
2079:
2080: static void exception_trace (int nr)
2081: {
2082: unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
2083: if (regs.t1 && !regs.t0) {
2084: /* trace stays pending if exception is div by zero, chk,
2085: * trapv or trap #x
2086: */
2087: if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
2088: set_special (SPCFLAG_DOTRACE);
2089: }
2090: regs.t1 = regs.t0 = regs.m = 0;
2091: }
2092:
2093: static void exception_debug (int nr)
2094: {
2095: #ifdef DEBUGGER
2096: if (!exception_debugging)
2097: return;
1.1.1.7 ! root 2098: console_out_f (_T("Exception %d, PC=%08X\n"), nr, M68K_GETPC);
1.1.1.4 root 2099: #endif
1.1.1.7 ! root 2100: #ifdef WINUAE_FOR_HATARI
1.1.1.6 root 2101: DebugUI_Exceptions(nr, M68K_GETPC);
1.1.1.7 ! root 2102: #endif
1.1.1.4 root 2103: }
2104:
1.1.1.7 ! root 2105: #ifdef CPUEMU_13
1.1.1.4 root 2106:
2107: /* cycle-exact exception handler, 68000 only */
2108:
2109: /*
2110:
2111: Address/Bus Error:
2112:
1.1.1.7 ! root 2113: - 8 idle cycles
1.1.1.4 root 2114: - write PC low word
2115: - write SR
2116: - write PC high word
2117: - write instruction word
2118: - write fault address low word
2119: - write status code
2120: - write fault address high word
2121: - 2 idle cycles
2122: - read exception address high word
2123: - read exception address low word
2124: - prefetch
2125: - 2 idle cycles
2126: - prefetch
2127:
2128: Division by Zero:
2129:
1.1.1.7 ! root 2130: - 8 idle cycles
1.1.1.4 root 2131: - write PC low word
2132: - write SR
2133: - write PC high word
2134: - read exception address high word
2135: - read exception address low word
2136: - prefetch
2137: - 2 idle cycles
2138: - prefetch
2139:
2140: Traps:
2141:
1.1.1.7 ! root 2142: - 4 idle cycles
1.1.1.4 root 2143: - write PC low word
2144: - write SR
2145: - write PC high word
2146: - read exception address high word
2147: - read exception address low word
2148: - prefetch
2149: - 2 idle cycles
2150: - prefetch
2151:
2152: TrapV:
2153:
1.1.1.7 ! root 2154: (- normal prefetch done by TRAPV)
1.1.1.4 root 2155: - write PC low word
2156: - write SR
2157: - write PC high word
2158: - read exception address high word
2159: - read exception address low word
2160: - prefetch
2161: - 2 idle cycles
2162: - prefetch
2163:
2164: CHK:
2165:
1.1.1.7 ! root 2166: - 8 idle cycles
1.1.1.4 root 2167: - write PC low word
2168: - write SR
2169: - write PC high word
2170: - read exception address high word
2171: - read exception address low word
2172: - prefetch
2173: - 2 idle cycles
2174: - prefetch
2175:
2176: Illegal Instruction:
1.1.1.7 ! root 2177: Privilege violation:
! 2178: Line A:
! 2179: Line F:
1.1.1.4 root 2180:
1.1.1.7 ! root 2181: - 4 idle cycles
1.1.1.4 root 2182: - write PC low word
2183: - write SR
2184: - write PC high word
2185: - read exception address high word
2186: - read exception address low word
2187: - prefetch
2188: - 2 idle cycles
2189: - prefetch
2190:
1.1.1.7 ! root 2191: Interrupt:
1.1.1.4 root 2192:
2193: - 6 idle cycles
2194: - write PC low word
2195: - read exception number byte from (0xfffff1 | (interrupt number << 1))
2196: - 4 idle cycles
2197: - write SR
2198: - write PC high word
2199: - read exception address high word
2200: - read exception address low word
2201: - prefetch
2202: - 2 idle cycles
2203: - prefetch
2204:
2205: */
2206:
1.1.1.7 ! root 2207: static int iack_cycle(int nr)
! 2208: {
! 2209: int vector;
! 2210:
! 2211: #ifndef WINUAE_FOR_HATARI
! 2212: if (1) {
! 2213: // non-autovectored
! 2214: vector = x_get_byte(0x00fffff1 | ((nr - 24) << 1));
! 2215: if (currprefs.cpu_cycle_exact)
! 2216: x_do_cycles(4 * cpucycleunit);
! 2217: } else {
! 2218: // autovectored
! 2219:
! 2220: }
! 2221: #else
! 2222: int iack_start = CPU_IACK_CYCLES_START;
! 2223: int e_cycles;
! 2224:
! 2225: /* In cycle exact mode, the cycles before reaching IACK are already counted */
! 2226: if ( currprefs.cpu_cycle_exact )
! 2227: iack_start = 0;
! 2228:
! 2229: /* Pending bits / vector number can change before the end of the IACK sequence. */
! 2230: /* We need to handle MFP/DSP and HBL/VBL cases for this. */
! 2231: /* - Level 6 (MFP/DSP) use vectored interrupts */
! 2232: /* - Level 2 (HBL) and 4 (VBL) use auto-vectored interrupts and require sync with E-clock */
! 2233: vector = nr;
! 2234: if ( nr == 30 ) /* MFP or DSP */
! 2235: {
! 2236: vector = -1;
! 2237: if (bDspEnabled) /* Check DSP first */
! 2238: {
! 2239: /* TODO : For DSP, we just get the vector, we don't add IACK cycles */
! 2240: vector = DSP_ProcessIACK ();
! 2241: }
! 2242:
! 2243: if ( vector < 0 ) /* No DSP, check MFP */
! 2244: {
! 2245: M68000_AddCycles ( iack_start + CPU_IACK_CYCLES_MFP );
! 2246: // TODO : add CE cycles too
! 2247: CPU_IACK = true;
! 2248: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
! 2249: CALL_VAR(PendingInterruptFunction);
! 2250: vector = MFP_ProcessIACK ( nr );
! 2251: CPU_IACK = false;
! 2252: }
! 2253: }
! 2254: else if ( ( nr == 26 ) || ( nr == 28 ) ) /* HBL / VBL */
! 2255: {
! 2256: iack_start -= 2; /* [NP] work in progress for e clock, TODO we need to check the complete sequence of interrupt micro code */
! 2257: e_cycles = M68000_WaitEClock ();
! 2258: //fprintf ( stderr , "wait e clock %d\n" , e_cycles);
! 2259:
! 2260: M68000_AddCycles ( iack_start + CPU_IACK_CYCLES_VIDEO + e_cycles );
! 2261: // TODO : add CE cycles too
! 2262: CPU_IACK = true;
! 2263: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
! 2264: CALL_VAR(PendingInterruptFunction);
! 2265: if ( MFP_UpdateNeeded == true )
! 2266: MFP_UpdateIRQ ( 0 ); /* update MFP's state if some internal timers related to MFP expired */
! 2267: pendingInterrupts &= ~( 1 << ( nr - 24 ) ); /* clear HBL or VBL pending bit */
! 2268: CPU_IACK = false;
! 2269: }
! 2270:
! 2271: /* TODO If there was no DSP and no MFP IRQ, then we have a spurious interrupt */
! 2272: /* In that case, we use vector 24 and we jump to $60 */
! 2273: if ( vector < 0 )
! 2274: {
! 2275: }
! 2276: #endif
! 2277: return vector;
! 2278: }
! 2279:
! 2280: static void Exception_ce000 (int nr)
1.1.1.4 root 2281: {
2282: uae_u32 currpc = m68k_getpc (), newpc;
2283: int sv = regs.s;
1.1.1.7 ! root 2284: int start, interrupt;
! 2285: int vector_nr = nr;
1.1.1.4 root 2286:
1.1.1.7 ! root 2287: //fprintf ( stderr , "ex in %d %ld\n" , nr , currcycle );
! 2288: currcycle=0;
! 2289: start = 6;
! 2290: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 2291: interrupt = nr >= 24 && nr < 24 + 8;
1.1.1.7 ! root 2292: #else
! 2293: if ( nr >= 24 && nr < 24 + 8 )
! 2294: interrupt = 1;
1.1.1.4 root 2295: #endif
1.1.1.7 ! root 2296: if (!interrupt) {
! 2297: start = 8;
! 2298: if (nr == 7) // TRAPV
! 2299: start = 0;
! 2300: else if (nr >= 32 && nr < 32 + 16) // TRAP #x
! 2301: start = 4;
! 2302: else if (nr == 4 || nr == 8 || nr == 10 || nr == 11) // ILLG, PRIV, LINEA, LINEF
! 2303: start = 4;
! 2304: }
1.1.1.4 root 2305:
2306: if (start)
1.1.1.7 ! root 2307: x_do_cycles (start * cpucycleunit);
1.1.1.4 root 2308:
1.1.1.7 ! root 2309: #ifdef WINUAE_FOR_HATARI
! 2310: LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x SR %x\n",
! 2311: nr, currpc, regs.instruction_pc, STMemory_ReadLong (regs.vbr + 4*nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3, regs.sr);
! 2312: #endif
1.1.1.4 root 2313: exception_debug (nr);
2314: MakeSR ();
2315:
1.1.1.7 ! root 2316: #ifdef WINUAE_FOR_HATARI
1.1.1.4 root 2317: /* Handle Hatari GEM and BIOS traps */
1.1.1.6 root 2318: if (nr == 0x22) {
1.1.1.4 root 2319: /* Intercept VDI & AES exceptions (Trap #2) */
1.1.1.6 root 2320: if (bVdiAesIntercept && VDI_AES_Entry()) {
1.1.1.4 root 2321: /* Set 'PC' to address of 'VDI_OPCODE' illegal instruction.
1.1.1.7 ! root 2322: * This will call OpCode_VDI() after completion of Trap call!
! 2323: * This is used to modify specific VDI return vectors contents.
1.1.1.4 root 2324: */
2325: VDI_OldPC = currpc;
2326: currpc = CART_VDI_OPCODE_ADDR;
2327: }
2328: }
1.1.1.6 root 2329: else if (nr == 0x2d) {
2330: /* Intercept BIOS (Trap #13) calls */
2331: if (Bios()) return;
2332: }
2333: else if (nr == 0x2e) {
2334: /* Intercept XBIOS (Trap #14) calls */
2335: if (XBios()) return;
1.1.1.4 root 2336: }
1.1.1.7 ! root 2337: #endif
1.1.1.4 root 2338:
2339: if (!regs.s) {
2340: regs.usp = m68k_areg (regs, 7);
2341: m68k_areg (regs, 7) = regs.isp;
2342: regs.s = 1;
2343: }
2344: if (nr == 2 || nr == 3) { /* 2=bus error, 3=address error */
1.1.1.7 ! root 2345: if ((m68k_areg(regs, 7) & 1) || exception_in_exception < 0) {
! 2346: cpu_halt (2);
! 2347: return;
! 2348: }
1.1.1.4 root 2349: uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
2350: mode |= last_writeaccess_for_exception_3 ? 0 : 16;
1.1.1.7 ! root 2351: mode |= last_notinstruction_for_exception_3 ? 8 : 0;
! 2352: // undocumented bits seem to contain opcode
! 2353: mode |= last_op_for_exception_3 & ~31;
1.1.1.4 root 2354: m68k_areg (regs, 7) -= 14;
1.1.1.7 ! root 2355: exception_in_exception = -1;
! 2356: x_put_word (m68k_areg (regs, 7) + 12, last_addr_for_exception_3);
! 2357: x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
! 2358: x_put_word (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16);
! 2359: x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
! 2360: x_put_word (m68k_areg (regs, 7) + 4, last_fault_for_exception_3);
! 2361: x_put_word (m68k_areg (regs, 7) + 0, mode);
! 2362: x_put_word (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16);
! 2363: x_do_cycles (2 * cpucycleunit);
! 2364: write_log (_T("Exception %d (%04x %x) at %x -> %x!\n"),
! 2365: nr, last_op_for_exception_3, last_addr_for_exception_3, currpc, get_long_debug (4 * nr));
! 2366: #ifdef WINUAE_FOR_HATARI
! 2367: fprintf(stderr,"%s Error at address $%x, PC=$%x addr_e3=%x op_e3=%x\n", nr==2?"Bus":"Address", last_fault_for_exception_3, currpc, last_addr_for_exception_3 , last_op_for_exception_3);
! 2368: #endif
1.1.1.4 root 2369: goto kludge_me_do;
2370: }
1.1.1.7 ! root 2371: if (currprefs.cpu_model == 68010) {
! 2372: // 68010 creates only format 0 and 8 stack frames
! 2373: m68k_areg (regs, 7) -= 8;
! 2374: if (m68k_areg(regs, 7) & 1) {
! 2375: exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4);
! 2376: return;
! 2377: }
! 2378: exception_in_exception = 1;
! 2379: x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
! 2380: if (interrupt)
! 2381: vector_nr = iack_cycle(nr);
! 2382: x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
! 2383: x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
! 2384: x_put_word (m68k_areg (regs, 7) + 6, vector_nr * 4);
! 2385: } else {
! 2386: m68k_areg (regs, 7) -= 6;
! 2387: if (m68k_areg(regs, 7) & 1) {
! 2388: exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4);
! 2389: return;
! 2390: }
! 2391: exception_in_exception = 1;
! 2392: x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
! 2393: if (interrupt)
! 2394: vector_nr = iack_cycle(nr);
! 2395: x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
! 2396: x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
1.1.1.4 root 2397: }
2398: kludge_me_do:
1.1.1.7 ! root 2399: newpc = x_get_word (regs.vbr + 4 * vector_nr) << 16; // read high address
! 2400: newpc |= x_get_word (regs.vbr + 4 * vector_nr + 2); // read low address
! 2401: exception_in_exception = 0;
1.1.1.4 root 2402: if (newpc & 1) {
2403: if (nr == 2 || nr == 3)
1.1.1.7 ! root 2404: cpu_halt (2);
1.1.1.4 root 2405: else
1.1.1.7 ! root 2406: exception3_notinstruction(regs.ir, newpc);
1.1.1.4 root 2407: return;
2408: }
2409: m68k_setpc (newpc);
1.1.1.7 ! root 2410: regs.ir = x_get_word (m68k_getpc ()); // prefetch 1
! 2411: x_do_cycles (2 * cpucycleunit);
! 2412: regs.irc = x_get_word (m68k_getpc () + 2); // prefetch 2
1.1.1.4 root 2413: #ifdef JIT
2414: set_special (SPCFLAG_END_COMPILE);
2415: #endif
2416: exception_trace (nr);
1.1.1.7 ! root 2417:
! 2418: //fprintf ( stderr , "ex out %d %ld\n" , nr , currcycle );
! 2419: #ifdef WINUAE_FOR_HATARI
! 2420: /* FIXME : Above code already counts 36 cycles for interrupt, add the remaining ST cycles */
! 2421: /* This is temporary, code should be in iack_cycle() */
! 2422: M68000_AddCycles(currcycle * 2 / CYCLE_UNIT);
! 2423:
! 2424: /* Handle exception cycles (special case for MFP) */
! 2425: if ( nr == 30 ) {
! 2426: //M68000_AddCycles(44+12-CPU_IACK_CYCLES_MFP); /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */
! 2427: M68000_AddCycles(44-36); /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */
! 2428: }
! 2429: else if (nr >= 24 && nr <= 31) {
! 2430: if ( nr == 26 ) /* HBL */
! 2431: //M68000_AddCycles(44+12-CPU_IACK_CYCLES_VIDEO); /* Video Interrupt */
! 2432: M68000_AddCycles(44-36); /* Video Interrupt */
! 2433: else if ( nr == 28 ) /* VBL */
! 2434: //M68000_AddCycles(44+12-CPU_IACK_CYCLES_VIDEO); /* Video Interrupt */
! 2435: M68000_AddCycles(44-36); /* Video Interrupt */
! 2436: else
! 2437: //M68000_AddCycles(44+4); /* Other Interrupts */
! 2438: M68000_AddCycles(44-36); /* Other Interrupts */
! 2439: }
! 2440: #endif
! 2441: }
! 2442: #endif
! 2443:
! 2444: static uae_u32 exception_pc (int nr)
! 2445: {
! 2446: // bus error, address error, illegal instruction, privilege violation, a-line, f-line
! 2447: if (nr == 2 || nr == 3 || nr == 4 || nr == 8 || nr == 10 || nr == 11)
! 2448: return regs.instruction_pc;
! 2449: return m68k_getpc ();
! 2450: }
! 2451:
! 2452: static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format)
! 2453: {
! 2454: int i;
! 2455:
! 2456: #if 0
! 2457: if (nr < 24 || nr > 31) { // do not print debugging for interrupts
! 2458: write_log(_T("Building exception stack frame (format %X)\n"), format);
! 2459: }
! 2460: #endif
! 2461:
! 2462: switch (format) {
! 2463: case 0x0: // four word stack frame
! 2464: case 0x1: // throwaway four word stack frame
! 2465: break;
! 2466: case 0x2: // six word stack frame
! 2467: m68k_areg (regs, 7) -= 4;
! 2468: x_put_long (m68k_areg (regs, 7), oldpc);
! 2469: break;
! 2470: case 0x7: // access error stack frame (68040)
! 2471:
! 2472: for (i = 3; i >= 0; i--) {
! 2473: // WB1D/PD0,PD1,PD2,PD3
! 2474: m68k_areg (regs, 7) -= 4;
! 2475: x_put_long (m68k_areg (regs, 7), mmu040_move16[i]);
! 2476: }
! 2477:
! 2478: m68k_areg (regs, 7) -= 4;
! 2479: x_put_long (m68k_areg (regs, 7), 0); // WB1A
! 2480: m68k_areg (regs, 7) -= 4;
! 2481: x_put_long (m68k_areg (regs, 7), 0); // WB2D
! 2482: m68k_areg (regs, 7) -= 4;
! 2483: x_put_long (m68k_areg (regs, 7), regs.wb2_address); // WB2A
! 2484: m68k_areg (regs, 7) -= 4;
! 2485: x_put_long (m68k_areg (regs, 7), regs.wb3_data); // WB3D
! 2486: m68k_areg (regs, 7) -= 4;
! 2487: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // WB3A
! 2488:
! 2489: m68k_areg (regs, 7) -= 4;
! 2490: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // FA
! 2491:
! 2492: m68k_areg (regs, 7) -= 2;
! 2493: x_put_word (m68k_areg (regs, 7), 0);
! 2494: m68k_areg (regs, 7) -= 2;
! 2495: x_put_word (m68k_areg (regs, 7), regs.wb2_status);
! 2496: regs.wb2_status = 0;
! 2497: m68k_areg (regs, 7) -= 2;
! 2498: x_put_word (m68k_areg (regs, 7), regs.wb3_status);
! 2499: regs.wb3_status = 0;
! 2500:
! 2501: m68k_areg (regs, 7) -= 2;
! 2502: x_put_word (m68k_areg (regs, 7), ssw);
! 2503: m68k_areg (regs, 7) -= 4;
! 2504: x_put_long (m68k_areg (regs, 7), regs.mmu_effective_addr);
! 2505: break;
! 2506: case 0x9: // coprocessor mid-instruction stack frame (68020, 68030)
! 2507: m68k_areg (regs, 7) -= 4;
! 2508: x_put_long (m68k_areg (regs, 7), 0);
! 2509: m68k_areg (regs, 7) -= 4;
! 2510: x_put_long (m68k_areg (regs, 7), 0);
! 2511: m68k_areg (regs, 7) -= 4;
! 2512: x_put_long (m68k_areg (regs, 7), oldpc);
! 2513: break;
! 2514: case 0x3: // floating point post-instruction stack frame (68040)
! 2515: case 0x8: // bus and address error stack frame (68010)
! 2516: write_log(_T("Exception stack frame format %X not implemented\n"), format);
! 2517: return;
! 2518: case 0x4: // floating point unimplemented stack frame (68LC040, 68EC040)
! 2519: // or 68060 bus access fault stack frame
! 2520: if (currprefs.cpu_model == 68040) {
! 2521: // this is actually created in fpp.c
! 2522: write_log(_T("Exception stack frame format %X not implemented\n"), format);
! 2523: return;
! 2524: }
! 2525: // 68060 bus access fault
! 2526: m68k_areg (regs, 7) -= 4;
! 2527: x_put_long (m68k_areg (regs, 7), regs.mmu_fslw);
! 2528: m68k_areg (regs, 7) -= 4;
! 2529: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
! 2530: break;
! 2531: case 0xB: // long bus cycle fault stack frame (68020, 68030)
! 2532: // We always use B frame because it is easier to emulate,
! 2533: // our PC always points at start of instruction but A frame assumes
! 2534: // it is + 2 and handling this properly is not easy.
! 2535: // Store state information to internal register space
! 2536: for (i = 0; i < mmu030_idx + 1; i++) {
! 2537: m68k_areg (regs, 7) -= 4;
! 2538: x_put_long (m68k_areg (regs, 7), mmu030_ad[i].val);
! 2539: }
! 2540: while (i < 9) {
! 2541: uae_u32 v = 0;
! 2542: m68k_areg (regs, 7) -= 4;
! 2543: // mmu030_idx is always small enough if instruction is FMOVEM.
! 2544: if (mmu030_state[1] & MMU030_STATEFLAG1_FMOVEM) {
! 2545: if (i == 7)
! 2546: v = mmu030_fmovem_store[0];
! 2547: else if (i == 8)
! 2548: v = mmu030_fmovem_store[1];
! 2549: }
! 2550: x_put_long (m68k_areg (regs, 7), v);
! 2551: i++;
! 2552: }
! 2553: // version & internal information (We store index here)
! 2554: m68k_areg (regs, 7) -= 2;
! 2555: x_put_word (m68k_areg (regs, 7), mmu030_idx);
! 2556: // 3* internal registers
! 2557: m68k_areg (regs, 7) -= 2;
! 2558: x_put_word (m68k_areg (regs, 7), mmu030_state[2]);
! 2559: m68k_areg (regs, 7) -= 2;
! 2560: x_put_word (m68k_areg (regs, 7), mmu030_state[1]);
! 2561: m68k_areg (regs, 7) -= 2;
! 2562: x_put_word (m68k_areg (regs, 7), mmu030_state[0]);
! 2563: // data input buffer = fault address
! 2564: m68k_areg (regs, 7) -= 4;
! 2565: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
! 2566: // 2xinternal
! 2567: m68k_areg (regs, 7) -= 2;
! 2568: x_put_word (m68k_areg (regs, 7), 0);
! 2569: m68k_areg (regs, 7) -= 2;
! 2570: x_put_word (m68k_areg (regs, 7), 0);
! 2571: // stage b address
! 2572: m68k_areg (regs, 7) -= 4;
! 2573: x_put_long (m68k_areg (regs, 7), mm030_stageb_address);
! 2574: // 2xinternal
! 2575: m68k_areg (regs, 7) -= 4;
! 2576: x_put_long (m68k_areg (regs, 7), mmu030_disp_store[1]);
! 2577: /* fall through */
! 2578: case 0xA: // short bus cycle fault stack frame (68020, 68030)
! 2579: m68k_areg (regs, 7) -= 4;
! 2580: x_put_long (m68k_areg (regs, 7), mmu030_disp_store[0]);
! 2581: m68k_areg (regs, 7) -= 4;
! 2582: // Data output buffer = value that was going to be written
! 2583: x_put_long (m68k_areg (regs, 7), (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) ? mmu030_data_buffer : mmu030_ad[mmu030_idx].val);
! 2584: m68k_areg (regs, 7) -= 4;
! 2585: x_put_long (m68k_areg (regs, 7), mmu030_opcode); // Internal register (opcode storage)
! 2586: m68k_areg (regs, 7) -= 4;
! 2587: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // data cycle fault address
! 2588: m68k_areg (regs, 7) -= 2;
! 2589: x_put_word (m68k_areg (regs, 7), 0); // Instr. pipe stage B
! 2590: m68k_areg (regs, 7) -= 2;
! 2591: x_put_word (m68k_areg (regs, 7), 0); // Instr. pipe stage C
! 2592: m68k_areg (regs, 7) -= 2;
! 2593: x_put_word (m68k_areg (regs, 7), ssw);
! 2594: m68k_areg (regs, 7) -= 2;
! 2595: x_put_word (m68k_areg (regs, 7), 0); // Internal register
! 2596: break;
! 2597: default:
! 2598: write_log(_T("Unknown exception stack frame format: %X\n"), format);
! 2599: return;
! 2600: }
! 2601: m68k_areg (regs, 7) -= 2;
! 2602: x_put_word (m68k_areg (regs, 7), (format << 12) | (nr * 4));
! 2603: m68k_areg (regs, 7) -= 4;
! 2604: x_put_long (m68k_areg (regs, 7), currpc);
! 2605: m68k_areg (regs, 7) -= 2;
! 2606: x_put_word (m68k_areg (regs, 7), regs.sr);
1.1.1.4 root 2607: }
1.1.1.7 ! root 2608:
! 2609:
! 2610: // 68030 MMU
! 2611: static void Exception_mmu030 (int nr, uaecptr oldpc)
! 2612: {
! 2613: uae_u32 currpc = m68k_getpc (), newpc;
! 2614: int interrupt;
! 2615:
! 2616: #ifndef WINUAE_FOR_HATARI
! 2617: interrupt = nr >= 24 && nr < 24 + 8;
! 2618: #else
! 2619: if ( nr >= 24 && nr < 24 + 8 )
! 2620: interrupt = 1;
1.1.1.4 root 2621: #endif
2622:
1.1.1.7 ! root 2623: #ifdef WINUAE_FOR_HATARI
! 2624: if (interrupt)
! 2625: nr = iack_cycle(nr);
! 2626: #endif
! 2627:
! 2628: #ifdef WINUAE_FOR_HATARI
! 2629: LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x SR %x\n",
! 2630: nr, currpc, regs.instruction_pc, STMemory_ReadLong (regs.vbr + 4*nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3, regs.sr);
! 2631: #endif
! 2632: exception_debug (nr);
! 2633: MakeSR ();
! 2634:
! 2635: if (!regs.s) {
! 2636: regs.usp = m68k_areg (regs, 7);
! 2637: m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
! 2638: regs.s = 1;
! 2639: mmu_set_super (1);
! 2640: }
! 2641:
! 2642: #if 0
! 2643: if (nr < 24 || nr > 31) { // do not print debugging for interrupts
! 2644: write_log (_T("Exception_mmu030: Exception %i: %08x %08x %08x\n"),
! 2645: nr, currpc, oldpc, regs.mmu_fault_addr);
! 2646: }
! 2647: #endif
! 2648:
! 2649: #if 0
! 2650: write_log (_T("Exception %d -> %08x\n", nr, newpc));
! 2651: #endif
! 2652:
! 2653:
! 2654: newpc = x_get_long (regs.vbr + 4 * nr);
! 2655:
! 2656: if (regs.m && interrupt) { /* M + Interrupt */
! 2657: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
! 2658: MakeSR ();
! 2659: regs.m = 0;
! 2660: regs.msp = m68k_areg (regs, 7);
! 2661: m68k_areg (regs, 7) = regs.isp;
! 2662: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1);
! 2663: } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9 || nr == 56) {
! 2664: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x2);
! 2665: } else if (nr == 2) {
! 2666: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0xB);
! 2667: } else if (nr == 3) {
! 2668: regs.mmu_fault_addr = last_fault_for_exception_3;
! 2669: mmu030_state[0] = mmu030_state[1] = 0;
! 2670: mmu030_data_buffer = 0;
! 2671: Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr, 0xA);
! 2672: } else {
! 2673: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
! 2674: }
! 2675:
! 2676: if (newpc & 1) {
! 2677: if (nr == 2 || nr == 3)
! 2678: cpu_halt (2);
! 2679: else
! 2680: exception3_read(regs.ir, newpc);
! 2681: return;
! 2682: }
! 2683: m68k_setpci (newpc);
! 2684: fill_prefetch ();
! 2685: exception_trace (nr);
! 2686: }
! 2687:
! 2688: // 68040/060 MMU
1.1.1.4 root 2689: static void Exception_mmu (int nr, uaecptr oldpc)
2690: {
2691: uae_u32 currpc = m68k_getpc (), newpc;
1.1.1.7 ! root 2692: int interrupt;
1.1.1.4 root 2693:
1.1.1.7 ! root 2694: #ifndef WINUAE_FOR_HATARI
! 2695: interrupt = nr >= 24 && nr < 24 + 8;
! 2696: #else
! 2697: if ( nr >= 24 && nr < 24 + 8 )
! 2698: interrupt = 1;
! 2699: #endif
! 2700:
! 2701: #ifdef WINUAE_FOR_HATARI
! 2702: if (interrupt)
! 2703: nr = iack_cycle(nr);
! 2704: #endif
! 2705:
! 2706: #ifdef WINUAE_FOR_HATARI
! 2707: LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x SR %x\n",
! 2708: nr, currpc, regs.instruction_pc, STMemory_ReadLong (regs.vbr + 4*nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3, regs.sr);
! 2709: #endif
1.1.1.4 root 2710: exception_debug (nr);
2711: MakeSR ();
2712:
2713: if (!regs.s) {
2714: regs.usp = m68k_areg (regs, 7);
1.1.1.7 ! root 2715: if (currprefs.cpu_model == 68060) {
! 2716: m68k_areg (regs, 7) = regs.isp;
! 2717: if (interrupt)
! 2718: regs.m = 0;
! 2719: } else if (currprefs.cpu_model >= 68020) {
1.1.1.4 root 2720: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.7 ! root 2721: } else {
1.1.1.4 root 2722: m68k_areg (regs, 7) = regs.isp;
1.1.1.7 ! root 2723: }
1.1.1.4 root 2724: regs.s = 1;
2725: mmu_set_super (1);
2726: }
1.1.1.7 ! root 2727:
! 2728: newpc = x_get_long (regs.vbr + 4 * nr);
! 2729: #if 0
! 2730: write_log (_T("Exception %d: %08x -> %08x\n"), nr, currpc, newpc);
! 2731: #endif
1.1.1.5 root 2732:
1.1.1.7 ! root 2733: if (nr == 2) { // bus error
! 2734: //write_log (_T("Exception_mmu %08x %08x %08x\n"), currpc, oldpc, regs.mmu_fault_addr);
! 2735: if (currprefs.mmu_model == 68040)
! 2736: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x7);
! 2737: else
! 2738: Exception_build_stack_frame(oldpc, currpc, regs.mmu_fslw, nr, 0x4);
! 2739: } else if (nr == 3) { // address error
! 2740: Exception_build_stack_frame(last_fault_for_exception_3, currpc, 0, nr, 0x2);
! 2741: write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, get_long_debug (regs.vbr + 4 * nr));
! 2742: } else if (nr == 5 || nr == 6 || nr == 7 || nr == 9) {
! 2743: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2);
! 2744: } else if (regs.m && interrupt) { /* M + Interrupt */
! 2745: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x1);
! 2746: } else if (nr == 61) {
! 2747: Exception_build_stack_frame(oldpc, regs.instruction_pc, regs.mmu_ssw, nr, 0x0);
1.1.1.4 root 2748: } else {
1.1.1.7 ! root 2749: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
1.1.1.4 root 2750: }
1.1.1.7 ! root 2751:
1.1.1.4 root 2752: if (newpc & 1) {
2753: if (nr == 2 || nr == 3)
1.1.1.7 ! root 2754: cpu_halt (2);
1.1.1.4 root 2755: else
1.1.1.7 ! root 2756: exception3_read(regs.ir, newpc);
1.1.1.4 root 2757: return;
2758: }
1.1.1.7 ! root 2759: m68k_setpci (newpc);
! 2760: fill_prefetch ();
1.1.1.4 root 2761: exception_trace (nr);
2762: }
2763:
1.1.1.7 ! root 2764: static void add_approximate_exception_cycles(int nr)
1.1.1.4 root 2765: {
1.1.1.7 ! root 2766: int cycles;
! 2767:
! 2768: if (currprefs.cpu_model > 68000)
! 2769: return;
! 2770: #ifndef WINUAE_FOR_HATARI
! 2771: if (nr >= 24 && nr <= 31) {
! 2772: /* Interrupts */
! 2773: cycles = 44 + 4;
! 2774: #else
! 2775: if ( nr >= 24 && nr <= 31 ) {
! 2776: /* Atari's specific interrupts take 56 cycles instead of 44 */
! 2777: /* We must subtract IACK cycles already counted into iack_cycle() */
! 2778: if ( nr == 30 ) /* MFP/DSP */
! 2779: cycles = 56-CPU_IACK_CYCLES_START-CPU_IACK_CYCLES_MFP;
! 2780: else if ( nr == 28 ) /* VBL */
! 2781: cycles = 56-CPU_IACK_CYCLES_START-CPU_IACK_CYCLES_VIDEO;
! 2782: else if ( nr == 26 ) /* HBL */
! 2783: cycles = 56-CPU_IACK_CYCLES_START- CPU_IACK_CYCLES_VIDEO;
! 2784: else
! 2785: cycles = 44+4; /* Other interrupts */
! 2786: #endif
! 2787: } else if (nr >= 32 && nr <= 47) {
! 2788: /* Trap (total is 34, but cpuemux.c already adds 4) */
! 2789: cycles = 34 -4;
! 2790: } else {
! 2791: switch (nr)
! 2792: {
! 2793: case 2: cycles = 50; break; /* Bus error */
! 2794: case 3: cycles = 50; break; /* Address error */
! 2795: case 4: cycles = 34; break; /* Illegal instruction */
! 2796: case 5: cycles = 38; break; /* Division by zero */
! 2797: case 6: cycles = 40; break; /* CHK */
! 2798: case 7: cycles = 34; break; /* TRAPV */
! 2799: case 8: cycles = 34; break; /* Privilege violation */
! 2800: case 9: cycles = 34; break; /* Trace */
! 2801: case 10: cycles = 34; break; /* Line-A */
! 2802: case 11: cycles = 34; break; /* Line-F */
! 2803: default:
! 2804: cycles = 4;
! 2805: break;
! 2806: }
! 2807: }
! 2808: #ifdef WINUAE_FOR_HATARI
! 2809: M68000_AddCycles ( cycles );
! 2810: #endif
! 2811: cycles = adjust_cycles(cycles * CYCLE_UNIT / 2);
! 2812: x_do_cycles(cycles);
! 2813: }
! 2814:
! 2815: static void Exception_normal (int nr)
! 2816: {
! 2817: uae_u32 currpc, newpc;
1.1.1.4 root 2818: int sv = regs.s;
1.1.1.7 ! root 2819: int interrupt;
! 2820: int vector_nr = nr;
! 2821:
! 2822: interrupt = nr >= 24 && nr < 24 + 8;
1.1.1.4 root 2823:
1.1.1.7 ! root 2824: /* [NP] TODO : factorize in Hatari_Exception_Intercept() */
! 2825: #ifdef WINUAE_FOR_HATARI
! 2826: if (nr == 0x22) {
! 2827: /* Intercept VDI & AES exceptions (Trap #2) */
! 2828: if (bVdiAesIntercept && VDI_AES_Entry()) {
! 2829: /* Set 'PC' to address of 'VDI_OPCODE' illegal instruction.
! 2830: * This will call OpCode_VDI() after completion of Trap call!
! 2831: * This is used to modify specific VDI return vectors contents.
! 2832: */
! 2833: currpc = m68k_getpc ();
! 2834: VDI_OldPC = currpc;
! 2835: currpc = CART_VDI_OPCODE_ADDR;
1.1.1.4 root 2836: }
2837: }
1.1.1.7 ! root 2838: else if (nr == 0x2d) {
! 2839: /* Intercept BIOS (Trap #13) calls */
! 2840: if (Bios()) return;
! 2841: }
! 2842: else if (nr == 0x2e) {
! 2843: /* Intercept XBIOS (Trap #14) calls */
! 2844: if (XBios()) return;
! 2845: }
! 2846: #endif
1.1.1.4 root 2847:
1.1.1.7 ! root 2848: #ifndef WINUAE_FOR_HATARI
! 2849: if (interrupt && currprefs.cpu_model <= 68010)
! 2850: #else
! 2851: if (interrupt)
1.1.1.4 root 2852: #endif
1.1.1.7 ! root 2853: vector_nr = iack_cycle(nr);
1.1.1.4 root 2854:
2855: exception_debug (nr);
2856: MakeSR ();
2857:
2858: if (!regs.s) {
2859: regs.usp = m68k_areg (regs, 7);
1.1.1.7 ! root 2860: if (currprefs.cpu_model == 68060) {
! 2861: m68k_areg (regs, 7) = regs.isp;
! 2862: if (interrupt)
! 2863: regs.m = 0;
! 2864: } else if (currprefs.cpu_model >= 68020) {
1.1.1.4 root 2865: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.7 ! root 2866: } else {
1.1.1.4 root 2867: m68k_areg (regs, 7) = regs.isp;
1.1.1.7 ! root 2868: }
1.1.1.4 root 2869: regs.s = 1;
2870: if (currprefs.mmu_model)
2871: mmu_set_super (regs.s != 0);
2872: }
1.1.1.7 ! root 2873:
! 2874: if (m68k_areg(regs, 7) & 1) {
! 2875: if (nr == 2 || nr == 3)
! 2876: cpu_halt (2);
! 2877: else
! 2878: exception3_notinstruction(regs.ir, m68k_areg(regs, 7));
! 2879: return;
! 2880: }
! 2881: if ((nr == 2 || nr == 3) && exception_in_exception < 0) {
! 2882: cpu_halt (2);
! 2883: return;
! 2884: }
! 2885:
! 2886: if (currprefs.cpu_model > 68000) {
! 2887: currpc = exception_pc (nr);
! 2888: #ifdef WINUAE_FOR_HATARI
! 2889: LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d vector %x currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x SR %x\n",
! 2890: nr, 4*vector_nr , currpc, regs.instruction_pc, STMemory_ReadLong (regs.vbr + 4*vector_nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3, regs.sr);
! 2891: #endif
! 2892: if (nr == 2 || nr == 3) {
! 2893: int i;
1.1.1.4 root 2894: if (currprefs.cpu_model >= 68040) {
2895: if (nr == 2) {
2896: if (currprefs.mmu_model) {
1.1.1.7 ! root 2897: // 68040 mmu bus error
1.1.1.4 root 2898: for (i = 0 ; i < 7 ; i++) {
2899: m68k_areg (regs, 7) -= 4;
2900: x_put_long (m68k_areg (regs, 7), 0);
2901: }
2902: m68k_areg (regs, 7) -= 4;
2903: x_put_long (m68k_areg (regs, 7), regs.wb3_data);
2904: m68k_areg (regs, 7) -= 4;
2905: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2906: m68k_areg (regs, 7) -= 4;
2907: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2908: m68k_areg (regs, 7) -= 2;
2909: x_put_word (m68k_areg (regs, 7), 0);
2910: m68k_areg (regs, 7) -= 2;
2911: x_put_word (m68k_areg (regs, 7), 0);
2912: m68k_areg (regs, 7) -= 2;
2913: x_put_word (m68k_areg (regs, 7), regs.wb3_status);
2914: regs.wb3_status = 0;
2915: m68k_areg (regs, 7) -= 2;
2916: x_put_word (m68k_areg (regs, 7), regs.mmu_ssw);
2917: m68k_areg (regs, 7) -= 4;
2918: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2919:
2920: m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root 2921: x_put_word (m68k_areg (regs, 7), 0x7000 + vector_nr * 4);
1.1.1.4 root 2922: m68k_areg (regs, 7) -= 4;
1.1.1.7 ! root 2923: x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
1.1.1.4 root 2924: m68k_areg (regs, 7) -= 2;
2925: x_put_word (m68k_areg (regs, 7), regs.sr);
1.1.1.7 ! root 2926: newpc = x_get_long (regs.vbr + 4 * vector_nr);
1.1.1.4 root 2927: if (newpc & 1) {
2928: if (nr == 2 || nr == 3)
1.1.1.7 ! root 2929: cpu_halt (2);
1.1.1.4 root 2930: else
1.1.1.7 ! root 2931: exception3_read(regs.ir, newpc);
1.1.1.4 root 2932: return;
2933: }
2934: m68k_setpc (newpc);
2935: #ifdef JIT
2936: set_special (SPCFLAG_END_COMPILE);
2937: #endif
2938: exception_trace (nr);
2939: return;
2940:
2941: } else {
2942:
1.1.1.7 ! root 2943: // 68040 bus error (not really, some garbage?)
1.1.1.4 root 2944: for (i = 0 ; i < 18 ; i++) {
2945: m68k_areg (regs, 7) -= 2;
2946: x_put_word (m68k_areg (regs, 7), 0);
2947: }
2948: m68k_areg (regs, 7) -= 4;
2949: x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
2950: m68k_areg (regs, 7) -= 2;
2951: x_put_word (m68k_areg (regs, 7), 0);
2952: m68k_areg (regs, 7) -= 2;
2953: x_put_word (m68k_areg (regs, 7), 0);
2954: m68k_areg (regs, 7) -= 2;
2955: x_put_word (m68k_areg (regs, 7), 0);
2956: m68k_areg (regs, 7) -= 2;
2957: x_put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */
2958: m68k_areg (regs, 7) -= 4;
2959: x_put_long (m68k_areg (regs, 7), last_addr_for_exception_3);
2960: m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root 2961: x_put_word (m68k_areg (regs, 7), 0x7000 + vector_nr * 4);
1.1.1.4 root 2962: m68k_areg (regs, 7) -= 4;
1.1.1.7 ! root 2963: x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
1.1.1.4 root 2964: m68k_areg (regs, 7) -= 2;
2965: x_put_word (m68k_areg (regs, 7), regs.sr);
2966: goto kludge_me_do;
2967:
2968: }
2969:
2970: } else {
2971: m68k_areg (regs, 7) -= 4;
2972: x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
2973: m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root 2974: x_put_word (m68k_areg (regs, 7), 0x2000 + vector_nr * 4);
1.1.1.4 root 2975: }
2976: } else {
1.1.1.7 ! root 2977: // 68020 address error
1.1.1.4 root 2978: uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
2979: ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
2980: ssw |= 0x20;
2981: for (i = 0 ; i < 36; i++) {
2982: m68k_areg (regs, 7) -= 2;
2983: x_put_word (m68k_areg (regs, 7), 0);
2984: }
2985: m68k_areg (regs, 7) -= 4;
2986: x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
2987: m68k_areg (regs, 7) -= 2;
2988: x_put_word (m68k_areg (regs, 7), 0);
2989: m68k_areg (regs, 7) -= 2;
2990: x_put_word (m68k_areg (regs, 7), 0);
2991: m68k_areg (regs, 7) -= 2;
2992: x_put_word (m68k_areg (regs, 7), 0);
2993: m68k_areg (regs, 7) -= 2;
2994: x_put_word (m68k_areg (regs, 7), ssw);
2995: m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root 2996: x_put_word (m68k_areg (regs, 7), 0xb000 + vector_nr * 4);
1.1.1.4 root 2997: }
1.1.1.7 ! root 2998: write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, regs.instruction_pc, currpc, get_long_debug (regs.vbr + 4 * vector_nr));
1.1.1.4 root 2999: } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
3000: m68k_areg (regs, 7) -= 4;
1.1.1.7 ! root 3001: x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
1.1.1.4 root 3002: m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root 3003: x_put_word (m68k_areg (regs, 7), 0x2000 + vector_nr * 4);
! 3004: } else if (regs.m && interrupt) { /* M + Interrupt */
1.1.1.4 root 3005: m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root 3006: x_put_word (m68k_areg (regs, 7), vector_nr * 4);
1.1.1.4 root 3007: m68k_areg (regs, 7) -= 4;
3008: x_put_long (m68k_areg (regs, 7), currpc);
3009: m68k_areg (regs, 7) -= 2;
3010: x_put_word (m68k_areg (regs, 7), regs.sr);
3011: regs.sr |= (1 << 13);
3012: regs.msp = m68k_areg (regs, 7);
1.1.1.7 ! root 3013: regs.m = 0;
1.1.1.4 root 3014: m68k_areg (regs, 7) = regs.isp;
3015: m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root 3016: x_put_word (m68k_areg (regs, 7), 0x1000 + vector_nr * 4);
1.1.1.4 root 3017: } else {
3018: m68k_areg (regs, 7) -= 2;
1.1.1.7 ! root 3019: x_put_word (m68k_areg (regs, 7), vector_nr * 4);
! 3020: }
! 3021: } else {
! 3022: add_approximate_exception_cycles(nr);
! 3023: currpc = m68k_getpc ();
! 3024: #ifdef WINUAE_FOR_HATARI
! 3025: LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d vector %x currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x SR %x\n",
! 3026: nr, 4*vector_nr , currpc, regs.instruction_pc, STMemory_ReadLong (regs.vbr + 4*vector_nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3, regs.sr);
! 3027: #endif
! 3028: if (nr == 2 || nr == 3) {
! 3029: // 68000 address error
! 3030: uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
! 3031: mode |= last_writeaccess_for_exception_3 ? 0 : 16;
! 3032: mode |= last_notinstruction_for_exception_3 ? 8 : 0;
! 3033: // undocumented bits seem to contain opcode
! 3034: mode |= last_op_for_exception_3 & ~31;
! 3035: m68k_areg (regs, 7) -= 14;
! 3036: exception_in_exception = -1;
! 3037: x_put_word (m68k_areg (regs, 7) + 0, mode);
! 3038: x_put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3);
! 3039: x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
! 3040: x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
! 3041: x_put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3);
! 3042: write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, get_long_debug (regs.vbr + 4 * vector_nr));
! 3043: #ifdef WINUAE_FOR_HATARI
! 3044: fprintf(stderr,"%s Error at address $%x, PC=$%x addr_e3=%x op_e3=%x\n", nr==2?"Bus":"Address", last_fault_for_exception_3, currpc, last_addr_for_exception_3 , last_op_for_exception_3);
! 3045: #endif
! 3046: goto kludge_me_do;
1.1.1.4 root 3047: }
3048: }
3049: m68k_areg (regs, 7) -= 4;
1.1.1.7 ! root 3050: #ifndef WINUAE_FOR_HATARI
! 3051: /* TODO NP check exception_pc() is fixed and remove ifndef */
1.1.1.4 root 3052: x_put_long (m68k_areg (regs, 7), currpc);
1.1.1.7 ! root 3053: #else
! 3054: x_put_long (m68k_areg (regs, 7), m68k_getpc ());
! 3055: #endif
! 3056: m68k_areg (regs, 7) -= 2;
1.1.1.4 root 3057: x_put_word (m68k_areg (regs, 7), regs.sr);
3058: kludge_me_do:
1.1.1.7 ! root 3059: newpc = x_get_long (regs.vbr + 4 * vector_nr);
! 3060: exception_in_exception = 0;
1.1.1.4 root 3061: if (newpc & 1) {
3062: if (nr == 2 || nr == 3)
1.1.1.7 ! root 3063: cpu_halt (2);
1.1.1.4 root 3064: else
1.1.1.7 ! root 3065: exception3_notinstruction(regs.ir, newpc);
1.1.1.4 root 3066: return;
3067: }
3068: m68k_setpc (newpc);
3069: #ifdef JIT
3070: set_special (SPCFLAG_END_COMPILE);
3071: #endif
1.1.1.7 ! root 3072: fill_prefetch ();
1.1.1.4 root 3073: exception_trace (nr);
3074: }
3075:
1.1.1.7 ! root 3076: // address = format $2 stack frame address field
! 3077: static void ExceptionX (int nr, uaecptr address)
1.1.1.4 root 3078: {
1.1.1.7 ! root 3079: regs.exception = nr;
! 3080: if (cpu_tracer) {
! 3081: cputrace.state = nr;
1.1.1.6 root 3082: }
3083:
1.1.1.7 ! root 3084: #ifdef JIT
! 3085: if (currprefs.cachesize)
! 3086: regs.instruction_pc = address == -1 ? m68k_getpc () : address;
! 3087: #endif
! 3088: #ifdef CPUEMU_13
! 3089: if (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010)
! 3090: Exception_ce000 (nr);
1.1.1.4 root 3091: else
3092: #endif
1.1.1.7 ! root 3093: if (currprefs.mmu_model) {
! 3094: if (currprefs.cpu_model == 68030)
! 3095: Exception_mmu030 (nr, m68k_getpc ());
! 3096: else
! 3097: Exception_mmu (nr, m68k_getpc ());
! 3098: } else {
! 3099: Exception_normal (nr);
! 3100: }
1.1.1.4 root 3101:
1.1.1.7 ! root 3102: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 3103: if (debug_illegal && !in_rom (M68K_GETPC)) {
3104: if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) {
1.1.1.7 ! root 3105: write_log (_T("Exception %d breakpoint\n"), nr);
1.1.1.4 root 3106: activate_debugger ();
3107: }
3108: }
3109: #endif
1.1.1.7 ! root 3110: regs.exception = 0;
! 3111: if (cpu_tracer) {
! 3112: cputrace.state = 0;
! 3113: }
! 3114: }
! 3115:
! 3116: void REGPARAM2 Exception (int nr)
! 3117: {
! 3118: ExceptionX (nr, -1);
! 3119: }
! 3120: void REGPARAM2 ExceptionL (int nr, uaecptr address)
! 3121: {
! 3122: ExceptionX (nr, address);
1.1.1.4 root 3123: }
3124:
1.1.1.7 ! root 3125: static void do_interrupt (int nr)
1.1.1.4 root 3126: {
1.1.1.7 ! root 3127: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 3128: if (debug_dma)
3129: record_dma_event (DMA_EVENT_CPUIRQ, current_hpos (), vpos);
1.1.1.7 ! root 3130:
! 3131: if (inputrecord_debug & 2) {
! 3132: if (input_record > 0)
! 3133: inprec_recorddebug_cpu (2);
! 3134: else if (input_play > 0)
! 3135: inprec_playdebug_cpu (2);
! 3136: }
1.1.1.4 root 3137: #endif
3138:
3139: regs.stopped = 0;
3140: unset_special (SPCFLAG_STOP);
3141: assert (nr < 8 && nr >= 0);
3142:
1.1.1.7 ! root 3143: Exception (nr + 24);
1.1.1.4 root 3144:
3145: regs.intmask = nr;
3146: doint ();
3147: }
3148:
3149: void NMI (void)
3150: {
1.1.1.7 ! root 3151: do_interrupt (7);
1.1.1.4 root 3152: }
3153:
1.1.1.7 ! root 3154: static void m68k_reset_sr(void)
1.1.1.4 root 3155: {
1.1.1.7 ! root 3156: SET_XFLG ((regs.sr >> 4) & 1);
! 3157: SET_NFLG ((regs.sr >> 3) & 1);
! 3158: SET_ZFLG ((regs.sr >> 2) & 1);
! 3159: SET_VFLG ((regs.sr >> 1) & 1);
! 3160: SET_CFLG (regs.sr & 1);
! 3161: regs.t1 = (regs.sr >> 15) & 1;
! 3162: regs.t0 = (regs.sr >> 14) & 1;
! 3163: regs.s = (regs.sr >> 13) & 1;
! 3164: regs.m = (regs.sr >> 12) & 1;
! 3165: regs.intmask = (regs.sr >> 8) & 7;
! 3166: /* set stack pointer */
! 3167: if (regs.s)
! 3168: m68k_areg (regs, 7) = regs.isp;
! 3169: else
! 3170: m68k_areg (regs, 7) = regs.usp;
1.1.1.4 root 3171: }
3172:
1.1.1.7 ! root 3173: static void m68k_reset2(bool hardreset)
1.1.1.4 root 3174: {
1.1.1.7 ! root 3175: uae_u32 v;
1.1.1.4 root 3176:
1.1.1.7 ! root 3177: regs.halted = 0;
! 3178: #ifndef WINUAE_FOR_HATARI
! 3179: gui_data.cpu_halted = 0;
! 3180: gui_led (LED_CPU, 0, -1);
1.1.1.4 root 3181: #endif
3182:
1.1.1.7 ! root 3183: regs.spcflags = 0;
! 3184: m68k_reset_delay = 0;
! 3185: regs.ipl = regs.ipl_pin = 0;
1.1.1.4 root 3186:
1.1.1.7 ! root 3187: #ifdef SAVESTATE
! 3188: if (isrestore ()) {
! 3189: m68k_reset_sr();
! 3190: m68k_setpc_normal (regs.pc);
1.1.1.4 root 3191: return;
3192: } else {
1.1.1.7 ! root 3193: m68k_reset_delay = currprefs.reset_delay;
! 3194: set_special(SPCFLAG_CHECK);
1.1.1.4 root 3195: }
3196: #endif
1.1.1.7 ! root 3197: regs.s = 1;
! 3198: #ifndef WINUAE_FOR_HATARI
! 3199: if (currprefs.cpuboard_type) {
! 3200: uaecptr stack;
! 3201: v = cpuboard_get_reset_pc(&stack);
! 3202: m68k_areg (regs, 7) = stack;
1.1.1.4 root 3203: } else {
1.1.1.7 ! root 3204: v = get_long (4);
! 3205: m68k_areg (regs, 7) = get_long (0);
! 3206: }
1.1.1.4 root 3207: #else
1.1.1.7 ! root 3208: v = get_long (4);
! 3209: m68k_areg (regs, 7) = get_long (0);
1.1.1.4 root 3210: #endif
1.1.1.7 ! root 3211: m68k_setpc_normal(v);
1.1.1.4 root 3212: regs.m = 0;
3213: regs.stopped = 0;
3214: regs.t1 = 0;
3215: regs.t0 = 0;
3216: SET_ZFLG (0);
3217: SET_XFLG (0);
3218: SET_CFLG (0);
3219: SET_VFLG (0);
3220: SET_NFLG (0);
3221: regs.intmask = 7;
3222: regs.vbr = regs.sfc = regs.dfc = 0;
3223: regs.irc = 0xffff;
3224: #ifdef FPUEMU
3225: fpu_reset ();
3226: #endif
3227: regs.caar = regs.cacr = 0;
3228: regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0;
3229: regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0;
1.1.1.7 ! root 3230: mmu_tt_modified ();
1.1.1.4 root 3231: if (currprefs.cpu_model == 68020) {
3232: regs.cacr |= 8;
1.1.1.7 ! root 3233: set_cpu_caches (false);
1.1.1.4 root 3234: }
3235:
3236: mmufixup[0].reg = -1;
3237: mmufixup[1].reg = -1;
1.1.1.7 ! root 3238: if (currprefs.mmu_model >= 68040) {
! 3239: mmu_reset ();
! 3240: mmu_set_tc (regs.tcr);
! 3241: mmu_set_super (regs.s != 0);
! 3242: } else if (currprefs.mmu_model == 68030) {
! 3243: mmu030_reset (hardreset || regs.halted);
! 3244: } else {
! 3245: #ifndef WINUAE_FOR_HATARI
! 3246: a3000_fakekick (0);
! 3247: #endif
! 3248: /* only (E)nable bit is zeroed when CPU is reset, A3000 SuperKickstart expects this */
! 3249: fake_tc_030 &= ~0x80000000;
! 3250: fake_tt0_030 &= ~0x80000000;
! 3251: fake_tt1_030 &= ~0x80000000;
! 3252: if (hardreset || regs.halted) {
! 3253: fake_srp_030 = fake_crp_030 = 0;
! 3254: fake_tt0_030 = fake_tt1_030 = fake_tc_030 = 0;
1.1.1.5 root 3255: }
1.1.1.7 ! root 3256: fake_mmusr_030 = 0;
1.1.1.4 root 3257: }
3258:
3259: /* 68060 FPU is not compatible with 68040,
3260: * 68060 accelerators' boot ROM disables the FPU
3261: */
3262: regs.pcr = 0;
3263: if (currprefs.cpu_model == 68060) {
3264: regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR;
3265: regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8;
1.1.1.7 ! root 3266: #ifndef WINUAE_FOR_HATARI
! 3267: if (kickstart_rom)
! 3268: regs.pcr |= 2; /* disable FPU */
! 3269: #endif
! 3270: }
! 3271: regs.ce020memcycles = 0;
! 3272: fill_prefetch ();
! 3273: }
! 3274: void m68k_reset(void)
! 3275: {
! 3276: m68k_reset2(false);
! 3277: }
! 3278:
! 3279:
! 3280: void REGPARAM2 op_unimpl (uae_u16 opcode)
! 3281: {
! 3282: static int warned;
! 3283: if (warned < 20) {
! 3284: write_log (_T("68060 unimplemented opcode %04X, PC=%08x\n"), opcode, regs.instruction_pc);
! 3285: warned++;
1.1.1.4 root 3286: }
1.1.1.7 ! root 3287: ExceptionL (61, regs.instruction_pc);
1.1.1.4 root 3288: }
3289:
1.1.1.7 ! root 3290: uae_u32 REGPARAM2 op_illg (uae_u32 opcode)
1.1.1.4 root 3291: {
3292: uaecptr pc = m68k_getpc ();
3293: static int warned;
3294:
1.1.1.7 ! root 3295: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 3296: int inrom = in_rom (pc);
3297: int inrt = in_rtarea (pc);
3298:
3299: if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
3300: m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
1.1.1.7 ! root 3301: m68k_incpc_normal (2);
! 3302: fill_prefetch ();
1.1.1.4 root 3303: return 4;
3304: }
3305:
1.1.1.7 ! root 3306: if (opcode == 0x4E7B && inrom) {
! 3307: if (get_long (0x10) == 0) {
! 3308: notify_user (NUMSG_KS68020);
! 3309: uae_restart (-1, NULL);
! 3310: }
1.1.1.4 root 3311: }
3312:
3313: #ifdef AUTOCONFIG
1.1.1.7 ! root 3314: if (opcode == 0xFF0D && inrt) {
! 3315: /* User-mode STOP replacement */
! 3316: m68k_setstopped ();
! 3317: return 4;
1.1.1.4 root 3318: }
3319:
3320: if ((opcode & 0xF000) == 0xA000 && inrt) {
3321: /* Calltrap. */
1.1.1.7 ! root 3322: m68k_incpc_normal (2);
! 3323: m68k_handle_trap(opcode & 0xFFF);
! 3324: fill_prefetch ();
1.1.1.4 root 3325: return 4;
3326: }
3327: #endif
1.1.1.7 ! root 3328: #endif
1.1.1.4 root 3329:
3330: if ((opcode & 0xF000) == 0xF000) {
1.1.1.7 ! root 3331: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 3332: if (warned < 20) {
1.1.1.7 ! root 3333: write_log(_T("B-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x2c));
1.1.1.4 root 3334: warned++;
3335: }
1.1.1.7 ! root 3336: #endif
! 3337: Exception (0xB);
1.1.1.4 root 3338: //activate_debugger ();
3339: return 4;
3340: }
3341: if ((opcode & 0xF000) == 0xA000) {
1.1.1.7 ! root 3342: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 3343: if (warned < 20) {
1.1.1.7 ! root 3344: write_log(_T("A-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x28));
1.1.1.4 root 3345: warned++;
3346: }
1.1.1.7 ! root 3347: #endif
! 3348: Exception (0xA);
1.1.1.4 root 3349: //activate_debugger();
3350: return 4;
3351: }
3352: if (warned < 20) {
1.1.1.7 ! root 3353: write_log (_T("Illegal instruction: %04x at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x10));
1.1.1.4 root 3354: warned++;
3355: //activate_debugger();
3356: }
3357:
1.1.1.7 ! root 3358: Exception (4);
1.1.1.4 root 3359: return 4;
3360: }
3361:
3362: #ifdef CPUEMU_0
3363:
1.1.1.7 ! root 3364: static bool mmu_op30fake_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
1.1.1.4 root 3365: {
1.1.1.7 ! root 3366: int mode = (opcode >> 3) & 7;
! 3367: int rreg = opcode & 7;
! 3368: int preg = (next >> 10) & 31;
! 3369: int rw = (next >> 9) & 1;
! 3370: int fd = (next >> 8) & 1;
! 3371: const TCHAR *reg = NULL;
! 3372: uae_u32 otc = fake_tc_030;
! 3373: int siz;
! 3374:
! 3375: // Dn, An, (An)+, -(An), immediate and PC-relative not allowed
! 3376: if (mode == 0 || mode == 1 || mode == 3 || mode == 4 || mode == 6 || (mode == 7 && rreg > 1)) {
1.1.1.4 root 3377: op_illg (opcode);
1.1.1.7 ! root 3378: return true;
1.1.1.4 root 3379: }
1.1.1.5 root 3380:
1.1.1.7 ! root 3381: switch (preg)
! 3382: {
! 3383: case 0x10: // TC
! 3384: reg = _T("TC");
! 3385: siz = 4;
! 3386: if (rw)
! 3387: x_put_long (extra, fake_tc_030);
! 3388: else
! 3389: fake_tc_030 = x_get_long (extra);
! 3390: break;
! 3391: case 0x12: // SRP
! 3392: reg = _T("SRP");
! 3393: siz = 8;
! 3394: if (rw) {
! 3395: x_put_long (extra, fake_srp_030 >> 32);
! 3396: x_put_long (extra + 4, (uae_u32)fake_srp_030);
! 3397: } else {
! 3398: fake_srp_030 = (uae_u64)x_get_long (extra) << 32;
! 3399: fake_srp_030 |= x_get_long (extra + 4);
! 3400: }
! 3401: break;
! 3402: case 0x13: // CRP
! 3403: reg = _T("CRP");
! 3404: siz = 8;
! 3405: if (rw) {
! 3406: x_put_long (extra, fake_crp_030 >> 32);
! 3407: x_put_long (extra + 4, (uae_u32)fake_crp_030);
! 3408: } else {
! 3409: fake_crp_030 = (uae_u64)x_get_long (extra) << 32;
! 3410: fake_crp_030 |= x_get_long (extra + 4);
! 3411: }
! 3412: break;
! 3413: case 0x18: // MMUSR
! 3414: reg = _T("MMUSR");
! 3415: siz = 2;
! 3416: if (rw)
! 3417: x_put_word (extra, fake_mmusr_030);
! 3418: else
! 3419: fake_mmusr_030 = x_get_word (extra);
! 3420: break;
! 3421: case 0x02: // TT0
! 3422: reg = _T("TT0");
! 3423: siz = 4;
! 3424: if (rw)
! 3425: x_put_long (extra, fake_tt0_030);
! 3426: else
! 3427: fake_tt0_030 = x_get_long (extra);
! 3428: break;
! 3429: case 0x03: // TT1
! 3430: reg = _T("TT1");
! 3431: siz = 4;
! 3432: if (rw)
! 3433: x_put_long (extra, fake_tt1_030);
! 3434: else
! 3435: fake_tt1_030 = x_get_long (extra);
! 3436: break;
! 3437: }
1.1.1.4 root 3438:
1.1.1.7 ! root 3439: if (!reg) {
! 3440: op_illg (opcode);
! 3441: return true;
1.1.1.4 root 3442: }
3443: #if MMUOP_DEBUG > 0
1.1.1.7 ! root 3444: {
! 3445: uae_u32 val;
! 3446: if (siz == 8) {
! 3447: uae_u32 val2 = x_get_long (extra);
! 3448: val = x_get_long (extra + 4);
! 3449: if (rw)
! 3450: write_log (_T("PMOVE %s,%08X%08X"), reg, val2, val);
! 3451: else
! 3452: write_log (_T("PMOVE %08X%08X,%s"), val2, val, reg);
! 3453: } else {
! 3454: if (siz == 4)
! 3455: val = x_get_long (extra);
! 3456: else
! 3457: val = x_get_word (extra);
! 3458: if (rw)
! 3459: write_log (_T("PMOVE %s,%08X"), reg, val);
! 3460: else
! 3461: write_log (_T("PMOVE %08X,%s"), val, reg);
1.1.1.4 root 3462: }
1.1.1.7 ! root 3463: write_log (_T(" PC=%08X\n"), pc);
! 3464: }
1.1.1.4 root 3465: #endif
1.1.1.7 ! root 3466: #ifndef WINUAE_FOR_HATARI
! 3467: if ((currprefs.cs_mbdmac & 1) && currprefs.mbresmem_low_size > 0) {
! 3468: if (otc != fake_tc_030) {
! 3469: a3000_fakekick (fake_tc_030 & 0x80000000);
1.1.1.4 root 3470: }
3471: }
3472: #endif
1.1.1.7 ! root 3473: return false;
1.1.1.4 root 3474: }
3475:
1.1.1.7 ! root 3476: static bool mmu_op30fake_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
! 3477: {
! 3478: #if MMUOP_DEBUG > 0
! 3479: TCHAR tmp[10];
! 3480:
! 3481: tmp[0] = 0;
! 3482: if ((next >> 8) & 1)
! 3483: _stprintf (tmp, _T(",A%d"), (next >> 4) & 15);
! 3484: write_log (_T("PTEST%c %02X,%08X,#%X%s PC=%08X\n"),
! 3485: ((next >> 9) & 1) ? 'W' : 'R', (next & 15), extra, (next >> 10) & 7, tmp, pc);
1.1.1.4 root 3486: #endif
1.1.1.7 ! root 3487: fake_mmusr_030 = 0;
! 3488: return false;
! 3489: }
1.1.1.4 root 3490:
1.1.1.7 ! root 3491: static bool mmu_op30fake_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
! 3492: {
! 3493: int mode = (opcode >> 3) & 7;
! 3494: int rreg = opcode & 7;
! 3495: int flushmode = (next >> 10) & 7;
! 3496: int fc = next & 31;
! 3497: int mask = (next >> 5) & 3;
! 3498: TCHAR fname[100];
! 3499:
! 3500: switch (flushmode)
! 3501: {
! 3502: case 6:
! 3503: // Dn, An, (An)+, -(An), immediate and PC-relative not allowed
! 3504: if (mode == 0 || mode == 1 || mode == 3 || mode == 4 || mode == 6 || (mode == 7 && rreg > 1)) {
! 3505: op_illg (opcode);
! 3506: return true;
! 3507: }
! 3508: _stprintf (fname, _T("FC=%x MASK=%x EA=%08x"), fc, mask, 0);
! 3509: break;
! 3510: case 4:
! 3511: _stprintf (fname, _T("FC=%x MASK=%x"), fc, mask);
! 3512: break;
! 3513: case 1:
! 3514: _tcscpy (fname, _T("ALL"));
! 3515: break;
! 3516: default:
! 3517: op_illg (opcode);
! 3518: return true;
! 3519: }
! 3520: #if MMUOP_DEBUG > 0
! 3521: write_log (_T("PFLUSH %s PC=%08X\n"), fname, pc);
! 3522: #endif
! 3523: return false;
! 3524: }
! 3525:
! 3526: // 68030 (68851) MMU instructions only
! 3527: bool mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
! 3528: {
! 3529: if (currprefs.mmu_model) {
! 3530: if (extra & 0x8000) {
! 3531: return mmu_op30_ptest (pc, opcode, extra, extraa);
! 3532: } else if ((extra&0xE000)==0x2000 && (extra & 0x1C00)) {
! 3533: return mmu_op30_pflush (pc, opcode, extra, extraa);
! 3534: } else if ((extra&0xE000)==0x2000 && !(extra & 0x1C00)) {
! 3535: return mmu_op30_pload (pc, opcode, extra, extraa);
! 3536: } else {
! 3537: return mmu_op30_pmove (pc, opcode, extra, extraa);
! 3538: }
! 3539: return false;
! 3540: }
! 3541:
! 3542: int type = extra >> 13;
! 3543:
! 3544: switch (type)
! 3545: {
! 3546: case 0:
! 3547: case 2:
! 3548: case 3:
! 3549: return mmu_op30fake_pmove (pc, opcode, extra, extraa);
! 3550: break;
! 3551: case 1:
! 3552: return mmu_op30fake_pflush (pc, opcode, extra, extraa);
! 3553: break;
! 3554: case 4:
! 3555: return mmu_op30fake_ptest (pc, opcode, extra, extraa);
! 3556: break;
! 3557: default:
! 3558: op_illg (opcode);
! 3559: return true;
! 3560: break;
! 3561: }
! 3562: }
! 3563:
! 3564: // 68040+ MMU instructions only
! 3565: void mmu_op (uae_u32 opcode, uae_u32 extra)
! 3566: {
! 3567: if (currprefs.mmu_model) {
! 3568: mmu_op_real (opcode, extra);
! 3569: return;
! 3570: }
! 3571: #if MMUOP_DEBUG > 1
! 3572: write_log (_T("mmu_op %04X PC=%08X\n"), opcode, m68k_getpc ());
! 3573: #endif
! 3574: if ((opcode & 0xFE0) == 0x0500) {
! 3575: /* PFLUSH */
! 3576: regs.mmusr = 0;
! 3577: #if MMUOP_DEBUG > 0
! 3578: write_log (_T("PFLUSH\n"));
! 3579: #endif
! 3580: return;
! 3581: } else if ((opcode & 0x0FD8) == 0x548) {
! 3582: if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
! 3583: /* PTEST */
! 3584: #if MMUOP_DEBUG > 0
! 3585: write_log (_T("PTEST\n"));
! 3586: #endif
! 3587: return;
! 3588: }
! 3589: } else if ((opcode & 0x0FB8) == 0x588) {
! 3590: /* PLPA */
! 3591: if (currprefs.cpu_model == 68060) {
! 3592: #if MMUOP_DEBUG > 0
! 3593: write_log (_T("PLPA\n"));
! 3594: #endif
! 3595: return;
! 3596: }
! 3597: }
! 3598: #if MMUOP_DEBUG > 0
! 3599: write_log (_T("Unknown MMU OP %04X\n"), opcode);
! 3600: #endif
! 3601: m68k_setpc_normal (m68k_getpc () - 2);
! 3602: op_illg (opcode);
! 3603: }
! 3604:
! 3605: #endif
! 3606:
! 3607: static uaecptr last_trace_ad = 0;
1.1.1.4 root 3608:
3609: static void do_trace (void)
3610: {
3611: if (regs.t0 && currprefs.cpu_model >= 68020) {
3612: uae_u16 opcode;
3613: /* should also include TRAP, CHK, SR modification FPcc */
3614: /* probably never used so why bother */
3615: /* We can afford this to be inefficient... */
1.1.1.7 ! root 3616: m68k_setpc_normal (m68k_getpc ());
! 3617: fill_prefetch ();
1.1.1.4 root 3618: opcode = x_get_word (regs.pc);
3619: if (opcode == 0x4e73 /* RTE */
3620: || opcode == 0x4e74 /* RTD */
3621: || opcode == 0x4e75 /* RTS */
3622: || opcode == 0x4e77 /* RTR */
3623: || opcode == 0x4e76 /* TRAPV */
3624: || (opcode & 0xffc0) == 0x4e80 /* JSR */
3625: || (opcode & 0xffc0) == 0x4ec0 /* JMP */
3626: || (opcode & 0xff00) == 0x6100 /* BSR */
3627: || ((opcode & 0xf000) == 0x6000 /* Bcc */
3628: && cctrue ((opcode >> 8) & 0xf))
3629: || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
3630: && !cctrue ((opcode >> 8) & 0xf)
3631: && (uae_s16)m68k_dreg (regs, opcode & 7) != 0))
3632: {
3633: last_trace_ad = m68k_getpc ();
3634: unset_special (SPCFLAG_TRACE);
3635: set_special (SPCFLAG_DOTRACE);
3636: }
3637: } else if (regs.t1) {
3638: last_trace_ad = m68k_getpc ();
3639: unset_special (SPCFLAG_TRACE);
3640: set_special (SPCFLAG_DOTRACE);
3641: }
3642: }
3643:
1.1.1.7 ! root 3644: static void check_uae_int_request(void)
! 3645: {
! 3646: #ifndef WINUAE_FOR_HATARI
! 3647: if (uae_int_requested || uaenet_int_requested) {
! 3648: if ((uae_int_requested & 0x00ff) || uaenet_int_requested)
! 3649: INTREQ_f(0x8000 | 0x0008);
! 3650: if (uae_int_requested & 0xff00)
! 3651: INTREQ_f(0x8000 | 0x2000);
! 3652: set_special(SPCFLAG_INT);
! 3653: }
! 3654: #endif
! 3655: }
1.1.1.4 root 3656:
1.1.1.7 ! root 3657: void cpu_sleep_millis(int ms)
1.1.1.4 root 3658: {
1.1.1.7 ! root 3659: #ifndef WINUAE_FOR_HATARI
! 3660: #ifdef WITH_PPC
! 3661: int state = ppc_state;
! 3662: if (state)
! 3663: uae_ppc_spinlock_release();
! 3664: #endif
! 3665: sleep_millis_main(ms);
! 3666: #ifdef WITH_PPC
! 3667: if (state)
! 3668: uae_ppc_spinlock_get();
! 3669: #endif
! 3670: #endif
! 3671: }
! 3672:
! 3673: #define PPC_HALTLOOP_SCANLINES 25
! 3674: // ppc_cpu_idle
! 3675: // 0 = busy
! 3676: // 1-9 = wait, levels
! 3677: // 10 = max wait
! 3678:
! 3679: static bool haltloop(void)
! 3680: {
! 3681: #ifndef WINUAE_FOR_HATARI
! 3682: #ifdef WITH_PPC
! 3683: if (regs.halted < 0) {
! 3684: int rpt_end = 0;
! 3685: int ovpos = vpos;
! 3686:
! 3687: while (regs.halted) {
! 3688: int vsynctimeline = vsynctimebase / (maxvpos_display + 1);
! 3689: int lines;
! 3690: int rpt_scanline = read_processor_time();
! 3691: int rpt_end = rpt_scanline + vsynctimeline;
! 3692:
! 3693: // See expansion handling.
! 3694: // Dialog must be opened from main thread.
! 3695: if (regs.halted == -2) {
! 3696: regs.halted = -1;
! 3697: notify_user (NUMSG_UAEBOOTROM_PPC);
! 3698: }
! 3699:
! 3700: if (currprefs.ppc_cpu_idle) {
! 3701:
! 3702: int maxlines = 100 - (currprefs.ppc_cpu_idle - 1) * 10;
! 3703: int i;
! 3704:
! 3705: event_wait = false;
! 3706: for (i = 0; i < ev_max; i++) {
! 3707: if (i == ev_hsync)
! 3708: continue;
! 3709: if (i == ev_audio)
! 3710: continue;
! 3711: if (!eventtab[i].active)
! 3712: continue;
! 3713: if (eventtab[i].evtime - currcycle < maxlines * maxhpos * CYCLE_UNIT)
! 3714: break;
! 3715: }
! 3716: if (currprefs.ppc_cpu_idle >= 10 || (i == ev_max && vpos > 0 && vpos < maxvpos - maxlines)) {
! 3717: cpu_sleep_millis(1);
! 3718: }
! 3719: check_uae_int_request();
! 3720: uae_ppc_execute_check();
! 3721:
! 3722: lines = (read_processor_time() - rpt_scanline) / vsynctimeline + 1;
! 3723:
! 3724: } else {
! 3725:
! 3726: event_wait = true;
! 3727: lines = 0;
! 3728:
! 3729: }
! 3730:
! 3731: if (lines > maxvpos / 2)
! 3732: lines = maxvpos / 2;
! 3733:
! 3734: while (lines-- >= 0) {
! 3735: ovpos = vpos;
! 3736: while (ovpos == vpos) {
! 3737: x_do_cycles(8 * CYCLE_UNIT);
! 3738: uae_ppc_execute_check();
! 3739: if (regs.spcflags & SPCFLAG_COPPER)
! 3740: do_copper();
! 3741: if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
! 3742: if (regs.spcflags & SPCFLAG_BRK) {
! 3743: unset_special(SPCFLAG_BRK);
! 3744: #ifdef DEBUGGER
! 3745: if (debugging)
! 3746: debug();
! 3747: #endif
! 3748: }
! 3749: return true;
! 3750: }
! 3751: }
! 3752:
! 3753: // sync chipset with real time
! 3754: for (;;) {
! 3755: check_uae_int_request();
! 3756: ppc_interrupt(intlev());
! 3757: uae_ppc_execute_check();
! 3758: if (event_wait)
! 3759: break;
! 3760: int d = read_processor_time() - rpt_end;
! 3761: if (d < -2 * vsynctimeline || d >= 0)
! 3762: break;
! 3763: }
! 3764: }
! 3765:
! 3766:
1.1.1.4 root 3767: }
1.1.1.7 ! root 3768:
! 3769: } else {
1.1.1.4 root 3770: #endif
1.1.1.7 ! root 3771: while (regs.halted) {
! 3772: static int prevvpos;
! 3773: if (vpos == 0 && prevvpos) {
! 3774: prevvpos = 0;
! 3775: cpu_sleep_millis(8);
! 3776: }
! 3777: if (vpos)
! 3778: prevvpos = 1;
! 3779: x_do_cycles(8 * CYCLE_UNIT);
! 3780:
! 3781: if (regs.spcflags & SPCFLAG_COPPER)
! 3782: do_copper();
! 3783:
! 3784: if (regs.spcflags) {
! 3785: if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
! 3786: return true;
! 3787: }
! 3788: }
! 3789: #ifdef WITH_PPC
1.1.1.4 root 3790: }
1.1.1.7 ! root 3791: #endif
! 3792:
! 3793: return false;
! 3794: #else
! 3795: /* In Hatari, we don't use the halt state, we do a reset */
! 3796: return false;
! 3797: #endif
1.1.1.4 root 3798: }
3799:
1.1.1.7 ! root 3800: #ifdef WITH_PPC
! 3801: static bool uae_ppc_poll_check_halt(void)
1.1.1.4 root 3802: {
1.1.1.7 ! root 3803: if (regs.halted) {
! 3804: if (haltloop())
! 3805: return true;
1.1.1.4 root 3806: }
1.1.1.7 ! root 3807: return false;
1.1.1.4 root 3808: }
1.1.1.7 ! root 3809: #endif
1.1.1.4 root 3810:
3811:
1.1.1.7 ! root 3812: // handle interrupt delay (few cycles)
! 3813: STATIC_INLINE bool time_for_interrupt (void)
1.1.1.4 root 3814: {
1.1.1.7 ! root 3815: return regs.ipl > regs.intmask || regs.ipl == 7;
! 3816: }
1.1.1.4 root 3817:
1.1.1.7 ! root 3818: void doint (void)
! 3819: {
! 3820: #ifdef WITH_PPC
! 3821: if (ppc_state) {
! 3822: if (!ppc_interrupt(intlev()))
! 3823: return;
1.1.1.4 root 3824: }
1.1.1.7 ! root 3825: #endif
! 3826: if (m68k_interrupt_delay) {
! 3827: regs.ipl_pin = intlev ();
! 3828: unset_special (SPCFLAG_INT);
! 3829: return;
1.1.1.4 root 3830: }
1.1.1.7 ! root 3831: if (currprefs.cpu_compatible && currprefs.cpu_model < 68020)
! 3832: set_special (SPCFLAG_INT);
! 3833: else
! 3834: set_special (SPCFLAG_DOINT);
1.1.1.4 root 3835: }
3836:
1.1.1.7 ! root 3837: #ifndef WINUAE_FOR_HATARI
! 3838: #define IDLETIME (currprefs.cpu_idle * sleep_resolution / 1000)
! 3839: #endif
1.1.1.4 root 3840:
1.1.1.7 ! root 3841: #ifdef WINUAE_FOR_HATARI
1.1.1.4 root 3842: /*
3843: * Handle special flags
3844: */
3845:
3846: static bool do_specialties_interrupt (int Pending)
3847: {
1.1.1.5 root 3848: #if ENABLE_DSP_EMU
3849: /* Check for DSP int first (if enabled) (level 6) */
3850: if (regs.spcflags & SPCFLAG_DSP) {
3851: if (DSP_ProcessIRQ() == true)
3852: return true;
3853: }
3854: #endif
3855:
3856: /* Check for MFP ints (level 6) */
1.1.1.4 root 3857: if (regs.spcflags & SPCFLAG_MFP) {
1.1.1.5 root 3858: if (MFP_ProcessIRQ() == true)
1.1.1.4 root 3859: return true; /* MFP exception was generated, no higher interrupt can happen */
3860: }
3861:
3862: /* No MFP int, check for VBL/HBL ints (levels 4/2) */
3863: if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
3864: int intr = intlev ();
3865: /* SPCFLAG_DOINT will be enabled again in MakeFromSR to handle pending interrupts! */
3866: // unset_special (SPCFLAG_DOINT);
3867: unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
3868: if (intr != -1 && intr > regs.intmask) {
1.1.1.7 ! root 3869: do_interrupt (intr); /* process the interrupt */
1.1.1.4 root 3870: return true;
3871: }
3872: }
3873:
3874: return false; /* no interrupt was found */
3875: }
1.1.1.7 ! root 3876: #endif
1.1.1.4 root 3877:
1.1.1.7 ! root 3878: static int do_specialties (int cycles)
1.1.1.4 root 3879: {
1.1.1.7 ! root 3880: if (regs.spcflags & SPCFLAG_MODE_CHANGE)
! 3881: return 1;
! 3882:
! 3883: #ifndef WINUAE_FOR_HATARI
! 3884: if (regs.spcflags & SPCFLAG_CHECK) {
! 3885: if (regs.halted) {
! 3886: if (haltloop())
! 3887: return 1;
! 3888: }
! 3889: if (m68k_reset_delay) {
! 3890: int vsynccnt = 60;
! 3891: int vsyncstate = -1;
! 3892: while (vsynccnt > 0 && !quit_program) {
! 3893: x_do_cycles(8 * CYCLE_UNIT);
! 3894: if (regs.spcflags & SPCFLAG_COPPER)
! 3895: do_copper();
! 3896: if (timeframes != vsyncstate) {
! 3897: vsyncstate = timeframes;
! 3898: vsynccnt--;
! 3899: }
! 3900: }
! 3901: }
! 3902: m68k_reset_delay = 0;
! 3903: unset_special(SPCFLAG_CHECK);
! 3904: }
! 3905: #endif
! 3906:
! 3907: #ifdef ACTION_REPLAY
! 3908: #ifdef ACTION_REPLAY_HRTMON
! 3909: if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) {
! 3910: int isinhrt = (m68k_getpc () >= hrtmem_start && m68k_getpc () < hrtmem_start + hrtmem_size);
! 3911: /* exit from HRTMon? */
! 3912: if (hrtmon_flag == ACTION_REPLAY_ACTIVE && !isinhrt)
! 3913: hrtmon_hide ();
! 3914: /* HRTMon breakpoint? (not via IRQ7) */
! 3915: if (hrtmon_flag == ACTION_REPLAY_IDLE && isinhrt)
! 3916: hrtmon_breakenter ();
! 3917: if (hrtmon_flag == ACTION_REPLAY_ACTIVATE)
! 3918: hrtmon_enter ();
! 3919: }
! 3920: #endif
! 3921: if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE) {
! 3922: /*if (action_replay_flag == ACTION_REPLAY_ACTIVE && !is_ar_pc_in_rom ())*/
! 3923: /* write_log (_T("PC:%p\n"), m68k_getpc ());*/
! 3924:
! 3925: if (action_replay_flag == ACTION_REPLAY_ACTIVATE || action_replay_flag == ACTION_REPLAY_DORESET)
! 3926: action_replay_enter ();
! 3927: if ((action_replay_flag == ACTION_REPLAY_HIDE || action_replay_flag == ACTION_REPLAY_ACTIVE) && !is_ar_pc_in_rom ()) {
! 3928: action_replay_hide ();
! 3929: unset_special (SPCFLAG_ACTION_REPLAY);
! 3930: }
! 3931: if (action_replay_flag == ACTION_REPLAY_WAIT_PC) {
! 3932: /*write_log (_T("Waiting for PC: %p, current PC= %p\n"), wait_for_pc, m68k_getpc ());*/
! 3933: if (m68k_getpc () == wait_for_pc) {
! 3934: action_replay_flag = ACTION_REPLAY_ACTIVATE; /* Activate after next instruction. */
! 3935: }
! 3936: }
! 3937: }
! 3938: #endif
! 3939:
! 3940: #ifndef WINUAE_FOR_HATARI
! 3941: if (regs.spcflags & SPCFLAG_COPPER)
! 3942: do_copper ();
! 3943: #endif
! 3944:
1.1.1.4 root 3945: #ifdef JIT
3946: unset_special (SPCFLAG_END_COMPILE); /* has done its job */
3947: #endif
3948:
1.1.1.7 ! root 3949: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 3950: while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && !currprefs.blitter_cycle_exact) {
3951: int c = blitnasty ();
1.1.1.7 ! root 3952: if (c < 0) {
! 3953: break;
! 3954: } else if (c > 0) {
1.1.1.4 root 3955: cycles -= c * CYCLE_UNIT * 2;
3956: if (cycles < CYCLE_UNIT)
3957: cycles = 0;
1.1.1.7 ! root 3958: } else {
1.1.1.4 root 3959: c = 4;
1.1.1.7 ! root 3960: }
! 3961: x_do_cycles (c * CYCLE_UNIT);
1.1.1.4 root 3962: if (regs.spcflags & SPCFLAG_COPPER)
3963: do_copper ();
1.1.1.7 ! root 3964: #ifdef WITH_PPC
! 3965: if (ppc_state) {
! 3966: if (uae_ppc_poll_check_halt())
! 3967: return true;
! 3968: uae_ppc_execute_check();
! 3969: }
! 3970: #endif
1.1.1.4 root 3971: }
3972: #endif
3973:
1.1.1.7 ! root 3974: #ifdef WINUAE_FOR_HATARI
1.1.1.4 root 3975: if (regs.spcflags & SPCFLAG_BUSERROR) {
3976: /* We can not execute bus errors directly in the memory handler
3977: * functions since the PC should point to the address of the next
3978: * instruction, so we're executing the bus errors here: */
3979: unset_special(SPCFLAG_BUSERROR);
1.1.1.7 ! root 3980: Exception(2);
1.1.1.4 root 3981: }
1.1.1.7 ! root 3982: #endif
1.1.1.4 root 3983:
3984: if (regs.spcflags & SPCFLAG_DOTRACE)
1.1.1.7 ! root 3985: Exception (9);
1.1.1.4 root 3986:
1.1.1.7 ! root 3987: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 3988: if (regs.spcflags & SPCFLAG_TRAP) {
3989: unset_special (SPCFLAG_TRAP);
1.1.1.7 ! root 3990: Exception (3);
1.1.1.4 root 3991: }
1.1.1.7 ! root 3992: #endif
! 3993: bool first = true;
! 3994: while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) {
! 3995: isstopped:
! 3996: #ifndef WINUAE_FOR_HATARI
! 3997: check_uae_int_request();
! 3998: {
! 3999: extern void bsdsock_fake_int_handler (void);
! 4000: extern int volatile bsd_int_requested;
! 4001: if (bsd_int_requested)
! 4002: bsdsock_fake_int_handler ();
! 4003: }
! 4004: #endif
! 4005:
! 4006: if (cpu_tracer > 0) {
! 4007: cputrace.stopped = regs.stopped;
! 4008: cputrace.intmask = regs.intmask;
! 4009: cputrace.sr = regs.sr;
! 4010: cputrace.state = 1;
! 4011: cputrace.pc = m68k_getpc ();
! 4012: cputrace.memoryoffset = 0;
! 4013: cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
! 4014: cputrace.readcounter = cputrace.writecounter = 0;
! 4015: }
! 4016: if (!first)
! 4017: x_do_cycles (currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT);
1.1.1.4 root 4018:
1.1.1.7 ! root 4019: #ifdef WINUAE_FOR_HATARI
! 4020: if (!first)
! 4021: {
! 4022: if ( currprefs.cpu_cycle_exact )
! 4023: M68000_AddCycles(2);
! 4024: else /* TODO [NP] : always do only M68000_AddCycles(2) ? */
! 4025: M68000_AddCycles(4);
! 4026: }
1.1.1.4 root 4027:
4028: /* It is possible one or more ints happen at the same time */
1.1.1.5 root 4029: /* We must process them during the same cpu cycle then choose the highest priority one */
4030: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
1.1.1.7 ! root 4031: CALL_VAR(PendingInterruptFunction);
1.1.1.5 root 4032: if ( MFP_UpdateNeeded == true )
1.1.1.7 ! root 4033: MFP_UpdateIRQ ( 0 );
1.1.1.4 root 4034:
1.1.1.5 root 4035: /* Check is there's an interrupt to process (could be a delayed MFP interrupt) */
1.1.1.7 ! root 4036: if (regs.spcflags & SPCFLAG_MFP) {
! 4037: MFP_DelayIRQ (); /* Handle IRQ propagation */
! 4038: M68000_Update_intlev (); /* Refresh the list of pending interrupts */
1.1.1.5 root 4039: }
1.1.1.7 ! root 4040: #endif
! 4041: first = false;
! 4042: #ifndef WINUAE_FOR_HATARI
1.1.1.5 root 4043: if (regs.spcflags & SPCFLAG_COPPER)
4044: do_copper ();
1.1.1.4 root 4045: #endif
4046:
1.1.1.7 ! root 4047: if (m68k_interrupt_delay) {
1.1.1.5 root 4048: ipl_fetch ();
4049: if (time_for_interrupt ()) {
1.1.1.7 ! root 4050: do_interrupt (regs.ipl);
1.1.1.5 root 4051: }
4052: } else {
1.1.1.7 ! root 4053: if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
! 4054: int intr = intlev ();
! 4055: unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
! 4056: #ifdef WITH_PPC
! 4057: bool m68kint = true;
! 4058: if (ppc_state) {
! 4059: m68kint = ppc_interrupt(intr);
! 4060: }
! 4061: if (m68kint) {
1.1.1.4 root 4062: #endif
1.1.1.7 ! root 4063: if (intr > 0 && intr > regs.intmask)
! 4064: do_interrupt (intr);
! 4065: #ifdef WITH_PPC
! 4066: }
! 4067: #endif
! 4068: }
1.1.1.5 root 4069: }
1.1.1.7 ! root 4070:
! 4071: if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
! 4072: m68k_resumestopped();
1.1.1.5 root 4073: return 1;
4074: }
1.1.1.4 root 4075:
1.1.1.7 ! root 4076: #ifdef WITH_PPC
! 4077: if (ppc_state) {
! 4078: uae_ppc_execute_check();
! 4079: uae_ppc_poll_check_halt();
1.1.1.4 root 4080: }
1.1.1.7 ! root 4081: #endif
! 4082:
1.1.1.4 root 4083: }
4084:
4085: if (regs.spcflags & SPCFLAG_TRACE)
4086: do_trace ();
4087:
1.1.1.7 ! root 4088: #ifdef WINUAE_FOR_HATARI
! 4089: if (regs.spcflags & SPCFLAG_MFP) {
! 4090: MFP_DelayIRQ (); /* Handle IRQ propagation */
! 4091: M68000_Update_intlev (); /* Refresh the list of pending interrupts */
! 4092: }
! 4093: #endif
! 4094:
! 4095: if (m68k_interrupt_delay) {
1.1.1.4 root 4096: if (time_for_interrupt ()) {
1.1.1.7 ! root 4097: do_interrupt (regs.ipl);
1.1.1.4 root 4098: }
4099: } else {
4100: if (regs.spcflags & SPCFLAG_INT) {
4101: int intr = intlev ();
4102: unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
4103: if (intr > 0 && (intr > regs.intmask || intr == 7))
1.1.1.7 ! root 4104: do_interrupt (intr);
1.1.1.4 root 4105: }
4106: }
4107:
4108: if (regs.spcflags & SPCFLAG_DOINT) {
4109: unset_special (SPCFLAG_DOINT);
4110: set_special (SPCFLAG_INT);
4111: }
4112:
1.1.1.7 ! root 4113: #ifdef WINUAE_FOR_HATARI
! 4114: if (regs.spcflags & SPCFLAG_DEBUGGER)
1.1.1.4 root 4115: DebugCpu_Check();
1.1.1.7 ! root 4116: #endif
1.1.1.4 root 4117:
1.1.1.7 ! root 4118: if (regs.spcflags & SPCFLAG_BRK) {
! 4119: unset_special(SPCFLAG_BRK);
! 4120: #ifdef DEBUGGER
! 4121: if (debugging) {
! 4122: debug();
! 4123: if (regs.stopped)
! 4124: goto isstopped;
! 4125: }
! 4126: #endif
! 4127: #ifdef WINUAE_FOR_HATARI
! 4128: return 1; /* Exit the upper run_xxx() function */
! 4129: #endif
1.1.1.4 root 4130: }
1.1.1.7 ! root 4131:
1.1.1.4 root 4132: return 0;
4133: }
4134:
4135: //static uae_u32 pcs[1000];
4136:
1.1.1.7 ! root 4137: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 4138: #if DEBUG_CD32CDTVIO
4139:
4140: static uae_u32 cd32nextpc, cd32request;
4141:
4142: static void out_cd32io2 (void)
4143: {
4144: uae_u32 request = cd32request;
1.1.1.7 ! root 4145: write_log (_T("%08x returned\n"), request);
! 4146: //write_log (_T("ACTUAL=%d ERROR=%d\n"), get_long (request + 32), get_byte (request + 31));
1.1.1.4 root 4147: cd32nextpc = 0;
4148: cd32request = 0;
4149: }
4150:
4151: static void out_cd32io (uae_u32 pc)
4152: {
4153: TCHAR out[100];
4154: int ioreq = 0;
4155: uae_u32 request = m68k_areg (regs, 1);
4156:
4157: if (pc == cd32nextpc) {
4158: out_cd32io2 ();
4159: return;
4160: }
4161: out[0] = 0;
4162: switch (pc)
4163: {
4164: case 0xe57cc0:
4165: case 0xf04c34:
1.1.1.7 ! root 4166: _stprintf (out, _T("opendevice"));
1.1.1.4 root 4167: break;
4168: case 0xe57ce6:
4169: case 0xf04c56:
1.1.1.7 ! root 4170: _stprintf (out, _T("closedevice"));
1.1.1.4 root 4171: break;
4172: case 0xe57e44:
4173: case 0xf04f2c:
1.1.1.7 ! root 4174: _stprintf (out, _T("beginio"));
1.1.1.4 root 4175: ioreq = 1;
4176: break;
4177: case 0xe57ef2:
4178: case 0xf0500e:
1.1.1.7 ! root 4179: _stprintf (out, _T("abortio"));
1.1.1.4 root 4180: ioreq = -1;
4181: break;
4182: }
4183: if (out[0] == 0)
4184: return;
4185: if (cd32request)
1.1.1.7 ! root 4186: write_log (_T("old request still not returned!\n"));
1.1.1.4 root 4187: cd32request = request;
4188: cd32nextpc = get_long (m68k_areg (regs, 7));
1.1.1.7 ! root 4189: write_log (_T("%s A1=%08X\n"), out, request);
1.1.1.4 root 4190: if (ioreq) {
4191: static int cnt = 0;
4192: int cmd = get_word (request + 28);
4193: #if 0
1.1.1.7 ! root 4194: if (cmd == 33) {
! 4195: uaecptr data = get_long (request + 40);
! 4196: write_log (_T("CD_CONFIG:\n"));
! 4197: for (int i = 0; i < 16; i++) {
! 4198: write_log (_T("%08X=%08X\n"), get_long (data), get_long (data + 4));
! 4199: data += 8;
! 4200: }
! 4201: }
! 4202: #endif
! 4203: #if 0
1.1.1.4 root 4204: if (cmd == 37) {
4205: cnt--;
4206: if (cnt <= 0)
4207: activate_debugger ();
4208: }
4209: #endif
1.1.1.7 ! root 4210: write_log (_T("CMD=%d DATA=%08X LEN=%d %OFF=%d PC=%x\n"),
! 4211: cmd, get_long (request + 40),
! 4212: get_long (request + 36), get_long (request + 44), M68K_GETPC);
1.1.1.4 root 4213: }
4214: if (ioreq < 0)
4215: ;//activate_debugger ();
4216: }
4217:
1.1.1.7 ! root 4218: #endif
! 4219: #endif
! 4220:
! 4221: static void bus_error(void)
! 4222: {
! 4223: TRY (prb2) {
! 4224: Exception (2);
! 4225: } CATCH (prb2) {
! 4226: cpu_halt (1);
! 4227: } ENDTRY
! 4228: }
1.1.1.4 root 4229:
4230: #ifndef CPUEMU_11
4231:
4232: static void m68k_run_1 (void)
4233: {
4234: }
4235:
4236: #else
4237:
4238: /* It's really sad to have two almost identical functions for this, but we
4239: do it all for performance... :(
4240: This version emulates 68000's prefetch "cache" */
4241: static void m68k_run_1 (void)
4242: {
4243: struct regstruct *r = ®s;
1.1.1.7 ! root 4244: bool exit = false;
! 4245: printf ( "run_1\n" );
1.1.1.4 root 4246:
1.1.1.7 ! root 4247: while (!exit) {
! 4248: TRY (prb) {
! 4249: while (!exit) {
! 4250: r->opcode = r->ir;
! 4251:
! 4252: count_instr (r->opcode);
! 4253:
! 4254: #ifdef WINUAE_FOR_HATARI
! 4255: //m68k_dumpstate_file(stderr, NULL);
! 4256: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
! 4257: {
! 4258: int FrameCycles, HblCounterVideo, LineCycles;
1.1.1.4 root 4259:
1.1.1.7 ! root 4260: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1.1.1.4 root 4261:
1.1.1.7 ! root 4262: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
! 4263: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
! 4264: }
! 4265: #endif
1.1.1.4 root 4266:
1.1.1.7 ! root 4267: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 4268: #if DEBUG_CD32CDTVIO
1.1.1.7 ! root 4269: out_cd32io (m68k_getpc ());
! 4270: #endif
1.1.1.4 root 4271: #endif
4272:
4273: #if 0
1.1.1.7 ! root 4274: int pc = m68k_getpc ();
! 4275: if (pc == 0xdff002)
! 4276: write_log (_T("hip\n"));
! 4277: if (pc != pcs[0] && (pc < 0xd00000 || pc > 0x1000000)) {
! 4278: memmove (pcs + 1, pcs, 998 * 4);
! 4279: pcs[0] = pc;
! 4280: //write_log (_T("%08X-%04X "), pc, r->opcode);
! 4281: }
1.1.1.4 root 4282: #endif
1.1.1.7 ! root 4283: do_cycles (cpu_cycles);
! 4284: r->instruction_pc = m68k_getpc ();
! 4285: cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
! 4286: cpu_cycles = adjust_cycles (cpu_cycles);
! 4287:
! 4288: #ifdef WINUAE_FOR_HATARI
! 4289: M68000_AddCyclesWithPairing(cpu_cycles * 2 / CYCLE_UNIT);
! 4290:
! 4291: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
! 4292: /* Add some extra cycles to simulate a wait state */
! 4293: unset_special(SPCFLAG_EXTRA_CYCLES);
! 4294: M68000_AddCycles(nWaitStateCycles);
! 4295: nWaitStateCycles = 0;
! 4296: }
1.1.1.5 root 4297:
1.1.1.7 ! root 4298: /* We can have several interrupts at the same time before the next CPU instruction */
! 4299: /* We must check for pending interrupt and call do_specialties_interrupt() only */
! 4300: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
! 4301: /* and prevent exiting the STOP state when calling do_specialties() after. */
! 4302: /* For performance, we first test PendingInterruptCount, then regs.spcflags */
! 4303: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
! 4304: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */
! 4305: if ( MFP_UpdateNeeded == true )
! 4306: MFP_UpdateIRQ ( 0 );
! 4307: #endif
1.1.1.4 root 4308:
1.1.1.7 ! root 4309: if (r->spcflags) {
! 4310: if (do_specialties (cpu_cycles))
! 4311: exit = true;
! 4312: }
! 4313: regs.ipl = regs.ipl_pin;
! 4314: if (!currprefs.cpu_compatible || (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010))
! 4315: exit = true;
! 4316: }
! 4317: } CATCH (prb) {
! 4318: bus_error();
! 4319: if (r->spcflags) {
! 4320: if (do_specialties(cpu_cycles))
! 4321: exit = true;
! 4322: }
! 4323: regs.ipl = regs.ipl_pin;
! 4324: } ENDTRY
! 4325: }
! 4326: }
1.1.1.4 root 4327:
4328: #endif /* CPUEMU_11 */
4329:
1.1.1.7 ! root 4330: #ifndef CPUEMU_13
1.1.1.4 root 4331:
4332: static void m68k_run_1_ce (void)
4333: {
4334: }
4335:
4336: #else
4337:
4338: /* cycle-exact m68k_run () */
4339:
4340: static void m68k_run_1_ce (void)
4341: {
4342: struct regstruct *r = ®s;
1.1.1.7 ! root 4343: bool first = true;
! 4344: bool exit = false;
! 4345: printf ( "run_1_ce\n" );
! 4346:
! 4347: while (!exit) {
! 4348: TRY (prb) {
! 4349: if (first) {
! 4350: if (cpu_tracer < 0) {
! 4351: memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
! 4352: r->ir = cputrace.ir;
! 4353: r->irc = cputrace.irc;
! 4354: r->sr = cputrace.sr;
! 4355: r->usp = cputrace.usp;
! 4356: r->isp = cputrace.isp;
! 4357: r->intmask = cputrace.intmask;
! 4358: r->stopped = cputrace.stopped;
! 4359: m68k_setpc (cputrace.pc);
! 4360: if (!r->stopped) {
! 4361: if (cputrace.state > 1) {
! 4362: write_log (_T("CPU TRACE: EXCEPTION %d\n"), cputrace.state);
! 4363: Exception (cputrace.state);
! 4364: } else if (cputrace.state == 1) {
! 4365: write_log (_T("CPU TRACE: %04X\n"), cputrace.opcode);
! 4366: (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
! 4367: }
! 4368: } else {
! 4369: write_log (_T("CPU TRACE: STOPPED\n"));
! 4370: }
! 4371: if (r->stopped)
! 4372: set_special (SPCFLAG_STOP);
! 4373: set_cpu_tracer (false);
! 4374: goto cont;
! 4375: }
! 4376: set_cpu_tracer (false);
! 4377: first = false;
! 4378: }
1.1.1.4 root 4379:
1.1.1.7 ! root 4380: while (!exit) {
! 4381: r->opcode = r->ir;
1.1.1.4 root 4382:
1.1.1.7 ! root 4383: #ifdef WINUAE_FOR_HATARI
! 4384: //m68k_dumpstate_file(stderr, NULL);
! 4385: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
! 4386: {
! 4387: int FrameCycles, HblCounterVideo, LineCycles;
1.1.1.4 root 4388:
1.1.1.7 ! root 4389: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1.1.1.4 root 4390:
1.1.1.7 ! root 4391: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
! 4392: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
! 4393: }
! 4394: #endif
! 4395:
! 4396: #ifndef WINUAE_FOR_HATARI
! 4397: #if DEBUG_CD32CDTVIO
! 4398: out_cd32io (m68k_getpc ());
! 4399: #endif
! 4400: #endif
! 4401: if (cpu_tracer) {
! 4402: memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
! 4403: cputrace.opcode = r->opcode;
! 4404: cputrace.ir = r->ir;
! 4405: cputrace.irc = r->irc;
! 4406: cputrace.sr = r->sr;
! 4407: cputrace.usp = r->usp;
! 4408: cputrace.isp = r->isp;
! 4409: cputrace.intmask = r->intmask;
! 4410: cputrace.stopped = r->stopped;
! 4411: cputrace.state = 1;
! 4412: cputrace.pc = m68k_getpc ();
! 4413: cputrace.startcycles = get_cycles ();
! 4414: cputrace.memoryoffset = 0;
! 4415: cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
! 4416: cputrace.readcounter = cputrace.writecounter = 0;
! 4417: }
! 4418:
! 4419: #ifndef WINUAE_FOR_HATARI
! 4420: if (inputrecord_debug & 4) {
! 4421: if (input_record > 0)
! 4422: inprec_recorddebug_cpu (1);
! 4423: else if (input_play > 0)
! 4424: inprec_playdebug_cpu (1);
! 4425: }
! 4426: #endif
! 4427:
! 4428: #ifdef WINUAE_FOR_HATARI
! 4429: currcycle = 0;
! 4430: #endif
! 4431:
! 4432: r->instruction_pc = m68k_getpc ();
! 4433: (*cpufunctbl[r->opcode])(r->opcode);
! 4434: wait_memory_cycles(); // TODO NP : ici, ou plus bas ?
! 4435: #ifdef WINUAE_FOR_HATARI
! 4436: //fprintf ( stderr, "cyc_1ce %d\n" , currcycle );
! 4437: /* HACK for Hatari: Adding cycles should of course not be done
! 4438: * here in CE mode (so this should be removed later), but until
! 4439: * we're really there, this helps to get this mode running
! 4440: * at least to a basic extend! */
! 4441: M68000_AddCyclesWithPairing(currcycle * 2 / CYCLE_UNIT);
! 4442:
! 4443: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
! 4444: /* Add some extra cycles to simulate a wait state */
! 4445: unset_special(SPCFLAG_EXTRA_CYCLES);
! 4446: M68000_AddCycles(nWaitStateCycles);
! 4447: nWaitStateCycles = 0;
! 4448: }
! 4449:
! 4450: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
! 4451: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */
! 4452: if ( MFP_UpdateNeeded == true )
! 4453: MFP_UpdateIRQ ( 0 );
! 4454: #endif
! 4455:
! 4456: if (cpu_tracer) {
! 4457: cputrace.state = 0;
! 4458: }
! 4459: cont:
! 4460: if (cputrace.needendcycles) {
! 4461: cputrace.needendcycles = 0;
! 4462: write_log (_T("STARTCYCLES=%08x ENDCYCLES=%08lx\n"), cputrace.startcycles, get_cycles ());
! 4463: #ifndef WINUAE_FOR_HATARI
! 4464: log_dma_record ();
! 4465: #endif
! 4466: }
! 4467:
! 4468: if (r->spcflags || time_for_interrupt ()) {
! 4469: if (do_specialties (0))
! 4470: exit = true;
! 4471: }
! 4472:
! 4473: if (!currprefs.cpu_cycle_exact || currprefs.cpu_model > 68010)
! 4474: exit = true;
! 4475: }
! 4476: } CATCH (prb) {
! 4477: bus_error();
! 4478: if (r->spcflags || time_for_interrupt()) {
! 4479: if (do_specialties(0))
! 4480: exit = true;
! 4481: }
! 4482: } ENDTRY
! 4483: }
! 4484: }
! 4485:
! 4486: #endif
! 4487:
! 4488: #ifdef CPUEMU_20
! 4489: // emulate simple prefetch
! 4490: static uae_u16 get_word_020_prefetchf (uae_u32 pc)
! 4491: {
! 4492: if (pc == regs.prefetch020addr) {
! 4493: uae_u16 v = regs.prefetch020[0];
! 4494: regs.prefetch020[0] = regs.prefetch020[1];
! 4495: regs.prefetch020[1] = regs.prefetch020[2];
! 4496: regs.prefetch020[2] = x_get_word (pc + 6);
! 4497: regs.prefetch020addr += 2;
! 4498: return v;
! 4499: } else if (pc == regs.prefetch020addr + 2) {
! 4500: uae_u16 v = regs.prefetch020[1];
! 4501: regs.prefetch020[0] = regs.prefetch020[2];
! 4502: regs.prefetch020[1] = x_get_word (pc + 4);
! 4503: regs.prefetch020[2] = x_get_word (pc + 6);
! 4504: regs.prefetch020addr = pc + 2;
! 4505: return v;
! 4506: } else if (pc == regs.prefetch020addr + 4) {
! 4507: uae_u16 v = regs.prefetch020[2];
! 4508: regs.prefetch020[0] = x_get_word (pc + 2);
! 4509: regs.prefetch020[1] = x_get_word (pc + 4);
! 4510: regs.prefetch020[2] = x_get_word (pc + 6);
! 4511: regs.prefetch020addr = pc + 2;
! 4512: return v;
! 4513: } else {
! 4514: regs.prefetch020addr = pc + 2;
! 4515: regs.prefetch020[0] = x_get_word (pc + 2);
! 4516: regs.prefetch020[1] = x_get_word (pc + 4);
! 4517: regs.prefetch020[2] = x_get_word (pc + 6);
! 4518: return x_get_word (pc);
1.1.1.4 root 4519: }
4520: }
4521: #endif
4522:
4523: #ifdef JIT /* Completely different run_2 replacement */
4524:
4525: void do_nothing (void)
4526: {
4527: /* What did you expect this to do? */
4528: do_cycles (0);
4529: /* I bet you didn't expect *that* ;-) */
4530: }
4531:
4532: void exec_nostats (void)
4533: {
4534: struct regstruct *r = ®s;
4535:
4536: for (;;)
4537: {
1.1.1.7 ! root 4538: if (currprefs.cpu_compatible) {
! 4539: r->opcode = get_word_020_prefetchf(m68k_getpc());
! 4540: } else {
! 4541: r->opcode = x_get_iword(0);
! 4542: }
! 4543: cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
! 4544: cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.4 root 4545: do_cycles (cpu_cycles);
4546:
1.1.1.7 ! root 4547: #ifdef WITH_PPC
! 4548: if (ppc_state)
! 4549: ppc_interrupt(intlev());
! 4550: #endif
! 4551: #ifdef WINUAE_FOR_HATARI
! 4552: if (end_block(r->opcode) || r->spcflags)
! 4553: #else
! 4554:
! 4555: if (end_block(r->opcode) || r->spcflags || uae_int_requested || uaenet_int_requested)
! 4556: #endif
1.1.1.4 root 4557: return; /* We will deal with the spcflags in the caller */
4558: }
4559: }
4560:
4561: void execute_normal (void)
4562: {
4563: struct regstruct *r = ®s;
4564: int blocklen;
4565: cpu_history pc_hist[MAXRUN];
4566: int total_cycles;
4567:
4568: if (check_for_cache_miss ())
4569: return;
4570:
4571: total_cycles = 0;
4572: blocklen = 0;
4573: start_pc_p = r->pc_oldp;
4574: start_pc = r->pc;
4575: for (;;) {
4576: /* Take note: This is the do-it-normal loop */
1.1.1.7 ! root 4577: regs.instruction_pc = m68k_getpc ();
! 4578: if (currprefs.cpu_compatible) {
! 4579: r->opcode = get_word_020_prefetchf (regs.instruction_pc);
! 4580: } else {
! 4581: r->opcode = x_get_iword(0);
! 4582: }
1.1.1.4 root 4583:
4584: special_mem = DISTRUST_CONSISTENT_MEM;
4585: pc_hist[blocklen].location = (uae_u16*)r->pc_p;
4586:
1.1.1.7 ! root 4587: cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
! 4588: cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.4 root 4589: do_cycles (cpu_cycles);
4590: total_cycles += cpu_cycles;
4591: pc_hist[blocklen].specmem = special_mem;
4592: blocklen++;
1.1.1.7 ! root 4593: #ifdef WINUAE_FOR_HATARI
! 4594: if (end_block (r->opcode) || blocklen >= MAXRUN || r->spcflags) {
! 4595: #else
! 4596: if (end_block (r->opcode) || blocklen >= MAXRUN || r->spcflags || uae_int_requested || uaenet_int_requested) {
! 4597: #endif
1.1.1.4 root 4598: compile_block (pc_hist, blocklen, total_cycles);
4599: return; /* We will deal with the spcflags in the caller */
4600: }
4601: /* No need to check regs.spcflags, because if they were set,
4602: we'd have ended up inside that "if" */
1.1.1.7 ! root 4603:
! 4604: #ifdef WITH_PPC
! 4605: if (ppc_state)
! 4606: ppc_interrupt(intlev());
! 4607: #endif
1.1.1.4 root 4608: }
4609: }
4610:
4611: typedef void compiled_handler (void);
4612:
4613: static void m68k_run_jit (void)
4614: {
1.1.1.7 ! root 4615: printf ( "run_jit\n" );
1.1.1.4 root 4616: for (;;) {
1.1.1.7 ! root 4617: #ifdef WINUAE_FOR_HATARI
! 4618: //m68k_dumpstate_file(stderr, NULL);
1.1.1.4 root 4619: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
4620: {
4621: int FrameCycles, HblCounterVideo, LineCycles;
4622: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
4623: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.7 ! root 4624: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
1.1.1.4 root 4625: }
1.1.1.7 ! root 4626: #endif
1.1.1.4 root 4627:
4628: ((compiled_handler*)(pushall_call_handler))();
4629: /* Whenever we return from that, we should check spcflags */
1.1.1.7 ! root 4630: #ifndef WINUAE_FOR_HATARI
! 4631: check_uae_int_request();
! 4632: #endif
1.1.1.4 root 4633: if (regs.spcflags) {
4634: if (do_specialties (0)) {
4635: return;
4636: }
4637: }
4638: }
4639: }
4640: #endif /* JIT */
4641:
4642: #ifndef CPUEMU_0
4643:
4644: static void m68k_run_2 (void)
4645: {
4646: }
4647:
4648: #else
4649:
1.1.1.7 ! root 4650: static void opcodedebug (uae_u32 pc, uae_u16 opcode, bool full)
1.1.1.4 root 4651: {
4652: struct mnemolookup *lookup;
4653: struct instr *dp;
4654: uae_u32 addr;
4655: int fault;
4656:
4657: if (cpufunctbl[opcode] == op_illg_1)
4658: opcode = 0x4AFC;
4659: dp = table68k + opcode;
4660: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
4661: ;
4662: fault = 0;
4663: TRY(prb) {
4664: addr = mmu_translate (pc, (regs.mmu_ssw & 4) ? 1 : 0, 0, 0);
4665: } CATCH (prb) {
4666: fault = 1;
4667: } ENDTRY
4668: if (!fault) {
1.1.1.7 ! root 4669: TCHAR buf[100];
! 4670: if (full)
! 4671: write_log (_T("mmufixup=%d %04x %04x\n"), mmufixup[0].reg, regs.wb3_status, regs.mmu_ssw);
! 4672: m68k_disasm_2 (buf, sizeof buf / sizeof (TCHAR), addr, NULL, 1, NULL, NULL, 0);
! 4673: write_log (_T("%s\n"), buf);
! 4674: if (full)
! 4675: m68k_dumpstate (NULL);
! 4676: }
! 4677: }
! 4678:
! 4679: void cpu_halt (int id)
! 4680: {
! 4681: #ifndef WINUAE_FOR_HATARI
! 4682: // id < 0: m68k halted, PPC active.
! 4683: // id > 0: emulation halted.
! 4684: if (!regs.halted) {
! 4685: write_log (_T("CPU halted: reason = %d PC=%08x\n"), id, M68K_GETPC);
! 4686: regs.halted = id;
! 4687: gui_data.cpu_halted = id;
! 4688: gui_led(LED_CPU, 0, -1);
! 4689: if (id >= 0) {
! 4690: regs.intmask = 7;
! 4691: MakeSR ();
! 4692: audio_deactivate ();
! 4693: }
! 4694: set_special(SPCFLAG_CHECK);
! 4695: }
! 4696:
! 4697: #else
! 4698: Dialog_HaltDlg();
! 4699: #endif
! 4700: }
! 4701:
! 4702: #ifdef CPUEMU_33
! 4703: /* [NP] TODO : use 68060 in Hatari ? with DSP ? */
! 4704: /* MMU 68060 */
! 4705: static void m68k_run_mmu060 (void)
! 4706: {
! 4707: struct flag_struct f;
! 4708: int halt = 0;
! 4709: printf ( "run_mmu060\n" );
! 4710:
! 4711: while (!halt) {
! 4712: TRY (prb) {
! 4713: for (;;) {
! 4714: f.cznv = regflags.cznv;
! 4715: f.x = regflags.x;
! 4716: regs.instruction_pc = m68k_getpc ();
! 4717:
! 4718: do_cycles (cpu_cycles);
! 4719:
! 4720: mmu_opcode = -1;
! 4721: mmu060_state = 0;
! 4722: mmu_opcode = regs.opcode = x_prefetch (0);
! 4723: mmu060_state = 1;
! 4724:
! 4725: count_instr (regs.opcode);
! 4726: cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
! 4727:
! 4728: cpu_cycles = adjust_cycles (cpu_cycles);
! 4729:
! 4730: if (regs.spcflags) {
! 4731: if (do_specialties (cpu_cycles))
! 4732: return;
! 4733: }
! 4734: }
! 4735: } CATCH (prb) {
! 4736:
! 4737: m68k_setpci (regs.instruction_pc);
! 4738: regflags.cznv = f.cznv;
! 4739: regflags.x = f.x;
! 4740:
! 4741: if (mmufixup[0].reg >= 0) {
! 4742: m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
! 4743: mmufixup[0].reg = -1;
! 4744: }
! 4745: if (mmufixup[1].reg >= 0) {
! 4746: m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
! 4747: mmufixup[1].reg = -1;
! 4748: }
! 4749:
! 4750: TRY (prb2) {
! 4751: Exception (prb);
! 4752: } CATCH (prb2) {
! 4753: halt = 1;
! 4754: } ENDTRY
! 4755: } ENDTRY
1.1.1.4 root 4756: }
1.1.1.7 ! root 4757: cpu_halt(halt);
1.1.1.4 root 4758: }
1.1.1.7 ! root 4759:
1.1.1.4 root 4760: #endif
4761:
1.1.1.7 ! root 4762: #ifdef CPUEMU_31
1.1.1.4 root 4763:
4764: /* Aranym MMU 68040 */
4765: static void m68k_run_mmu040 (void)
4766: {
1.1.1.7 ! root 4767: struct flag_struct f;
! 4768: int halt = 0;
! 4769: printf ( "run_mmu040\n" );
! 4770:
! 4771: while (!halt) {
! 4772: TRY (prb) {
! 4773: for (;;) {
! 4774: #ifdef WINUAE_FOR_HATARI
! 4775: //m68k_dumpstate_file(stderr, NULL);
! 4776: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
! 4777: {
! 4778: int FrameCycles, HblCounterVideo, LineCycles;
! 4779: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 4780: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
! 4781: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
! 4782: }
! 4783: #endif
! 4784: f.cznv = regflags.cznv;
! 4785: f.x = regflags.x;
! 4786: mmu_restart = true;
! 4787: regs.instruction_pc = m68k_getpc ();
! 4788:
! 4789: do_cycles (cpu_cycles);
! 4790:
! 4791: mmu_opcode = -1;
! 4792: mmu_opcode = regs.opcode = x_prefetch (0);
! 4793: count_instr (regs.opcode);
! 4794: cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
! 4795: cpu_cycles = adjust_cycles (cpu_cycles);
! 4796:
! 4797: #ifdef WINUAE_FOR_HATARI
! 4798: M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
! 4799:
! 4800: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
! 4801: /* Add some extra cycles to simulate a wait state */
! 4802: unset_special(SPCFLAG_EXTRA_CYCLES);
! 4803: M68000_AddCycles(nWaitStateCycles);
! 4804: nWaitStateCycles = 0;
! 4805: }
1.1.1.4 root 4806:
1.1.1.7 ! root 4807: /* We can have several interrupts at the same time before the next CPU instruction */
! 4808: /* We must check for pending interrupt and call do_specialties_interrupt() only */
! 4809: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
! 4810: /* and prevent exiting the STOP state when calling do_specialties() after. */
! 4811: /* For performance, we first test PendingInterruptCount, then regs.spcflags */
! 4812: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
! 4813: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */
! 4814: if ( MFP_UpdateNeeded == true )
! 4815: MFP_UpdateIRQ ( 0 );
! 4816: #endif
1.1.1.4 root 4817:
1.1.1.7 ! root 4818: if (regs.spcflags) {
! 4819: if (do_specialties (cpu_cycles))
! 4820: return;
1.1.1.4 root 4821: }
1.1.1.7 ! root 4822:
! 4823: #ifdef WINUAE_FOR_HATARI
! 4824: /* Run DSP 56k code if necessary */
! 4825: if (bDspEnabled) {
! 4826: DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
! 4827: }
! 4828: #endif
1.1.1.4 root 4829: }
1.1.1.7 ! root 4830: } CATCH (prb) {
! 4831:
! 4832: if (mmu_restart) {
! 4833: /* restore state if instruction restart */
! 4834: regflags.cznv = f.cznv;
! 4835: regflags.x = f.x;
! 4836: m68k_setpci (regs.instruction_pc);
1.1.1.4 root 4837: }
1.1.1.7 ! root 4838:
! 4839: if (mmufixup[0].reg >= 0) {
! 4840: m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
! 4841: mmufixup[0].reg = -1;
1.1.1.4 root 4842: }
1.1.1.7 ! root 4843:
! 4844: TRY (prb2) {
! 4845: Exception (prb);
! 4846: } CATCH (prb2) {
! 4847: halt = 1;
! 4848: } ENDTRY
! 4849: } ENDTRY
! 4850: }
! 4851: cpu_halt(halt);
! 4852: }
! 4853:
! 4854: #endif
! 4855:
! 4856: #ifdef CPUEMU_32
! 4857:
! 4858: // Previous MMU 68030
! 4859: static void m68k_run_mmu030 (void)
! 4860: {
! 4861: struct flag_struct f;
! 4862: int halt = 0;
! 4863: printf ( "run_mmu030\n" );
! 4864:
! 4865: mmu030_opcode_stageb = -1;
! 4866: mmu030_fake_prefetch = -1;
! 4867: while(!halt) {
! 4868: TRY (prb) {
! 4869: for (;;) {
! 4870: int cnt;
! 4871: insretry:
! 4872: #ifdef WINUAE_FOR_HATARI
! 4873: //m68k_dumpstate_file(stderr, NULL);
! 4874: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
! 4875: {
! 4876: int FrameCycles, HblCounterVideo, LineCycles;
! 4877: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 4878: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
! 4879: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
1.1.1.4 root 4880: }
4881: #endif
1.1.1.7 ! root 4882: regs.instruction_pc = m68k_getpc ();
! 4883: f.cznv = regflags.cznv;
! 4884: f.x = regflags.x;
! 4885:
! 4886: mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0;
! 4887: mmu030_opcode = -1;
! 4888: if (mmu030_fake_prefetch >= 0) {
! 4889: regs.opcode = mmu030_fake_prefetch;
! 4890: // use fake prefetch opcode only if mapping changed
! 4891: uaecptr new_addr = mmu030_translate(regs.instruction_pc, regs.s != 0, false, false);
! 4892: if (mmu030_fake_prefetch_addr != new_addr) {
! 4893: regs.opcode = mmu030_fake_prefetch;
! 4894: write_log(_T("MMU030 fake prefetch remap: %04x, %08x -> %08x\n"), mmu030_fake_prefetch, mmu030_fake_prefetch_addr, new_addr);
! 4895: } else {
! 4896: if (mmu030_opcode_stageb < 0) {
! 4897: regs.opcode = x_prefetch (0);
! 4898: } else {
! 4899: regs.opcode = mmu030_opcode_stageb;
! 4900: mmu030_opcode_stageb = -1;
! 4901: }
! 4902: }
! 4903: mmu030_fake_prefetch = -1;
! 4904: } else if (mmu030_opcode_stageb < 0) {
! 4905: regs.opcode = x_prefetch (0);
! 4906: } else {
! 4907: regs.opcode = mmu030_opcode_stageb;
! 4908: mmu030_opcode_stageb = -1;
! 4909: }
! 4910:
! 4911: mmu030_opcode = regs.opcode;
! 4912: mmu030_ad[0].done = false;
! 4913:
! 4914: cnt = 50;
! 4915: for (;;) {
! 4916: regs.opcode = mmu030_opcode;
! 4917: mmu030_idx = 0;
! 4918: count_instr (regs.opcode);
! 4919: do_cycles (cpu_cycles);
! 4920: mmu030_retry = false;
! 4921:
! 4922: cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
! 4923: cnt--; // so that we don't get in infinite loop if things go horribly wrong
! 4924: if (!mmu030_retry)
! 4925: break;
! 4926: if (cnt < 0) {
! 4927: cpu_halt (9);
! 4928: break;
! 4929: }
! 4930: if (mmu030_retry && mmu030_opcode == -1)
! 4931: goto insretry; // urgh
! 4932: }
1.1.1.4 root 4933:
1.1.1.7 ! root 4934: mmu030_opcode = -1;
1.1.1.4 root 4935:
1.1.1.7 ! root 4936: cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.4 root 4937:
1.1.1.7 ! root 4938: #ifdef WINUAE_FOR_HATARI
! 4939: M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.4 root 4940:
1.1.1.7 ! root 4941: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
! 4942: /* Add some extra cycles to simulate a wait state */
! 4943: unset_special(SPCFLAG_EXTRA_CYCLES);
! 4944: M68000_AddCycles(nWaitStateCycles);
! 4945: nWaitStateCycles = 0;
! 4946: }
! 4947:
! 4948: /* We can have several interrupts at the same time before the next CPU instruction */
! 4949: /* We must check for pending interrupt and call do_specialties_interrupt() only */
! 4950: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
! 4951: /* and prevent exiting the STOP state when calling do_specialties() after. */
! 4952: /* For performance, we first test PendingInterruptCount, then regs.spcflags */
1.1.1.5 root 4953: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
4954: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */
4955: if ( MFP_UpdateNeeded == true )
4956: MFP_UpdateIRQ ( 0 );
1.1.1.7 ! root 4957: #endif
! 4958: if (regs.spcflags) {
! 4959: if (do_specialties (cpu_cycles))
! 4960: return;
! 4961: }
1.1.1.4 root 4962:
1.1.1.7 ! root 4963: #ifdef WINUAE_FOR_HATARI
! 4964: /* Run DSP 56k code if necessary */
! 4965: if (bDspEnabled) {
! 4966: DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
! 4967: }
! 4968: #endif
1.1.1.4 root 4969: }
1.1.1.7 ! root 4970: } CATCH (prb) {
! 4971:
! 4972: regflags.cznv = f.cznv;
! 4973: regflags.x = f.x;
1.1.1.4 root 4974:
1.1.1.7 ! root 4975: m68k_setpci (regs.instruction_pc);
! 4976:
! 4977: if (mmufixup[0].reg >= 0) {
! 4978: m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
! 4979: mmufixup[0].reg = -1;
1.1.1.4 root 4980: }
4981: if (mmufixup[1].reg >= 0) {
4982: m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
4983: mmufixup[1].reg = -1;
4984: }
1.1.1.7 ! root 4985:
! 4986: TRY (prb2) {
! 4987: Exception (prb);
! 4988: } CATCH (prb2) {
! 4989: halt = 1;
! 4990: } ENDTRY
! 4991: } ENDTRY
! 4992: }
! 4993: cpu_halt (halt);
! 4994: }
! 4995:
! 4996: #endif
! 4997:
! 4998:
! 4999: /* "cycle exact" 68040/060 */
! 5000:
! 5001: static void m68k_run_3ce (void)
! 5002: {
! 5003: struct regstruct *r = ®s;
! 5004: bool exit = false;
! 5005: printf ( "run_3ce\n" );
! 5006:
! 5007: while (!exit) {
! 5008: TRY(prb) {
! 5009: while (!exit) {
! 5010: #ifdef WINUAE_FOR_HATARI
! 5011: //m68k_dumpstate_file(stderr, NULL);
! 5012: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
! 5013: {
! 5014: int FrameCycles, HblCounterVideo, LineCycles;
! 5015: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 5016: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
! 5017: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
! 5018: }
! 5019: #endif
! 5020: r->instruction_pc = m68k_getpc();
! 5021: r->opcode = get_iword_cache_040(0);
! 5022: // "prefetch"
! 5023: if (regs.cacr & 0x8000)
! 5024: fill_icache040(r->instruction_pc + 16);
! 5025:
! 5026: (*cpufunctbl[r->opcode])(r->opcode);
! 5027:
! 5028: #ifdef WINUAE_FOR_HATARI
! 5029: //fprintf ( stderr, "cyc_3ce %d\n" , currcycle );
! 5030: M68000_AddCycles(currcycle * 2 / CYCLE_UNIT);
! 5031:
! 5032: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
! 5033: /* Add some extra cycles to simulate a wait state */
! 5034: unset_special(SPCFLAG_EXTRA_CYCLES);
! 5035: M68000_AddCycles(nWaitStateCycles);
! 5036: nWaitStateCycles = 0;
! 5037: }
! 5038:
! 5039: /* We can have several interrupts at the same time before the next CPU instruction */
! 5040: /* We must check for pending interrupt and call do_specialties_interrupt() only */
! 5041: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
! 5042: /* and prevent exiting the STOP state when calling do_specialties() after. */
! 5043: /* For performance, we first test PendingInterruptCount, then regs.spcflags */
! 5044: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
! 5045: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */
! 5046: if ( MFP_UpdateNeeded == true )
! 5047: MFP_UpdateIRQ ( 0 );
! 5048: #endif
! 5049: if (r->spcflags) {
! 5050: if (do_specialties (0))
! 5051: exit = true;
! 5052: }
! 5053:
! 5054: #ifdef WINUAE_FOR_HATARI
! 5055: /* Run DSP 56k code if necessary */
! 5056: if (bDspEnabled) {
! 5057: DSP_Run(2 * currcycle * 2 / CYCLE_UNIT);
1.1.1.4 root 5058: }
1.1.1.7 ! root 5059: #endif
1.1.1.4 root 5060: }
1.1.1.7 ! root 5061: } CATCH(prb) {
! 5062: bus_error();
! 5063: if (r->spcflags) {
! 5064: if (do_specialties(0))
! 5065: exit = true;
! 5066: }
! 5067: } ENDTRY
! 5068: }
! 5069: }
1.1.1.4 root 5070:
1.1.1.7 ! root 5071: /* "prefetch" 68040/060 */
1.1.1.4 root 5072:
1.1.1.7 ! root 5073: static void m68k_run_3p(void)
! 5074: {
! 5075: struct regstruct *r = ®s;
! 5076: bool exit = false;
! 5077: int cycles;
! 5078: printf ( "run_3p\n" );
! 5079:
! 5080: while (!exit) {
! 5081: TRY(prb) {
! 5082: while (!exit) {
! 5083: #ifdef WINUAE_FOR_HATARI
! 5084: //m68k_dumpstate_file(stderr, NULL);
! 5085: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
! 5086: {
! 5087: int FrameCycles, HblCounterVideo, LineCycles;
! 5088: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 5089: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
! 5090: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
! 5091: }
! 5092: #endif
! 5093: r->instruction_pc = m68k_getpc();
! 5094: r->opcode = get_iword_cache_040(0);
! 5095: // "prefetch"
! 5096: if (regs.cacr & 0x8000)
! 5097: fill_icache040(r->instruction_pc + 16);
! 5098:
! 5099: (*cpufunctbl[r->opcode])(r->opcode);
! 5100:
! 5101: cpu_cycles = 1 * CYCLE_UNIT;
! 5102: cycles = adjust_cycles(cpu_cycles);
! 5103: do_cycles(cycles);
! 5104: #ifdef WINUAE_FOR_HATARI
! 5105: M68000_AddCycles(cycles * 2 / CYCLE_UNIT);
! 5106:
! 5107: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
! 5108: /* Add some extra cycles to simulate a wait state */
! 5109: unset_special(SPCFLAG_EXTRA_CYCLES);
! 5110: M68000_AddCycles(nWaitStateCycles);
! 5111: nWaitStateCycles = 0;
! 5112: }
1.1.1.4 root 5113:
1.1.1.7 ! root 5114: /* We can have several interrupts at the same time before the next CPU instruction */
! 5115: /* We must check for pending interrupt and call do_specialties_interrupt() only */
! 5116: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
! 5117: /* and prevent exiting the STOP state when calling do_specialties() after. */
! 5118: /* For performance, we first test PendingInterruptCount, then regs.spcflags */
! 5119: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
! 5120: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */
! 5121: if ( MFP_UpdateNeeded == true )
! 5122: MFP_UpdateIRQ ( 0 );
! 5123: #endif
! 5124:
! 5125: if (r->spcflags) {
! 5126: if (do_specialties(0))
! 5127: exit = true;
! 5128: }
! 5129:
! 5130: #ifdef WINUAE_FOR_HATARI
! 5131: /* Run DSP 56k code if necessary */
! 5132: if (bDspEnabled) {
! 5133: DSP_Run(2 * cycles * 2 / CYCLE_UNIT);
! 5134: }
! 5135: #endif
! 5136: }
! 5137: } CATCH(prb) {
! 5138: bus_error();
! 5139: if (r->spcflags) {
! 5140: if (do_specialties(0))
! 5141: exit = true;
! 5142: }
! 5143: } ENDTRY
! 5144: }
1.1.1.4 root 5145: }
5146:
5147: /* "cycle exact" 68020/030 */
1.1.1.7 ! root 5148:
! 5149: STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp);
1.1.1.4 root 5150: static void m68k_run_2ce (void)
5151: {
5152: struct regstruct *r = ®s;
1.1.1.7 ! root 5153: bool exit = false;
! 5154: bool first = true;
! 5155: printf ( "run_2ce\n" );
! 5156:
! 5157: while (!exit) {
! 5158: TRY(prb) {
! 5159: if (first) {
! 5160: if (cpu_tracer < 0) {
! 5161: memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
! 5162: r->ir = cputrace.ir;
! 5163: r->irc = cputrace.irc;
! 5164: r->sr = cputrace.sr;
! 5165: r->usp = cputrace.usp;
! 5166: r->isp = cputrace.isp;
! 5167: r->intmask = cputrace.intmask;
! 5168: r->stopped = cputrace.stopped;
! 5169:
! 5170: r->msp = cputrace.msp;
! 5171: r->vbr = cputrace.vbr;
! 5172: r->caar = cputrace.caar;
! 5173: r->cacr = cputrace.cacr;
! 5174: r->cacheholdingdata020 = cputrace.cacheholdingdata020;
! 5175: r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
! 5176: r->prefetch020addr = cputrace.prefetch020addr;
! 5177: memcpy (&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
! 5178: memcpy (&caches020, &cputrace.caches020, sizeof caches020);
! 5179:
! 5180: m68k_setpc (cputrace.pc);
! 5181: if (!r->stopped) {
! 5182: if (cputrace.state > 1)
! 5183: Exception (cputrace.state);
! 5184: else if (cputrace.state == 1)
! 5185: (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
! 5186: }
! 5187: if (regs.stopped)
! 5188: set_special (SPCFLAG_STOP);
! 5189: set_cpu_tracer (false);
! 5190: goto cont;
! 5191: }
! 5192: set_cpu_tracer (false);
! 5193: first = false;
! 5194: }
1.1.1.4 root 5195:
1.1.1.7 ! root 5196: while (!exit) {
! 5197: static int prevopcode;
! 5198: #ifdef WINUAE_FOR_HATARI
! 5199: //m68k_dumpstate_file(stderr, NULL);
! 5200: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
! 5201: {
! 5202: int FrameCycles, HblCounterVideo, LineCycles;
! 5203: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 5204: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
! 5205: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
! 5206: #if 0
! 5207: // logs to debug data cache issues
! 5208: struct cache030 *c1 ,*c2;
! 5209: int lws1, lws2;
! 5210: uae_u32 tag1, tag2;
! 5211: c1 = getcache030 (dcaches030, (uaecptr)0x27ece, &tag1, &lws1);
! 5212: c2 = getcache030 (dcaches030, (uaecptr)0x7f8192+4, &tag2, &lws2);
! 5213: fprintf ( stderr , "cache valid %d tag1 %x lws1 %x ctag %x data %x mem=%x\n" , c1->valid[lws1] , tag1 , lws1 , c1->tag , c1->data[lws1] , get_long(0x27ece) );
! 5214: //fprintf ( stderr , "cache valid %d tag2 %x lws2 %x ctag %x data %x mem=%x\n" , c2->valid[lws2] , tag2 , lws2 , c2->tag , c2->data[lws2] , get_long(0x7f8192+4) );
! 5215: #endif
! 5216: }
1.1.1.4 root 5217:
1.1.1.7 ! root 5218: currcycle = 0;
! 5219: #endif
! 5220: r->instruction_pc = m68k_getpc ();
1.1.1.4 root 5221:
1.1.1.7 ! root 5222: if (regs.irc == 0xfffb) {
! 5223: gui_message (_T("OPCODE %04X HAS FAULTY PREFETCH! PC=%08X"), prevopcode, r->instruction_pc);
! 5224: }
1.1.1.4 root 5225:
1.1.1.7 ! root 5226: //write_log (_T("%x %04x\n"), r->instruction_pc, regs.irc);
1.1.1.4 root 5227:
1.1.1.7 ! root 5228: r->opcode = regs.irc;
! 5229: prevopcode = r->opcode;
! 5230: regs.irc = 0xfffb;
1.1.1.4 root 5231:
1.1.1.7 ! root 5232: //write_log (_T("%08x %04x\n"), r->instruction_pc, opcode);
1.1.1.5 root 5233:
1.1.1.7 ! root 5234: #ifndef WINUAE_FOR_HATARI
! 5235: #if DEBUG_CD32CDTVIO
! 5236: out_cd32io (r->instruction_pc);
! 5237: #endif
! 5238: #endif
1.1.1.4 root 5239:
1.1.1.7 ! root 5240: if (cpu_tracer) {
1.1.1.4 root 5241:
1.1.1.7 ! root 5242: #if CPUTRACE_DEBUG
! 5243: validate_trace ();
! 5244: #endif
! 5245: memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
! 5246: cputrace.opcode = r->opcode;
! 5247: cputrace.ir = r->ir;
! 5248: cputrace.irc = r->irc;
! 5249: cputrace.sr = r->sr;
! 5250: cputrace.usp = r->usp;
! 5251: cputrace.isp = r->isp;
! 5252: cputrace.intmask = r->intmask;
! 5253: cputrace.stopped = r->stopped;
! 5254: cputrace.state = 1;
! 5255: cputrace.pc = m68k_getpc ();
! 5256:
! 5257: cputrace.msp = r->msp;
! 5258: cputrace.vbr = r->vbr;
! 5259: cputrace.caar = r->caar;
! 5260: cputrace.cacr = r->cacr;
! 5261: cputrace.cacheholdingdata020 = r->cacheholdingdata020;
! 5262: cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
! 5263: cputrace.prefetch020addr = r->prefetch020addr;
! 5264: memcpy (&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
! 5265: memcpy (&cputrace.caches020, &caches020, sizeof caches020);
! 5266:
! 5267: cputrace.memoryoffset = 0;
! 5268: cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
! 5269: cputrace.readcounter = cputrace.writecounter = 0;
! 5270: }
1.1.1.4 root 5271:
1.1.1.7 ! root 5272: #ifndef WINUAE_FOR_HATARI
! 5273: if (inputrecord_debug & 4) {
! 5274: if (input_record > 0)
! 5275: inprec_recorddebug_cpu (1);
! 5276: else if (input_play > 0)
! 5277: inprec_playdebug_cpu (1);
! 5278: }
! 5279: #endif
1.1.1.4 root 5280:
1.1.1.7 ! root 5281: (*cpufunctbl[r->opcode])(r->opcode);
! 5282:
! 5283: wait_memory_cycles();
! 5284:
! 5285: #ifdef WINUAE_FOR_HATARI
! 5286: //fprintf ( stderr, "cyc_2ce %d\n" , currcycle );
! 5287: M68000_AddCycles(currcycle * 2 / CYCLE_UNIT);
! 5288:
! 5289: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
! 5290: /* Add some extra cycles to simulate a wait state */
! 5291: unset_special(SPCFLAG_EXTRA_CYCLES);
! 5292: M68000_AddCycles(nWaitStateCycles);
! 5293: nWaitStateCycles = 0;
! 5294: }
1.1.1.4 root 5295:
1.1.1.7 ! root 5296: /* We can have several interrupts at the same time before the next CPU instruction */
! 5297: /* We must check for pending interrupt and call do_specialties_interrupt() only */
! 5298: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
! 5299: /* and prevent exiting the STOP state when calling do_specialties() after. */
! 5300: /* For performance, we first test PendingInterruptCount, then regs.spcflags */
! 5301: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
! 5302: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */
! 5303: if ( MFP_UpdateNeeded == true )
! 5304: MFP_UpdateIRQ ( 0 );
! 5305: #endif
1.1.1.4 root 5306:
1.1.1.7 ! root 5307: cont:
! 5308: if (r->spcflags || time_for_interrupt ()) {
! 5309: if (do_specialties (0))
! 5310: exit = true;
! 5311: }
1.1.1.4 root 5312:
1.1.1.7 ! root 5313: #ifdef WINUAE_FOR_HATARI
! 5314: /* Run DSP 56k code if necessary */
! 5315: if (bDspEnabled) {
! 5316: //fprintf ( stderr, "dsp cyc_2ce %d\n" , currcycle );
! 5317: DSP_Run(2 * currcycle * 2 / CYCLE_UNIT);
! 5318: }
! 5319: #endif
1.1.1.4 root 5320:
1.1.1.7 ! root 5321: regs.ipl = regs.ipl_pin;
1.1.1.4 root 5322:
1.1.1.7 ! root 5323: }
! 5324: } CATCH(prb) {
! 5325: bus_error();
! 5326: if (r->spcflags || time_for_interrupt()) {
! 5327: if (do_specialties(0)) {
! 5328: exit = true;
! 5329: regs.ipl = regs.ipl_pin;
! 5330: }
! 5331: }
! 5332: } ENDTRY
1.1.1.4 root 5333: }
5334: }
5335:
1.1.1.7 ! root 5336: #ifdef CPUEMU_20
! 5337:
! 5338: // full prefetch 020 (more compatible)
1.1.1.4 root 5339: static void m68k_run_2p (void)
5340: {
5341: struct regstruct *r = ®s;
1.1.1.7 ! root 5342: bool exit = false;
! 5343: printf ( "run_2p\n" );
1.1.1.4 root 5344:
1.1.1.7 ! root 5345: while (!exit) {
! 5346: TRY(prb) {
! 5347: while (!exit) {
! 5348: #ifdef WINUAE_FOR_HATARI
! 5349: //m68k_dumpstate_file(stderr, NULL);
! 5350: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
! 5351: {
! 5352: int FrameCycles, HblCounterVideo, LineCycles;
! 5353: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 5354: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
! 5355: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
! 5356: }
! 5357: #endif
! 5358: r->instruction_pc = m68k_getpc ();
1.1.1.4 root 5359:
1.1.1.7 ! root 5360: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 5361: #if DEBUG_CD32CDTVIO
1.1.1.7 ! root 5362: out_cd32io (m68k_getpc ());
! 5363: #endif
1.1.1.4 root 5364: #endif
5365:
1.1.1.7 ! root 5366: x_do_cycles (cpu_cycles);
1.1.1.4 root 5367:
1.1.1.7 ! root 5368: r->opcode = regs.irc;
! 5369: count_instr (r->opcode);
1.1.1.4 root 5370:
1.1.1.7 ! root 5371: cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
! 5372: cpu_cycles = adjust_cycles (cpu_cycles);
! 5373: #ifdef WINUAE_FOR_HATARI
! 5374: M68000_AddCycles(cpu_cycles * 2 / CYCLE_UNIT);
1.1.1.4 root 5375:
1.1.1.7 ! root 5376: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
! 5377: /* Add some extra cycles to simulate a wait state */
! 5378: unset_special(SPCFLAG_EXTRA_CYCLES);
! 5379: M68000_AddCycles(nWaitStateCycles);
! 5380: nWaitStateCycles = 0;
! 5381: }
1.1.1.4 root 5382:
1.1.1.7 ! root 5383: /* We can have several interrupts at the same time before the next CPU instruction */
! 5384: /* We must check for pending interrupt and call do_specialties_interrupt() only */
! 5385: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
! 5386: /* and prevent exiting the STOP state when calling do_specialties() after. */
! 5387: /* For performance, we first test PendingInterruptCount, then regs.spcflags */
! 5388: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
! 5389: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */
! 5390: if ( MFP_UpdateNeeded == true )
! 5391: MFP_UpdateIRQ ( 0 );
! 5392: #endif
1.1.1.4 root 5393:
1.1.1.7 ! root 5394: if (r->spcflags) {
! 5395: if (do_specialties (cpu_cycles))
! 5396: exit = true;
! 5397: }
! 5398:
! 5399: #ifdef WINUAE_FOR_HATARI
! 5400: /* Run DSP 56k code if necessary */
! 5401: if (bDspEnabled) {
! 5402: DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
! 5403: }
! 5404: #endif
! 5405:
! 5406: ipl_fetch ();
! 5407: }
! 5408: } CATCH(prb) {
! 5409: bus_error();
! 5410: if (r->spcflags) {
! 5411: if (do_specialties(cpu_cycles))
! 5412: exit = true;;
! 5413: }
! 5414: ipl_fetch();
! 5415: } ENDTRY
1.1.1.4 root 5416: }
5417: }
5418:
1.1.1.7 ! root 5419: #endif
1.1.1.4 root 5420:
5421: //static int used[65536];
5422:
5423: /* Same thing, but don't use prefetch to get opcode. */
5424: static void m68k_run_2 (void)
5425: {
1.1.1.7 ! root 5426: // static int done;
1.1.1.4 root 5427: struct regstruct *r = ®s;
1.1.1.7 ! root 5428: bool exit = false;
! 5429: printf ( "run_2\n" );
1.1.1.4 root 5430:
1.1.1.7 ! root 5431: while (!exit) {
! 5432: TRY(prb) {
! 5433: while (!exit) {
! 5434: #ifdef WINUAE_FOR_HATARI
! 5435: //m68k_dumpstate_file(stderr, NULL);
! 5436: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
! 5437: {
! 5438: int FrameCycles, HblCounterVideo, LineCycles;
! 5439: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
! 5440: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
! 5441: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
! 5442: }
! 5443: #endif
! 5444: r->instruction_pc = m68k_getpc ();
1.1.1.4 root 5445:
1.1.1.7 ! root 5446: r->opcode = x_get_iword(0);
! 5447: count_instr (r->opcode);
1.1.1.4 root 5448:
1.1.1.7 ! root 5449: do_cycles (cpu_cycles);
1.1.1.5 root 5450:
1.1.1.7 ! root 5451: cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
! 5452: cpu_cycles = adjust_cycles (cpu_cycles);
! 5453: #ifdef WINUAE_FOR_HATARI
! 5454: //fprintf ( stderr , "cyc_2 %d\n" , cpu_cycles );
! 5455: M68000_AddCyclesWithPairing(cpu_cycles * 2 / CYCLE_UNIT);
! 5456:
! 5457: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
! 5458: /* Add some extra cycles to simulate a wait state */
! 5459: unset_special(SPCFLAG_EXTRA_CYCLES);
! 5460: M68000_AddCycles(nWaitStateCycles);
! 5461: nWaitStateCycles = 0;
! 5462: }
1.1.1.4 root 5463:
1.1.1.7 ! root 5464: /* We can have several interrupts at the same time before the next CPU instruction */
! 5465: /* We must check for pending interrupt and call do_specialties_interrupt() only */
! 5466: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
! 5467: /* and prevent exiting the STOP state when calling do_specialties() after. */
! 5468: /* For performance, we first test PendingInterruptCount, then regs.spcflags */
! 5469: while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
! 5470: CALL_VAR(PendingInterruptFunction); /* call the interrupt handler */
! 5471: if ( MFP_UpdateNeeded == true )
! 5472: MFP_UpdateIRQ ( 0 );
! 5473: #endif
1.1.1.4 root 5474:
1.1.1.7 ! root 5475: if (r->spcflags) {
! 5476: if (do_specialties (cpu_cycles))
! 5477: exit = true;
! 5478: }
! 5479:
! 5480: #ifdef WINUAE_FOR_HATARI
! 5481: /* Run DSP 56k code if necessary */
! 5482: if (bDspEnabled) {
! 5483: DSP_Run(2 * cpu_cycles * 2 / CYCLE_UNIT);
! 5484: }
! 5485: #endif
! 5486: }
! 5487: } CATCH(prb) {
! 5488: bus_error();
! 5489: if (r->spcflags) {
! 5490: if (do_specialties(cpu_cycles))
! 5491: exit = true;
! 5492: }
! 5493: } ENDTRY
1.1.1.4 root 5494: }
5495: }
5496:
5497: /* fake MMU 68k */
5498: static void m68k_run_mmu (void)
5499: {
1.1.1.7 ! root 5500: printf ( "run_mmu\n" );
1.1.1.4 root 5501: for (;;) {
1.1.1.7 ! root 5502: #ifdef WINUAE_FOR_HATARI
! 5503: //m68k_dumpstate_file(stderr, NULL);
1.1.1.4 root 5504: if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
5505: {
5506: int FrameCycles, HblCounterVideo, LineCycles;
5507: Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
5508: LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1.1.1.7 ! root 5509: m68k_disasm_file(stderr, m68k_getpc (), NULL, 1);
1.1.1.4 root 5510: }
1.1.1.7 ! root 5511: #endif
! 5512: regs.opcode = get_iiword (0);
1.1.1.4 root 5513: do_cycles (cpu_cycles);
5514: mmu_backup_regs = regs;
1.1.1.7 ! root 5515: cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
! 5516: cpu_cycles = adjust_cycles (cpu_cycles);
1.1.1.4 root 5517: if (mmu_triggered)
5518: mmu_do_hit ();
5519: if (regs.spcflags) {
5520: if (do_specialties (cpu_cycles))
5521: return;
5522: }
5523: }
5524: }
5525:
5526: #endif /* CPUEMU_0 */
5527:
5528: int in_m68k_go = 0;
5529:
5530: static void exception2_handle (uaecptr addr, uaecptr fault)
5531: {
5532: last_addr_for_exception_3 = addr;
5533: last_fault_for_exception_3 = fault;
5534: last_writeaccess_for_exception_3 = 0;
5535: last_instructionaccess_for_exception_3 = 0;
1.1.1.7 ! root 5536: Exception (2);
! 5537: }
! 5538:
! 5539: static bool cpu_hardreset, cpu_keyboardreset;
! 5540:
! 5541: bool is_hardreset(void)
! 5542: {
! 5543: return cpu_hardreset;
! 5544: }
! 5545: bool is_keyboardreset(void)
! 5546: {
! 5547: return cpu_keyboardreset;
1.1.1.4 root 5548: }
5549:
5550: void m68k_go (int may_quit)
5551: {
1.1.1.7 ! root 5552: #ifndef WINUAE_FOR_HATARI
! 5553: int hardboot = 1;
! 5554: int startup = 1;
! 5555: #endif
! 5556:
1.1.1.4 root 5557: if (in_m68k_go || !may_quit) {
1.1.1.7 ! root 5558: write_log (_T("Bug! m68k_go is not reentrant.\n"));
1.1.1.4 root 5559: abort ();
5560: }
5561:
5562: reset_frame_rate_hack ();
5563: update_68k_cycles ();
1.1.1.7 ! root 5564: #ifndef WINUAE_FOR_HATARI
! 5565: start_cycles = 0;
! 5566: #endif
! 5567:
! 5568: set_cpu_tracer (false);
1.1.1.4 root 5569:
1.1.1.7 ! root 5570: cpu_prefs_changed_flag = 0;
1.1.1.4 root 5571: in_m68k_go++;
5572: for (;;) {
5573: void (*run_func)(void);
5574:
1.1.1.7 ! root 5575: #ifdef WINUAE_FOR_HATARI
1.1.1.4 root 5576: /* Exit hatari ? */
5577: if (bQuitProgram == true)
5578: break;
1.1.1.7 ! root 5579: #endif
! 5580:
! 5581: cputrace.state = -1;
! 5582:
! 5583: #ifndef WINUAE_FOR_HATARI
! 5584: if (currprefs.inprecfile[0] && input_play) {
! 5585: inprec_open (currprefs.inprecfile, NULL);
! 5586: changed_prefs.inprecfile[0] = currprefs.inprecfile[0] = 0;
! 5587: quit_program = UAE_RESET;
! 5588: }
! 5589: if (input_play || input_record)
! 5590: inprec_startup ();
! 5591:
! 5592: if (quit_program > 0) {
! 5593: int restored = 0;
! 5594: cpu_keyboardreset = quit_program == UAE_RESET_KEYBOARD;
! 5595: cpu_hardreset = ((quit_program == UAE_RESET_HARD ? 1 : 0) | hardboot) != 0;
! 5596:
! 5597: if (quit_program == UAE_QUIT)
! 5598: break;
! 5599:
! 5600: hsync_counter = 0;
! 5601: vsync_counter = 0;
! 5602: quit_program = 0;
! 5603: hardboot = 0;
! 5604:
! 5605: #ifdef SAVESTATE
! 5606: if (savestate_state == STATE_DORESTORE)
! 5607: savestate_state = STATE_RESTORE;
! 5608: if (savestate_state == STATE_RESTORE)
! 5609: restore_state (savestate_fname);
! 5610: else if (savestate_state == STATE_REWIND)
! 5611: savestate_rewind ();
! 5612: #endif
! 5613: #ifndef WINUAE_FOR_HATARI
! 5614: set_cycles (start_cycles);
! 5615: #endif
! 5616: custom_reset (cpu_hardreset != 0, cpu_keyboardreset);
! 5617: m68k_reset2 (cpu_hardreset != 0);
! 5618: if (cpu_hardreset) {
! 5619: memory_clear ();
! 5620: write_log (_T("hardreset, memory cleared\n"));
! 5621: }
! 5622: cpu_hardreset = false;
! 5623: #ifdef SAVESTATE
! 5624: /* We may have been restoring state, but we're done now. */
! 5625: if (isrestore ()) {
! 5626: if (debug_dma) {
! 5627: record_dma_reset ();
! 5628: record_dma_reset ();
! 5629: }
! 5630: savestate_restore_finish ();
! 5631: memory_map_dump ();
! 5632: if (currprefs.mmu_model == 68030) {
! 5633: mmu030_decode_tc (tc_030);
! 5634: } else if (currprefs.mmu_model >= 68040) {
! 5635: mmu_set_tc (regs.tcr);
! 5636: }
! 5637: startup = 1;
! 5638: restored = 1;
! 5639: }
! 5640: #endif
! 5641: if (currprefs.produce_sound == 0)
! 5642: eventtab[ev_audio].active = 0;
! 5643: m68k_setpc_normal (regs.pc);
! 5644: check_prefs_changed_audio ();
! 5645:
! 5646: if (!restored || hsync_counter == 0)
! 5647: savestate_check ();
! 5648: if (input_record == INPREC_RECORD_START)
! 5649: input_record = INPREC_RECORD_NORMAL;
! 5650: statusline_clear();
! 5651: } else {
! 5652: if (input_record == INPREC_RECORD_START) {
! 5653: input_record = INPREC_RECORD_NORMAL;
! 5654: savestate_init ();
! 5655: hsync_counter = 0;
! 5656: vsync_counter = 0;
! 5657: savestate_check ();
! 5658: }
! 5659: }
! 5660:
! 5661: if (changed_prefs.inprecfile[0] && input_record)
! 5662: inprec_prepare_record (savestate_fname[0] ? savestate_fname : NULL);
! 5663: #endif
! 5664:
! 5665: set_cpu_tracer (false);
1.1.1.4 root 5666:
5667: #ifdef DEBUGGER
5668: if (debugging)
5669: debug ();
5670: #endif
1.1.1.7 ! root 5671: /* [NP] TODO : allow changing cpu on the fly ? */
! 5672: #ifndef WINUAE_FOR_HATARI
! 5673: if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
! 5674: if (cpu_prefs_changed_flag & 1) {
! 5675: uaecptr pc = m68k_getpc();
! 5676: prefs_changed_cpu();
! 5677: build_cpufunctbl();
! 5678: m68k_setpc_normal(pc);
! 5679: fill_prefetch();
! 5680: }
! 5681: if (cpu_prefs_changed_flag & 2) {
! 5682: fixup_cpu(&changed_prefs);
! 5683: currprefs.m68k_speed = changed_prefs.m68k_speed;
! 5684: currprefs.m68k_speed_throttle = changed_prefs.m68k_speed_throttle;
! 5685: update_68k_cycles();
! 5686: }
! 5687: cpu_prefs_changed_flag = 0;
! 5688: }
! 5689: #else
! 5690: /* [NP] : in Hatari, build_cpufunctbl() is called directly from check_prefs_changed_cpu2() */
! 5691: /* so we just need to set PC here */
! 5692: if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
! 5693: if (cpu_prefs_changed_flag & 1) {
! 5694: printf ( "cpu change %d\n" , cpu_prefs_changed_flag );
! 5695: uaecptr pc = m68k_getpc();
! 5696: m68k_setpc_normal(pc);
! 5697: fill_prefetch();
1.1.1.4 root 5698: }
1.1.1.7 ! root 5699: cpu_prefs_changed_flag = 0;
1.1.1.4 root 5700: }
1.1.1.7 ! root 5701: #endif
1.1.1.4 root 5702:
1.1.1.7 ! root 5703: set_x_funcs();
! 5704: #ifndef WINUAE_FOR_HATARI
! 5705: if (startup) {
! 5706: custom_prepare ();
! 5707: protect_roms (true);
1.1.1.4 root 5708: }
1.1.1.7 ! root 5709: startup = 0;
! 5710: event_wait = true;
1.1.1.4 root 5711: #endif
1.1.1.7 ! root 5712: unset_special(SPCFLAG_MODE_CHANGE);
1.1.1.4 root 5713:
1.1.1.7 ! root 5714: if (regs.halted) {
! 5715: cpu_halt (regs.halted);
! 5716: if (regs.halted < 0) {
! 5717: haltloop();
! 5718: continue;
! 5719: }
! 5720: }
! 5721:
! 5722: #if 0
1.1.1.4 root 5723: if (mmu_enabled && !currprefs.cachesize) {
5724: run_func = m68k_run_mmu;
5725: } else {
1.1.1.7 ! root 5726: #endif
! 5727: run_func = currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010 ? m68k_run_1_ce :
! 5728: currprefs.cpu_compatible && currprefs.cpu_model <= 68010 ? m68k_run_1 :
1.1.1.4 root 5729: #ifdef JIT
5730: currprefs.cpu_model >= 68020 && currprefs.cachesize ? m68k_run_jit :
5731: #endif
1.1.1.7 ! root 5732: currprefs.cpu_model == 68030 && currprefs.mmu_model ? m68k_run_mmu030 :
! 5733: currprefs.cpu_model == 68040 && currprefs.mmu_model ? m68k_run_mmu040 :
! 5734: currprefs.cpu_model == 68060 && currprefs.mmu_model ? m68k_run_mmu060 :
! 5735:
! 5736: currprefs.cpu_model >= 68040 && currprefs.cpu_cycle_exact ? m68k_run_3ce :
1.1.1.4 root 5737: currprefs.cpu_model >= 68020 && currprefs.cpu_cycle_exact ? m68k_run_2ce :
1.1.1.7 ! root 5738:
! 5739: currprefs.cpu_model <= 68020 && currprefs.cpu_compatible ? m68k_run_2p :
! 5740: currprefs.cpu_model == 68030 && currprefs.cpu_compatible ? m68k_run_2p :
! 5741: currprefs.cpu_model >= 68040 && currprefs.cpu_compatible ? m68k_run_3p :
! 5742:
! 5743: m68k_run_2;
! 5744: #if 0
1.1.1.4 root 5745: }
1.1.1.7 ! root 5746: #endif
! 5747: run_func();
! 5748: printf ( "exit m68k_run\n" );
1.1.1.4 root 5749: }
1.1.1.7 ! root 5750: #ifndef WINUAE_FOR_HATARI
! 5751: protect_roms (false);
! 5752: #endif
1.1.1.4 root 5753: in_m68k_go--;
5754: }
5755:
5756: #if 0
5757: static void m68k_verify (uaecptr addr, uaecptr *nextpc)
5758: {
1.1.1.7 ! root 5759: uae_u16 opcode, val;
1.1.1.4 root 5760: struct instr *dp;
5761:
5762: opcode = get_iword_1 (0);
5763: last_op_for_exception_3 = opcode;
5764: m68kpc_offset = 2;
5765:
5766: if (cpufunctbl[opcode] == op_illg_1) {
5767: opcode = 0x4AFC;
5768: }
5769: dp = table68k + opcode;
5770:
5771: if (dp->suse) {
5772: if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
5773: Exception (3, 0);
5774: return;
5775: }
5776: }
5777: if (dp->duse) {
5778: if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
5779: Exception (3, 0);
5780: return;
5781: }
5782: }
5783: }
5784: #endif
5785:
5786: static const TCHAR *ccnames[] =
1.1.1.7 ! root 5787: {
! 5788: _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
! 5789: _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE")
! 5790: };
! 5791: static const TCHAR *fpccnames[] =
! 5792: {
! 5793: _T("F"),
! 5794: _T("EQ"),
! 5795: _T("OGT"),
! 5796: _T("OGE"),
! 5797: _T("OLT"),
! 5798: _T("OLE"),
! 5799: _T("OGL"),
! 5800: _T("OR"),
! 5801: _T("UN"),
! 5802: _T("UEQ"),
! 5803: _T("UGT"),
! 5804: _T("UGE"),
! 5805: _T("ULT"),
! 5806: _T("ULE"),
! 5807: _T("NE"),
! 5808: _T("T"),
! 5809: _T("SF"),
! 5810: _T("SEQ"),
! 5811: _T("GT"),
! 5812: _T("GE"),
! 5813: _T("LT"),
! 5814: _T("LE"),
! 5815: _T("GL"),
! 5816: _T("GLE"),
! 5817: _T("NGLE"),
! 5818: _T("NGL"),
! 5819: _T("NLE"),
! 5820: _T("NLT"),
! 5821: _T("NGE"),
! 5822: _T("NGT"),
! 5823: _T("SNE"),
! 5824: _T("ST")
! 5825: };
! 5826: static const TCHAR *fpuopcodes[] =
! 5827: {
! 5828: _T("FMOVE"),
! 5829: _T("FINT"),
! 5830: _T("FSINH"),
! 5831: _T("FINTRZ"),
! 5832: _T("FSQRT"),
! 5833: NULL,
! 5834: _T("FLOGNP1"),
! 5835: NULL,
! 5836: _T("FETOXM1"),
! 5837: _T("FTANH"),
! 5838: _T("FATAN"),
! 5839: NULL,
! 5840: _T("FASIN"),
! 5841: _T("FATANH"),
! 5842: _T("FSIN"),
! 5843: _T("FTAN"),
! 5844: _T("FETOX"), // 0x10
! 5845: _T("FTWOTOX"),
! 5846: _T("FTENTOX"),
! 5847: NULL,
! 5848: _T("FLOGN"),
! 5849: _T("FLOG10"),
! 5850: _T("FLOG2"),
! 5851: NULL,
! 5852: _T("FABS"),
! 5853: _T("FCOSH"),
! 5854: _T("FNEG"),
! 5855: NULL,
! 5856: _T("FACOS"),
! 5857: _T("FCOS"),
! 5858: _T("FGETEXP"),
! 5859: _T("FGETMAN"),
! 5860: _T("FDIV"), // 0x20
! 5861: _T("FMOD"),
! 5862: _T("FADD"),
! 5863: _T("FMUL"),
! 5864: _T("FSGLDIV"),
! 5865: _T("FREM"),
! 5866: _T("FSCALE"),
! 5867: _T("FSGLMUL"),
! 5868: _T("FSUB"),
! 5869: NULL,
! 5870: NULL,
! 5871: NULL,
! 5872: NULL,
! 5873: NULL,
! 5874: NULL,
! 5875: NULL,
! 5876: _T("FSINCOS"), // 0x30
! 5877: _T("FSINCOS"),
! 5878: _T("FSINCOS"),
! 5879: _T("FSINCOS"),
! 5880: _T("FSINCOS"),
! 5881: _T("FSINCOS"),
! 5882: _T("FSINCOS"),
! 5883: _T("FSINCOS"),
! 5884: _T("FCMP"),
! 5885: NULL,
! 5886: _T("FTST"),
! 5887: NULL,
! 5888: NULL,
! 5889: NULL,
! 5890: NULL,
! 5891: NULL
! 5892: };
! 5893:
! 5894: static const TCHAR *movemregs[] =
! 5895: {
! 5896: _T("D0"),
! 5897: _T("D1"),
! 5898: _T("D2"),
! 5899: _T("D3"),
! 5900: _T("D4"),
! 5901: _T("D5"),
! 5902: _T("D6"),
! 5903: _T("D7"),
! 5904: _T("A0"),
! 5905: _T("A1"),
! 5906: _T("A2"),
! 5907: _T("A3"),
! 5908: _T("A4"),
! 5909: _T("A5"),
! 5910: _T("A6"),
! 5911: _T("A7"),
! 5912: _T("FP0"),
! 5913: _T("FP1"),
! 5914: _T("FP2"),
! 5915: _T("FP3"),
! 5916: _T("FP4"),
! 5917: _T("FP5"),
! 5918: _T("FP6"),
! 5919: _T("FP7"),
! 5920: _T("FPCR"),
! 5921: _T("FPSR"),
! 5922: _T("FPIAR")
! 5923: };
1.1.1.4 root 5924:
1.1.1.7 ! root 5925: static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode)
1.1.1.4 root 5926: {
5927: TCHAR *p = out + _tcslen (out);
5928: if (*prevreg < 0) {
5929: *prevreg = reg;
5930: *lastreg = reg;
5931: return;
5932: }
1.1.1.7 ! root 5933: if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
! 5934: _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]);
1.1.1.4 root 5935: p = p + _tcslen (p);
5936: if ((*lastreg) + 2 == reg) {
1.1.1.7 ! root 5937: _stprintf (p, _T("/%s"), movemregs[*prevreg]);
1.1.1.4 root 5938: } else if ((*lastreg) != (*prevreg)) {
1.1.1.7 ! root 5939: _stprintf (p, _T("-%s"), movemregs[*prevreg]);
1.1.1.4 root 5940: }
5941: *lastreg = reg;
5942: *first = 0;
5943: }
5944: *prevreg = reg;
5945: }
5946:
1.1.1.7 ! root 5947: static void movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode)
1.1.1.4 root 5948: {
5949: unsigned int dmask, amask;
5950: int prevreg = -1, lastreg = -1, first = 1;
1.1.1.7 ! root 5951: int i;
1.1.1.4 root 5952:
1.1.1.7 ! root 5953: if (mode == Apdi && !fpmode) {
! 5954: uae_u8 dmask2;
! 5955: uae_u8 amask2;
! 5956:
! 5957: amask2 = mask & 0xff;
! 5958: dmask2 = (mask >> 8) & 0xff;
1.1.1.4 root 5959: dmask = 0;
5960: amask = 0;
5961: for (i = 0; i < 8; i++) {
5962: if (dmask2 & (1 << i))
5963: dmask |= 1 << (7 - i);
5964: if (amask2 & (1 << i))
5965: amask |= 1 << (7 - i);
5966: }
5967: } else {
5968: dmask = mask & 0xff;
5969: amask = (mask >> 8) & 0xff;
1.1.1.7 ! root 5970: if (fpmode == 1 && mode != Apdi) {
! 5971: uae_u8 dmask2 = dmask;
! 5972: dmask = 0;
! 5973: for (i = 0; i < 8; i++) {
! 5974: if (dmask2 & (1 << i))
! 5975: dmask |= 1 << (7 - i);
! 5976: }
! 5977: }
! 5978: }
! 5979: if (fpmode) {
! 5980: while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; }
! 5981: } else {
! 5982: while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; }
! 5983: while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; }
1.1.1.4 root 5984: }
1.1.1.7 ! root 5985: addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode);
1.1.1.4 root 5986: }
5987:
1.1.1.7 ! root 5988: static const TCHAR *fpsizes[] = {
! 5989: _T("L"),
! 5990: _T("S"),
! 5991: _T("X"),
! 5992: _T("P"),
! 5993: _T("W"),
! 5994: _T("D"),
! 5995: _T("B"),
! 5996: _T("P")
! 5997: };
! 5998: static const int fpsizeconv[] = {
! 5999: sz_long,
! 6000: sz_single,
! 6001: sz_extended,
! 6002: sz_packed,
! 6003: sz_word,
! 6004: sz_double,
! 6005: sz_byte,
! 6006: sz_packed
! 6007: };
! 6008:
1.1.1.4 root 6009: static void disasm_size (TCHAR *instrname, struct instr *dp)
6010: {
1.1.1.7 ! root 6011: if (dp->unsized) {
! 6012: _tcscat(instrname, _T(" "));
! 6013: return;
1.1.1.4 root 6014: }
6015: switch (dp->size)
6016: {
6017: case sz_byte:
1.1.1.7 ! root 6018: _tcscat (instrname, _T(".B "));
1.1.1.4 root 6019: break;
6020: case sz_word:
1.1.1.7 ! root 6021: _tcscat (instrname, _T(".W "));
1.1.1.4 root 6022: break;
6023: case sz_long:
1.1.1.7 ! root 6024: _tcscat (instrname, _T(".L "));
1.1.1.4 root 6025: break;
6026: default:
1.1.1.7 ! root 6027: _tcscat (instrname, _T(" "));
1.1.1.4 root 6028: break;
6029: }
6030: }
6031:
1.1.1.7 ! root 6032: void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode)
1.1.1.4 root 6033: {
1.1.1.7 ! root 6034: uae_u32 seaddr2;
! 6035: uae_u32 deaddr2;
1.1.1.4 root 6036:
1.1.1.7 ! root 6037: if (buf)
! 6038: memset (buf, 0, bufsize * sizeof (TCHAR));
1.1.1.4 root 6039: if (!table68k)
6040: return;
6041: while (cnt-- > 0) {
6042: TCHAR instrname[100], *ccpt;
6043: int i;
6044: uae_u32 opcode;
1.1.1.7 ! root 6045: uae_u16 extra;
1.1.1.4 root 6046: struct mnemolookup *lookup;
6047: struct instr *dp;
1.1.1.7 ! root 6048: uaecptr oldpc;
! 6049: uaecptr m68kpc_illg = 0;
! 6050: bool illegal = false;
! 6051:
! 6052: seaddr2 = deaddr2 = 0;
! 6053: oldpc = pc;
! 6054: opcode = get_word_debug (pc);
! 6055: extra = get_word_debug (pc + 2);
! 6056: if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) {
! 6057: m68kpc_illg = pc + 2;
! 6058: illegal = TRUE;
! 6059: }
1.1.1.4 root 6060:
1.1.1.7 ! root 6061: dp = table68k + opcode;
! 6062: if (dp->mnemo == i_ILLG) {
! 6063: illegal = FALSE;
1.1.1.4 root 6064: opcode = 0x4AFC;
1.1.1.7 ! root 6065: dp = table68k + opcode;
1.1.1.4 root 6066: }
6067: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
6068: ;
6069:
1.1.1.7 ! root 6070: buf = buf_out (buf, &bufsize, _T("%08X "), pc);
1.1.1.4 root 6071:
1.1.1.7 ! root 6072: pc += 2;
! 6073:
! 6074: if (lookup->friendlyname)
1.1.1.4 root 6075: _tcscpy (instrname, lookup->friendlyname);
6076: else
6077: _tcscpy (instrname, lookup->name);
1.1.1.7 ! root 6078: ccpt = _tcsstr (instrname, _T("cc"));
1.1.1.4 root 6079: if (ccpt != 0) {
1.1.1.7 ! root 6080: if ((opcode & 0xf000) == 0xf000)
! 6081: _tcscpy (ccpt, fpccnames[extra & 0x1f]);
! 6082: else
! 6083: _tcsncpy (ccpt, ccnames[dp->cc], 2);
1.1.1.4 root 6084: }
6085: disasm_size (instrname, dp);
6086:
6087: if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
1.1.1.7 ! root 6088: uae_u16 imm = extra;
1.1.1.4 root 6089: uae_u16 creg = imm & 0x0fff;
6090: uae_u16 r = imm >> 12;
6091: TCHAR regs[16];
1.1.1.7 ! root 6092: const TCHAR *cname = _T("?");
1.1.1.4 root 6093: int i;
6094: for (i = 0; m2cregs[i].regname; i++) {
6095: if (m2cregs[i].regno == creg)
6096: break;
6097: }
1.1.1.7 ! root 6098: _stprintf (regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
1.1.1.4 root 6099: if (m2cregs[i].regname)
6100: cname = m2cregs[i].regname;
6101: if (lookup->mnemo == i_MOVE2C) {
6102: _tcscat (instrname, regs);
1.1.1.7 ! root 6103: _tcscat (instrname, _T(","));
1.1.1.4 root 6104: _tcscat (instrname, cname);
6105: } else {
6106: _tcscat (instrname, cname);
1.1.1.7 ! root 6107: _tcscat (instrname, _T(","));
1.1.1.4 root 6108: _tcscat (instrname, regs);
6109: }
1.1.1.7 ! root 6110: pc += 2;
1.1.1.4 root 6111: } else if (lookup->mnemo == i_MVMEL) {
1.1.1.7 ! root 6112: uae_u16 mask = extra;
! 6113: pc += 2;
! 6114: pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
! 6115: _tcscat (instrname, _T(","));
! 6116: movemout (instrname, mask, dp->dmode, 0);
1.1.1.4 root 6117: } else if (lookup->mnemo == i_MVMLE) {
1.1.1.7 ! root 6118: uae_u16 mask = extra;
! 6119: pc += 2;
! 6120: movemout(instrname, mask, dp->dmode, 0);
! 6121: _tcscat(instrname, _T(","));
! 6122: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
! 6123: } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) {
! 6124: TCHAR *p;
! 6125: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
! 6126: extra = get_word_debug(pc);
! 6127: pc += 2;
! 6128: p = instrname + _tcslen(instrname);
! 6129: if (extra & 0x0400)
! 6130: _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7);
! 6131: else
! 6132: _stprintf(p, _T(",D%d"), (extra >> 12) & 7);
! 6133: } else if (lookup->mnemo == i_MOVES) {
! 6134: TCHAR *p;
! 6135: pc += 2;
! 6136: if (!(extra & 0x1000)) {
! 6137: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
! 6138: p = instrname + _tcslen(instrname);
! 6139: _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
! 6140: } else {
! 6141: p = instrname + _tcslen(instrname);
! 6142: _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
! 6143: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
! 6144: }
! 6145: } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU ||
! 6146: lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR ||
! 6147: lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS ||
! 6148: lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) {
! 6149: TCHAR *p;
! 6150: int reg = -1;
! 6151:
! 6152: pc += 2;
! 6153: p = instrname + _tcslen(instrname);
! 6154: if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS)
! 6155: reg = (extra >> 12) & 7;
! 6156: if (lookup->mnemo == i_BFINS)
! 6157: _stprintf(p, _T("D%d,"), reg);
! 6158: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
! 6159: _tcscat(instrname, _T(" {"));
! 6160: p = instrname + _tcslen(instrname);
! 6161: if (extra & 0x0800)
! 6162: _stprintf(p, _T("D%d"), (extra >> 6) & 7);
! 6163: else
! 6164: _stprintf(p, _T("%d"), (extra >> 6) & 31);
! 6165: _tcscat(instrname, _T(":"));
! 6166: p = instrname + _tcslen(instrname);
! 6167: if (extra & 0x0020)
! 6168: _stprintf(p, _T("D%d"), extra & 7);
! 6169: else
! 6170: _stprintf(p, _T("%d"), extra & 31);
! 6171: _tcscat(instrname, _T("}"));
! 6172: p = instrname + _tcslen(instrname);
! 6173: if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU)
! 6174: _stprintf(p, _T(",D%d"), reg);
! 6175: } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP ||
! 6176: lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
! 6177: if ((opcode & 0xc0) == 0xc0)
! 6178: _tcscat(instrname, _T("BC"));
! 6179: else if (opcode & 0x80)
! 6180: _tcscat(instrname, _T("IC"));
! 6181: else if (opcode & 0x40)
! 6182: _tcscat(instrname, _T("DC"));
! 6183: else
! 6184: _tcscat(instrname, _T("?"));
! 6185: if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
! 6186: TCHAR *p = instrname + _tcslen(instrname);
! 6187: _stprintf(p, _T(",(A%d)"), opcode & 7);
! 6188: }
! 6189: } else if (lookup->mnemo == i_FPP) {
! 6190: TCHAR *p;
! 6191: int ins = extra & 0x3f;
! 6192: int size = (extra >> 10) & 7;
! 6193:
! 6194: pc += 2;
! 6195: if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7)
! 6196: fpdata fp;
! 6197: if (fpu_get_constant(&fp, extra))
! 6198: #if USE_LONG_DOUBLE
! 6199: _stprintf(instrname, _T("FMOVECR.X #%Le,FP%d"), fp.fp, (extra >> 7) & 7);
! 6200: #else
! 6201: _stprintf(instrname, _T("FMOVECR.X #%e,FP%d"), fp.fp, (extra >> 7) & 7);
! 6202: #endif
! 6203: else
! 6204: _stprintf(instrname, _T("FMOVECR.X #?,FP%d"), (extra >> 7) & 7);
! 6205: } else if ((extra & 0x8000) == 0x8000) { // FMOVEM
! 6206: int dr = (extra >> 13) & 1;
! 6207: int mode;
! 6208: int dreg = (extra >> 4) & 7;
! 6209: int regmask, fpmode;
! 6210:
! 6211: if (extra & 0x4000) {
! 6212: mode = (extra >> 11) & 3;
! 6213: regmask = extra & 0xff; // FMOVEM FPx
! 6214: fpmode = 1;
! 6215: _tcscpy(instrname, _T("FMOVEM.X "));
! 6216: } else {
! 6217: mode = 0;
! 6218: regmask = (extra >> 10) & 7; // FMOVEM control
! 6219: fpmode = 2;
! 6220: _tcscpy(instrname, _T("FMOVEM.L "));
! 6221: if (regmask == 1 || regmask == 2 || regmask == 4)
! 6222: _tcscpy(instrname, _T("FMOVE.L "));
! 6223: }
! 6224: p = instrname + _tcslen(instrname);
! 6225: if (dr) {
! 6226: if (mode & 1)
! 6227: _stprintf(instrname, _T("D%d"), dreg);
! 6228: else
! 6229: movemout(instrname, regmask, dp->dmode, fpmode);
! 6230: _tcscat(instrname, _T(","));
! 6231: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
! 6232: } else {
! 6233: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
! 6234: _tcscat(instrname, _T(","));
! 6235: p = instrname + _tcslen(instrname);
! 6236: if (mode & 1)
! 6237: _stprintf(p, _T("D%d"), dreg);
! 6238: else
! 6239: movemout(p, regmask, dp->dmode, fpmode);
! 6240: }
! 6241: } else {
! 6242: if (fpuopcodes[ins])
! 6243: _tcscpy(instrname, fpuopcodes[ins]);
! 6244: else
! 6245: _tcscpy(instrname, _T("F?"));
! 6246:
! 6247: if ((extra & 0xe000) == 0x6000) { // FMOVE to memory
! 6248: int kfactor = extra & 0x7f;
! 6249: _tcscpy(instrname, _T("FMOVE."));
! 6250: _tcscat(instrname, fpsizes[size]);
! 6251: _tcscat(instrname, _T(" "));
! 6252: p = instrname + _tcslen(instrname);
! 6253: _stprintf(p, _T("FP%d,"), (extra >> 7) & 7);
! 6254: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
! 6255: p = instrname + _tcslen(instrname);
! 6256: if (size == 7) {
! 6257: _stprintf(p, _T(" {D%d}"), (kfactor >> 4));
! 6258: } else if (kfactor) {
! 6259: if (kfactor & 0x40)
! 6260: kfactor |= ~0x3f;
! 6261: _stprintf(p, _T(" {%d}"), kfactor);
! 6262: }
! 6263: } else {
! 6264: if (extra & 0x4000) { // source is EA
! 6265: _tcscat(instrname, _T("."));
! 6266: _tcscat(instrname, fpsizes[size]);
! 6267: _tcscat(instrname, _T(" "));
! 6268: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
! 6269: } else { // source is FPx
! 6270: p = instrname + _tcslen(instrname);
! 6271: _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7);
! 6272: }
! 6273: p = instrname + _tcslen(instrname);
! 6274: if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7)))
! 6275: _stprintf(p, _T(",FP%d"), (extra >> 7) & 7);
! 6276: if (ins >= 0x30 && ins < 0x38) { // FSINCOS
! 6277: p = instrname + _tcslen(instrname);
! 6278: _stprintf(p, _T(",FP%d"), extra & 7);
! 6279: }
! 6280: }
! 6281: }
! 6282: } else if ((opcode & 0xf000) == 0xa000) {
! 6283: _tcscpy(instrname, _T("A-LINE"));
1.1.1.4 root 6284: } else {
6285: if (dp->suse) {
1.1.1.7 ! root 6286: pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
1.1.1.4 root 6287: }
6288: if (dp->suse && dp->duse)
1.1.1.7 ! root 6289: _tcscat (instrname, _T(","));
1.1.1.4 root 6290: if (dp->duse) {
1.1.1.7 ! root 6291: pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
1.1.1.4 root 6292: }
6293: }
6294:
1.1.1.7 ! root 6295: for (i = 0; i < (int)(pc - oldpc) / 2 && i < 5; i++) {
! 6296: buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2));
1.1.1.4 root 6297: }
6298: while (i++ < 5)
1.1.1.7 ! root 6299: buf = buf_out (buf, &bufsize, _T(" "));
1.1.1.4 root 6300:
1.1.1.7 ! root 6301: if (illegal)
! 6302: buf = buf_out (buf, &bufsize, _T("[ "));
! 6303: buf = buf_out (buf, &bufsize, instrname);
! 6304: if (illegal)
! 6305: buf = buf_out (buf, &bufsize, _T(" ]"));
1.1.1.4 root 6306:
6307: if (ccpt != 0) {
1.1.1.7 ! root 6308: uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
1.1.1.4 root 6309: if (deaddr)
1.1.1.7 ! root 6310: *deaddr = pc;
! 6311: if ((opcode & 0xf000) == 0xf000) {
! 6312: if (fpp_cond(dp->cc)) {
! 6313: buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
! 6314: } else {
! 6315: buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
! 6316: }
! 6317: } else {
! 6318: if (cctrue (dp->cc)) {
! 6319: buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), addr2);
! 6320: } else {
! 6321: buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), addr2);
! 6322: }
! 6323: }
1.1.1.4 root 6324: } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
6325: if (deaddr)
1.1.1.7 ! root 6326: *deaddr = pc;
! 6327: buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2);
1.1.1.4 root 6328: }
1.1.1.7 ! root 6329: buf = buf_out (buf, &bufsize, _T("\n"));
! 6330:
! 6331: if (illegal)
! 6332: pc = m68kpc_illg;
1.1.1.4 root 6333: }
6334: if (nextpc)
1.1.1.7 ! root 6335: *nextpc = pc;
! 6336: if (seaddr)
! 6337: *seaddr = seaddr2;
! 6338: if (deaddr)
! 6339: *deaddr = deaddr2;
1.1.1.4 root 6340: }
6341:
1.1.1.7 ! root 6342: void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr)
! 6343: {
! 6344: TCHAR *buf;
! 6345:
! 6346: buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
! 6347: if (!buf)
! 6348: return;
! 6349: m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, seaddr, deaddr, 1);
! 6350: xfree (buf);
! 6351: }
! 6352: void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt)
1.1.1.4 root 6353: {
1.1.1.7 ! root 6354: TCHAR *buf;
! 6355:
! 6356: buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
! 6357: if (!buf)
! 6358: return;
! 6359: m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0);
! 6360: console_out_f (_T("%s"), buf);
! 6361: xfree (buf);
1.1.1.4 root 6362: }
1.1.1.7 ! root 6363: void m68k_disasm_file (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt)
1.1.1.4 root 6364: {
1.1.1.7 ! root 6365: TCHAR *buf;
! 6366:
! 6367: buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
! 6368: if (!buf)
! 6369: return;
! 6370: console_out_FILE = f;
! 6371: m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0);
! 6372: f_out (f, _T("%s"), buf);
! 6373: xfree (buf);
! 6374: console_out_FILE = NULL;
1.1.1.4 root 6375: }
6376:
6377: /*************************************************************
6378: Disasm the m68kcode at the given address into instrname
6379: and instrcode
6380: *************************************************************/
6381: void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc)
6382: {
6383: TCHAR *ccpt;
6384: uae_u32 opcode;
6385: struct mnemolookup *lookup;
6386: struct instr *dp;
1.1.1.7 ! root 6387: uaecptr pc, oldpc;
1.1.1.4 root 6388:
1.1.1.7 ! root 6389: pc = oldpc = addr;
! 6390: opcode = get_word_debug (pc);
1.1.1.4 root 6391: if (cpufunctbl[opcode] == op_illg_1) {
6392: opcode = 0x4AFC;
6393: }
6394: dp = table68k + opcode;
6395: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
6396:
1.1.1.7 ! root 6397: pc += 2;
1.1.1.4 root 6398:
6399: _tcscpy (instrname, lookup->name);
1.1.1.7 ! root 6400: ccpt = _tcsstr (instrname, _T("cc"));
1.1.1.4 root 6401: if (ccpt != 0) {
6402: _tcsncpy (ccpt, ccnames[dp->cc], 2);
6403: }
6404: switch (dp->size){
1.1.1.7 ! root 6405: case sz_byte: _tcscat (instrname, _T(".B ")); break;
! 6406: case sz_word: _tcscat (instrname, _T(".W ")); break;
! 6407: case sz_long: _tcscat (instrname, _T(".L ")); break;
! 6408: default: _tcscat (instrname, _T(" ")); break;
1.1.1.4 root 6409: }
6410:
6411: if (dp->suse) {
1.1.1.7 ! root 6412: pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
1.1.1.4 root 6413: }
6414: if (dp->suse && dp->duse)
1.1.1.7 ! root 6415: _tcscat (instrname, _T(","));
1.1.1.4 root 6416: if (dp->duse) {
1.1.1.7 ! root 6417: pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
1.1.1.4 root 6418: }
6419: if (instrcode)
6420: {
6421: int i;
1.1.1.7 ! root 6422: for (i = 0; i < (int)(pc - oldpc) / 2; i++)
1.1.1.4 root 6423: {
1.1.1.7 ! root 6424: _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
1.1.1.4 root 6425: instrcode += _tcslen (instrcode);
6426: }
6427: }
6428: if (nextpc)
1.1.1.7 ! root 6429: *nextpc = pc;
1.1.1.4 root 6430: }
6431:
6432: struct cpum2c m2cregs[] = {
1.1.1.7 ! root 6433: { 0, _T("SFC") },
! 6434: { 1, _T("DFC") },
! 6435: { 2, _T("CACR") },
! 6436: { 3, _T("TC") },
! 6437: { 4, _T("ITT0") },
! 6438: { 5, _T("ITT1") },
! 6439: { 6, _T("DTT0") },
! 6440: { 7, _T("DTT1") },
! 6441: { 8, _T("BUSC") },
! 6442: { 0x800, _T("USP") },
! 6443: { 0x801, _T("VBR") },
! 6444: { 0x802, _T("CAAR") },
! 6445: { 0x803, _T("MSP") },
! 6446: { 0x804, _T("ISP") },
! 6447: { 0x805, _T("MMUS") },
! 6448: { 0x806, _T("URP") },
! 6449: { 0x807, _T("SRP") },
! 6450: { 0x808, _T("PCR") },
! 6451: { -1, NULL }
1.1.1.4 root 6452: };
6453:
1.1.1.7 ! root 6454: void m68k_dumpstate_2 (uaecptr pc, uaecptr *nextpc)
1.1.1.4 root 6455: {
6456: int i, j;
6457:
6458: for (i = 0; i < 8; i++){
1.1.1.7 ! root 6459: console_out_f (_T(" D%d %08X "), i, m68k_dreg (regs, i));
! 6460: if ((i & 3) == 3) console_out_f (_T("\n"));
1.1.1.4 root 6461: }
6462: for (i = 0; i < 8; i++){
1.1.1.7 ! root 6463: console_out_f (_T(" A%d %08X "), i, m68k_areg (regs, i));
! 6464: if ((i & 3) == 3) console_out_f (_T("\n"));
1.1.1.4 root 6465: }
6466: if (regs.s == 0)
6467: regs.usp = m68k_areg (regs, 7);
6468: if (regs.s && regs.m)
6469: regs.msp = m68k_areg (regs, 7);
6470: if (regs.s && regs.m == 0)
6471: regs.isp = m68k_areg (regs, 7);
6472: j = 2;
1.1.1.7 ! root 6473: console_out_f (_T("USP %08X ISP %08X "), regs.usp, regs.isp);
1.1.1.4 root 6474: for (i = 0; m2cregs[i].regno>= 0; i++) {
6475: if (!movec_illg (m2cregs[i].regno)) {
1.1.1.7 ! root 6476: if (!_tcscmp (m2cregs[i].regname, _T("USP")) || !_tcscmp (m2cregs[i].regname, _T("ISP")))
1.1.1.4 root 6477: continue;
6478: if (j > 0 && (j % 4) == 0)
1.1.1.7 ! root 6479: console_out_f (_T("\n"));
! 6480: console_out_f (_T("%-4s %08X "), m2cregs[i].regname, val_move2c (m2cregs[i].regno));
1.1.1.4 root 6481: j++;
6482: }
6483: }
6484: if (j > 0)
1.1.1.7 ! root 6485: console_out_f (_T("\n"));
! 6486: console_out_f (_T("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d STP=%d\n"),
1.1.1.4 root 6487: regs.t1, regs.t0, regs.s, regs.m,
6488: GET_XFLG (), GET_NFLG (), GET_ZFLG (),
6489: GET_VFLG (), GET_CFLG (),
6490: regs.intmask, regs.stopped);
6491: #ifdef FPUEMU
6492: if (currprefs.fpu_model) {
6493: uae_u32 fpsr;
6494: for (i = 0; i < 8; i++){
1.1.1.7 ! root 6495: console_out_f (_T("FP%d: %g "), i, regs.fp[i].fp);
1.1.1.4 root 6496: if ((i & 3) == 3)
1.1.1.7 ! root 6497: console_out_f (_T("\n"));
1.1.1.4 root 6498: }
1.1.1.7 ! root 6499: fpsr = fpp_get_fpsr ();
! 6500: console_out_f (_T("FPSR: %04X FPCR: %08x FPIAR: %08x N=%d Z=%d I=%d NAN=%d\n"),
! 6501: fpsr, regs.fpcr, regs.fpiar,
1.1.1.4 root 6502: (fpsr & 0x8000000) != 0,
6503: (fpsr & 0x4000000) != 0,
6504: (fpsr & 0x2000000) != 0,
6505: (fpsr & 0x1000000) != 0);
6506: }
6507: #endif
1.1.1.7 ! root 6508: if (currprefs.mmu_model == 68030) {
! 6509: #ifndef WINUAE_FOR_HATARI
! 6510: console_out_f (_T("SRP: %llX CRP: %llX\n"), srp_030, crp_030);
! 6511: #else
! 6512: console_out_f (_T("SRP: %"PRIX64" CRP: %"PRIX64"\n"), srp_030, crp_030);
! 6513: #endif
! 6514: console_out_f (_T("TT0: %08X TT1: %08X TC: %08X\n"), tt0_030, tt1_030, tc_030);
! 6515: }
1.1.1.4 root 6516: if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) {
6517: struct instr *dp;
6518: struct mnemolookup *lookup1, *lookup2;
6519: dp = table68k + regs.irc;
6520: for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++);
6521: dp = table68k + regs.ir;
6522: for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++);
1.1.1.7 ! root 6523: console_out_f (_T("Prefetch %04x (%s) %04x (%s) Chip latch %08X\n"), regs.irc, lookup1->name, regs.ir, lookup2->name, regs.chipset_latch_rw);
1.1.1.4 root 6524: }
6525:
1.1.1.7 ! root 6526: if (pc != 0xffffffff) {
! 6527: m68k_disasm (pc, nextpc, 1);
! 6528: if (nextpc)
! 6529: console_out_f (_T("Next PC: %08x\n"), *nextpc);
! 6530: }
! 6531: }
! 6532: void m68k_dumpstate (uaecptr *nextpc)
! 6533: {
! 6534: m68k_dumpstate_2 (m68k_getpc (), nextpc);
! 6535: }
! 6536: #ifdef WINUAE_FOR_HATARI
! 6537: void m68k_dumpstate_file (FILE *f, uaecptr *nextpc)
! 6538: {
! 6539: console_out_FILE = f;
! 6540: m68k_dumpstate_2 (m68k_getpc (), nextpc);
! 6541: console_out_FILE = NULL;
! 6542: }
! 6543: #endif
! 6544: void m68k_dumpcache (void)
! 6545: {
! 6546: int i , j;
! 6547:
! 6548: if (!currprefs.cpu_compatible)
! 6549: return;
! 6550: if (currprefs.cpu_model == 68020) {
! 6551: for (i = 0; i < CACHELINES020; i += 4) {
! 6552: for (j = 0; j < 4; j++) {
! 6553: int s = i + j;
! 6554: uaecptr addr;
! 6555: struct cache020 *c = &caches020[s];
! 6556: addr = c->tag & ~1;
! 6557: addr |= s << 2;
! 6558: console_out_f (_T("%08X:%08X%c "), addr, c->data, c->valid ? '*' : ' ');
! 6559: }
! 6560: console_out_f (_T("\n"));
! 6561: }
! 6562: } else if (currprefs.cpu_model == 68030) {
! 6563: for (i = 0; i < CACHELINES030; i++) {
! 6564: struct cache030 *c = &icaches030[i];
! 6565: uaecptr addr;
! 6566: addr = c->tag & ~1;
! 6567: addr |= i << 4;
! 6568: console_out_f (_T("%08X: "), addr);
! 6569: for (j = 0; j < 4; j++) {
! 6570: console_out_f (_T("%08X%c "), c->data[j], c->valid[j] ? '*' : ' ');
! 6571: }
! 6572: console_out_f (_T("\n"));
! 6573: }
! 6574: }
1.1.1.4 root 6575: }
6576:
6577: #ifdef SAVESTATE
6578:
6579: /* CPU save/restore code */
6580:
6581: #define CPUTYPE_EC 1
6582: #define CPUMODE_HALT 1
6583:
6584: uae_u8 *restore_cpu (uae_u8 *src)
6585: {
1.1.1.7 ! root 6586: int i, j , flags, model;
1.1.1.4 root 6587: uae_u32 l;
6588:
1.1.1.7 ! root 6589: currprefs.cpu_model = changed_prefs.cpu_model = model = restore_u32 ();
1.1.1.4 root 6590: flags = restore_u32 ();
6591: changed_prefs.address_space_24 = 0;
6592: if (flags & CPUTYPE_EC)
6593: changed_prefs.address_space_24 = 1;
6594: currprefs.address_space_24 = changed_prefs.address_space_24;
6595: currprefs.cpu_compatible = changed_prefs.cpu_compatible;
6596: currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
6597: currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
6598: currprefs.cpu_frequency = changed_prefs.cpu_frequency = 0;
6599: currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 0;
6600: for (i = 0; i < 15; i++)
6601: regs.regs[i] = restore_u32 ();
6602: regs.pc = restore_u32 ();
6603: regs.irc = restore_u16 ();
6604: regs.ir = restore_u16 ();
6605: regs.usp = restore_u32 ();
6606: regs.isp = restore_u32 ();
6607: regs.sr = restore_u16 ();
1.1.1.7 ! root 6608: printf ( "restore %x %x %x\n" , regs.usp , regs.isp , regs.sr );
1.1.1.4 root 6609: l = restore_u32 ();
6610: if (l & CPUMODE_HALT) {
6611: regs.stopped = 1;
6612: } else {
6613: regs.stopped = 0;
6614: }
6615: if (model >= 68010) {
6616: regs.dfc = restore_u32 ();
6617: regs.sfc = restore_u32 ();
6618: regs.vbr = restore_u32 ();
6619: }
6620: if (model >= 68020) {
6621: regs.caar = restore_u32 ();
6622: regs.cacr = restore_u32 ();
6623: regs.msp = restore_u32 ();
6624: }
6625: if (model >= 68030) {
1.1.1.7 ! root 6626: crp_030 = fake_crp_030 = restore_u64 ();
! 6627: srp_030 = fake_srp_030 = restore_u64 ();
! 6628: tt0_030 = fake_tt0_030 = restore_u32 ();
! 6629: tt1_030 = fake_tt1_030 = restore_u32 ();
! 6630: tc_030 = fake_tc_030 = restore_u32 ();
! 6631: mmusr_030 = fake_mmusr_030 = restore_u16 ();
1.1.1.4 root 6632: }
6633: if (model >= 68040) {
6634: regs.itt0 = restore_u32 ();
6635: regs.itt1 = restore_u32 ();
6636: regs.dtt0 = restore_u32 ();
6637: regs.dtt1 = restore_u32 ();
6638: regs.tcr = restore_u32 ();
6639: regs.urp = restore_u32 ();
6640: regs.srp = restore_u32 ();
6641: }
6642: if (model >= 68060) {
6643: regs.buscr = restore_u32 ();
6644: regs.pcr = restore_u32 ();
6645: }
6646: if (flags & 0x80000000) {
6647: int khz = restore_u32 ();
6648: restore_u32 ();
6649: if (khz > 0 && khz < 800000)
6650: currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
6651: }
1.1.1.7 ! root 6652: set_cpu_caches (true);
! 6653: if (flags & 0x40000000) {
! 6654: if (model == 68020) {
! 6655: for (i = 0; i < CACHELINES020; i++) {
! 6656: caches020[i].data = restore_u32 ();
! 6657: caches020[i].tag = restore_u32 ();
! 6658: caches020[i].valid = restore_u8 () != 0;
! 6659: }
! 6660: regs.prefetch020addr = restore_u32 ();
! 6661: regs.cacheholdingaddr020 = restore_u32 ();
! 6662: regs.cacheholdingdata020 = restore_u32 ();
! 6663: if (flags & 0x20000000) {
! 6664: // 2.7.0 new
! 6665: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 6666: regs.prefetch020[i] = restore_u32 ();
! 6667: } else {
! 6668: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 6669: regs.prefetch020[i] = restore_u16 ();
! 6670: }
! 6671: } else if (model == 68030) {
! 6672: for (i = 0; i < CACHELINES030; i++) {
! 6673: for (j = 0; j < 4; j++) {
! 6674: icaches030[i].data[j] = restore_u32 ();
! 6675: icaches030[i].valid[j] = restore_u8 () != 0;
! 6676: }
! 6677: icaches030[i].tag = restore_u32 ();
! 6678: }
! 6679: for (i = 0; i < CACHELINES030; i++) {
! 6680: for (j = 0; j < 4; j++) {
! 6681: dcaches030[i].data[j] = restore_u32 ();
! 6682: dcaches030[i].valid[j] = restore_u8 () != 0;
! 6683: }
! 6684: dcaches030[i].tag = restore_u32 ();
! 6685: }
! 6686: regs.prefetch020addr = restore_u32 ();
! 6687: regs.cacheholdingaddr020 = restore_u32 ();
! 6688: regs.cacheholdingdata020 = restore_u32 ();
! 6689: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 6690: regs.prefetch020[i] = restore_u32 ();
! 6691: } else if (model == 68040) {
! 6692: if (flags & 0x8000000) {
! 6693: for (i = 0; i < CACHESETS040; i++) {
! 6694: for (j = 0; j < CACHELINES040; j++) {
! 6695: icaches040[i].data[j][0] = restore_u32();
! 6696: icaches040[i].data[j][1] = restore_u32();
! 6697: icaches040[i].data[j][2] = restore_u32();
! 6698: icaches040[i].data[j][3] = restore_u32();
! 6699: icaches040[i].tag[j] = restore_u32();
! 6700: icaches040[i].valid[j] = restore_u16() & 1;
! 6701: }
! 6702: }
! 6703: regs.prefetch020addr = restore_u32();
! 6704: regs.cacheholdingaddr020 = restore_u32();
! 6705: regs.cacheholdingdata020 = restore_u32();
! 6706: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 6707: regs.prefetch020[i] = restore_u32();
! 6708: }
! 6709: }
! 6710: if (model >= 68020) {
! 6711: regs.ce020memcycles = restore_u32 ();
! 6712: restore_u32 ();
! 6713: }
! 6714: }
! 6715: if (flags & 0x10000000) {
! 6716: regs.chipset_latch_rw = restore_u32 ();
! 6717: regs.chipset_latch_read = restore_u32 ();
! 6718: regs.chipset_latch_write = restore_u32 ();
! 6719: }
! 6720:
! 6721: m68k_reset_sr();
! 6722:
! 6723: write_log (_T("CPU: %d%s%03d, PC=%08X\n"),
! 6724: model / 1000, flags & 1 ? _T("EC") : _T(""), model % 1000, regs.pc);
1.1.1.4 root 6725:
6726: return src;
6727: }
6728:
1.1.1.7 ! root 6729: static void fill_prefetch_quick (void)
! 6730: {
! 6731: if (currprefs.cpu_model >= 68020) {
! 6732: fill_prefetch ();
! 6733: return;
! 6734: }
! 6735: // old statefile compatibility, this needs to done,
! 6736: // even in 68000 cycle-exact mode
! 6737: regs.ir = get_word (m68k_getpc ());
! 6738: regs.irc = get_word (m68k_getpc () + 2);
! 6739: }
! 6740:
1.1.1.4 root 6741: void restore_cpu_finish (void)
6742: {
6743: init_m68k ();
1.1.1.7 ! root 6744: m68k_setpc_normal (regs.pc);
1.1.1.4 root 6745: doint ();
1.1.1.7 ! root 6746: fill_prefetch_quick ();
! 6747: printf ( "SR %x %x %x %x\n" , regs.sr , regs.isp , regs.usp , regs.regs[15] );
! 6748: #ifndef WINUAE_FOR_HATARI
! 6749: set_cycles (start_cycles);
! 6750: events_schedule ();
! 6751: #endif
1.1.1.4 root 6752: if (regs.stopped)
6753: set_special (SPCFLAG_STOP);
6754: //activate_debugger ();
6755: }
6756:
1.1.1.7 ! root 6757: uae_u8 *save_cpu_trace (int *len, uae_u8 *dstptr)
1.1.1.4 root 6758: {
1.1.1.7 ! root 6759: uae_u8 *dstbak, *dst;
! 6760: int i;
1.1.1.4 root 6761:
1.1.1.7 ! root 6762: if (cputrace.state <= 0)
! 6763: return NULL;
1.1.1.4 root 6764:
1.1.1.7 ! root 6765: if (dstptr)
! 6766: dstbak = dst = dstptr;
! 6767: else
! 6768: dstbak = dst = xmalloc (uae_u8, 1000);
! 6769:
! 6770: save_u32 (2 | 4 | 8);
! 6771: save_u16 (cputrace.opcode);
! 6772: for (i = 0; i < 16; i++)
! 6773: save_u32 (cputrace.regs[i]);
! 6774: save_u32 (cputrace.pc);
! 6775: save_u16 (cputrace.irc);
! 6776: save_u16 (cputrace.ir);
! 6777: save_u32 (cputrace.usp);
! 6778: save_u32 (cputrace.isp);
! 6779: save_u16 (cputrace.sr);
! 6780: save_u16 (cputrace.intmask);
! 6781: save_u16 ((cputrace.stopped ? 1 : 0) | (regs.stopped ? 2 : 0));
! 6782: save_u16 (cputrace.state);
! 6783: save_u32 (cputrace.cyclecounter);
! 6784: save_u32 (cputrace.cyclecounter_pre);
! 6785: save_u32 (cputrace.cyclecounter_post);
! 6786: save_u32 (cputrace.readcounter);
! 6787: save_u32 (cputrace.writecounter);
! 6788: save_u32 (cputrace.memoryoffset);
! 6789: write_log (_T("CPUT SAVE: PC=%08x C=%08X %08x %08x %08x %d %d %d\n"),
! 6790: cputrace.pc, cputrace.startcycles,
! 6791: cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
! 6792: cputrace.readcounter, cputrace.writecounter, cputrace.memoryoffset);
! 6793: for (i = 0; i < cputrace.memoryoffset; i++) {
! 6794: save_u32 (cputrace.ctm[i].addr);
! 6795: save_u32 (cputrace.ctm[i].data);
! 6796: save_u32 (cputrace.ctm[i].mode);
! 6797: write_log (_T("CPUT%d: %08x %08x %08x\n"), i, cputrace.ctm[i].addr, cputrace.ctm[i].data, cputrace.ctm[i].mode);
! 6798: }
! 6799: save_u32 (cputrace.startcycles);
! 6800:
! 6801: if (currprefs.cpu_model == 68020) {
! 6802: for (i = 0; i < CACHELINES020; i++) {
! 6803: save_u32 (cputrace.caches020[i].data);
! 6804: save_u32 (cputrace.caches020[i].tag);
! 6805: save_u8 (cputrace.caches020[i].valid ? 1 : 0);
! 6806: }
! 6807: save_u32 (cputrace.prefetch020addr);
! 6808: save_u32 (cputrace.cacheholdingaddr020);
! 6809: save_u32 (cputrace.cacheholdingdata020);
! 6810: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 6811: save_u16 (cputrace.prefetch020[i]);
! 6812: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 6813: save_u32 (cputrace.prefetch020[i]);
! 6814: }
! 6815:
! 6816: *len = dst - dstbak;
! 6817: cputrace.needendcycles = 1;
! 6818: return dstbak;
! 6819: }
! 6820:
! 6821: uae_u8 *restore_cpu_trace (uae_u8 *src)
! 6822: {
! 6823: int i;
! 6824:
! 6825: cpu_tracer = 0;
! 6826: cputrace.state = 0;
! 6827: uae_u32 v = restore_u32 ();
! 6828: if (!(v & 2))
! 6829: return src;
! 6830: cputrace.opcode = restore_u16 ();
! 6831: for (i = 0; i < 16; i++)
! 6832: cputrace.regs[i] = restore_u32 ();
! 6833: cputrace.pc = restore_u32 ();
! 6834: cputrace.irc = restore_u16 ();
! 6835: cputrace.ir = restore_u16 ();
! 6836: cputrace.usp = restore_u32 ();
! 6837: cputrace.isp = restore_u32 ();
! 6838: cputrace.sr = restore_u16 ();
! 6839: cputrace.intmask = restore_u16 ();
! 6840: cputrace.stopped = restore_u16 ();
! 6841: cputrace.state = restore_u16 ();
! 6842: cputrace.cyclecounter = restore_u32 ();
! 6843: cputrace.cyclecounter_pre = restore_u32 ();
! 6844: cputrace.cyclecounter_post = restore_u32 ();
! 6845: cputrace.readcounter = restore_u32 ();
! 6846: cputrace.writecounter = restore_u32 ();
! 6847: cputrace.memoryoffset = restore_u32 ();
! 6848: for (i = 0; i < cputrace.memoryoffset; i++) {
! 6849: cputrace.ctm[i].addr = restore_u32 ();
! 6850: cputrace.ctm[i].data = restore_u32 ();
! 6851: cputrace.ctm[i].mode = restore_u32 ();
! 6852: }
! 6853: cputrace.startcycles = restore_u32 ();
! 6854:
! 6855: if (v & 4) {
! 6856: if (currprefs.cpu_model == 68020) {
! 6857: for (i = 0; i < CACHELINES020; i++) {
! 6858: cputrace.caches020[i].data = restore_u32 ();
! 6859: cputrace.caches020[i].tag = restore_u32 ();
! 6860: cputrace.caches020[i].valid = restore_u8 () != 0;
! 6861: }
! 6862: cputrace.prefetch020addr = restore_u32 ();
! 6863: cputrace.cacheholdingaddr020 = restore_u32 ();
! 6864: cputrace.cacheholdingdata020 = restore_u32 ();
! 6865: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 6866: cputrace.prefetch020[i] = restore_u16 ();
! 6867: if (v & 8) {
! 6868: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 6869: cputrace.prefetch020[i] = restore_u32 ();
! 6870: }
! 6871: }
! 6872: }
! 6873:
! 6874: cputrace.needendcycles = 1;
! 6875: if (v && cputrace.state) {
! 6876: if (currprefs.cpu_model > 68000) {
! 6877: if (v & 4)
! 6878: cpu_tracer = -1;
! 6879: // old format?
! 6880: if ((v & (4 | 8)) != (4 | 8))
! 6881: cpu_tracer = 0;
! 6882: } else {
! 6883: cpu_tracer = -1;
! 6884: }
! 6885: }
! 6886:
! 6887: return src;
! 6888: }
! 6889:
! 6890: uae_u8 *restore_cpu_extra (uae_u8 *src)
! 6891: {
! 6892: restore_u32 ();
! 6893: uae_u32 flags = restore_u32 ();
! 6894:
! 6895: currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact = (flags & 1) ? true : false;
! 6896: currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact = currprefs.cpu_cycle_exact;
! 6897: currprefs.cpu_compatible = changed_prefs.cpu_compatible = (flags & 2) ? true : false;
! 6898: currprefs.cpu_frequency = changed_prefs.cpu_frequency = restore_u32 ();
! 6899: currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = restore_u32 ();
! 6900: //currprefs.cachesize = changed_prefs.cachesize = (flags & 8) ? 8192 : 0;
! 6901:
! 6902: currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
! 6903: if (flags & 4)
1.1.1.4 root 6904: currprefs.m68k_speed = changed_prefs.m68k_speed = -1;
1.1.1.7 ! root 6905: if (flags & 16)
! 6906: currprefs.m68k_speed = changed_prefs.m68k_speed = (flags >> 24) * CYCLE_UNIT;
1.1.1.4 root 6907:
6908: currprefs.cpu060_revision = changed_prefs.cpu060_revision = restore_u8 ();
6909: currprefs.fpu_revision = changed_prefs.fpu_revision = restore_u8 ();
6910:
6911: return src;
6912: }
6913:
6914: uae_u8 *save_cpu_extra (int *len, uae_u8 *dstptr)
6915: {
6916: uae_u8 *dstbak, *dst;
6917: uae_u32 flags;
6918:
6919: if (dstptr)
6920: dstbak = dst = dstptr;
6921: else
6922: dstbak = dst = xmalloc (uae_u8, 1000);
6923: save_u32 (0); // version
6924: flags = 0;
6925: flags |= currprefs.cpu_cycle_exact ? 1 : 0;
6926: flags |= currprefs.cpu_compatible ? 2 : 0;
6927: flags |= currprefs.m68k_speed < 0 ? 4 : 0;
6928: flags |= currprefs.cachesize > 0 ? 8 : 0;
1.1.1.7 ! root 6929: flags |= currprefs.m68k_speed > 0 ? 16 : 0;
! 6930: if (currprefs.m68k_speed > 0)
! 6931: flags |= (currprefs.m68k_speed / CYCLE_UNIT) << 24;
1.1.1.4 root 6932: save_u32 (flags);
6933: save_u32 (currprefs.cpu_frequency);
6934: save_u32 (currprefs.cpu_clock_multiplier);
6935: save_u8 (currprefs.cpu060_revision);
6936: save_u8 (currprefs.fpu_revision);
6937: *len = dst - dstbak;
6938: return dstbak;
6939: }
6940:
6941: uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
6942: {
6943: uae_u8 *dstbak, *dst;
1.1.1.7 ! root 6944: int model, i, j, khz;
1.1.1.4 root 6945:
6946: if (dstptr)
6947: dstbak = dst = dstptr;
6948: else
6949: dstbak = dst = xmalloc (uae_u8, 1000);
6950: model = currprefs.cpu_model;
6951: save_u32 (model); /* MODEL */
1.1.1.7 ! root 6952: save_u32(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | 0x8000000 |(currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
1.1.1.4 root 6953: for (i = 0;i < 15; i++)
6954: save_u32 (regs.regs[i]); /* D0-D7 A0-A6 */
6955: save_u32 (m68k_getpc ()); /* PC */
6956: save_u16 (regs.irc); /* prefetch */
6957: save_u16 (regs.ir); /* instruction prefetch */
6958: MakeSR ();
6959: save_u32 (!regs.s ? regs.regs[15] : regs.usp); /* USP */
6960: save_u32 (regs.s ? regs.regs[15] : regs.isp); /* ISP */
6961: save_u16 (regs.sr); /* SR/CCR */
6962: save_u32 (regs.stopped ? CPUMODE_HALT : 0); /* flags */
6963: if (model >= 68010) {
6964: save_u32 (regs.dfc); /* DFC */
6965: save_u32 (regs.sfc); /* SFC */
6966: save_u32 (regs.vbr); /* VBR */
6967: }
6968: if (model >= 68020) {
6969: save_u32 (regs.caar); /* CAAR */
6970: save_u32 (regs.cacr); /* CACR */
6971: save_u32 (regs.msp); /* MSP */
6972: }
6973: if (model >= 68030) {
1.1.1.7 ! root 6974: if (currprefs.mmu_model) {
! 6975: save_u64 (crp_030); /* CRP */
! 6976: save_u64 (srp_030); /* SRP */
! 6977: save_u32 (tt0_030); /* TT0/AC0 */
! 6978: save_u32 (tt1_030); /* TT1/AC1 */
! 6979: save_u32 (tc_030); /* TCR */
! 6980: save_u16 (mmusr_030); /* MMUSR/ACUSR */
! 6981: } else {
! 6982: save_u64 (fake_crp_030); /* CRP */
! 6983: save_u64 (fake_srp_030); /* SRP */
! 6984: save_u32 (fake_tt0_030); /* TT0/AC0 */
! 6985: save_u32 (fake_tt1_030); /* TT1/AC1 */
! 6986: save_u32 (fake_tc_030); /* TCR */
! 6987: save_u16 (fake_mmusr_030); /* MMUSR/ACUSR */
! 6988: }
1.1.1.4 root 6989: }
6990: if (model >= 68040) {
6991: save_u32 (regs.itt0); /* ITT0 */
6992: save_u32 (regs.itt1); /* ITT1 */
6993: save_u32 (regs.dtt0); /* DTT0 */
6994: save_u32 (regs.dtt1); /* DTT1 */
6995: save_u32 (regs.tcr); /* TCR */
6996: save_u32 (regs.urp); /* URP */
6997: save_u32 (regs.srp); /* SRP */
6998: }
6999: if (model >= 68060) {
7000: save_u32 (regs.buscr); /* BUSCR */
7001: save_u32 (regs.pcr); /* PCR */
7002: }
7003: khz = -1;
7004: if (currprefs.m68k_speed == 0) {
7005: khz = currprefs.ntscmode ? 715909 : 709379;
7006: if (currprefs.cpu_model >= 68020)
7007: khz *= 2;
7008: }
7009: save_u32 (khz); // clock rate in KHz: -1 = fastest possible
7010: save_u32 (0); // spare
1.1.1.7 ! root 7011: if (model == 68020) {
! 7012: for (i = 0; i < CACHELINES020; i++) {
! 7013: save_u32 (caches020[i].data);
! 7014: save_u32 (caches020[i].tag);
! 7015: save_u8 (caches020[i].valid ? 1 : 0);
! 7016: }
! 7017: save_u32 (regs.prefetch020addr);
! 7018: save_u32 (regs.cacheholdingaddr020);
! 7019: save_u32 (regs.cacheholdingdata020);
! 7020: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 7021: save_u32 (regs.prefetch020[i]);
! 7022: } else if (model == 68030) {
! 7023: for (i = 0; i < CACHELINES030; i++) {
! 7024: for (j = 0; j < 4; j++) {
! 7025: save_u32 (icaches030[i].data[j]);
! 7026: save_u8 (icaches030[i].valid[j] ? 1 : 0);
! 7027: }
! 7028: save_u32 (icaches030[i].tag);
! 7029: }
! 7030: for (i = 0; i < CACHELINES030; i++) {
! 7031: for (j = 0; j < 4; j++) {
! 7032: save_u32 (dcaches030[i].data[j]);
! 7033: save_u8 (dcaches030[i].valid[j] ? 1 : 0);
! 7034: }
! 7035: save_u32 (dcaches030[i].tag);
! 7036: }
! 7037: save_u32 (regs.prefetch020addr);
! 7038: save_u32 (regs.cacheholdingaddr020);
! 7039: save_u32 (regs.cacheholdingdata020);
! 7040: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 7041: save_u32 (regs.prefetch020[i]);
! 7042: } else if (model >= 68040) {
! 7043: for (i = 0; i < CACHESETS040; i++) {
! 7044: for (j = 0; j < CACHELINES040; j++) {
! 7045: save_u32(icaches040[i].data[j][0]);
! 7046: save_u32(icaches040[i].data[j][1]);
! 7047: save_u32(icaches040[i].data[j][2]);
! 7048: save_u32(icaches040[i].data[j][3]);
! 7049: save_u32(icaches040[i].tag[j]);
! 7050: save_u16(icaches040[i].valid[j] ? 1 : 0);
! 7051: }
! 7052: }
! 7053: save_u32(regs.prefetch020addr);
! 7054: save_u32(regs.cacheholdingaddr020);
! 7055: save_u32(regs.cacheholdingdata020);
! 7056: for (i = 0; i < CPU_PIPELINE_MAX; i++)
! 7057: save_u32(regs.prefetch020[i]);
! 7058: }
! 7059: if (currprefs.cpu_model >= 68020) {
! 7060: save_u32 (regs.ce020memcycles);
! 7061: save_u32 (0);
! 7062: }
! 7063: save_u32 (regs.chipset_latch_rw);
! 7064: save_u32 (regs.chipset_latch_read);
! 7065: save_u32 (regs.chipset_latch_write);
1.1.1.4 root 7066: *len = dst - dstbak;
7067: return dstbak;
7068: }
7069:
7070: uae_u8 *save_mmu (int *len, uae_u8 *dstptr)
7071: {
7072: uae_u8 *dstbak, *dst;
7073: int model;
7074:
7075: model = currprefs.mmu_model;
1.1.1.7 ! root 7076: #ifndef WINUAE_FOR_HATARI
! 7077: /* Under Hatari, we save all MMU variables, even if mmu_model==0 */
! 7078: if (model != 68030 && model != 68040 && model != 68060)
1.1.1.4 root 7079: return NULL;
1.1.1.7 ! root 7080: #endif
1.1.1.4 root 7081: if (dstptr)
7082: dstbak = dst = dstptr;
7083: else
7084: dstbak = dst = xmalloc (uae_u8, 1000);
7085: save_u32 (model); /* MODEL */
1.1.1.7 ! root 7086: save_u32 (0); /* FLAGS */
1.1.1.4 root 7087: *len = dst - dstbak;
7088: return dstbak;
7089: }
7090:
7091: uae_u8 *restore_mmu (uae_u8 *src)
7092: {
7093: int flags, model;
7094:
7095: changed_prefs.mmu_model = model = restore_u32 ();
7096: flags = restore_u32 ();
1.1.1.7 ! root 7097: write_log (_T("MMU: %d\n"), model);
1.1.1.4 root 7098: return src;
7099: }
7100:
7101: #endif /* SAVESTATE */
7102:
1.1.1.7 ! root 7103: static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, bool plus2)
1.1.1.4 root 7104: {
7105: if (currprefs.cpu_model >= 68040)
7106: addr &= ~1;
1.1.1.7 ! root 7107: if (currprefs.cpu_model >= 68020) {
! 7108: if (pc == 0xffffffff)
! 7109: last_addr_for_exception_3 = regs.instruction_pc;
! 7110: else
! 7111: last_addr_for_exception_3 = pc;
! 7112: } else if (pc == 0xffffffff) {
! 7113: last_addr_for_exception_3 = m68k_getpc ();
! 7114: if (plus2)
! 7115: last_addr_for_exception_3 += 2;
! 7116: } else {
! 7117: last_addr_for_exception_3 = pc;
! 7118: }
! 7119: last_fault_for_exception_3 = addr;
1.1.1.4 root 7120: last_op_for_exception_3 = opcode;
7121: last_writeaccess_for_exception_3 = writeaccess;
7122: last_instructionaccess_for_exception_3 = instructionaccess;
1.1.1.7 ! root 7123: last_notinstruction_for_exception_3 = notinstruction;
! 7124: Exception (3);
! 7125: #if EXCEPTION3_DEBUGGER
! 7126: activate_debugger();
! 7127: #endif
1.1.1.4 root 7128: }
7129:
1.1.1.7 ! root 7130: void exception3_notinstruction(uae_u32 opcode, uaecptr addr)
1.1.1.4 root 7131: {
1.1.1.7 ! root 7132: exception3f (opcode, addr, true, false, true, 0xffffffff, false);
1.1.1.4 root 7133: }
1.1.1.7 ! root 7134: void exception3_read(uae_u32 opcode, uaecptr addr)
! 7135: {
! 7136: exception3f (opcode, addr, false, 0, false, 0xffffffff, false);
! 7137: }
! 7138: void exception3_write(uae_u32 opcode, uaecptr addr)
! 7139: {
! 7140: exception3f (opcode, addr, true, 0, false, 0xffffffff, false);
! 7141: }
! 7142: void exception3i (uae_u32 opcode, uaecptr addr)
! 7143: {
! 7144: exception3f (opcode, addr, 0, 1, false, 0xffffffff, true);
! 7145: }
! 7146: void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
1.1.1.4 root 7147: {
1.1.1.7 ! root 7148: exception3f (opcode, addr, w, i, false, pc, true);
1.1.1.4 root 7149: }
7150:
1.1.1.7 ! root 7151: void exception2 (uaecptr addr, bool read, int size, uae_u32 fc)
1.1.1.4 root 7152: {
1.1.1.7 ! root 7153: if (currprefs.mmu_model) {
! 7154: if (currprefs.mmu_model == 68030) {
! 7155: uae_u32 flags = size == 1 ? MMU030_SSW_SIZE_B : (size == 2 ? MMU030_SSW_SIZE_W : MMU030_SSW_SIZE_L);
! 7156: mmu030_page_fault (addr, read, flags, fc);
! 7157: } else {
! 7158: mmu_bus_error (addr, fc, read == false, size, false, 0, true);
! 7159: }
! 7160: } else {
! 7161: last_addr_for_exception_3 = m68k_getpc() + bus_error_offset;
! 7162: last_fault_for_exception_3 = addr;
! 7163: last_writeaccess_for_exception_3 = read == 0;
! 7164: last_instructionaccess_for_exception_3 = (fc & 1) == 0;
! 7165: last_op_for_exception_3 = regs.opcode;
! 7166: last_notinstruction_for_exception_3 = exception_in_exception != 0;
! 7167: THROW(2);
! 7168: }
1.1.1.4 root 7169: }
7170:
7171: void cpureset (void)
7172: {
1.1.1.7 ! root 7173: /* RESET hasn't increased PC yet, 1 word offset */
1.1.1.4 root 7174: uaecptr pc;
1.1.1.7 ! root 7175: #ifndef WINUAE_FOR_HATARI
! 7176: uaecptr ksboot = 0xf80002 - 2;
1.1.1.4 root 7177: uae_u16 ins;
1.1.1.7 ! root 7178: #endif
! 7179: addrbank *ab;
1.1.1.4 root 7180:
1.1.1.7 ! root 7181: m68k_reset_delay = currprefs.reset_delay;
! 7182: set_special(SPCFLAG_CHECK);
! 7183: #ifndef WINUAE_FOR_HATARI
! 7184: send_internalevent(INTERNALEVENT_CPURESET);
! 7185: if ((currprefs.cpu_compatible || currprefs.cpu_cycle_exact) && currprefs.cpu_model <= 68020) {
! 7186: custom_reset (false, false);
1.1.1.4 root 7187: return;
7188: }
1.1.1.7 ! root 7189: #endif
! 7190: pc = m68k_getpc () + 2;
! 7191: ab = &get_mem_bank (pc);
! 7192: if (ab->check (pc, 2)) {
! 7193: write_log (_T("CPU reset PC=%x (%s)..\n"), pc - 2, ab->name);
! 7194: #ifndef WINUAE_FOR_HATARI
! 7195: ins = get_word (pc);
! 7196: custom_reset (false, false);
! 7197: // did memory disappear under us?
! 7198: if (ab == &get_mem_bank (pc))
! 7199: return;
! 7200: // it did
! 7201: if ((ins & ~7) == 0x4ed0) {
! 7202: int reg = ins & 7;
! 7203: uae_u32 addr = m68k_areg (regs, reg);
! 7204: if (addr < 0x80000)
! 7205: addr += 0xf80000;
! 7206: write_log (_T("reset/jmp (ax) combination at %08x emulated -> %x\n"), pc, addr);
! 7207: m68k_setpc_normal (addr - 2);
1.1.1.4 root 7208: return;
7209: }
1.1.1.7 ! root 7210: #else
! 7211: customreset (); /* From hatari-glue.c */
! 7212: return;
! 7213: #endif
! 7214: }
! 7215: // the best we can do, jump directly to ROM entrypoint
! 7216: // (which is probably what program wanted anyway)
! 7217: #ifndef WINUAE_FOR_HATARI
! 7218: write_log (_T("CPU Reset PC=%x (%s), invalid memory -> %x.\n"), pc, ab->name, ksboot + 2);
! 7219: custom_reset (false, false);
! 7220: m68k_setpc_normal (ksboot);
! 7221: #else
! 7222: write_log (_T("CPU Reset PC=%x (%s), invalid memory\n"), pc, ab->name);
! 7223: customreset (); /* From hatari-glue.c */
! 7224: #endif
1.1.1.4 root 7225: }
7226:
7227:
7228: void m68k_setstopped (void)
7229: {
7230: regs.stopped = 1;
7231: /* A traced STOP instruction drops through immediately without
7232: actually stopping. */
7233: if ((regs.spcflags & SPCFLAG_DOTRACE) == 0)
7234: set_special (SPCFLAG_STOP);
7235: else
7236: m68k_resumestopped ();
7237: }
7238:
7239: void m68k_resumestopped (void)
7240: {
7241: if (!regs.stopped)
7242: return;
7243: regs.stopped = 0;
7244: if (currprefs.cpu_cycle_exact) {
7245: if (currprefs.cpu_model == 68000)
1.1.1.7 ! root 7246: x_do_cycles (6 * cpucycleunit);
1.1.1.4 root 7247: }
1.1.1.7 ! root 7248: fill_prefetch ();
1.1.1.4 root 7249: unset_special (SPCFLAG_STOP);
7250: }
7251:
7252: // this one is really simple and easy
1.1.1.7 ! root 7253: static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr))
1.1.1.4 root 7254: {
7255: int index;
7256: uae_u32 tag;
7257: uae_u32 data;
7258: struct cache020 *c;
7259:
7260: addr &= ~3;
1.1.1.7 ! root 7261: if (regs.cacheholdingaddr020 == addr)
! 7262: return;
1.1.1.4 root 7263: index = (addr >> 2) & (CACHELINES020 - 1);
7264: tag = regs.s | (addr & ~((CACHELINES020 << 2) - 1));
7265: c = &caches020[index];
7266: if (c->valid && c->tag == tag) {
7267: // cache hit
1.1.1.7 ! root 7268: regs.cacheholdingaddr020 = addr;
! 7269: regs.cacheholdingdata020 = c->data;
! 7270: #ifdef WINUAE_FOR_HATARI
! 7271: CpuInstruction.I_Cache_hit++;
! 7272: #endif
1.1.1.4 root 7273: return;
7274: }
7275: // cache miss
1.1.1.7 ! root 7276: // Prefetch apparently can be queued by bus controller
! 7277: // even if bus controller is currently processing
! 7278: // previous data access.
! 7279: // Other combinations are not possible.
! 7280: if (!regs.ce020memcycle_data)
! 7281: regs.ce020memcycles = 0;
! 7282: regs.ce020memcycle_data = false;
! 7283: unsigned long cycs = get_cycles ();
! 7284: data = fetch (addr);
! 7285: // add as available "free" internal CPU time.
! 7286: cycs = get_cycles () - cycs;
! 7287: regs.ce020memcycles += cycs;
1.1.1.4 root 7288: if (!(regs.cacr & 2)) {
7289: c->tag = tag;
7290: c->valid = !!(regs.cacr & 1);
7291: c->data = data;
7292: }
1.1.1.7 ! root 7293: regs.cacheholdingaddr020 = addr;
! 7294: regs.cacheholdingdata020 = data;
! 7295: #ifdef WINUAE_FOR_HATARI
! 7296: CpuInstruction.I_Cache_miss++;
! 7297: #endif
1.1.1.4 root 7298: }
7299:
1.1.1.7 ! root 7300: #if MORE_ACCURATE_68020_PIPELINE
! 7301: #define PIPELINE_DEBUG 0
! 7302: #if PIPELINE_DEBUG
! 7303: static uae_u16 pipeline_opcode;
! 7304: #endif
! 7305: static void pipeline_020(uae_u16 w, uaecptr pc)
1.1.1.4 root 7306: {
1.1.1.7 ! root 7307: if (regs.pipeline_pos < 0)
! 7308: return;
! 7309: if (regs.pipeline_pos > 0) {
! 7310: // handle annoying 68020+ addressing modes
! 7311: if (regs.pipeline_pos == regs.pipeline_r8[0]) {
! 7312: regs.pipeline_r8[0] = 0;
! 7313: if (w & 0x100) {
! 7314: int extra = 0;
! 7315: if ((w & 0x30) == 0x20)
! 7316: extra += 2;
! 7317: if ((w & 0x30) == 0x30)
! 7318: extra += 4;
! 7319: if ((w & 0x03) == 0x02)
! 7320: extra += 2;
! 7321: if ((w & 0x03) == 0x03)
! 7322: extra += 4;
! 7323: regs.pipeline_pos += extra;
! 7324: }
! 7325: return;
! 7326: }
! 7327: if (regs.pipeline_pos == regs.pipeline_r8[1]) {
! 7328: regs.pipeline_r8[1] = 0;
! 7329: if (w & 0x100) {
! 7330: int extra = 0;
! 7331: if ((w & 0x30) == 0x20)
! 7332: extra += 2;
! 7333: if ((w & 0x30) == 0x30)
! 7334: extra += 4;
! 7335: if ((w & 0x03) == 0x02)
! 7336: extra += 2;
! 7337: if ((w & 0x03) == 0x03)
! 7338: extra += 4;
! 7339: regs.pipeline_pos += extra;
1.1.1.4 root 7340: }
1.1.1.7 ! root 7341: return;
! 7342: }
! 7343: }
! 7344: if (regs.pipeline_pos > 2) {
! 7345: regs.pipeline_pos -= 2;
! 7346: // If stop set, prefetches stop 1 word early.
! 7347: if (regs.pipeline_stop > 0 && regs.pipeline_pos == 2)
! 7348: regs.pipeline_stop = -1;
! 7349: return;
! 7350: }
! 7351: if (regs.pipeline_stop) {
! 7352: regs.pipeline_stop = -1;
! 7353: return;
! 7354: }
! 7355: #if PIPELINE_DEBUG
! 7356: pipeline_opcode = w;
! 7357: #endif
! 7358: regs.pipeline_r8[0] = cpudatatbl[w].disp020[0];
! 7359: regs.pipeline_r8[1] = cpudatatbl[w].disp020[1];
! 7360: regs.pipeline_pos = cpudatatbl[w].length;
! 7361: #if PIPELINE_DEBUG
! 7362: if (!regs.pipeline_pos) {
! 7363: write_log(_T("Opcode %04x has no size PC=%08x!\n"), w, pc);
! 7364: }
! 7365: #endif
! 7366: int branch = cpudatatbl[w].branch;
! 7367: if (regs.pipeline_pos > 0 && branch) {
! 7368: // Short branches (Bcc.s) still do one more prefetch.
! 7369: #if 0
! 7370: // RTS and other unconditional single opcode instruction stop immediately.
! 7371: if (branch == 2) {
! 7372: // Immediate stop
! 7373: regs.pipeline_stop = -1;
! 7374: } else {
! 7375: // Stop 1 word early than normally
! 7376: regs.pipeline_stop = 1;
1.1.1.4 root 7377: }
1.1.1.7 ! root 7378: #else
! 7379: regs.pipeline_stop = 1;
! 7380: #endif
1.1.1.4 root 7381: }
7382: }
7383:
1.1.1.7 ! root 7384: // Not exactly right, requires logic analyzer checks.
! 7385: void continue_ce020_prefetch(void)
1.1.1.4 root 7386: {
1.1.1.7 ! root 7387: fill_prefetch_020();
1.1.1.4 root 7388: }
1.1.1.7 ! root 7389: void continue_020_prefetch(void)
1.1.1.4 root 7390: {
1.1.1.7 ! root 7391: fill_prefetch_020();
1.1.1.4 root 7392: }
1.1.1.7 ! root 7393: #endif
1.1.1.4 root 7394:
1.1.1.7 ! root 7395: uae_u32 get_word_ce020_prefetch (int o)
1.1.1.4 root 7396: {
1.1.1.7 ! root 7397: uae_u32 pc = m68k_getpc () + o;
! 7398: uae_u32 v;
1.1.1.4 root 7399:
1.1.1.7 ! root 7400: if (pc & 2) {
! 7401: v = regs.prefetch020[0] & 0xffff;
! 7402: #if MORE_ACCURATE_68020_PIPELINE
! 7403: pipeline_020(regs.prefetch020[1], pc );
! 7404: #endif
! 7405: regs.prefetch020[0] = regs.prefetch020[1];
! 7406: // branch instruction detected in pipeline: stop fetches until branch executed.
! 7407: if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
! 7408: fill_icache020 (pc + 2 + 4, mem_access_delay_longi_read_ce020);
! 7409: regs.prefetch020[1] = regs.cacheholdingdata020;
1.1.1.4 root 7410: }
1.1.1.7 ! root 7411: regs.db = regs.prefetch020[0] >> 16;
! 7412: } else {
! 7413: v = regs.prefetch020[0] >> 16;
! 7414: #if MORE_ACCURATE_68020_PIPELINE
! 7415: pipeline_020(regs.prefetch020[1] >> 16, pc);
1.1.1.4 root 7416: #endif
1.1.1.7 ! root 7417: regs.db = regs.prefetch020[1] >> 16;
1.1.1.4 root 7418: }
1.1.1.7 ! root 7419: do_cycles_ce020_internal (2);
! 7420: return v;
1.1.1.4 root 7421: }
7422:
1.1.1.7 ! root 7423: uae_u32 get_word_020_prefetch (int o)
1.1.1.4 root 7424: {
1.1.1.7 ! root 7425: uae_u32 pc = m68k_getpc () + o;
! 7426: uae_u32 v;
1.1.1.4 root 7427:
1.1.1.7 ! root 7428: if (pc & 2) {
! 7429: v = regs.prefetch020[0] & 0xffff;
! 7430: #if MORE_ACCURATE_68020_PIPELINE
! 7431: pipeline_020(regs.prefetch020[1], pc);
! 7432: #endif
! 7433: regs.prefetch020[0] = regs.prefetch020[1];
! 7434: if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
! 7435: fill_icache020 (pc + 2 + 4, get_longi);
! 7436: regs.prefetch020[1] = regs.cacheholdingdata020;
! 7437: }
! 7438: regs.db = regs.prefetch020[0] >> 16;
! 7439: } else {
! 7440: v = regs.prefetch020[0] >> 16;
! 7441: #if MORE_ACCURATE_68020_PIPELINE
! 7442: pipeline_020(regs.prefetch020[1] >> 16, pc);
! 7443: #endif
! 7444: regs.db = regs.prefetch020[0];
! 7445: }
! 7446: //if ( ( v & 0xffff ) != ( get_word(pc) & 0xffff ) )
! 7447: // fprintf ( stderr , "prefetch mismatch pc=%x prefetch=%x != mem=%x, i-cache error ?\n" , pc , v&0xffff , get_word(pc)&0xffff );
! 7448: return v;
! 7449: }
1.1.1.4 root 7450:
1.1.1.7 ! root 7451: // these are also used by 68030.
1.1.1.4 root 7452:
1.1.1.7 ! root 7453: #define RESET_CE020_CYCLES \
! 7454: regs.ce020memcycles = 0; \
! 7455: regs.ce020memcycle_data = true;
! 7456: #define STORE_CE020_CYCLES \
! 7457: unsigned long cycs = get_cycles ()
! 7458: #define ADD_CE020_CYCLES \
! 7459: regs.ce020memcycles += get_cycles () - cycs
1.1.1.4 root 7460:
1.1.1.7 ! root 7461: uae_u32 mem_access_delay_long_read_ce020 (uaecptr addr)
! 7462: {
! 7463: uae_u32 v;
! 7464: RESET_CE020_CYCLES;
! 7465: STORE_CE020_CYCLES;
! 7466: switch (ce_banktype[addr >> 16])
! 7467: {
! 7468: case CE_MEMBANK_CHIP16:
! 7469: v = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
! 7470: v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) << 0;
! 7471: break;
! 7472: case CE_MEMBANK_CHIP32:
! 7473: if ((addr & 3) != 0) {
! 7474: v = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
! 7475: v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) << 0;
! 7476: } else {
! 7477: v = wait_cpu_cycle_read_ce020 (addr, -1);
! 7478: }
! 7479: break;
! 7480: case CE_MEMBANK_FAST32:
! 7481: v = get_long (addr);
! 7482: if ((addr & 3) != 0)
! 7483: do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
! 7484: else
! 7485: do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
! 7486: break;
! 7487: case CE_MEMBANK_FAST16:
! 7488: v = get_long (addr);
! 7489: do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
! 7490: break;
! 7491: default:
! 7492: v = get_long (addr);
! 7493: break;
! 7494: }
! 7495: ADD_CE020_CYCLES;
! 7496: return v;
! 7497: }
! 7498:
! 7499: uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr)
! 7500: {
! 7501: uae_u32 v;
! 7502: switch (ce_banktype[addr >> 16])
! 7503: {
! 7504: case CE_MEMBANK_CHIP16:
! 7505: v = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
! 7506: v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) << 0;
! 7507: break;
! 7508: case CE_MEMBANK_CHIP32:
! 7509: if ((addr & 3) != 0) {
! 7510: v = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
! 7511: v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) << 0;
! 7512: } else {
! 7513: v = wait_cpu_cycle_read_ce020 (addr, -1);
! 7514: }
! 7515: break;
! 7516: case CE_MEMBANK_FAST32:
! 7517: v = get_longi (addr);
! 7518: if ((addr & 3) != 0)
! 7519: do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
! 7520: else
! 7521: do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
! 7522: break;
! 7523: case CE_MEMBANK_FAST16:
! 7524: v = get_longi (addr);
! 7525: do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
! 7526: break;
! 7527: default:
! 7528: v = get_longi (addr);
! 7529: break;
! 7530: }
! 7531: return v;
! 7532: }
! 7533:
! 7534: uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr)
! 7535: {
! 7536: uae_u32 v;
! 7537: RESET_CE020_CYCLES;
! 7538: STORE_CE020_CYCLES;
! 7539: switch (ce_banktype[addr >> 16])
! 7540: {
! 7541: case CE_MEMBANK_CHIP16:
! 7542: case CE_MEMBANK_CHIP32:
! 7543: if ((addr & 3) == 3) {
! 7544: v = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
! 7545: v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
! 7546: } else {
! 7547: v = wait_cpu_cycle_read_ce020 (addr, 1);
! 7548: }
! 7549: break;
! 7550: case CE_MEMBANK_FAST16:
! 7551: case CE_MEMBANK_FAST32:
! 7552: v = get_word (addr);
! 7553: if ((addr & 3) == 3)
! 7554: do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
! 7555: else
! 7556: do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
! 7557: break;
! 7558: default:
! 7559: v = get_word (addr);
! 7560: break;
! 7561: }
! 7562: ADD_CE020_CYCLES;
! 7563: return v;
! 7564: }
! 7565:
! 7566: uae_u32 mem_access_delay_byte_read_ce020 (uaecptr addr)
! 7567: {
! 7568: uae_u32 v;
! 7569: RESET_CE020_CYCLES;
! 7570: STORE_CE020_CYCLES;
! 7571: switch (ce_banktype[addr >> 16])
! 7572: {
! 7573: case CE_MEMBANK_CHIP16:
! 7574: case CE_MEMBANK_CHIP32:
! 7575: v = wait_cpu_cycle_read_ce020 (addr, 0);
! 7576: break;
! 7577: case CE_MEMBANK_FAST16:
! 7578: case CE_MEMBANK_FAST32:
! 7579: v = get_byte (addr);
! 7580: do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
! 7581: break;
! 7582: default:
! 7583: v = get_byte (addr);
! 7584: break;
! 7585: }
! 7586: ADD_CE020_CYCLES;
! 7587: return v;
! 7588: }
! 7589:
! 7590: void mem_access_delay_byte_write_ce020 (uaecptr addr, uae_u32 v)
! 7591: {
! 7592: RESET_CE020_CYCLES;
! 7593: STORE_CE020_CYCLES;
! 7594: switch (ce_banktype[addr >> 16])
! 7595: {
! 7596: case CE_MEMBANK_CHIP16:
! 7597: case CE_MEMBANK_CHIP32:
! 7598: wait_cpu_cycle_write_ce020 (addr, 0, v);
! 7599: break;
! 7600: case CE_MEMBANK_FAST16:
! 7601: case CE_MEMBANK_FAST32:
! 7602: put_byte (addr, v);
! 7603: do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
! 7604: break;
! 7605: default:
! 7606: put_byte (addr, v);
! 7607: break;
1.1.1.4 root 7608: }
1.1.1.7 ! root 7609: ADD_CE020_CYCLES;
! 7610: }
! 7611:
! 7612: void mem_access_delay_word_write_ce020 (uaecptr addr, uae_u32 v)
! 7613: {
! 7614: RESET_CE020_CYCLES;
! 7615: STORE_CE020_CYCLES;
! 7616: switch (ce_banktype[addr >> 16])
! 7617: {
! 7618: case CE_MEMBANK_CHIP16:
! 7619: case CE_MEMBANK_CHIP32:
! 7620: if ((addr & 3) == 3) {
! 7621: wait_cpu_cycle_write_ce020 (addr + 0, 0, (v >> 8) & 0xff);
! 7622: wait_cpu_cycle_write_ce020 (addr + 1, 0, (v >> 0) & 0xff);
! 7623: } else {
! 7624: wait_cpu_cycle_write_ce020 (addr + 0, 1, v);
! 7625: }
! 7626: break;
! 7627: case CE_MEMBANK_FAST16:
! 7628: case CE_MEMBANK_FAST32:
! 7629: put_word (addr, v);
! 7630: if ((addr & 3) == 3)
! 7631: do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
! 7632: else
! 7633: do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
! 7634: break;
! 7635: default:
! 7636: put_word (addr, v);
! 7637: break;
! 7638: }
! 7639: ADD_CE020_CYCLES;
! 7640: }
! 7641:
! 7642: void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v)
! 7643: {
! 7644: RESET_CE020_CYCLES;
! 7645: STORE_CE020_CYCLES;
! 7646: switch (ce_banktype[addr >> 16])
! 7647: {
! 7648: case CE_MEMBANK_CHIP16:
! 7649: wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
! 7650: wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >> 0) & 0xffff);
! 7651: break;
! 7652: case CE_MEMBANK_CHIP32:
! 7653: if ((addr & 3) == 3) {
! 7654: wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
! 7655: wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >> 0) & 0xffff);
! 7656: } else {
! 7657: wait_cpu_cycle_write_ce020 (addr + 0, -1, v);
! 7658: }
! 7659: break;
! 7660: case CE_MEMBANK_FAST32:
! 7661: put_long (addr, v);
! 7662: if ((addr & 3) != 0)
! 7663: do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
! 7664: else
! 7665: do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
! 7666: break;
! 7667: case CE_MEMBANK_FAST16:
! 7668: put_long (addr, v);
! 7669: do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
! 7670: break;
! 7671: default:
! 7672: put_long (addr, v);
! 7673: break;
! 7674: }
! 7675: ADD_CE020_CYCLES;
! 7676: }
! 7677:
! 7678:
! 7679: // 68030 caches aren't so simple as 68020 cache..
! 7680: STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
! 7681: {
! 7682: int index, lws;
! 7683: uae_u32 tag;
! 7684: struct cache030 *c;
! 7685:
! 7686: addr &= ~3;
! 7687: index = (addr >> 4) & (CACHELINES030 - 1);
! 7688: tag = regs.s | (addr & ~((CACHELINES030 << 4) - 1));
! 7689: lws = (addr >> 2) & 3;
! 7690: c = &cp[index];
! 7691: *tagp = tag;
! 7692: *lwsp = lws;
! 7693: return c;
! 7694: }
! 7695:
! 7696: STATIC_INLINE void update_cache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, int lws)
! 7697: {
! 7698: if (c->tag != tag)
! 7699: c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
! 7700: c->tag = tag;
! 7701: c->valid[lws] = true;
! 7702: c->data[lws] = val;
! 7703: }
! 7704:
! 7705: static void fill_icache030 (uae_u32 addr)
! 7706: {
! 7707: int lws;
! 7708: uae_u32 tag;
! 7709: uae_u32 data;
! 7710: struct cache030 *c;
! 7711: //fprintf ( stderr , "fill ica %x\n" , addr );
! 7712:
! 7713: addr &= ~3;
! 7714: if (regs.cacheholdingaddr020 == addr)
! 7715: return;
! 7716: c = getcache030 (icaches030, addr, &tag, &lws);
! 7717: if (c->valid[lws] && c->tag == tag) {
! 7718: // cache hit
! 7719: regs.cacheholdingaddr020 = addr;
! 7720: regs.cacheholdingdata020 = c->data[lws];
! 7721: //fprintf ( stderr , "fill ica %x -> hit %x\n" , addr , regs.cacheholdingdata020 );
! 7722: #ifdef WINUAE_FOR_HATARI
! 7723: CpuInstruction.I_Cache_hit++;
1.1.1.4 root 7724: #endif
1.1.1.7 ! root 7725: return;
! 7726: }
! 7727:
! 7728: // cache miss
! 7729: if (currprefs.cpu_cycle_exact) {
! 7730: if (!regs.ce020memcycle_data)
! 7731: regs.ce020memcycles = 0;
! 7732: regs.ce020memcycle_data = false;
! 7733: unsigned long cycs = get_cycles ();
! 7734: data = mem_access_delay_longi_read_ce020 (addr);
! 7735: // add as available "free" internal CPU time.
! 7736: cycs = get_cycles () - cycs;
! 7737: regs.ce020memcycles += cycs;
! 7738: } else {
! 7739: data = get_longi (addr);
! 7740: }
! 7741: if ((regs.cacr & 3) == 1) { // not frozen and enabled
! 7742: //fprintf ( stderr , "fill ica %x -> update %x\n" , addr , data );
! 7743: update_cache030 (c, data, tag, lws);
! 7744: }
! 7745: if ((regs.cacr & 0x11) == 0x11 && lws == 0 && !c->valid[1] && !c->valid[2] && !c->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
! 7746: //fprintf ( stderr , "fill ica %x -> burst %x\n" , addr , data );
! 7747: // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
! 7748: c->data[1] = get_longi (addr + 4);
! 7749: c->data[2] = get_longi (addr + 8);
! 7750: c->data[3] = get_longi (addr + 12);
! 7751: if (currprefs.cpu_cycle_exact)
! 7752: do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[3]);
! 7753: c->valid[1] = c->valid[2] = c->valid[3] = true;
! 7754: }
! 7755: regs.cacheholdingaddr020 = addr;
! 7756: regs.cacheholdingdata020 = data;
! 7757: //fprintf ( stderr , "fill ica %x -> miss %x\n" , addr , regs.cacheholdingdata020 );
! 7758: #ifdef WINUAE_FOR_HATARI
! 7759: CpuInstruction.I_Cache_miss++;
! 7760: #endif
! 7761: }
! 7762:
! 7763: STATIC_INLINE bool cancache030 (uaecptr addr)
! 7764: {
! 7765: //return false;
! 7766: return ce_cachable[addr >> 16] != 0;
! 7767: }
! 7768:
! 7769: // and finally the worst part, 68030 data cache..
! 7770: static void write_dcache030x (uaecptr addr, uae_u32 val, int size)
! 7771: {
! 7772: struct cache030 *c1, *c2;
! 7773: int lws1, lws2;
! 7774: uae_u32 tag1, tag2;
! 7775: int aligned = addr & 3;
! 7776: int wa = regs.cacr & 0x2000;
! 7777: int hit;
! 7778:
! 7779: if (!(regs.cacr & 0x100)) // data cache disabled?
! 7780: return;
! 7781: if (!cancache030 (addr))
! 7782: return;
! 7783:
! 7784: c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
1.1.1.4 root 7785:
7786: // easy one
1.1.1.7 ! root 7787: if (size == 2 && aligned == 0 && wa == 1) {
1.1.1.4 root 7788: update_cache030 (c1, val, tag1, lws1);
1.1.1.7 ! root 7789: //fprintf ( stderr , "write cache1 %x %x %d tag1 %x lws1 %x tag2 %x lws2 %x ctag %x data %x\n", addr, val, size, tag1, lws1, tag2, lws2, c1->tag , c1->data[lws1] );
1.1.1.4 root 7790: return;
7791: }
1.1.1.7 ! root 7792:
! 7793: hit = ( c1->tag == tag1 && c1->valid[lws1] );
! 7794: if ( hit || wa ) {
! 7795: if (size == 2) {
! 7796: if (hit) {
! 7797: c1->data[lws1] &= ~(0xffffffff >> (aligned * 8));
! 7798: c1->data[lws1] |= val >> (aligned * 8);
! 7799: }
! 7800: else
! 7801: c1->valid[lws1] = false;
! 7802: } else if (size == 1) {
! 7803: if (hit) {
! 7804: c1->data[lws1] &= ~(0xffff0000 >> (aligned * 8));
! 7805: c1->data[lws1] |= (val<<16) >> (aligned * 8);
! 7806: }
! 7807: else
! 7808: c1->valid[lws1] = false;
! 7809: } else if (size == 0) {
! 7810: if (hit) {
! 7811: c1->data[lws1] &= ~(0xff000000 >> (aligned * 8));
! 7812: c1->data[lws1] |= (val<<24) >> (aligned * 8);
! 7813: }
! 7814: else
! 7815: c1->valid[lws1] = false;
! 7816: }
! 7817: }
! 7818:
! 7819: // do we need to update a 2nd cache entry ?
! 7820: if ( (size == 0) || (size == 1 && aligned <= 2) || (size == 2 && aligned == 0) )
! 7821: return;
! 7822:
1.1.1.4 root 7823: c2 = getcache030 (dcaches030, addr + 4, &tag2, &lws2);
1.1.1.7 ! root 7824: //fprintf ( stderr , "write cache2 %x %x %d tag1 %x lws1 %x tag2 %x lws2 %x ctag %x data %x\n", addr, val, size, tag1, lws1, tag2, lws2, c2->tag , c2->data[lws2] );
! 7825: hit = ( c2->tag == tag2 && c2->valid[lws2] );
! 7826: if ( hit || wa ) {
! 7827: if (size == 2) {
! 7828: if (hit) {
! 7829: c2->data[lws2] &= 0xffffffff >> (aligned * 8);
! 7830: c2->data[lws2] |= val << ((4 - aligned) * 8);
! 7831: }
! 7832: else
! 7833: c2->valid[lws2] = false;
! 7834: } else if (size == 1) {
! 7835: if (hit) {
! 7836: c2->data[lws2] &= 0x00ffffff;
! 7837: c2->data[lws2] |= val << 24;
! 7838: }
! 7839: else
! 7840: c2->valid[lws2] = false;
1.1.1.4 root 7841: }
7842: }
7843: }
7844:
1.1.1.7 ! root 7845: void write_dcache030(uaecptr addr, uae_u32 v, int size)
! 7846: {
! 7847: //fprintf ( stderr , "write dcache %x %x %d\n" , addr , v , size );
! 7848: write_dcache030x(addr, v, size);
! 7849: if (currprefs.cpu_cycle_exact) {
! 7850: if (size == 2)
! 7851: mem_access_delay_long_write_ce020(addr, v);
! 7852: else if (size == 1)
! 7853: mem_access_delay_word_write_ce020(addr, v);
! 7854: else
! 7855: mem_access_delay_byte_write_ce020(addr, v);
! 7856: } else {
! 7857: if (size == 2)
! 7858: put_long(addr, v);
! 7859: else if (size == 1)
! 7860: put_word(addr, v);
! 7861: else
! 7862: put_byte(addr, v);
! 7863: }
! 7864: }
! 7865:
! 7866: // [HATARI] Define next line to check for 68030 data cache mismatch after every write
! 7867: //#define WINUAE_FOR_HATARI_DEBUG_CACHE
! 7868: #ifdef WINUAE_FOR_HATARI_DEBUG_CACHE
! 7869: uae_u32 read_dcache030_0 (uaecptr addr, int size);
! 7870: uae_u32 read_dcache030 (uaecptr addr, int size)
! 7871: {
! 7872: uae_u32 v;
! 7873:
! 7874: v = read_dcache030_0 ( addr , size );
! 7875: if (!(regs.cacr & 0x100) || !cancache030 (addr))
! 7876: return v;
! 7877: if ( ( ( size==2 ) && ( v != get_long ( addr ) ) )
! 7878: || ( ( size==1 ) && ( (v&0xffff) != (get_word ( addr ) & 0xffff) ) )
! 7879: || ( ( size==0 ) && ( (v&0xff) != (get_byte ( addr ) & 0xff ) ) ) )
! 7880: fprintf ( stderr , "d-cache mismatch pc=%x addr=%x size=%d cache=%x != mem=%x, d-cache error ?\n" , m68k_getpc(), addr, size, v , get_long(addr) );
! 7881: return v;
! 7882: }
! 7883: uae_u32 read_dcache030_0 (uaecptr addr, int size)
! 7884: #else
1.1.1.4 root 7885: uae_u32 read_dcache030 (uaecptr addr, int size)
1.1.1.7 ! root 7886: #endif
1.1.1.4 root 7887: {
7888: struct cache030 *c1, *c2;
7889: int lws1, lws2;
7890: uae_u32 tag1, tag2;
7891: int aligned = addr & 3;
7892: uae_u32 v1, v2;
7893:
1.1.1.7 ! root 7894: if (!(regs.cacr & 0x100) || !cancache030 (addr)) { // data cache disabled?
! 7895: if (currprefs.cpu_cycle_exact) {
! 7896: if (size == 2)
! 7897: return mem_access_delay_long_read_ce020 (addr);
! 7898: else if (size == 1)
! 7899: return mem_access_delay_word_read_ce020 (addr);
! 7900: else
! 7901: return mem_access_delay_byte_read_ce020 (addr);
! 7902: } else {
! 7903: if (size == 2)
! 7904: return get_long (addr);
! 7905: else if (size == 1)
! 7906: return get_word (addr);
! 7907: else
! 7908: return get_byte (addr);
! 7909: }
1.1.1.4 root 7910: }
7911: c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
7912: addr &= ~3;
7913: if (!c1->valid[lws1] || c1->tag != tag1) {
1.1.1.7 ! root 7914: v1 = currprefs.cpu_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr);
1.1.1.4 root 7915: update_cache030 (c1, v1, tag1, lws1);
1.1.1.7 ! root 7916: //fprintf ( stderr , "read cache %x %x %d tag1 %x lws1 %x tag2 %x lws2 %x ref %x\n", addr, v1, size, tag1, lws1, tag2, lws2 , get_long (0x1f81ec) );
! 7917: #ifdef WINUAE_FOR_HATARI
! 7918: CpuInstruction.D_Cache_miss++;
! 7919: #endif
1.1.1.4 root 7920: } else {
7921: v1 = c1->data[lws1];
1.1.1.7 ! root 7922: #ifndef WINUAE_FOR_HATARI
! 7923: if (uae_boot_rom_type > 0) {
! 7924: // this check and fix is needed for UAE filesystem handler because it runs in host side and in
! 7925: // separate thread. No way to access via cache without locking that would cause major slowdown
! 7926: // and unneeded complexity
! 7927: uae_u32 tv = get_long(addr);
! 7928: if (tv != v1) {
! 7929: write_log(_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
! 7930: size, aligned, addr, tv, v1, tag1, lws1, M68K_GETPC);
! 7931: v1 = tv;
! 7932: }
1.1.1.4 root 7933: }
1.1.1.7 ! root 7934: #else
! 7935: CpuInstruction.D_Cache_hit++;
! 7936: #endif
1.1.1.4 root 7937: }
1.1.1.7 ! root 7938:
1.1.1.4 root 7939: // only one long fetch needed?
7940: if (size == 0) {
7941: v1 >>= (3 - aligned) * 8;
7942: return v1;
7943: } else if (size == 1 && aligned <= 2) {
7944: v1 >>= (2 - aligned) * 8;
7945: return v1;
7946: } else if (size == 2 && aligned == 0) {
1.1.1.7 ! root 7947: if ((regs.cacr & 0x1100) == 0x1100 && lws1 == 0 && !c1->valid[1] && !c1->valid[2] && !c1->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
! 7948: // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
! 7949: c1->data[1] = get_long (addr + 4);
! 7950: c1->data[2] = get_long (addr + 8);
! 7951: c1->data[3] = get_long (addr + 12);
! 7952: do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c1->data[3]);
! 7953: c1->valid[1] = c1->valid[2] = c1->valid[3] = true;
! 7954: }
1.1.1.4 root 7955: return v1;
7956: }
1.1.1.7 ! root 7957: // no, need another one
1.1.1.4 root 7958: addr += 4;
7959: c2 = getcache030 (dcaches030, addr, &tag2, &lws2);
7960: if (!c2->valid[lws2] || c2->tag != tag2) {
1.1.1.7 ! root 7961: v2 = currprefs.cpu_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr);
1.1.1.4 root 7962: update_cache030 (c2, v2, tag2, lws2);
1.1.1.7 ! root 7963: //fprintf ( stderr , "read cache %x %x %d tag1 %x lws1 %x tag2 %x lws2 %x\n", addr, v1, size, tag1, lws1, tag2, lws2 );
! 7964: #ifdef WINUAE_FOR_HATARI
! 7965: CpuInstruction.D_Cache_miss++;
! 7966: #endif
1.1.1.4 root 7967: } else {
7968: v2 = c2->data[lws2];
1.1.1.7 ! root 7969: #ifndef WINUAE_FOR_HATARI
! 7970: if (uae_boot_rom_type > 0) {
! 7971: uae_u32 tv = get_long(addr);
! 7972: if (tv != v2) {
! 7973: write_log (_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
! 7974: size, aligned, addr, get_long (addr), v2, tag2, lws2, M68K_GETPC);
! 7975: v2 = tv;
! 7976: }
1.1.1.4 root 7977: }
1.1.1.7 ! root 7978: #else
! 7979: CpuInstruction.D_Cache_hit++;
! 7980: #endif
! 7981: }
! 7982:
1.1.1.4 root 7983: if (size == 1 && aligned == 3)
7984: return (v1 << 8) | (v2 >> 24);
7985: else if (size == 2 && aligned == 1)
7986: return (v1 << 8) | (v2 >> 24);
7987: else if (size == 2 && aligned == 2)
7988: return (v1 << 16) | (v2 >> 16);
7989: else if (size == 2 && aligned == 3)
7990: return (v1 << 24) | (v2 >> 8);
7991:
1.1.1.7 ! root 7992: write_log (_T("dcache030 weirdness!?\n"));
1.1.1.4 root 7993: return 0;
7994: }
7995:
7996: uae_u32 get_word_ce030_prefetch (int o)
7997: {
7998: uae_u32 pc = m68k_getpc () + o;
1.1.1.7 ! root 7999: uae_u32 v;
1.1.1.4 root 8000:
1.1.1.7 ! root 8001: if (pc & 2) {
! 8002: v = regs.prefetch020[0] & 0xffff;
! 8003: #if MORE_ACCURATE_68020_PIPELINE
! 8004: pipeline_020(regs.prefetch020[1], pc);
! 8005: #endif
! 8006: regs.prefetch020[0] = regs.prefetch020[1];
! 8007: // branch instruction detected in pipeline: stop fetches until branch executed.
! 8008: if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
! 8009: fill_icache030 (pc + 2 + 4);
! 8010: regs.prefetch020[1] = regs.cacheholdingdata020;
! 8011: }
! 8012: } else {
! 8013: v = regs.prefetch020[0] >> 16;
! 8014: #if MORE_ACCURATE_68020_PIPELINE
! 8015: pipeline_020(regs.prefetch020[1] >> 16, pc);
! 8016: #endif
! 8017: }
! 8018: do_cycles_ce020_internal (2);
! 8019: return v;
! 8020: }
! 8021:
! 8022: uae_u32 get_word_030_prefetch(int o)
! 8023: {
! 8024: uae_u32 pc = m68k_getpc() + o;
! 8025: uae_u32 v;
! 8026:
! 8027: if (pc & 2) {
! 8028: v = regs.prefetch020[0] & 0xffff;
! 8029: #if MORE_ACCURATE_68020_PIPELINE
! 8030: pipeline_020(regs.prefetch020[1], pc);
! 8031: #endif
! 8032: regs.prefetch020[0] = regs.prefetch020[1];
! 8033: // branch instruction detected in pipeline: stop fetches until branch executed.
! 8034: if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
! 8035: fill_icache030(pc + 2 + 4);
! 8036: regs.prefetch020[1] = regs.cacheholdingdata020;
! 8037: }
! 8038: } else {
! 8039: v = regs.prefetch020[0] >> 16;
! 8040: #if MORE_ACCURATE_68020_PIPELINE
! 8041: pipeline_020(regs.prefetch020[1] >> 16, pc);
! 8042: #endif
! 8043: }
! 8044: return v;
! 8045: }
! 8046:
! 8047: uae_u32 get_word_icache030(uaecptr addr)
! 8048: {
! 8049: fill_icache030(addr);
! 8050: return regs.cacheholdingdata020 >> ((addr & 2) ? 0 : 16);
! 8051: }
! 8052: uae_u32 get_long_icache030(uaecptr addr)
! 8053: {
! 8054: uae_u32 v;
! 8055: fill_icache030(addr);
! 8056: if ((addr & 2) == 0)
! 8057: return regs.cacheholdingdata020;
! 8058: v = regs.cacheholdingdata020 << 16;
! 8059: fill_icache030(addr + 4);
! 8060: v |= regs.cacheholdingdata020 >> 16;
! 8061: return v;
! 8062: }
! 8063:
! 8064: uae_u32 fill_icache040(uae_u32 addr)
! 8065: {
! 8066: int index, i, lws;
! 8067: uae_u32 tag;
! 8068: struct cache040 *c;
! 8069: int line;
! 8070:
! 8071: if (!(regs.cacr & 0x8000)) {
! 8072: uae_u32 addr2 = addr & ~15;
! 8073: lws = (addr >> 2) & 3;
! 8074: addr &= ~3;
! 8075: if (regs.prefetch020addr == addr2)
! 8076: return regs.prefetch020[lws];
! 8077: regs.prefetch020addr = addr2;
! 8078: if (currprefs.cpu_cycle_exact) {
! 8079: regs.prefetch020[0] = mem_access_delay_longi_read_ce020(addr2 + 0);
! 8080: regs.prefetch020[1] = mem_access_delay_longi_read_ce020(addr2 + 4);
! 8081: regs.prefetch020[2] = mem_access_delay_longi_read_ce020(addr2 + 8);
! 8082: regs.prefetch020[3] = mem_access_delay_longi_read_ce020(addr2 + 12);
! 8083: } else {
! 8084: regs.prefetch020[0] = get_longi(addr2 + 0);
! 8085: regs.prefetch020[1] = get_longi(addr2 + 4);
! 8086: regs.prefetch020[2] = get_longi(addr2 + 8);
! 8087: regs.prefetch020[3] = get_longi(addr2 + 12);
! 8088: x_do_cycles(4 * cpucycleunit);
! 8089: }
! 8090: return regs.prefetch020[lws];
! 8091: }
! 8092:
! 8093: index = (addr >> 4) & (CACHESETS040 - 1);
! 8094: tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
! 8095: lws = (addr >> 2) & 3;
! 8096: addr &= ~15;
! 8097: c = &icaches040[index];
! 8098: for (i = 0; i < CACHELINES040; i++) {
! 8099: if (c->valid[i] && c->tag[i] == tag) {
! 8100: // cache hit
! 8101: icachelinecnt++;
! 8102: x_do_cycles(1 * cpucycleunit);
! 8103: #ifdef WINUAE_FOR_HATARI
! 8104: CpuInstruction.I_Cache_hit++;
! 8105: #endif
! 8106: return c->data[i][lws];
! 8107: }
! 8108: }
! 8109: // cache miss
! 8110: if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
! 8111: line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
! 8112: }
! 8113: else {
! 8114: for (line = 0; line < CACHELINES040; line++) {
! 8115: if (c->valid[line] == false)
! 8116: break;
! 8117: }
! 8118: }
! 8119: c->tag[line] = tag;
! 8120: c->valid[line] = true;
! 8121: if (currprefs.cpu_cycle_exact) {
! 8122: c->data[line][0] = mem_access_delay_longi_read_ce020(addr + 0);
! 8123: c->data[line][1] = mem_access_delay_longi_read_ce020(addr + 4);
! 8124: c->data[line][2] = mem_access_delay_longi_read_ce020(addr + 8);
! 8125: c->data[line][3] = mem_access_delay_longi_read_ce020(addr + 12);
! 8126: } else {
! 8127: c->data[line][0] = get_longi(addr + 0);
! 8128: c->data[line][1] = get_longi(addr + 4);
! 8129: c->data[line][2] = get_longi(addr + 8);
! 8130: c->data[line][3] = get_longi(addr + 12);
! 8131: x_do_cycles(4 * cpucycleunit);
! 8132: }
! 8133: #ifdef WINUAE_FOR_HATARI
! 8134: CpuInstruction.I_Cache_miss++;
! 8135: #endif
! 8136: return c->data[line][lws];
! 8137: }
! 8138:
! 8139: #if 0
! 8140: static bool is_dcache040(uae_u32 addr)
! 8141: {
! 8142: int index, i, lws;
! 8143: uae_u32 tag;
! 8144: struct cache040 *c;
! 8145:
! 8146: addr &= ~15;
! 8147: index = (addr >> 4) & (CACHESETS040 - 1);
! 8148: tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
! 8149: lws = (addr >> 2) & 3;
! 8150: c = &dcaches040[index];
! 8151: for (i = 0; i < CACHELINES040; i++) {
! 8152: if (c->valid[i] && c->tag[i] == tag) {
! 8153: return true;
! 8154: }
! 8155: }
! 8156: return false;
! 8157: }
! 8158:
! 8159: uae_u32 read_dcache040(uae_u32 addr)
! 8160: {
! 8161: int index, i, lws;
! 8162: uae_u32 tag;
! 8163: struct cache040 *c;
! 8164: int line;
! 8165:
! 8166: addr &= ~15;
! 8167: index = (addr >> 4) & (CACHESETS040 - 1);
! 8168: tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
! 8169: lws = (addr >> 2) & 3;
! 8170: c = &dcaches040[index];
! 8171: for (i = 0; i < CACHELINES040; i++) {
! 8172: if (c->valid[i] && c->tag[i] == tag) {
! 8173: // cache hit
! 8174: dcachelinecnt++;
! 8175: return c->data[i][lws];
! 8176: }
! 8177: }
! 8178: // cache miss
! 8179: if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
! 8180: line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
! 8181: for (i = 0; i < 4; i++) {
! 8182: if (c->dirty[line][i]) {
! 8183: c->dirty[line][i] = false;
! 8184: mem_access_delay_long_write_ce020(addr + i * 4, c->data[line][i]);
! 8185: }
! 8186: }
! 8187: }
! 8188: else {
! 8189: for (line = 0; line < CACHELINES040; line++) {
! 8190: if (c->valid[line] == false)
! 8191: break;
! 8192: }
! 8193: }
! 8194: c->tag[line] = tag;
! 8195: c->valid[line] = true;
! 8196: c->data[line][0] = mem_access_delay_long_read_ce020(addr + 0);
! 8197: c->data[line][1] = mem_access_delay_long_read_ce020(addr + 4);
! 8198: c->data[line][2] = mem_access_delay_long_read_ce020(addr + 8);
! 8199: c->data[line][3] = mem_access_delay_long_read_ce020(addr + 12);
! 8200: regs.cacheholdingaddr020 = addr;
! 8201: }
! 8202:
! 8203: void write_dcache040(uae_u32 addr, uae_u32 val)
! 8204: {
! 8205: int index, i, lws;
! 8206: uae_u32 tag;
! 8207: struct cache040 *c;
! 8208: int line;
! 8209:
! 8210: addr &= ~15;
! 8211: index = (addr >> 4) & (CACHESETS040 - 1);
! 8212: tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
! 8213: lws = (addr >> 2) & 3;
! 8214: c = &dcaches040[index];
! 8215: for (i = 0; i < CACHELINES040; i++) {
! 8216: if (c->valid[i] && c->tag[i] == tag) {
! 8217: // cache hit
! 8218: dcachelinecnt++;
! 8219: c->data[i][lws] = val;
! 8220: mem_access_delay_long_write_ce020(addr + i * 4, c->data[i][lws]);
! 8221: //c->dirty[i][lws] = true;
! 8222: }
! 8223: }
! 8224: #if 0
! 8225: // cache miss
! 8226: if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
! 8227: line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
! 8228: for (i = 0; i < 4; i++) {
! 8229: if (c->dirty[line][i]) {
! 8230: c->dirty[line][i] = false;
! 8231: mem_access_delay_long_write_ce020(addr + i * 4, c->data[line][i]);
1.1.1.4 root 8232: }
8233: }
8234: }
1.1.1.7 ! root 8235: else {
! 8236: for (line = 0; line < CACHELINES040; line++) {
! 8237: if (c->valid[line] == false)
! 8238: break;
! 8239: }
! 8240: }
! 8241: c->tag[line] = tag;
! 8242: c->valid[line] = true;
! 8243: c->data[line][0] = mem_access_delay_long_read_ce020(addr + 0);
! 8244: c->data[line][1] = mem_access_delay_long_read_ce020(addr + 4);
! 8245: c->data[line][2] = mem_access_delay_long_read_ce020(addr + 8);
! 8246: c->data[line][3] = mem_access_delay_long_read_ce020(addr + 12);
! 8247: c->data[line][lws] = val;
! 8248: c->dirty[line][lws] = true;
! 8249: #endif
! 8250: }
! 8251: #endif
! 8252:
! 8253: // really unoptimized
! 8254: uae_u32 get_word_icache040(uaecptr addr)
! 8255: {
! 8256: uae_u32 v = fill_icache040(addr);
! 8257: return v >> ((addr & 2) ? 0 : 16);
! 8258: }
! 8259: uae_u32 get_long_icache040(uaecptr addr)
! 8260: {
! 8261: uae_u32 v1, v2;
! 8262: v1 = fill_icache040(addr);
! 8263: if ((addr & 2) == 0)
! 8264: return v1;
! 8265: v2 = fill_icache040(addr + 4);
! 8266: return (v2 >> 16) | (v1 << 16);
! 8267: }
! 8268: uae_u32 get_ilong_cache_040(int o)
! 8269: {
! 8270: return get_long_icache040(m68k_getpci() + o);
! 8271: }
! 8272: uae_u32 get_iword_cache_040(int o)
! 8273: {
! 8274: return get_word_icache040(m68k_getpci() + o);
! 8275: }
! 8276:
! 8277: STATIC_INLINE bool nocache040(uaecptr addr)
! 8278: {
! 8279: if (!currprefs.cpu_cycle_exact)
! 8280: return false;
! 8281: if (!(regs.cacr & 0x80000000))
! 8282: return true;
! 8283: if (addr >= 0xd80000 && addr < 0xc00000)
! 8284: return true;
! 8285: if (addr >= 0xe80000 && addr < 0xf00000)
! 8286: return true;
! 8287: return false;
! 8288: }
! 8289:
! 8290: void put_long_cache_040(uaecptr addr, uae_u32 v)
! 8291: {
! 8292: #if 1
! 8293: if (nocache040(addr))
! 8294: mem_access_delay_long_write_ce020(addr, v);
! 8295: else
! 8296: put_long(addr, v);
! 8297: #else
! 8298: if ((addr & 2) == 0) {
! 8299: if (is_dcache040(addr))
! 8300: write_dcache040(addr, v);
! 8301: else if (currprefs.cpu_cycle_exact)
! 8302: mem_access_delay_long_write_ce020(addr, v);
! 8303: else
! 8304: put_long(addr, v);
! 8305: } else {
! 8306: uae_u32 vp;
! 8307: if (is_dcache040(addr)) {
! 8308: vp = read_dcache040(addr);
! 8309: vp &= 0xffff0000;
! 8310: vp |= v >> 16;
! 8311: write_dcache040(addr, vp);
! 8312: } else if (currprefs.cpu_cycle_exact) {
! 8313: mem_access_delay_word_write_ce020(addr + 0, v >> 16);
! 8314: } else {
! 8315: put_word(addr + 0, v >> 16);
! 8316: }
! 8317: if (is_dcache040(addr + 4)) {
! 8318: vp = read_dcache040(addr + 4);
! 8319: vp &= 0x0000ffff;
! 8320: vp |= v << 16;
! 8321: write_dcache040(addr + 4, vp);
! 8322: } else if (currprefs.cpu_cycle_exact) {
! 8323: mem_access_delay_word_write_ce020(addr + 2, v);
! 8324: } else {
! 8325: put_word(addr + 2, v);
! 8326: }
! 8327: }
! 8328: #endif
! 8329: }
! 8330: void put_word_cache_040(uaecptr addr, uae_u32 v)
! 8331: {
! 8332: #if 1
! 8333: if (nocache040(addr))
! 8334: mem_access_delay_word_write_ce020(addr, v);
! 8335: else
! 8336: put_word(addr, v);
! 8337: #else
! 8338: if (is_dcache040(addr)) {
! 8339: uae_u32 vp;
! 8340: vp = read_dcache040(addr);
! 8341: if (addr & 2) {
! 8342: vp &= 0xffff0000;
! 8343: vp |= v & 0xffff;
! 8344: } else {
! 8345: vp &= 0x0000ffff;
! 8346: vp |= v << 16;
! 8347: }
! 8348: write_dcache040(addr, vp);
! 8349: } else if (currprefs.cpu_cycle_exact) {
! 8350: mem_access_delay_word_write_ce020(addr, v);
! 8351: } else {
! 8352: put_word(addr, v);
! 8353: }
! 8354: #endif
! 8355: }
! 8356: void put_byte_cache_040(uaecptr addr, uae_u32 v)
! 8357: {
! 8358: #if 1
! 8359: if (nocache040(addr))
! 8360: mem_access_delay_byte_write_ce020(addr, v);
! 8361: else
! 8362: put_byte(addr, v);
! 8363: #else
! 8364: if (is_dcache040(addr)) {
! 8365: uae_u32 vp;
! 8366: uae_u32 mask = 0xff000000 >> (addr & 3);
! 8367: vp = read_dcache040(addr);
! 8368: vp &= ~mask;
! 8369: vp |= (v << (3 - (addr & 3))) & mask;
! 8370: write_dcache040(addr, vp);
! 8371: } else if (currprefs.cpu_cycle_exact) {
! 8372: mem_access_delay_byte_write_ce020(addr, v);
! 8373: } else {
! 8374: put_byte(addr, v);
! 8375: }
! 8376: #endif
1.1.1.4 root 8377: }
8378:
1.1.1.7 ! root 8379: uae_u32 get_long_cache_040(uaecptr addr)
! 8380: {
! 8381: #if 1
! 8382: if (nocache040(addr))
! 8383: return mem_access_delay_long_read_ce020(addr);
! 8384: else
! 8385: return get_long(addr);
! 8386: #else
! 8387: uae_u32 v1, v2;
! 8388: v1 = read_dcache040(addr);
! 8389: if ((addr & 2) == 0)
! 8390: return v1;
! 8391: v2 = read_dcache040(addr + 4);
! 8392: return (v2 >> 16) | (v1 << 16);
! 8393: #endif
! 8394: }
! 8395: uae_u32 get_word_cache_040(uaecptr addr)
! 8396: {
! 8397: #if 1
! 8398: if (nocache040(addr))
! 8399: return mem_access_delay_word_read_ce020(addr);
! 8400: else
! 8401: return get_word(addr);
! 8402: #else
! 8403: uae_u32 v = read_dcache040(addr);
! 8404: return v >> ((addr & 2) ? 0 : 16);
! 8405: #endif
! 8406: }
! 8407: uae_u32 get_byte_cache_040(uaecptr addr)
! 8408: {
! 8409: #if 1
! 8410: if (nocache040(addr))
! 8411: return mem_access_delay_byte_read_ce020(addr);
! 8412: else
! 8413: return get_byte(addr);
! 8414: #else
! 8415: uae_u32 v = read_dcache040(addr);
! 8416: return v >> (8 * (3 - (addr & 3)));
! 8417: #endif
! 8418: }
! 8419: uae_u32 next_iword_cache040(void)
! 8420: {
! 8421: uae_u32 r = get_word_icache040(m68k_getpci());
! 8422: m68k_incpci(2);
! 8423: return r;
! 8424: }
! 8425: uae_u32 next_ilong_cache040(void)
! 8426: {
! 8427: uae_u32 r = get_long_icache040(m68k_getpci());
! 8428: m68k_incpci(4);
! 8429: return r;
! 8430: }
1.1.1.4 root 8431:
8432: void flush_dcache (uaecptr addr, int size)
8433: {
8434: int i;
1.1.1.7 ! root 8435: if (!currprefs.cpu_cycle_exact && !currprefs.cpu_compatible)
1.1.1.4 root 8436: return;
8437: if (currprefs.cpu_model >= 68030) {
8438: for (i = 0; i < CACHELINES030; i++) {
8439: dcaches030[i].valid[0] = 0;
8440: dcaches030[i].valid[1] = 0;
8441: dcaches030[i].valid[2] = 0;
8442: dcaches030[i].valid[3] = 0;
8443: }
8444: }
8445: }
8446:
1.1.1.7 ! root 8447: #ifdef WINUAE_FOR_HATARI
! 8448: void flush_instr_cache (uaecptr addr, int size)
1.1.1.4 root 8449: {
1.1.1.7 ! root 8450: int i;
! 8451: if (!currprefs.cpu_cycle_exact && !currprefs.cpu_compatible)
! 8452: return;
! 8453: if (currprefs.cpu_model == 68020) {
! 8454: for (i = 0; i < CACHELINES020; i++)
! 8455: caches020[i].valid = 0;
! 8456: }
! 8457: else if (currprefs.cpu_model == 68030) {
! 8458: for (i = 0; i < CACHELINES030; i++) {
! 8459: icaches030[i].valid[0] = 0;
! 8460: icaches030[i].valid[1] = 0;
! 8461: icaches030[i].valid[2] = 0;
! 8462: icaches030[i].valid[3] = 0;
! 8463: }
! 8464: }
! 8465: else if (currprefs.cpu_model >= 68040) {
! 8466: icachelinecnt = 0;
! 8467: dcachelinecnt = 0;
! 8468: for (i = 0; i < CACHESETS040; i++) {
! 8469: icaches040[i].valid[0] = 0;
! 8470: icaches040[i].valid[1] = 0;
! 8471: icaches040[i].valid[2] = 0;
! 8472: icaches040[i].valid[3] = 0;
! 8473: }
! 8474: }
1.1.1.4 root 8475: }
1.1.1.7 ! root 8476: #endif
1.1.1.4 root 8477:
1.1.1.7 ! root 8478: void fill_prefetch_030 (void)
1.1.1.4 root 8479: {
1.1.1.7 ! root 8480: uaecptr pc = m68k_getpc ();
! 8481: uaecptr pc2 = pc;
! 8482: pc &= ~3;
! 8483: regs.pipeline_pos = 0;
! 8484: regs.pipeline_stop = 0;
1.1.1.4 root 8485:
1.1.1.7 ! root 8486: fill_icache030 (pc);
! 8487: if (currprefs.cpu_cycle_exact)
! 8488: do_cycles_ce020_internal(2);
! 8489: regs.prefetch020[0] = regs.cacheholdingdata020;
! 8490:
! 8491: fill_icache030 (pc + 4);
! 8492: if (currprefs.cpu_cycle_exact)
! 8493: do_cycles_ce020_internal(2);
! 8494: regs.prefetch020[1] = regs.cacheholdingdata020;
! 8495:
! 8496: #if MORE_ACCURATE_68020_PIPELINE
! 8497: if (pc2 & 2) {
! 8498: pipeline_020(regs.prefetch020[0], pc);
! 8499: pipeline_020(regs.prefetch020[1] >> 16, pc);
! 8500: } else {
! 8501: pipeline_020(regs.prefetch020[0] >> 16, pc);
! 8502: pipeline_020(regs.prefetch020[0], pc);
1.1.1.4 root 8503: }
1.1.1.7 ! root 8504: #endif
1.1.1.4 root 8505:
1.1.1.7 ! root 8506: if (currprefs.cpu_cycle_exact)
! 8507: regs.irc = get_word_ce030_prefetch (0);
! 8508: else
! 8509: regs.irc = get_word_030_prefetch(0);
1.1.1.4 root 8510: }
8511:
1.1.1.7 ! root 8512: void fill_prefetch_020 (void)
1.1.1.4 root 8513: {
1.1.1.7 ! root 8514: uaecptr pc = m68k_getpc ();
! 8515: uaecptr pc2 = pc;
! 8516: pc &= ~3;
! 8517: uae_u32 (*fetch)(uaecptr) = currprefs.cpu_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi;
! 8518: regs.pipeline_pos = 0;
! 8519: regs.pipeline_stop = 0;
! 8520: regs.pipeline_r8[0] = regs.pipeline_r8[1] = -1;
! 8521:
! 8522: fill_icache020 (pc, fetch);
! 8523: if (currprefs.cpu_cycle_exact)
! 8524: do_cycles_ce020_internal(2);
! 8525: regs.prefetch020[0] = regs.cacheholdingdata020;
! 8526:
! 8527: fill_icache020 (pc + 4, fetch);
! 8528: if (currprefs.cpu_cycle_exact)
! 8529: do_cycles_ce020_internal(2);
! 8530: regs.prefetch020[1] = regs.cacheholdingdata020;
! 8531:
! 8532: #if MORE_ACCURATE_68020_PIPELINE
! 8533: if (pc2 & 2) {
! 8534: pipeline_020(regs.prefetch020[0], pc);
! 8535: pipeline_020(regs.prefetch020[1] >> 16, pc);
! 8536: } else {
! 8537: pipeline_020(regs.prefetch020[0] >> 16, pc);
! 8538: pipeline_020(regs.prefetch020[0], pc);
! 8539: }
! 8540: #endif
! 8541:
! 8542: if (currprefs.cpu_cycle_exact)
! 8543: regs.irc = get_word_ce020_prefetch (0);
! 8544: else
! 8545: regs.irc = get_word_020_prefetch (0);
1.1.1.4 root 8546: }
8547:
1.1.1.7 ! root 8548: void fill_prefetch (void)
1.1.1.4 root 8549: {
1.1.1.7 ! root 8550: regs.pipeline_pos = 0;
! 8551: if (currprefs.cachesize)
! 8552: return;
! 8553: if (!currprefs.cpu_compatible)
! 8554: return;
! 8555: if (currprefs.cpu_model >= 68040) {
! 8556: if (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) {
! 8557: fill_icache040(m68k_getpc() + 16);
! 8558: fill_icache040(m68k_getpc());
! 8559: }
! 8560: } else if (currprefs.cpu_model == 68020) {
! 8561: fill_prefetch_020 ();
! 8562: } else if (currprefs.cpu_model == 68030) {
! 8563: fill_prefetch_030 ();
! 8564: } else if (currprefs.cpu_model <= 68010) {
! 8565: uaecptr pc = m68k_getpc ();
! 8566: regs.ir = x_get_word (pc);
! 8567: regs.irc = x_get_word (pc + 2);
! 8568: }
1.1.1.4 root 8569: }
1.1.1.7 ! root 8570:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.