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