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