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