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