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