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