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