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