|
|
1.1.1.2 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * MC68000 emulation
5: *
6: * (c) 1995 Bernd Schmidt
7: */
8:
9: #define MMUOP_DEBUG 2
10: #define DEBUG_CD32CDTVIO 0
11:
1.1.1.3 root 12: #include "main.h"
1.1.1.5 root 13: #include "m68000.h"
1.1.1.2 root 14: #include "compat.h"
15: #include "sysconfig.h"
16: #include "sysdeps.h"
17: #include "hatari-glue.h"
18: #include "options_cpu.h"
19: #include "maccess.h"
20: #include "memory.h"
21: #include "newcpu.h"
22: #include "cpummu.h"
1.1.1.3 root 23: #include "cpummu030.h"
1.1.1.5 root 24: #ifdef WITH_SOFTFLOAT
25: #include "fpp-softfloat.h"
26: #else
27: #include "md-fpp.h"
28: #endif
1.1.1.2 root 29: #include "main.h"
1.1.1.4 root 30: #include "dsp.h"
1.1.1.6 ! root 31: #include "dimension.hpp"
1.1.1.2 root 32: #include "reset.h"
33: #include "cycInt.h"
34: #include "dialog.h"
35: #include "screen.h"
36: #include "video.h"
37: #include "log.h"
38: #include "debugui.h"
39: #include "debugcpu.h"
1.1.1.6 ! root 40: #include "sysReg.h"
1.1.1.2 root 41:
42:
43: /* Opcode of faulting instruction */
44: static uae_u16 last_op_for_exception_3;
45: /* PC at fault time */
46: static uaecptr last_addr_for_exception_3;
47: /* Address that generated the exception */
48: static uaecptr last_fault_for_exception_3;
49: /* read (0) or write (1) access */
50: static int last_writeaccess_for_exception_3;
51: /* instruction (1) or data (0) access */
52: static int last_instructionaccess_for_exception_3;
53: int mmu_enabled, mmu_triggered;
54: int cpu_cycles;
55:
56: const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };
57: const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
58:
59: int movem_index1[256];
60: int movem_index2[256];
61: int movem_next[256];
62:
63: cpuop_func *cpufunctbl[65536];
64:
65: int OpcodeFamily;
66: struct mmufixup mmufixup[2];
67:
1.1.1.5 root 68: uae_u32 fpp_get_fpsr (void);
1.1.1.2 root 69:
70: static struct cache030 icaches030[CACHELINES030];
71: static struct cache030 dcaches030[CACHELINES030];
72:
1.1.1.5 root 73: void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode);
1.1.1.2 root 74:
75: uae_u32 (*x_prefetch)(int);
76: uae_u32 (*x_next_iword)(void);
77: uae_u32 (*x_next_ilong)(void);
1.1.1.4 root 78: uae_u32 (*x_get_ilong)(int);
79: uae_u32 (*x_get_iword)(int);
80: uae_u32 (*x_get_ibyte)(int);
1.1.1.2 root 81: uae_u32 (*x_get_long)(uaecptr);
82: uae_u32 (*x_get_word)(uaecptr);
83: uae_u32 (*x_get_byte)(uaecptr);
84: void (*x_put_long)(uaecptr,uae_u32);
85: void (*x_put_word)(uaecptr,uae_u32);
86: void (*x_put_byte)(uaecptr,uae_u32);
87:
1.1.1.4 root 88: uae_u32 (*x_cp_next_iword)(void);
89: uae_u32 (*x_cp_next_ilong)(void);
90: uae_u32 (*x_cp_get_long)(uaecptr);
91: uae_u32 (*x_cp_get_word)(uaecptr);
92: uae_u32 (*x_cp_get_byte)(uaecptr);
93: void (*x_cp_put_long)(uaecptr,uae_u32);
94: void (*x_cp_put_word)(uaecptr,uae_u32);
95: void (*x_cp_put_byte)(uaecptr,uae_u32);
96: uae_u32 (REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
97:
1.1.1.2 root 98: // shared memory access functions
99: static void set_x_funcs (void)
100: {
1.1.1.5 root 101: if (currprefs.cpu_model == 68040) {
102: x_prefetch = get_iword_mmu040;
103: x_get_ilong = get_ilong_mmu040;
104: x_get_iword = get_iword_mmu040;
105: x_get_ibyte = get_ibyte_mmu040;
106: x_next_iword = next_iword_mmu040;
107: x_next_ilong = next_ilong_mmu040;
108: x_put_long = put_long_mmu040;
109: x_put_word = put_word_mmu040;
110: x_put_byte = put_byte_mmu040;
111: x_get_long = get_long_mmu040;
112: x_get_word = get_word_mmu040;
113: x_get_byte = get_byte_mmu040;
114: } else {
115: x_prefetch = get_iword_mmu030;
116: x_get_ilong = get_ilong_mmu030;
117: x_get_iword = get_iword_mmu030;
118: x_get_ibyte = get_ibyte_mmu030;
119: x_next_iword = next_iword_mmu030;
120: x_next_ilong = next_ilong_mmu030;
121: x_put_long = put_long_mmu030;
122: x_put_word = put_word_mmu030;
123: x_put_byte = put_byte_mmu030;
124: x_get_long = get_long_mmu030;
125: x_get_word = get_word_mmu030;
126: x_get_byte = get_byte_mmu030;
127: }
128:
129: if (currprefs.mmu_model == 68030) {
130: x_cp_put_long = put_long_mmu030_state;
131: x_cp_put_word = put_word_mmu030_state;
132: x_cp_put_byte = put_byte_mmu030_state;
133: x_cp_get_long = get_long_mmu030_state;
134: x_cp_get_word = get_word_mmu030_state;
135: x_cp_get_byte = get_byte_mmu030_state;
136: x_cp_next_iword = next_iword_mmu030_state;
137: x_cp_next_ilong = next_ilong_mmu030_state;
138: x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030;
139: } else {
140: x_cp_put_long = x_put_long;
141: x_cp_put_word = x_put_word;
142: x_cp_put_byte = x_put_byte;
143: x_cp_get_long = x_get_long;
144: x_cp_get_word = x_get_word;
145: x_cp_get_byte = x_get_byte;
146: x_cp_next_iword = x_next_iword;
147: x_cp_next_ilong = x_next_ilong;
148: x_cp_get_disp_ea_020 = x_get_disp_ea_020;
149: }
150: }
1.1.1.2 root 151:
1.1.1.5 root 152: void flush_cpu_caches_040(uae_u16 opcode)
153: {
154: int cache = (opcode >> 6) & 3;
155: if (!(cache & 2))
156: return;
157: set_cpu_caches(true);
1.1.1.2 root 158: }
159:
1.1.1.4 root 160: void set_cpu_caches (bool flush)
1.1.1.2 root 161: {
162: int i;
163:
1.1.1.5 root 164: if (currprefs.cpu_model == 68030) {
1.1.1.2 root 165: if (regs.cacr & 0x08) { // clear instr cache
166: for (i = 0; i < CACHELINES030; i++) {
167: icaches030[i].valid[0] = 0;
168: icaches030[i].valid[1] = 0;
169: icaches030[i].valid[2] = 0;
170: icaches030[i].valid[3] = 0;
171: }
1.1.1.5 root 172: regs.cacr &= ~0x08;
1.1.1.2 root 173: }
174: if (regs.cacr & 0x04) { // clear entry in instr cache
175: icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
176: regs.cacr &= ~0x04;
177: }
178: if (regs.cacr & 0x800) { // clear data cache
179: for (i = 0; i < CACHELINES030; i++) {
180: dcaches030[i].valid[0] = 0;
181: dcaches030[i].valid[1] = 0;
182: dcaches030[i].valid[2] = 0;
183: dcaches030[i].valid[3] = 0;
184: }
185: regs.cacr &= ~0x800;
186: }
187: if (regs.cacr & 0x400) { // clear entry in data cache
188: dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
189: regs.cacr &= ~0x400;
190: }
191: }
192: }
193:
1.1.1.5 root 194: static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode)
1.1.1.2 root 195: {
1.1.1.5 root 196: op_illg (opcode);
197: return 4;
1.1.1.2 root 198: }
1.1.1.5 root 199: static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
1.1.1.2 root 200: {
1.1.1.5 root 201: if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060)
202: op_illg (opcode);
203: else
204: op_unimpl (opcode);
205: return 4;
1.1.1.2 root 206: }
207:
208: void build_cpufunctbl (void)
209: {
210: int i, opcnt;
211: unsigned long opcode;
212: const struct cputbl *tbl = 0;
213: int lvl;
214:
215: switch (currprefs.cpu_model)
216: {
217: case 68040:
218: lvl = 4;
1.1.1.5 root 219: tbl = op_smalltbl_31_ff;
1.1.1.2 root 220: break;
221: case 68030:
222: lvl = 3;
1.1.1.5 root 223: tbl = op_smalltbl_32_ff;
1.1.1.2 root 224: break;
225: default:
1.1.1.5 root 226: changed_prefs.cpu_model = currprefs.cpu_model = 68030;
227: lvl = 3;
228: tbl = op_smalltbl_32_ff;
1.1.1.2 root 229: }
230:
231: if (tbl == 0) {
232: write_log ("no CPU emulation cores available CPU=%d!", currprefs.cpu_model);
1.1.1.5 root 233: DebugUI();
1.1.1.2 root 234: }
235:
236: for (opcode = 0; opcode < 65536; opcode++)
237: cpufunctbl[opcode] = op_illg_1;
238: for (i = 0; tbl[i].handler != NULL; i++) {
239: opcode = tbl[i].opcode;
240: cpufunctbl[opcode] = tbl[i].handler;
241: }
242:
243: opcnt = 0;
244: for (opcode = 0; opcode < 65536; opcode++) {
245: cpuop_func *f;
246:
247: if (table68k[opcode].mnemo == i_ILLG)
248: continue;
249: if (table68k[opcode].clev > lvl) {
250: continue;
251: }
252:
253: if (table68k[opcode].handler != -1) {
254: int idx = table68k[opcode].handler;
255: f = cpufunctbl[idx];
256: if (f == op_illg_1)
1.1.1.5 root 257: DebugUI();
1.1.1.2 root 258: cpufunctbl[opcode] = f;
259: opcnt++;
260: }
261: }
1.1.1.5 root 262: write_log ("Building CPU, %d opcodes (%d %d)\n",
263: opcnt, lvl, currprefs.cpu_compatible ? 1 : 0);
1.1.1.6 ! root 264: write_log ("CPU=%d, MMU=%d, FPU=%d ($%02x)\n",
1.1.1.4 root 265: currprefs.cpu_model, currprefs.mmu_model,
1.1.1.6 ! root 266: currprefs.fpu_model, currprefs.fpu_revision);
1.1.1.4 root 267: set_cpu_caches (0);
1.1.1.2 root 268: if (currprefs.mmu_model) {
1.1.1.3 root 269: if (currprefs.cpu_model >= 68040) {
270: mmu_reset ();
271: mmu_set_tc (regs.tcr);
272: mmu_set_super (regs.s != 0);
273: } else {
274: mmu030_reset(1);
275: }
276: }
1.1.1.2 root 277: }
278:
1.1.1.5 root 279: static void prefs_changed_cpu (void) {
1.1.1.2 root 280: currprefs.cpu_model = changed_prefs.cpu_model;
281: currprefs.fpu_model = changed_prefs.fpu_model;
1.1.1.4 root 282: currprefs.fpu_revision = changed_prefs.fpu_revision;
1.1.1.2 root 283: currprefs.mmu_model = changed_prefs.mmu_model;
284: currprefs.cpu_compatible = changed_prefs.cpu_compatible;
285: }
286:
287: void check_prefs_changed_cpu (void)
288: {
289: bool changed = 0;
290:
1.1.1.5 root 291: if (changed
1.1.1.2 root 292: || currprefs.cpu_model != changed_prefs.cpu_model
293: || currprefs.fpu_model != changed_prefs.fpu_model
1.1.1.4 root 294: || currprefs.fpu_revision != changed_prefs.fpu_revision
1.1.1.2 root 295: || currprefs.mmu_model != changed_prefs.mmu_model
1.1.1.5 root 296: || currprefs.cpu_compatible != changed_prefs.cpu_compatible) {
1.1.1.2 root 297:
298: prefs_changed_cpu ();
299: build_cpufunctbl ();
300: changed = 1;
301: }
302:
303: if (currprefs.cpu_idle != changed_prefs.cpu_idle) {
304: currprefs.cpu_idle = changed_prefs.cpu_idle;
305: }
306: if (changed)
1.1.1.4 root 307: set_special (SPCFLAG_MODE_CHANGE);
1.1.1.2 root 308:
309: }
310:
311: void init_m68k (void)
312: {
313: int i;
314:
315: prefs_changed_cpu ();
1.1.1.5 root 316:
1.1.1.2 root 317: for (i = 0 ; i < 256 ; i++) {
318: int j;
319: for (j = 0 ; j < 8 ; j++) {
320: if (i & (1 << j)) break;
321: }
322: movem_index1[i] = j;
323: movem_index2[i] = 7-j;
324: movem_next[i] = i & (~(1 << j));
325: }
326:
327: write_log ("Building CPU table for configuration: %d", currprefs.cpu_model);
328: regs.address_space_mask = 0xffffffff;
1.1.1.5 root 329:
330: if (currprefs.fpu_model > 0)
1.1.1.2 root 331: write_log ("/%d", currprefs.fpu_model);
1.1.1.5 root 332: if (currprefs.cpu_compatible)
1.1.1.2 root 333: write_log (" prefetch");
334: write_log ("\n");
335:
336: read_table68k ();
337: do_merges ();
338:
339: write_log ("%d CPU functions\n", nr_cpuop_funcs);
340:
341: build_cpufunctbl ();
342: set_x_funcs ();
343: }
344:
1.1.1.5 root 345: struct regstruct regs;
1.1.1.2 root 346: struct flag_struct regflags;
347:
1.1.1.5 root 348: #define get_word_debug(o) DBGMemory_ReadWord (o)
349: #define get_iword_debug(o) DBGMemory_ReadWord (o)
350: #define get_ilong_debug(o) DBGMemory_ReadLong (o)
351:
352: static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
353: {
354: uae_u16 dp;
355: uae_s8 disp8;
356: uae_s16 disp16;
357: int r;
358: uae_u32 dispreg;
359: uaecptr addr = pc;
360: uae_s32 offset = 0;
361: TCHAR buffer[80];
362:
363: switch (mode){
364: case Dreg:
365: _stprintf (buffer, _T("D%d"), reg);
366: break;
367: case Areg:
368: _stprintf (buffer, _T("A%d"), reg);
369: break;
370: case Aind:
371: _stprintf (buffer, _T("(A%d)"), reg);
372: addr = regs.regs[reg + 8];
373: break;
374: case Aipi:
375: _stprintf (buffer, _T("(A%d)+"), reg);
376: addr = regs.regs[reg + 8];
377: break;
378: case Apdi:
379: _stprintf (buffer, _T("-(A%d)"), reg);
380: addr = regs.regs[reg + 8];
381: break;
382: case Ad16:
383: {
384: TCHAR offtxt[80];
385: disp16 = get_iword_debug (pc); pc += 2;
386: if (disp16 < 0)
387: _stprintf (offtxt, _T("-$%04x"), -disp16);
388: else
389: _stprintf (offtxt, _T("$%04x"), disp16);
390: addr = m68k_areg (regs, reg) + disp16;
391: _stprintf (buffer, _T("(A%d, %s) == $%08x"), reg, offtxt, addr);
392: }
393: break;
394: case Ad8r:
395: dp = get_iword_debug (pc); pc += 2;
396: disp8 = dp & 0xFF;
397: r = (dp & 0x7000) >> 12;
398: dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
399: if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
400: dispreg <<= (dp >> 9) & 3;
401:
402: if (dp & 0x100) {
403: uae_s32 outer = 0, disp = 0;
404: uae_s32 base = m68k_areg (regs, reg);
405: TCHAR name[10];
406: _stprintf (name, _T("A%d, "), reg);
407: if (dp & 0x80) { base = 0; name[0] = 0; }
408: if (dp & 0x40) dispreg = 0;
409: if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
410: if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
411: base += disp;
412:
413: if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
414: if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
415:
416: if (!(dp & 4)) base += dispreg;
417: if ((dp & 3) && !safemode) base = get_ilong_debug (base);
418: if (dp & 4) base += dispreg;
419:
420: addr = base + outer;
421: _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
422: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
423: 1 << ((dp >> 9) & 3),
424: disp, outer, addr);
425: } else {
426: addr = m68k_areg (regs, reg) + (uae_s32)((uae_s8)disp8) + dispreg;
427: _stprintf (buffer, _T("(A%d, %c%d.%c*%d, $%02x) == $%08x"), reg,
428: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
429: 1 << ((dp >> 9) & 3), disp8, addr);
430: }
431: break;
432: case PC16:
433: disp16 = get_iword_debug (pc); pc += 2;
434: addr += (uae_s16)disp16;
435: _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr);
436: break;
437: case PC8r:
438: dp = get_iword_debug (pc); pc += 2;
439: disp8 = dp & 0xFF;
440: r = (dp & 0x7000) >> 12;
441: dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
442: if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
443: dispreg <<= (dp >> 9) & 3;
444:
445: if (dp & 0x100) {
446: uae_s32 outer = 0, disp = 0;
447: uae_s32 base = addr;
448: TCHAR name[10];
449: _stprintf (name, _T("PC, "));
450: if (dp & 0x80) { base = 0; name[0] = 0; }
451: if (dp & 0x40) dispreg = 0;
452: if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
453: if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
454: base += disp;
455:
456: if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
457: if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
458:
459: if (!(dp & 4)) base += dispreg;
460: if ((dp & 3) && !safemode) base = get_ilong_debug (base);
461: if (dp & 4) base += dispreg;
462:
463: addr = base + outer;
464: _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
465: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
466: 1 << ((dp >> 9) & 3),
467: disp, outer, addr);
468: } else {
469: addr += (uae_s32)((uae_s8)disp8) + dispreg;
470: _stprintf (buffer, _T("(PC, %c%d.%c*%d, $%02x) == $%08x"), dp & 0x8000 ? 'A' : 'D',
471: (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3),
472: disp8, addr);
473: }
474: break;
475: case absw:
476: addr = (uae_s32)(uae_s16)get_iword_debug (pc);
477: _stprintf (buffer, _T("$%08x"), addr);
478: pc += 2;
479: break;
480: case absl:
481: addr = get_ilong_debug (pc);
482: _stprintf (buffer, _T("$%08x"), addr);
483: pc += 4;
484: break;
485: case imm:
486: switch (size){
487: case sz_byte:
488: _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff));
489: pc += 2;
490: break;
491: case sz_word:
492: _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff));
493: pc += 2;
494: break;
495: case sz_long:
496: _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc)));
497: pc += 4;
498: break;
499: case sz_single:
500: {
501: fptype fp;
502: to_single(&fp, get_ilong_debug(pc));
503: _stprintf(buffer, _T("#%s"), fp_print(&fp));
504: pc += 4;
505: }
506: break;
507: case sz_double:
508: {
509: fptype fp;
510: to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
511: _stprintf(buffer, _T("#%s"), fp_print(&fp));
512: pc += 8;
513: }
514: break;
515: case sz_extended:
516: {
517: fptype fp;
518: to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
519: _stprintf(buffer, _T("#%s"), fp_print(&fp));
520: pc += 12;
521: break;
522: }
523: case sz_packed:
524: _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
525: pc += 12;
526: break;
527: default:
528: break;
529: }
530: break;
531: case imm0:
532: offset = (uae_s32)(uae_s8)get_iword_debug (pc);
533: _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff));
534: addr = pc + 2 + offset;
535: pc += 2;
536: break;
537: case imm1:
538: offset = (uae_s32)(uae_s16)get_iword_debug (pc);
539: buffer[0] = 0;
540: _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff));
541: addr = pc + offset;
542: pc += 2;
543: break;
544: case imm2:
545: offset = (uae_s32)get_ilong_debug (pc);
546: _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
547: addr = pc + offset;
548: pc += 4;
549: break;
550: case immi:
551: offset = (uae_s32)(uae_s8)(reg & 0xff);
552: _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
553: addr = pc + offset;
554: break;
555: default:
556: break;
557: }
558: if (buf == 0)
559: f_out (f, _T("%s"), buffer);
560: else
561: _tcscat (buf, buffer);
562: if (eaddr)
563: *eaddr = addr;
564: return pc;
1.1.1.2 root 565: }
566:
1.1.1.6 ! root 567: static void activate_trace(void)
! 568: {
! 569: unset_special (SPCFLAG_TRACE);
! 570: set_special (SPCFLAG_DOTRACE);
! 571: }
! 572:
! 573: void check_t0_trace(void)
! 574: {
! 575: if (regs.t0 && currprefs.cpu_model >= 68020) {
! 576: unset_special (SPCFLAG_TRACE);
! 577: set_special (SPCFLAG_DOTRACE);
! 578: }
! 579: }
! 580:
1.1.1.2 root 581: void REGPARAM2 MakeSR (void)
582: {
583: regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
584: | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
585: | (GET_XFLG () << 4) | (GET_NFLG () << 3)
586: | (GET_ZFLG () << 2) | (GET_VFLG () << 1)
587: | GET_CFLG ());
588: }
589:
1.1.1.6 ! root 590: static void MakeFromSR_x(int t0trace)
1.1.1.2 root 591: {
592: int oldm = regs.m;
593: int olds = regs.s;
1.1.1.6 ! root 594: int oldt0 = regs.t0;
! 595: int oldt1 = regs.t1;
1.1.1.2 root 596:
597: SET_XFLG ((regs.sr >> 4) & 1);
598: SET_NFLG ((regs.sr >> 3) & 1);
599: SET_ZFLG ((regs.sr >> 2) & 1);
600: SET_VFLG ((regs.sr >> 1) & 1);
601: SET_CFLG (regs.sr & 1);
602: if (regs.t1 == ((regs.sr >> 15) & 1) &&
603: regs.t0 == ((regs.sr >> 14) & 1) &&
604: regs.s == ((regs.sr >> 13) & 1) &&
605: regs.m == ((regs.sr >> 12) & 1) &&
606: regs.intmask == ((regs.sr >> 8) & 7))
607: return;
608: regs.t1 = (regs.sr >> 15) & 1;
609: regs.t0 = (regs.sr >> 14) & 1;
610: regs.s = (regs.sr >> 13) & 1;
611: regs.m = (regs.sr >> 12) & 1;
612: regs.intmask = (regs.sr >> 8) & 7;
613: if (currprefs.cpu_model >= 68020) {
614: if (olds != regs.s) {
615: if (olds) {
616: if (oldm)
617: regs.msp = m68k_areg (regs, 7);
618: else
619: regs.isp = m68k_areg (regs, 7);
620: m68k_areg (regs, 7) = regs.usp;
621: } else {
622: regs.usp = m68k_areg (regs, 7);
623: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
624: }
625: } else if (olds && oldm != regs.m) {
626: if (oldm) {
627: regs.msp = m68k_areg (regs, 7);
628: m68k_areg (regs, 7) = regs.isp;
629: } else {
630: regs.isp = m68k_areg (regs, 7);
631: m68k_areg (regs, 7) = regs.msp;
632: }
633: }
634: } else {
635: regs.t0 = regs.m = 0;
636: if (olds != regs.s) {
637: if (olds) {
638: regs.isp = m68k_areg (regs, 7);
639: m68k_areg (regs, 7) = regs.usp;
640: } else {
641: regs.usp = m68k_areg (regs, 7);
642: m68k_areg (regs, 7) = regs.isp;
643: }
644: }
645: }
646: if (currprefs.mmu_model)
647: mmu_set_super (regs.s != 0);
648:
649: doint ();
1.1.1.6 ! root 650: if (regs.t1 || regs.t0) {
1.1.1.2 root 651: set_special (SPCFLAG_TRACE);
1.1.1.6 ! root 652: } else {
1.1.1.2 root 653: /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
654: SR-modifying instructions (including STOP). */
655: unset_special (SPCFLAG_TRACE);
1.1.1.6 ! root 656: }
! 657: // Stop SR-modification does not generate T0
! 658: // If this SR modification set Tx bit, no trace until next instruction.
! 659: if ((oldt0 && t0trace && currprefs.cpu_model >= 68020) || oldt1) {
! 660: // Always trace if Tx bits were already set, even if this SR modification cleared them.
! 661: activate_trace();
! 662: }
! 663: }
! 664:
! 665: void REGPARAM2 MakeFromSR_T0(void)
! 666: {
! 667: MakeFromSR_x(1);
! 668: }
! 669: void REGPARAM2 MakeFromSR(void)
! 670: {
! 671: MakeFromSR_x(0);
! 672:
1.1.1.2 root 673: }
674:
1.1.1.5 root 675: static void exception_check_trace (int nr)
1.1.1.2 root 676: {
1.1.1.5 root 677: unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
678: if (regs.t1 && !regs.t0) {
679: /* trace stays pending if exception is div by zero, chk,
680: * trapv or trap #x
681: */
682: if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
683: set_special (SPCFLAG_DOTRACE);
684: }
685: regs.t1 = regs.t0 = 0;
1.1.1.2 root 686: }
687:
688: static void exception_debug (int nr)
689: {
690: #ifdef DEBUGGER
691: if (!exception_debugging)
692: return;
1.1.1.5 root 693: printf ("Exception %d, PC=%08X\n", nr, M68K_GETPC);
694: DebugUI();
1.1.1.2 root 695: #endif
696: }
697:
1.1.1.4 root 698: void cpu_halt (int e)
699: {
700: write_log("HALT!");
1.1.1.5 root 701: DebugUI();
1.1.1.4 root 702: }
1.1.1.3 root 703:
1.1.1.4 root 704: static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format)
705: {
1.1.1.3 root 706: int i;
1.1.1.4 root 707:
708: #if 0
1.1.1.3 root 709: if (nr < 24 || nr > 31) { // do not print debugging for interrupts
1.1.1.4 root 710: write_log(_T("Building exception stack frame (format %X)\n"), format);
1.1.1.3 root 711: }
1.1.1.4 root 712: #endif
713:
1.1.1.3 root 714: switch (format) {
715: case 0x0: // four word stack frame
716: case 0x1: // throwaway four word stack frame
717: break;
718: case 0x2: // six word stack frame
719: m68k_areg (regs, 7) -= 4;
720: x_put_long (m68k_areg (regs, 7), oldpc);
721: break;
1.1.1.5 root 722: case 0x3: // floating point post-instruction stack frame (68040)
723: m68k_areg (regs, 7) -= 4;
724: x_put_long (m68k_areg (regs, 7), regs.fp_ea);
725: break;
1.1.1.3 root 726: case 0x7: // access error stack frame (68040)
1.1.1.4 root 727:
728: for (i = 3; i >= 0; i--) {
729: // WB1D/PD0,PD1,PD2,PD3
1.1.1.3 root 730: m68k_areg (regs, 7) -= 4;
1.1.1.4 root 731: x_put_long (m68k_areg (regs, 7), mmu040_move16[i]);
732: }
733:
1.1.1.3 root 734: m68k_areg (regs, 7) -= 4;
1.1.1.4 root 735: x_put_long (m68k_areg (regs, 7), 0); // WB1A
736: m68k_areg (regs, 7) -= 4;
737: x_put_long (m68k_areg (regs, 7), 0); // WB2D
1.1.1.3 root 738: m68k_areg (regs, 7) -= 4;
1.1.1.4 root 739: x_put_long (m68k_areg (regs, 7), regs.wb2_address); // WB2A
740: m68k_areg (regs, 7) -= 4;
741: x_put_long (m68k_areg (regs, 7), regs.wb3_data); // WB3D
1.1.1.3 root 742: m68k_areg (regs, 7) -= 4;
1.1.1.4 root 743: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // WB3A
744:
745: m68k_areg (regs, 7) -= 4;
746: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // FA
747:
748: m68k_areg (regs, 7) -= 2;
1.1.1.3 root 749: x_put_word (m68k_areg (regs, 7), 0);
750: m68k_areg (regs, 7) -= 2;
1.1.1.4 root 751: x_put_word (m68k_areg (regs, 7), regs.wb2_status);
752: regs.wb2_status = 0;
1.1.1.3 root 753: m68k_areg (regs, 7) -= 2;
754: x_put_word (m68k_areg (regs, 7), regs.wb3_status);
755: regs.wb3_status = 0;
1.1.1.4 root 756:
757: m68k_areg (regs, 7) -= 2;
758: x_put_word (m68k_areg (regs, 7), ssw);
1.1.1.3 root 759: m68k_areg (regs, 7) -= 4;
1.1.1.4 root 760: x_put_long (m68k_areg (regs, 7), regs.mmu_effective_addr);
1.1.1.3 root 761: break;
762: case 0x9: // coprocessor mid-instruction stack frame (68020, 68030)
763: m68k_areg (regs, 7) -= 4;
1.1.1.5 root 764: x_put_long (m68k_areg (regs, 7), regs.fp_ea);
1.1.1.3 root 765: m68k_areg (regs, 7) -= 4;
1.1.1.5 root 766: x_put_long (m68k_areg (regs, 7), regs.fp_opword);
1.1.1.3 root 767: m68k_areg (regs, 7) -= 4;
768: x_put_long (m68k_areg (regs, 7), oldpc);
769: break;
770: case 0x8: // bus and address error stack frame (68010)
1.1.1.4 root 771: write_log(_T("Exception stack frame format %X not implemented\n"), format);
1.1.1.3 root 772: return;
1.1.1.4 root 773: case 0x4: // floating point unimplemented stack frame (68LC040, 68EC040)
774: // or 68060 bus access fault stack frame
775: m68k_areg (regs, 7) -= 4;
1.1.1.5 root 776: x_put_long (m68k_areg (regs, 7), ssw);
1.1.1.4 root 777: m68k_areg (regs, 7) -= 4;
1.1.1.5 root 778: x_put_long (m68k_areg (regs, 7), oldpc);
1.1.1.4 root 779: break;
780: case 0xB: // long bus cycle fault stack frame (68020, 68030)
781: // We always use B frame because it is easier to emulate,
782: // our PC always points at start of instruction but A frame assumes
783: // it is + 2 and handling this properly is not easy.
784: // Store state information to internal register space
785: for (i = 0; i < mmu030_idx + 1; i++) {
786: m68k_areg (regs, 7) -= 4;
787: x_put_long (m68k_areg (regs, 7), mmu030_ad[i].val);
788: }
789: while (i < 9) {
790: uae_u32 v = 0;
791: m68k_areg (regs, 7) -= 4;
1.1.1.5 root 792: // mmu030_idx is always small enough if instruction is FMOVEM.
1.1.1.4 root 793: if (mmu030_state[1] & MMU030_STATEFLAG1_FMOVEM) {
794: if (i == 7)
795: v = mmu030_fmovem_store[0];
796: else if (i == 8)
797: v = mmu030_fmovem_store[1];
798: }
799: x_put_long (m68k_areg (regs, 7), v);
800: i++;
801: }
802: // version & internal information (We store index here)
803: m68k_areg (regs, 7) -= 2;
804: x_put_word (m68k_areg (regs, 7), mmu030_idx);
805: // 3* internal registers
806: m68k_areg (regs, 7) -= 2;
807: x_put_word (m68k_areg (regs, 7), mmu030_state[2]);
808: m68k_areg (regs, 7) -= 2;
809: x_put_word (m68k_areg (regs, 7), mmu030_state[1]);
810: m68k_areg (regs, 7) -= 2;
811: x_put_word (m68k_areg (regs, 7), mmu030_state[0]);
812: // data input buffer = fault address
813: m68k_areg (regs, 7) -= 4;
814: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
815: // 2xinternal
816: m68k_areg (regs, 7) -= 2;
817: x_put_word (m68k_areg (regs, 7), 0);
818: m68k_areg (regs, 7) -= 2;
819: x_put_word (m68k_areg (regs, 7), 0);
820: // stage b address
821: m68k_areg (regs, 7) -= 4;
822: x_put_long (m68k_areg (regs, 7), mm030_stageb_address);
823: // 2xinternal
824: m68k_areg (regs, 7) -= 4;
825: x_put_long (m68k_areg (regs, 7), mmu030_disp_store[1]);
826: /* fall through */
827: case 0xA: // short bus cycle fault stack frame (68020, 68030)
828: m68k_areg (regs, 7) -= 4;
829: x_put_long (m68k_areg (regs, 7), mmu030_disp_store[0]);
830: m68k_areg (regs, 7) -= 4;
831: // Data output buffer = value that was going to be written
832: x_put_long (m68k_areg (regs, 7), (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) ? mmu030_data_buffer : mmu030_ad[mmu030_idx].val);
833: m68k_areg (regs, 7) -= 4;
834: x_put_long (m68k_areg (regs, 7), mmu030_opcode); // Internal register (opcode storage)
835: m68k_areg (regs, 7) -= 4;
836: x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // data cycle fault address
837: m68k_areg (regs, 7) -= 2;
838: x_put_word (m68k_areg (regs, 7), 0); // Instr. pipe stage B
839: m68k_areg (regs, 7) -= 2;
840: x_put_word (m68k_areg (regs, 7), 0); // Instr. pipe stage C
841: m68k_areg (regs, 7) -= 2;
842: x_put_word (m68k_areg (regs, 7), ssw);
843: m68k_areg (regs, 7) -= 2;
844: x_put_word (m68k_areg (regs, 7), 0); // Internal register
845: break;
846: default:
847: write_log(_T("Unknown exception stack frame format: %X\n"), format);
1.1.1.3 root 848: return;
849: }
850: m68k_areg (regs, 7) -= 2;
1.1.1.4 root 851: x_put_word (m68k_areg (regs, 7), (format << 12) | (nr * 4));
1.1.1.3 root 852: m68k_areg (regs, 7) -= 4;
853: x_put_long (m68k_areg (regs, 7), currpc);
854: m68k_areg (regs, 7) -= 2;
855: x_put_word (m68k_areg (regs, 7), regs.sr);
856: }
857:
1.1.1.4 root 858: // 68030 MMU
859: static void Exception_mmu030 (int nr, uaecptr oldpc)
860: {
861: uae_u32 currpc = m68k_getpc (), newpc;
1.1.1.3 root 862:
1.1.1.4 root 863: exception_debug (nr);
864: MakeSR ();
1.1.1.3 root 865:
866: if (!regs.s) {
1.1.1.4 root 867: regs.usp = m68k_areg (regs, 7);
1.1.1.3 root 868: m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
869: regs.s = 1;
1.1.1.4 root 870: mmu_set_super (1);
1.1.1.3 root 871: }
1.1.1.4 root 872:
873: #if 0
1.1.1.3 root 874: if (nr < 24 || nr > 31) { // do not print debugging for interrupts
1.1.1.4 root 875: write_log (_T("Exception_mmu030: Exception %i: %08x %08x %08x\n"),
1.1.1.3 root 876: nr, currpc, oldpc, regs.mmu_fault_addr);
877: }
1.1.1.4 root 878: #endif
879:
880: #if 0
881: write_log (_T("Exception %d -> %08x\n", nr, newpc));
882: #endif
883:
884:
885: newpc = x_get_long (regs.vbr + 4 * nr);
886:
887: if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */
888: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
889: MakeSR(); /* this sets supervisor bit in status reg */
890: regs.m = 0; /* clear the M bit (but frame 0x1 uses sr with M bit set) */
891: regs.msp = m68k_areg (regs, 7);
892: m68k_areg (regs, 7) = regs.isp;
893: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1);
1.1.1.3 root 894: } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9 || nr == 56) {
1.1.1.4 root 895: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x2);
896: } else if (nr == 2) {
897: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0xB);
898: } else if (nr == 3) {
899: regs.mmu_fault_addr = last_fault_for_exception_3;
900: mmu030_state[0] = mmu030_state[1] = 0;
901: mmu030_data_buffer = 0;
902: Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr, 0xA);
1.1.1.5 root 903: } else if (nr >= 48 && nr < 55) {
904: if (regs.fpu_exp_pre) {
905: Exception_build_stack_frame(oldpc, regs.instruction_pc, 0, nr, 0x0);
906: } else { /* mid-instruction */
907: Exception_build_stack_frame(regs.fpiar, currpc, 0, nr, 0x9);
908: }
1.1.1.3 root 909: } else {
1.1.1.4 root 910: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
1.1.1.3 root 911: }
912:
913: if (newpc & 1) {
914: if (nr == 2 || nr == 3)
1.1.1.4 root 915: cpu_halt (2);
1.1.1.3 root 916: else
1.1.1.5 root 917: exception3_read(regs.ir, newpc);
1.1.1.3 root 918: return;
919: }
1.1.1.5 root 920: m68k_setpci (newpc);
921: exception_check_trace (nr);
1.1.1.3 root 922: }
923:
924:
1.1.1.5 root 925: // 68040 MMU
1.1.1.2 root 926: static void Exception_mmu (int nr, uaecptr oldpc)
927: {
928: uae_u32 currpc = m68k_getpc (), newpc;
929:
930: exception_debug (nr);
931: MakeSR ();
932:
933: if (!regs.s) {
934: regs.usp = m68k_areg (regs, 7);
1.1.1.5 root 935: if (currprefs.cpu_model >= 68020 && currprefs.cpu_model < 68060) {
1.1.1.2 root 936: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
1.1.1.4 root 937: } else {
1.1.1.2 root 938: m68k_areg (regs, 7) = regs.isp;
1.1.1.4 root 939: }
1.1.1.2 root 940: regs.s = 1;
941: mmu_set_super (1);
942: }
1.1.1.3 root 943:
1.1.1.4 root 944: newpc = x_get_long (regs.vbr + 4 * nr);
945: #if 0
946: write_log (_T("Exception %d: %08x -> %08x\n"), nr, currpc, newpc);
947: #endif
948:
949: if (nr == 2) { // bus error
950: //write_log (_T("Exception_mmu %08x %08x %08x\n"), currpc, oldpc, regs.mmu_fault_addr);
951: if (currprefs.mmu_model == 68040)
952: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x7);
953: else
1.1.1.5 root 954: Exception_build_stack_frame(regs.mmu_fault_addr, currpc, regs.mmu_fslw, nr, 0x4);
1.1.1.3 root 955: } else if (nr == 3) { // address error
1.1.1.4 root 956: Exception_build_stack_frame(last_fault_for_exception_3, currpc, 0, nr, 0x2);
957: write_log (_T("Exception %d (%x) at %x!\n"), nr, last_fault_for_exception_3, currpc);
958: } else if (nr == 5 || nr == 6 || nr == 7 || nr == 9) {
1.1.1.3 root 959: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2);
1.1.1.2 root 960: } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */
1.1.1.4 root 961: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
962: MakeSR(); /* this sets supervisor bit in status reg */
963: regs.m = 0; /* clear the M bit (but frame 0x1 uses sr with M bit set) */
964: regs.msp = m68k_areg (regs, 7);
965: m68k_areg (regs, 7) = regs.isp;
966: Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1);
1.1.1.5 root 967: } else if (nr == 60 || nr == 61) {
1.1.1.4 root 968: Exception_build_stack_frame(oldpc, regs.instruction_pc, regs.mmu_ssw, nr, 0x0);
1.1.1.5 root 969: } else if (nr >= 48 && nr <= 55) {
970: if (regs.fpu_exp_pre) {
971: if (currprefs.cpu_model == 68060 && nr == 55 && regs.fp_unimp_pend == 2) { // packed decimal real
972: Exception_build_stack_frame(regs.fp_ea, regs.instruction_pc, 0, nr, 0x2);
973: } else {
974: Exception_build_stack_frame(oldpc, regs.instruction_pc, 0, nr, 0x0);
975: }
976: } else { /* post-instruction */
977: if (currprefs.cpu_model == 68060 && nr == 55 && regs.fp_unimp_pend == 2) { // packed decimal real
978: Exception_build_stack_frame(regs.fp_ea, currpc, 0, nr, 0x2);
979: } else {
980: Exception_build_stack_frame(oldpc, currpc, 0, nr, 0x3);
981: }
982: }
983: } else if (nr == 11 && regs.fp_unimp_ins) {
984: regs.fp_unimp_ins = false;
985: if ((currprefs.cpu_model == 68060 && (currprefs.fpu_model == 0 || (regs.pcr & 2))) ||
986: (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) {
987: Exception_build_stack_frame(regs.fp_ea, currpc, regs.instruction_pc, nr, 0x4);
988: } else {
989: Exception_build_stack_frame(regs.fp_ea, currpc, regs.mmu_ssw, nr, 0x2);
990: }
1.1.1.2 root 991: } else {
1.1.1.3 root 992: Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
1.1.1.2 root 993: }
1.1.1.3 root 994:
1.1.1.2 root 995: if (newpc & 1) {
996: if (nr == 2 || nr == 3)
1.1.1.4 root 997: cpu_halt (2);
1.1.1.2 root 998: else
1.1.1.5 root 999: exception3_read (regs.ir, newpc);
1.1.1.2 root 1000: return;
1001: }
1.1.1.5 root 1002: m68k_setpci (newpc);
1003: exception_check_trace (nr);
1.1.1.2 root 1004: }
1005:
1006:
1.1.1.5 root 1007: /* Handle exceptions. */
1008: static void ExceptionX (int nr, uaecptr address)
1.1.1.2 root 1009: {
1.1.1.5 root 1010: if (currprefs.cpu_model == 68030)
1011: Exception_mmu030 (nr, m68k_getpc ());
1.1.1.3 root 1012: else
1.1.1.5 root 1013: Exception_mmu (nr, m68k_getpc ());
1.1.1.2 root 1014: }
1.1.1.5 root 1015:
1.1.1.6 ! root 1016: void REGPARAM2 Exception_cpu(int nr)
! 1017: {
! 1018: bool t0 = currprefs.cpu_model >= 68020 && regs.t0;
! 1019: ExceptionX (nr, -1);
! 1020: // check T0 trace
! 1021: if (t0) {
! 1022: activate_trace();
! 1023: }
! 1024: }
1.1.1.4 root 1025: void REGPARAM2 Exception (int nr)
1026: {
1.1.1.5 root 1027: ExceptionX (nr, -1);
1.1.1.4 root 1028: }
1.1.1.5 root 1029: void REGPARAM2 ExceptionL (int nr, uaecptr address)
1.1.1.2 root 1030: {
1.1.1.5 root 1031: ExceptionX (nr, address);
1032: }
1.1.1.2 root 1033:
1.1.1.5 root 1034: static void do_interrupt (int nr, int Pending)
1035: {
1.1.1.2 root 1036: regs.stopped = 0;
1037: unset_special (SPCFLAG_STOP);
1038: assert (nr < 8 && nr >= 0);
1039:
1040: /* On Hatari, only video ints are using SPCFLAG_INT (see m68000.c) */
1.1.1.4 root 1041: Exception (nr + 24);
1.1.1.2 root 1042:
1043: regs.intmask = nr;
1044: doint ();
1045:
1046: set_special (SPCFLAG_INT);
1047: }
1048:
1049:
1050: void m68k_reset (int hardreset)
1051: {
1.1.1.4 root 1052: regs.spcflags &= (SPCFLAG_MODE_CHANGE | SPCFLAG_BRK);
1.1.1.2 root 1053: regs.ipl = regs.ipl_pin = 0;
1054: regs.s = 1;
1055: regs.m = 0;
1056: regs.stopped = 0;
1057: regs.t1 = 0;
1058: regs.t0 = 0;
1059: SET_ZFLG (0);
1060: SET_XFLG (0);
1061: SET_CFLG (0);
1062: SET_VFLG (0);
1063: SET_NFLG (0);
1064: regs.intmask = 7;
1065: regs.vbr = regs.sfc = regs.dfc = 0;
1066: regs.irc = 0xffff;
1067:
1068: m68k_areg (regs, 7) = get_long (0);
1069: m68k_setpc (get_long (4));
1070:
1071: fpu_reset ();
1072:
1073: regs.caar = regs.cacr = 0;
1074: regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0;
1075: regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0;
1076:
1077: mmufixup[0].reg = -1;
1078: mmufixup[1].reg = -1;
1079: if (currprefs.mmu_model) {
1.1.1.3 root 1080: if (currprefs.cpu_model >= 68040) {
1081: mmu_reset ();
1082: mmu_set_tc (regs.tcr);
1083: mmu_set_super (regs.s != 0);
1084: }
1085: else {
1086: mmu030_reset(hardreset);
1087: }
1088: }
1.1.1.2 root 1089:
1090: regs.pcr = 0;
1091: }
1092:
1.1.1.4 root 1093: void REGPARAM2 op_unimpl (uae_u16 opcode)
1094: {
1.1.1.5 root 1095: static int warned;
1096: if (warned < 20) {
1097: write_log (_T("68060 unimplemented opcode %04X, PC=%08x\n"), opcode, regs.instruction_pc);
1098: warned++;
1099: }
1100: ExceptionL (61, regs.instruction_pc);
1.1.1.4 root 1101: }
1102:
1103: uae_u32 REGPARAM2 op_illg (uae_u32 opcode)
1.1.1.2 root 1104: {
1105: uaecptr pc = m68k_getpc ();
1106: static int warned;
1107:
1108: if (warned < 20) {
1.1.1.4 root 1109: write_log ("Illegal instruction: %04x at %08X\n", opcode, pc);
1.1.1.2 root 1110: warned++;
1111: }
1112:
1113: if ((opcode & 0xF000)==0xA000)
1.1.1.4 root 1114: Exception (10);
1.1.1.2 root 1115: else
1116: if ((opcode & 0xF000)==0xF000)
1.1.1.4 root 1117: Exception (11);
1.1.1.2 root 1118: else
1.1.1.4 root 1119: Exception (4);
1.1.1.2 root 1120: return 4;
1121: }
1122:
1123: #ifdef CPUEMU_0
1124:
1.1.1.5 root 1125: // 68030 (68851) MMU instructions only
1126: bool mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
1.1.1.2 root 1127: {
1.1.1.5 root 1128: bool fline = false;
1129:
1130: if (extra & 0x8000) {
1131: fline = mmu_op30_ptest (pc, opcode, extra, extraa);
1132: } else if ((extra&0xE000)==0x2000 && (extra & 0x1C00)) {
1133: fline = mmu_op30_pflush (pc, opcode, extra, extraa);
1134: } else if ((extra&0xE000)==0x2000 && !(extra & 0x1C00)) {
1135: fline = mmu_op30_pload (pc, opcode, extra, extraa);
1136: } else {
1137: fline = mmu_op30_pmove (pc, opcode, extra, extraa);
1138: }
1139:
1140: if (fline) {
1141: m68k_setpc(pc);
1142: op_illg(opcode);
1143: }
1144: return fline;
1.1.1.2 root 1145: }
1146:
1147: void mmu_op (uae_u32 opcode, uae_u32 extra)
1148: {
1149: if (currprefs.cpu_model) {
1150: mmu_op_real (opcode, extra);
1151: return;
1152: }
1153: #if MMUOP_DEBUG > 1
1154: write_log ("mmu_op %04X PC=%08X\n", opcode, m68k_getpc ());
1155: #endif
1156: if ((opcode & 0xFE0) == 0x0500) {
1157: /* PFLUSH */
1158: regs.mmusr = 0;
1159: #if MMUOP_DEBUG > 0
1160: write_log ("PFLUSH\n");
1161: #endif
1162: return;
1163: } else if ((opcode & 0x0FD8) == 0x548) {
1164: if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
1165: /* PTEST */
1166: #if MMUOP_DEBUG > 0
1167: write_log ("PTEST\n");
1168: #endif
1169: return;
1170: }
1171: }
1172: #if MMUOP_DEBUG > 0
1173: write_log ("Unknown MMU OP %04X\n", opcode);
1174: #endif
1175: m68k_setpc (m68k_getpc () - 2);
1176: op_illg (opcode);
1177: }
1178:
1179: #endif
1180:
1181: static void do_trace (void)
1182: {
1183: if (regs.t0 && currprefs.cpu_model >= 68020) {
1.1.1.6 ! root 1184: // this is obsolete
! 1185: return;
! 1186: }
! 1187: if (regs.t1) {
! 1188: activate_trace();
! 1189: }
1.1.1.2 root 1190: }
1191:
1192: void doint (void)
1193: {
1194: if (currprefs.cpu_compatible)
1195: set_special (SPCFLAG_INT);
1196: else
1197: set_special (SPCFLAG_DOINT);
1198: }
1199:
1200: #define IDLETIME (currprefs.cpu_idle * sleep_resolution / 700)
1201:
1202: /*
1203: * Handle special flags
1204: */
1205:
1.1.1.6 ! root 1206: static int vpos = 0;
! 1207:
1.1.1.5 root 1208: static int do_specialties (int cycles)
1.1.1.2 root 1209: {
1210: if (regs.spcflags & SPCFLAG_DOTRACE)
1.1.1.4 root 1211: Exception (9);
1.1.1.2 root 1212:
1213: /* Handle the STOP instruction */
1214: if ( regs.spcflags & SPCFLAG_STOP ) {
1.1.1.5 root 1215: while (regs.spcflags & SPCFLAG_STOP) {
1.1.1.2 root 1216:
1.1.1.5 root 1217: /* Take care of quit event if needed */
1218: if (regs.spcflags & SPCFLAG_BRK)
1219: return 1;
1220:
1221: M68000_AddCycles(cpu_cycles);
1222:
1223: /* It is possible one or more ints happen at the same time */
1224: /* We must process them during the same cpu cycle until the special INT flag is set */
1225: while (PendingInterrupt.time <=0 && PendingInterrupt.pFunction) {
1226: /* 1st, we call the interrupt handler */
1227: CALL_VAR(PendingInterrupt.pFunction);
1228:
1229: if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
1230: unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
1231: // SPCFLAG_BRK breaks STOP condition, need to prefetch
1232: m68k_resumestopped ();
1233: return 1;
1234: }
1.1.1.2 root 1235:
1.1.1.5 root 1236: if (currprefs.cpu_idle && ((regs.spcflags & SPCFLAG_STOP)) == SPCFLAG_STOP) {
1237: /* sleep 1ms if STOP-instruction is executed */
1238: if (1) {
1239: static int sleepcnt, lvpos;
1240: if (vpos != lvpos) {
1241: sleepcnt--;
1242: lvpos = vpos;
1243: if (sleepcnt < 0) {
1244: /*sleepcnt = IDLETIME / 2; */ /* Laurent : badly removed for now */
1245: host_sleep_ms(1);
1246: }
1247: }
1248: }
1249: }
1250: }
1251: }
1.1.1.2 root 1252: }
1253:
1254: if (regs.spcflags & SPCFLAG_TRACE)
1255: do_trace ();
1256:
1257: if (regs.spcflags & SPCFLAG_DOINT) {
1258: unset_special (SPCFLAG_DOINT);
1259: set_special (SPCFLAG_INT);
1260: }
1261:
1262: if (regs.spcflags & SPCFLAG_DEBUGGER)
1263: DebugCpu_Check();
1264:
1265: if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
1266: unset_special(SPCFLAG_MODE_CHANGE);
1267: return 1;
1268: }
1.1.1.5 root 1269:
1.1.1.2 root 1270: return 0;
1271: }
1272:
1.1.1.5 root 1273: #ifndef CPUEMU_0
1.1.1.2 root 1274:
1.1.1.5 root 1275: #else
1.1.1.2 root 1276:
1.1.1.6 ! root 1277: static int ndCycles = 0;
! 1278: // give other MPUs (DSP, i860) some time to run on m68k thread
! 1279: static inline void run_other_MPUs() {
! 1280: ndCycles += cpu_cycles;
! 1281: // bundle some 68k cycles for MPUs
! 1282:
! 1283: if(dsp_core.running)
! 1284: DSP_Run(cpu_cycles);
! 1285:
! 1286: if(ndCycles > 100) {
! 1287: i860_Run(ndCycles);
! 1288: ndCycles = 0;
! 1289: }
! 1290: }
! 1291:
! 1292: /**
! 1293: * Return interrupt number (1 - 7), 0 means no interrupt.
! 1294: * Note that the interrupt stays pending if it can't be executed yet
! 1295: * due to the interrupt level field in the SR.
! 1296: */
! 1297: static inline int intlev(void) {
! 1298: /* Poll interrupt level from interrupt status and mask registers
! 1299: * --> see sysReg.c
! 1300: */
! 1301: Uint32 interrupt = scrIntStat&scrIntMask;
! 1302: return interrupt ? scr_get_interrupt_level(interrupt) : 0;
! 1303: }
! 1304:
1.1.1.5 root 1305: static int lastRegsS = 0;
1.1.1.2 root 1306:
1.1.1.5 root 1307: // Previous MMU 68030
1308: static void m68k_run_mmu030 (void)
1.1.1.2 root 1309: {
1.1.1.5 root 1310: uae_u16 opcode;
1311: uaecptr pc;
1312: struct flag_struct f;
1313: f.cznv = 0;
1314: f.x = 0;
1315: int intr = 0;
1316: int lastintr = 0;
1317: mmu030_opcode_stageb = -1;
1318: retry:
1319: TRY (prb) {
1320: for (;;) {
1321: int cnt;
1322: insretry:
1323: pc = regs.instruction_pc = m68k_getpc ();
1324: f.cznv = regflags.cznv;
1325: f.x = regflags.x;
1326:
1327: mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0;
1328: mmu030_opcode = -1;
1329: if (mmu030_opcode_stageb < 0) {
1330: opcode = get_iword_mmu030 (0);
1331: } else {
1332: opcode = mmu030_opcode_stageb;
1333: mmu030_opcode_stageb = -1;
1334: }
1.1.1.2 root 1335:
1.1.1.5 root 1336: mmu030_opcode = opcode;
1337: mmu030_ad[0].done = false;
1.1.1.2 root 1338:
1.1.1.5 root 1339: Uint64 beforeCycles = nCyclesMainCounter;
1340: cnt = 50;
1341: for (;;) {
1342: opcode = mmu030_opcode;
1343: mmu030_idx = 0;
1344: mmu030_retry = false;
1345: cpu_cycles = (*cpufunctbl[opcode])(opcode);
1346: cnt--; // so that we don't get in infinite loop if things go horribly wrong
1347: if (!mmu030_retry)
1348: break;
1349: if (cnt < 0) {
1350: cpu_halt (9);
1351: break;
1352: }
1353: if (mmu030_retry && mmu030_opcode == -1)
1354: goto insretry; // urgh
1355: }
1.1.1.2 root 1356:
1.1.1.5 root 1357: mmu030_opcode = -1;
1358:
1359: M68000_AddCycles(cpu_cycles);
1360: cpu_cycles = nCyclesMainCounter - beforeCycles;
1361:
1.1.1.6 ! root 1362: run_other_MPUs();
1.1.1.2 root 1363:
1.1.1.5 root 1364: /* We can have several interrupts at the same time before the next CPU instruction */
1365: /* We must check for pending interrupt and call do_specialties_interrupt() only */
1366: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
1367: /* and prevent exiting the STOP state when calling do_specialties() after. */
1368: /* For performance, we first test PendingInterruptCount, then regs.spcflags */
1369: while ( ( PendingInterrupt.time <= 0 ) && ( PendingInterrupt.pFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) {
1370: CALL_VAR(PendingInterrupt.pFunction); /* call the interrupt handler */
1371: }
1.1.1.2 root 1372:
1.1.1.5 root 1373: /* Previous: for now we poll the interrupt pins with every instruction.
1374: * TODO: only do this when an actual interrupt is active to not
1375: * unneccessarily slow down emulation.
1376: */
1377: intr = intlev ();
1378: if (intr>regs.intmask || (intr==7 && intr>lastintr))
1379: do_interrupt (intr, false);
1380: lastintr = intr;
1381:
1382: if(lastRegsS != regs.s) {
1383: host_realtime(!(regs.s));
1384: lastRegsS = regs.s;
1385: }
1.1.1.2 root 1386:
1.1.1.5 root 1387: if (regs.spcflags & ~SPCFLAG_INT) {
1388: if (do_specialties (cpu_cycles))
1389: return;
1390: }
1391: }
1392: } CATCH (prb) {
1.1.1.2 root 1393:
1.1.1.5 root 1394: regflags.cznv = f.cznv;
1395: regflags.x = f.x;
1.1.1.2 root 1396:
1.1.1.5 root 1397: m68k_setpci (regs.instruction_pc);
1.1.1.2 root 1398:
1.1.1.5 root 1399: if (mmufixup[0].reg >= 0) {
1400: m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
1401: mmufixup[0].reg = -1;
1.1.1.2 root 1402: }
1.1.1.5 root 1403: if (mmufixup[1].reg >= 0) {
1404: m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
1405: mmufixup[1].reg = -1;
1.1.1.2 root 1406: }
1407:
1.1.1.5 root 1408: TRY (prb2) {
1409: Exception (prb);
1410: } CATCH (prb2) {
1411: write_log("[FATAL] double fault\n");
1412: m68k_reset (1); // auto-reset CPU
1413: //cpu_halt (1);
1414: return;
1415: } ENDTRY
1416: } ENDTRY
1417: goto retry;
1.1.1.2 root 1418: }
1419:
1.1.1.5 root 1420: /* Aranym MMU 68040 */
1421: static void m68k_run_mmu040 (void)
1.1.1.2 root 1422: {
1.1.1.4 root 1423: uae_u16 opcode;
1424: struct flag_struct f;
1.1.1.5 root 1425: f.cznv = 0;
1426: f.x = 0;
1.1.1.4 root 1427: uaecptr pc;
1428: int intr = 0;
1429: int lastintr = 0;
1.1.1.6 ! root 1430:
1.1.1.2 root 1431: for (;;) {
1432: TRY (prb) {
1433: for (;;) {
1.1.1.4 root 1434: f.cznv = regflags.cznv;
1435: f.x = regflags.x;
1436: mmu_restart = true;
1437: pc = regs.instruction_pc = m68k_getpc ();
1.1.1.5 root 1438:
1439: Uint64 beforeCycles = nCyclesMainCounter;
1.1.1.4 root 1440: mmu_opcode = -1;
1.1.1.6 ! root 1441: mmu_opcode = opcode = get_iword_mmu040(0);
1.1.1.2 root 1442: cpu_cycles = (*cpufunctbl[opcode])(opcode);
1.1.1.5 root 1443: M68000_AddCycles(cpu_cycles);
1444: cpu_cycles = nCyclesMainCounter - beforeCycles;
1.1.1.2 root 1445:
1.1.1.6 ! root 1446: run_other_MPUs();
! 1447:
1.1.1.2 root 1448: /* We can have several interrupts at the same time before the next CPU instruction */
1449: /* We must check for pending interrupt and call do_specialties_interrupt() only */
1450: /* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
1451: /* and prevent exiting the STOP state when calling do_specialties() after. */
1452: /* For performance, we first test PendingInterruptCount, then regs.spcflags */
1.1.1.5 root 1453: while ( ( PendingInterrupt.time <= 0 ) && ( PendingInterrupt.pFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) ) {
1454: CALL_VAR(PendingInterrupt.pFunction); /* call the interrupt handler */
1.1.1.2 root 1455: }
1.1.1.4 root 1456:
1457: /* Previous: for now we poll the interrupt pins with every instruction.
1458: * TODO: only do this when an actual interrupt is active to not
1459: * unneccessarily slow down emulation.
1460: */
1461: intr = intlev ();
1.1.1.5 root 1462: if (intr>regs.intmask || (intr==7 && intr>lastintr))
1.1.1.4 root 1463: do_interrupt (intr, false);
1464: lastintr = intr;
1465:
1.1.1.5 root 1466: if(lastRegsS != regs.s) {
1467: host_realtime(!(regs.s));
1468: lastRegsS = regs.s;
1469: }
1.1.1.4 root 1470:
1.1.1.5 root 1471: if (regs.spcflags & ~SPCFLAG_INT) {
1472: if (do_specialties (cpu_cycles))
1.1.1.2 root 1473: return;
1474: }
1475: } // end of for(;;)
1476: } CATCH (prb) {
1477:
1.1.1.4 root 1478: if (mmu_restart) {
1479: /* restore state if instruction restart */
1480: regflags.cznv = f.cznv;
1481: regflags.x = f.x;
1.1.1.5 root 1482: m68k_setpci (regs.instruction_pc);
1.1.1.4 root 1483: }
1.1.1.2 root 1484:
1485: if (mmufixup[0].reg >= 0) {
1486: m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
1487: mmufixup[0].reg = -1;
1488: }
1489:
1.1.1.5 root 1490: TRY (prb2) {
1491: Exception (prb);
1492: } CATCH (prb2) {
1493: write_log("[FATAL] double fault\n");
1494: m68k_reset (1); // auto-reset CPU
1495: //cpu_halt (1);
1496: return;
1.1.1.2 root 1497: } ENDTRY
1498:
1499: } ENDTRY
1500: }
1501: }
1502:
1503: #endif /* CPUEMU_0 */
1504:
1505: int in_m68k_go = 0;
1506:
1.1.1.5 root 1507: #if 0
1.1.1.2 root 1508: static void exception2_handle (uaecptr addr, uaecptr fault)
1509: {
1510: last_addr_for_exception_3 = addr;
1511: last_fault_for_exception_3 = fault;
1512: last_writeaccess_for_exception_3 = 0;
1513: last_instructionaccess_for_exception_3 = 0;
1.1.1.4 root 1514: Exception (2);
1.1.1.2 root 1515: }
1.1.1.5 root 1516: #endif
1.1.1.2 root 1517:
1518: void m68k_go (int may_quit)
1519: {
1520: int hardboot = 1;
1521:
1522: if (in_m68k_go || !may_quit) {
1523: write_log ("Bug! m68k_go is not reentrant.\n");
1.1.1.5 root 1524: DebugUI();
1.1.1.2 root 1525: }
1.1.1.5 root 1526:
1.1.1.2 root 1527: in_m68k_go++;
1528: for (;;) {
1529: void (*run_func)(void);
1530:
1531: if (regs.spcflags & SPCFLAG_BRK) {
1532: unset_special(SPCFLAG_BRK);
1533: break;
1534: }
1535:
1536: hardboot = 0;
1537:
1538: #ifdef DEBUGGER
1539: if (debugging)
1540: debug ();
1541: #endif
1.1.1.5 root 1542:
1.1.1.2 root 1543: set_x_funcs ();
1.1.1.5 root 1544: run_func=currprefs.cpu_model == 68040 ? m68k_run_mmu040 : m68k_run_mmu030;
1.1.1.2 root 1545: run_func ();
1546: }
1547: in_m68k_go--;
1548: }
1549:
1550:
1.1.1.5 root 1551: #if 1
1552: TCHAR* buf_out (TCHAR *buffer, int *bufsize, const TCHAR *format, ...)
1.1.1.2 root 1553: {
1.1.1.5 root 1554: va_list parms;
1555:
1556: if (buffer == NULL)
1557: {
1558: return NULL;
1559: }
1560:
1561: va_start (parms, format);
1562: vsnprintf (buffer, (*bufsize) - 1, format, parms);
1563: va_end (parms);
1564: *bufsize -= _tcslen (buffer);
1565:
1566: return buffer + _tcslen (buffer);
1.1.1.2 root 1567: }
1.1.1.5 root 1568: #endif
1.1.1.2 root 1569:
1.1.1.5 root 1570: static const TCHAR *ccnames[] =
1.1.1.2 root 1571: {
1.1.1.5 root 1572: _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
1573: _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE")
1574: };
1575: static const TCHAR *fpccnames[] =
1576: {
1577: _T("F"),
1578: _T("EQ"),
1579: _T("OGT"),
1580: _T("OGE"),
1581: _T("OLT"),
1582: _T("OLE"),
1583: _T("OGL"),
1584: _T("OR"),
1585: _T("UN"),
1586: _T("UEQ"),
1587: _T("UGT"),
1588: _T("UGE"),
1589: _T("ULT"),
1590: _T("ULE"),
1591: _T("NE"),
1592: _T("T"),
1593: _T("SF"),
1594: _T("SEQ"),
1595: _T("GT"),
1596: _T("GE"),
1597: _T("LT"),
1598: _T("LE"),
1599: _T("GL"),
1600: _T("GLE"),
1601: _T("NGLE"),
1602: _T("NGL"),
1603: _T("NLE"),
1604: _T("NLT"),
1605: _T("NGE"),
1606: _T("NGT"),
1607: _T("SNE"),
1608: _T("ST")
1609: };
1610: static const TCHAR *fpuopcodes[] =
1611: {
1612: _T("FMOVE"),
1613: _T("FINT"),
1614: _T("FSINH"),
1615: _T("FINTRZ"),
1616: _T("FSQRT"),
1617: NULL,
1618: _T("FLOGNP1"),
1619: NULL,
1620: _T("FETOXM1"),
1621: _T("FTANH"),
1622: _T("FATAN"),
1623: NULL,
1624: _T("FASIN"),
1625: _T("FATANH"),
1626: _T("FSIN"),
1627: _T("FTAN"),
1628: _T("FETOX"), // 0x10
1629: _T("FTWOTOX"),
1630: _T("FTENTOX"),
1631: NULL,
1632: _T("FLOGN"),
1633: _T("FLOG10"),
1634: _T("FLOG2"),
1635: NULL,
1636: _T("FABS"),
1637: _T("FCOSH"),
1638: _T("FNEG"),
1639: NULL,
1640: _T("FACOS"),
1641: _T("FCOS"),
1642: _T("FGETEXP"),
1643: _T("FGETMAN"),
1644: _T("FDIV"), // 0x20
1645: _T("FMOD"),
1646: _T("FADD"),
1647: _T("FMUL"),
1648: _T("FSGLDIV"),
1649: _T("FREM"),
1650: _T("FSCALE"),
1651: _T("FSGLMUL"),
1652: _T("FSUB"),
1653: NULL,
1654: NULL,
1655: NULL,
1656: NULL,
1657: NULL,
1658: NULL,
1659: NULL,
1660: _T("FSINCOS"), // 0x30
1661: _T("FSINCOS"),
1662: _T("FSINCOS"),
1663: _T("FSINCOS"),
1664: _T("FSINCOS"),
1665: _T("FSINCOS"),
1666: _T("FSINCOS"),
1667: _T("FSINCOS"),
1668: _T("FCMP"),
1669: NULL,
1670: _T("FTST"),
1671: NULL,
1672: NULL,
1673: NULL,
1674: NULL,
1675: NULL
1676: };
1.1.1.2 root 1677:
1.1.1.5 root 1678: static const TCHAR *movemregs[] =
1.1.1.2 root 1679: {
1.1.1.5 root 1680: _T("D0"),
1681: _T("D1"),
1682: _T("D2"),
1683: _T("D3"),
1684: _T("D4"),
1685: _T("D5"),
1686: _T("D6"),
1687: _T("D7"),
1688: _T("A0"),
1689: _T("A1"),
1690: _T("A2"),
1691: _T("A3"),
1692: _T("A4"),
1693: _T("A5"),
1694: _T("A6"),
1695: _T("A7"),
1696: _T("FP0"),
1697: _T("FP1"),
1698: _T("FP2"),
1699: _T("FP3"),
1700: _T("FP4"),
1701: _T("FP5"),
1702: _T("FP6"),
1703: _T("FP7"),
1704: _T("FPIAR"),
1705: _T("FPSR"),
1706: _T("FPCR")
1707: };
1.1.1.2 root 1708:
1.1.1.5 root 1709: static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode)
1710: {
1711: TCHAR *p = out + _tcslen (out);
1712: if (*prevreg < 0) {
1713: *prevreg = reg;
1714: *lastreg = reg;
1715: return;
1716: }
1717: if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
1718: _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]);
1719: p = p + _tcslen (p);
1720: if (*lastreg != *prevreg) {
1721: if ((*lastreg) + 2 == reg) {
1722: _stprintf(p, _T("/%s"), movemregs[*prevreg]);
1723: } else if ((*lastreg) != (*prevreg)) {
1724: _stprintf(p, _T("-%s"), movemregs[*prevreg]);
1725: }
1726: }
1727: *lastreg = reg;
1728: *first = 0;
1729: }
1730: *prevreg = reg;
1.1.1.2 root 1731: }
1732:
1.1.1.5 root 1733: static void movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode)
1.1.1.2 root 1734: {
1.1.1.5 root 1735: unsigned int dmask, amask;
1736: int prevreg = -1, lastreg = -1, first = 1;
1737: int i;
1738:
1739: if (mode == Apdi && !fpmode) {
1740: uae_u8 dmask2;
1741: uae_u8 amask2;
1742:
1743: amask2 = mask & 0xff;
1744: dmask2 = (mask >> 8) & 0xff;
1745: dmask = 0;
1746: amask = 0;
1747: for (i = 0; i < 8; i++) {
1748: if (dmask2 & (1 << i))
1749: dmask |= 1 << (7 - i);
1750: if (amask2 & (1 << i))
1751: amask |= 1 << (7 - i);
1752: }
1753: } else {
1754: dmask = mask & 0xff;
1755: amask = (mask >> 8) & 0xff;
1756: if (fpmode == 1 && mode != Apdi) {
1757: uae_u8 dmask2 = dmask;
1758: dmask = 0;
1759: for (i = 0; i < 8; i++) {
1760: if (dmask2 & (1 << i))
1761: dmask |= 1 << (7 - i);
1762: }
1763: }
1764: }
1765: if (fpmode) {
1766: while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; }
1767: } else {
1768: while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; }
1769: while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; }
1770: }
1771: addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode);
1772: }
1.1.1.2 root 1773:
1.1.1.5 root 1774: static const TCHAR *fpsizes[] = {
1775: _T("L"),
1776: _T("S"),
1777: _T("X"),
1778: _T("P"),
1779: _T("W"),
1780: _T("D"),
1781: _T("B"),
1782: _T("P")
1783: };
1784: static const int fpsizeconv[] = {
1785: sz_long,
1786: sz_single,
1787: sz_extended,
1788: sz_packed,
1789: sz_word,
1790: sz_double,
1791: sz_byte,
1792: sz_packed
1793: };
1.1.1.2 root 1794:
1.1.1.5 root 1795: static void disasm_size (TCHAR *instrname, struct instr *dp)
1796: {
1797: if (dp->unsized) {
1798: _tcscat(instrname, _T(" "));
1799: return;
1800: }
1801: switch (dp->size)
1802: {
1803: case sz_byte:
1804: _tcscat (instrname, _T(".B "));
1805: break;
1806: case sz_word:
1807: _tcscat (instrname, _T(".W "));
1808: break;
1809: case sz_long:
1810: _tcscat (instrname, _T(".L "));
1811: break;
1812: default:
1813: _tcscat (instrname, _T(" "));
1814: break;
1815: }
1816: }
1.1.1.2 root 1817:
1.1.1.5 root 1818: void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode)
1819: {
1820: uae_u32 seaddr2;
1821: uae_u32 deaddr2;
1822:
1823: if (buf)
1824: memset (buf, 0, bufsize * sizeof (TCHAR));
1825: if (!table68k)
1826: return;
1827: while (cnt-- > 0) {
1828: TCHAR instrname[100], *ccpt;
1829: int i;
1830: uae_u32 opcode;
1831: uae_u16 extra;
1832: struct mnemolookup *lookup;
1833: struct instr *dp;
1834: uaecptr oldpc;
1835: uaecptr m68kpc_illg = 0;
1836: bool illegal = false;
1837:
1838: seaddr2 = deaddr2 = 0;
1839: oldpc = pc;
1840: opcode = get_word_debug (pc);
1841: extra = get_word_debug (pc + 2);
1842: if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) {
1843: m68kpc_illg = pc + 2;
1844: illegal = true;
1845: }
1846:
1847: dp = table68k + opcode;
1848: if (dp->mnemo == i_ILLG) {
1849: illegal = false;
1850: opcode = 0x4AFC;
1851: dp = table68k + opcode;
1852: }
1853: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
1854: ;
1855:
1856: buf = buf_out (buf, &bufsize, _T("%08X "), pc);
1857:
1858: pc += 2;
1859:
1860: if (lookup->friendlyname)
1861: _tcscpy (instrname, lookup->friendlyname);
1862: else
1863: _tcscpy (instrname, lookup->name);
1864: ccpt = _tcsstr (instrname, _T("cc"));
1865: if (ccpt != 0) {
1866: if ((opcode & 0xf000) == 0xf000)
1867: _tcscpy (ccpt, fpccnames[extra & 0x1f]);
1868: else
1869: _tcsncpy (ccpt, ccnames[dp->cc], 2);
1870: }
1871: disasm_size (instrname, dp);
1872:
1873: if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
1874: uae_u16 imm = extra;
1875: uae_u16 creg = imm & 0x0fff;
1876: uae_u16 r = imm >> 12;
1877: TCHAR regs[16];
1878: const TCHAR *cname = _T("?");
1879: int i;
1880: for (i = 0; m2cregs[i].regname; i++) {
1881: if (m2cregs[i].regno == creg)
1882: break;
1883: }
1884: _stprintf (regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
1885: if (m2cregs[i].regname)
1886: cname = m2cregs[i].regname;
1887: if (lookup->mnemo == i_MOVE2C) {
1888: _tcscat (instrname, regs);
1889: _tcscat (instrname, _T(","));
1890: _tcscat (instrname, cname);
1891: } else {
1892: _tcscat (instrname, cname);
1893: _tcscat (instrname, _T(","));
1894: _tcscat (instrname, regs);
1895: }
1896: pc += 2;
1897: } else if (lookup->mnemo == i_MVMEL) {
1898: uae_u16 mask = extra;
1899: pc += 2;
1900: pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
1901: _tcscat (instrname, _T(","));
1902: movemout (instrname, mask, dp->dmode, 0);
1903: } else if (lookup->mnemo == i_MVMLE) {
1904: uae_u16 mask = extra;
1905: pc += 2;
1906: movemout(instrname, mask, dp->dmode, 0);
1907: _tcscat(instrname, _T(","));
1908: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
1909: } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) {
1910: TCHAR *p;
1911: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
1912: extra = get_word_debug(pc);
1913: pc += 2;
1914: p = instrname + _tcslen(instrname);
1915: if (extra & 0x0400)
1916: _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7);
1917: else
1918: _stprintf(p, _T(",D%d"), (extra >> 12) & 7);
1919: } else if (lookup->mnemo == i_MOVES) {
1920: TCHAR *p;
1921: pc += 2;
1922: if (!(extra & 0x1000)) {
1923: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
1924: p = instrname + _tcslen(instrname);
1925: _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
1926: } else {
1927: p = instrname + _tcslen(instrname);
1928: _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
1929: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
1930: }
1931: } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU ||
1932: lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR ||
1933: lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS ||
1934: lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) {
1935: TCHAR *p;
1936: int reg = -1;
1937:
1938: pc += 2;
1939: p = instrname + _tcslen(instrname);
1940: if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS)
1941: reg = (extra >> 12) & 7;
1942: if (lookup->mnemo == i_BFINS)
1943: _stprintf(p, _T("D%d,"), reg);
1944: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
1945: _tcscat(instrname, _T(" {"));
1946: p = instrname + _tcslen(instrname);
1947: if (extra & 0x0800)
1948: _stprintf(p, _T("D%d"), (extra >> 6) & 7);
1949: else
1950: _stprintf(p, _T("%d"), (extra >> 6) & 31);
1951: _tcscat(instrname, _T(":"));
1952: p = instrname + _tcslen(instrname);
1953: if (extra & 0x0020)
1954: _stprintf(p, _T("D%d"), extra & 7);
1955: else
1956: _stprintf(p, _T("%d"), extra & 31);
1957: _tcscat(instrname, _T("}"));
1958: p = instrname + _tcslen(instrname);
1959: if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU)
1960: _stprintf(p, _T(",D%d"), reg);
1961: } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP ||
1962: lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
1963: if ((opcode & 0xc0) == 0xc0)
1964: _tcscat(instrname, _T("BC"));
1965: else if (opcode & 0x80)
1966: _tcscat(instrname, _T("IC"));
1967: else if (opcode & 0x40)
1968: _tcscat(instrname, _T("DC"));
1969: else
1970: _tcscat(instrname, _T("?"));
1971: if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
1972: TCHAR *p = instrname + _tcslen(instrname);
1973: _stprintf(p, _T(",(A%d)"), opcode & 7);
1974: }
1975: } else if (lookup->mnemo == i_FPP) {
1976: TCHAR *p;
1977: int ins = extra & 0x3f;
1978: int size = (extra >> 10) & 7;
1979:
1980: pc += 2;
1981: if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7)
1982: fptype fp;
1983: if (fpu_get_constant(&fp, extra & 0x3f))
1984: _stprintf(instrname, _T("FMOVECR.X #%s,FP%d"), fp_print(&fp), (extra >> 7) & 7);
1985: else
1986: _stprintf(instrname, _T("FMOVECR.X #?,FP%d"), (extra >> 7) & 7);
1987: } else if ((extra & 0x8000) == 0x8000) { // FMOVEM
1988: int dr = (extra >> 13) & 1;
1989: int mode;
1990: int dreg = (extra >> 4) & 7;
1991: int regmask, fpmode;
1992:
1993: if (extra & 0x4000) {
1994: mode = (extra >> 11) & 3;
1995: regmask = extra & 0xff; // FMOVEM FPx
1996: fpmode = 1;
1997: _tcscpy(instrname, _T("FMOVEM.X "));
1998: } else {
1999: mode = 0;
2000: regmask = (extra >> 10) & 7; // FMOVEM control
2001: fpmode = 2;
2002: _tcscpy(instrname, _T("FMOVEM.L "));
2003: if (regmask == 1 || regmask == 2 || regmask == 4)
2004: _tcscpy(instrname, _T("FMOVE.L "));
2005: }
2006: p = instrname + _tcslen(instrname);
2007: if (dr) {
2008: if (mode & 1)
2009: _stprintf(instrname, _T("D%d"), dreg);
2010: else
2011: movemout(instrname, regmask, dp->dmode, fpmode);
2012: _tcscat(instrname, _T(","));
2013: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
2014: } else {
2015: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
2016: _tcscat(instrname, _T(","));
2017: p = instrname + _tcslen(instrname);
2018: if (mode & 1)
2019: _stprintf(p, _T("D%d"), dreg);
2020: else
2021: movemout(p, regmask, dp->dmode, fpmode);
2022: }
2023: } else {
2024: if (fpuopcodes[ins])
2025: _tcscpy(instrname, fpuopcodes[ins]);
2026: else
2027: _tcscpy(instrname, _T("F?"));
2028:
2029: if ((extra & 0xe000) == 0x6000) { // FMOVE to memory
2030: int kfactor = extra & 0x7f;
2031: _tcscpy(instrname, _T("FMOVE."));
2032: _tcscat(instrname, fpsizes[size]);
2033: _tcscat(instrname, _T(" "));
2034: p = instrname + _tcslen(instrname);
2035: _stprintf(p, _T("FP%d,"), (extra >> 7) & 7);
2036: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
2037: p = instrname + _tcslen(instrname);
2038: if (size == 7) {
2039: _stprintf(p, _T(" {D%d}"), (kfactor >> 4));
2040: } else if (kfactor) {
2041: if (kfactor & 0x40)
2042: kfactor |= ~0x3f;
2043: _stprintf(p, _T(" {%d}"), kfactor);
2044: }
2045: } else {
2046: if (extra & 0x4000) { // source is EA
2047: _tcscat(instrname, _T("."));
2048: _tcscat(instrname, fpsizes[size]);
2049: _tcscat(instrname, _T(" "));
2050: pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
2051: } else { // source is FPx
2052: p = instrname + _tcslen(instrname);
2053: _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7);
2054: }
2055: p = instrname + _tcslen(instrname);
2056: if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7)))
2057: _stprintf(p, _T(",FP%d"), (extra >> 7) & 7);
2058: if (ins >= 0x30 && ins < 0x38) { // FSINCOS
2059: p = instrname + _tcslen(instrname);
2060: _stprintf(p, _T(",FP%d"), extra & 7);
2061: }
2062: }
2063: }
2064: } else if ((opcode & 0xf000) == 0xa000) {
2065: _tcscpy(instrname, _T("A-LINE"));
2066: } else {
2067: if (dp->suse) {
2068: pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
2069: }
2070: if (dp->suse && dp->duse)
2071: _tcscat (instrname, _T(","));
2072: if (dp->duse) {
2073: pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
2074: }
2075: }
2076:
2077: for (i = 0; i < (int)(pc - oldpc) / 2 && i < 5; i++) {
2078: buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2));
2079: }
2080: while (i++ < 5)
2081: buf = buf_out (buf, &bufsize, _T(" "));
2082:
2083: if (illegal)
2084: buf = buf_out (buf, &bufsize, _T("[ "));
2085: buf = buf_out (buf, &bufsize, instrname);
2086: if (illegal)
2087: buf = buf_out (buf, &bufsize, _T(" ]"));
2088:
2089: if (ccpt != 0) {
2090: uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
2091: if (deaddr)
2092: *deaddr = pc;
2093: if ((opcode & 0xf000) == 0xf000) {
2094: if (fpp_cond(dp->cc)) {
2095: buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
2096: } else {
2097: buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
2098: }
2099: } else {
2100: if (cctrue (dp->cc)) {
2101: buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), addr2);
2102: } else {
2103: buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), addr2);
2104: }
2105: }
2106: } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
2107: if (deaddr)
2108: *deaddr = pc;
2109: buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2);
2110: }
2111: buf = buf_out (buf, &bufsize, _T("\n"));
2112:
2113: if (illegal)
2114: pc = m68kpc_illg;
2115: }
2116: if (nextpc)
2117: *nextpc = pc;
2118: if (seaddr)
2119: *seaddr = seaddr2;
2120: if (deaddr)
2121: *deaddr = deaddr2;
1.1.1.2 root 2122: }
2123:
1.1.1.5 root 2124: void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr)
1.1.1.2 root 2125: {
1.1.1.5 root 2126: TCHAR *buf;
2127:
2128: buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
2129: if (!buf)
2130: return;
2131: m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, seaddr, deaddr, 1);
2132: xfree (buf);
1.1.1.2 root 2133: }
1.1.1.5 root 2134: void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt)
1.1.1.2 root 2135: {
1.1.1.5 root 2136: TCHAR *buf;
2137:
2138: buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
2139: if (!buf)
2140: return;
2141: m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0);
2142: printf (_T("%s"), buf);
2143: xfree (buf);
1.1.1.2 root 2144: }
2145:
2146: /*************************************************************
2147: Disasm the m68kcode at the given address into instrname
2148: and instrcode
2149: *************************************************************/
2150: void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc)
2151: {
1.1.1.5 root 2152: TCHAR *ccpt;
2153: uae_u32 opcode;
2154: struct mnemolookup *lookup;
2155: struct instr *dp;
2156: uaecptr pc, oldpc;
2157:
2158: pc = oldpc = addr;
2159: opcode = get_word_debug (pc);
2160: if (cpufunctbl[opcode] == op_illg_1) {
2161: opcode = 0x4AFC;
2162: }
2163: dp = table68k + opcode;
2164: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
2165:
2166: pc += 2;
2167:
2168: _tcscpy (instrname, lookup->name);
2169: ccpt = _tcsstr (instrname, _T("cc"));
2170: if (ccpt != 0) {
2171: _tcsncpy (ccpt, ccnames[dp->cc], 2);
2172: }
2173: switch (dp->size){
2174: case sz_byte: _tcscat (instrname, _T(".B ")); break;
2175: case sz_word: _tcscat (instrname, _T(".W ")); break;
2176: case sz_long: _tcscat (instrname, _T(".L ")); break;
2177: default: _tcscat (instrname, _T(" ")); break;
2178: }
2179:
2180: if (dp->suse) {
2181: pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
2182: }
2183: if (dp->suse && dp->duse)
2184: _tcscat (instrname, _T(","));
2185: if (dp->duse) {
2186: pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
2187: }
2188: if (instrcode)
2189: {
2190: int i;
2191: for (i = 0; i < (int)(pc - oldpc) / 2; i++)
2192: {
2193: _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
2194: instrcode += _tcslen (instrcode);
2195: }
2196: }
2197: if (nextpc)
2198: *nextpc = pc;
1.1.1.2 root 2199: }
2200:
2201: struct cpum2c m2cregs[] = {
2202: { 0, "SFC" },
2203: { 1, "DFC" },
2204: { 2, "CACR" },
2205: { 3, "TC" },
2206: { 4, "ITT0" },
2207: { 5, "ITT1" },
2208: { 6, "DTT0" },
2209: { 7, "DTT1" },
2210: { 8, "BUSC" },
2211: { 0x800, "USP" },
2212: { 0x801, "VBR" },
2213: { 0x802, "CAAR" },
2214: { 0x803, "MSP" },
2215: { 0x804, "ISP" },
2216: { 0x805, "MMUS" },
2217: { 0x806, "URP" },
2218: { 0x807, "SRP" },
2219: { 0x808, "PCR" },
2220: { -1, NULL }
2221: };
2222:
1.1.1.5 root 2223: void m68k_dumpstate_2 (uaecptr pc, uaecptr *nextpc)
1.1.1.2 root 2224: {
1.1.1.5 root 2225: int i, j;
2226:
2227: for (i = 0; i < 8; i++){
2228: printf (_T(" D%d %08X "), i, m68k_dreg (regs, i));
2229: if ((i & 3) == 3) printf (_T("\n"));
2230: }
2231: for (i = 0; i < 8; i++){
2232: printf (_T(" A%d %08X "), i, m68k_areg (regs, i));
2233: if ((i & 3) == 3) printf (_T("\n"));
2234: }
2235: if (regs.s == 0)
2236: regs.usp = m68k_areg (regs, 7);
2237: if (regs.s && regs.m)
2238: regs.msp = m68k_areg (regs, 7);
2239: if (regs.s && regs.m == 0)
2240: regs.isp = m68k_areg (regs, 7);
2241: j = 2;
2242: printf (_T("USP %08X ISP %08X "), regs.usp, regs.isp);
2243: for (i = 0; m2cregs[i].regno>= 0; i++) {
2244: if (!movec_illg (m2cregs[i].regno)) {
2245: if (!_tcscmp (m2cregs[i].regname, _T("USP")) || !_tcscmp (m2cregs[i].regname, _T("ISP")))
2246: continue;
2247: if (j > 0 && (j % 4) == 0)
2248: printf (_T("\n"));
2249: printf (_T("%-4s %08X "), m2cregs[i].regname, val_move2c (m2cregs[i].regno));
2250: j++;
2251: }
2252: }
2253: if (j > 0)
2254: printf (_T("\n"));
2255: printf (_T("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d STP=%d\n"),
2256: regs.t1, regs.t0, regs.s, regs.m,
2257: GET_XFLG (), GET_NFLG (), GET_ZFLG (),
2258: GET_VFLG (), GET_CFLG (),
2259: regs.intmask, regs.stopped);
1.1.1.2 root 2260: #ifdef FPUEMU
1.1.1.5 root 2261: if (currprefs.fpu_model) {
2262: uae_u32 fpsr;
2263: for (i = 0; i < 8; i++){
2264: printf (_T("FP%d: %s "), i, fp_print(®s.fp[i]));
2265: if ((i & 3) == 3)
2266: printf (_T("\n"));
2267: }
2268: fpsr = fpp_get_fpsr ();
2269: printf (_T("FPSR: %08X FPCR: %04x FPIAR: %08x N=%d Z=%d I=%d NAN=%d\n"),
2270: fpsr, regs.fpcr, regs.fpiar,
2271: (fpsr & 0x8000000) != 0,
2272: (fpsr & 0x4000000) != 0,
2273: (fpsr & 0x2000000) != 0,
2274: (fpsr & 0x1000000) != 0);
2275: }
1.1.1.2 root 2276: #endif
1.1.1.4 root 2277: if (currprefs.mmu_model == 68030) {
1.1.1.5 root 2278: printf (_T("SRP: %llX CRP: %llX\n"), srp_030, crp_030);
2279: printf (_T("TT0: %08X TT1: %08X TC: %08X\n"), tt0_030, tt1_030, tc_030);
2280: }
2281: if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) {
2282: struct instr *dp;
2283: struct mnemolookup *lookup1, *lookup2;
2284: dp = table68k + regs.irc;
2285: for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++);
2286: dp = table68k + regs.ir;
2287: for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++);
2288: printf (_T("Prefetch %04x (%s) %04x (%s) Chip latch %08X\n"), regs.irc, lookup1->name, regs.ir, lookup2->name, regs.chipset_latch_rw);
2289: }
2290:
2291: if (pc != 0xffffffff) {
2292: m68k_disasm (pc, nextpc, 1);
2293: if (nextpc)
2294: printf (_T("Next PC: %08x\n"), *nextpc);
1.1.1.4 root 2295: }
1.1.1.2 root 2296: }
1.1.1.5 root 2297: void m68k_dumpstate (uaecptr *nextpc)
1.1.1.2 root 2298: {
1.1.1.5 root 2299: m68k_dumpstate_2 (m68k_getpc (), nextpc);
1.1.1.2 root 2300: }
2301:
1.1.1.5 root 2302: static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, bool plus2)
1.1.1.2 root 2303: {
1.1.1.5 root 2304: if (currprefs.cpu_model >= 68040)
2305: addr &= ~1;
2306: if (currprefs.cpu_model >= 68020) {
2307: if (pc == 0xffffffff)
2308: last_addr_for_exception_3 = regs.instruction_pc;
2309: else
2310: last_addr_for_exception_3 = pc;
2311: } else if (pc == 0xffffffff) {
2312: last_addr_for_exception_3 = m68k_getpc ();
2313: if (plus2)
2314: last_addr_for_exception_3 += 2;
2315: } else {
2316: last_addr_for_exception_3 = pc;
2317: }
2318: last_fault_for_exception_3 = addr;
2319: last_op_for_exception_3 = opcode;
2320: last_writeaccess_for_exception_3 = writeaccess;
2321: last_instructionaccess_for_exception_3 = instructionaccess;
2322: Exception (3);
1.1.1.2 root 2323: }
2324:
1.1.1.5 root 2325: void exception3_read(uae_u32 opcode, uaecptr addr)
1.1.1.4 root 2326: {
1.1.1.5 root 2327: exception3f (opcode, addr, false, 0, false, 0xffffffff, false);
1.1.1.4 root 2328: }
2329: void exception3i (uae_u32 opcode, uaecptr addr)
1.1.1.2 root 2330: {
1.1.1.5 root 2331: exception3f (opcode, addr, 0, 1, false, 0xffffffff, true);
1.1.1.4 root 2332: }
2333: void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
2334: {
1.1.1.5 root 2335: exception3f (opcode, addr, w, i, false, pc, true);
1.1.1.2 root 2336: }
2337:
1.1.1.4 root 2338: void exception2 (uaecptr addr, bool read, int size, uae_u32 fc)
1.1.1.2 root 2339: {
1.1.1.5 root 2340: if (currprefs.mmu_model == 68030) {
2341: uae_u32 flags = size == 1 ? MMU030_SSW_SIZE_B : (size == 2 ? MMU030_SSW_SIZE_W : MMU030_SSW_SIZE_L);
2342: mmu030_page_fault (addr, read, flags, fc);
2343: } else {
2344: mmu_bus_error (addr, 0, fc, read == false, size, true);
2345: }
1.1.1.2 root 2346: }
2347:
1.1.1.5 root 2348: void cpureset (void) {
1.1.1.2 root 2349: uaecptr pc;
2350: uaecptr ksboot = 0xf80002 - 2; /* -2 = RESET hasn't increased PC yet */
2351: uae_u16 ins;
2352:
1.1.1.5 root 2353: if (currprefs.cpu_compatible) {
1.1.1.2 root 2354: return;
2355: }
1.1.1.5 root 2356:
1.1.1.2 root 2357: pc = m68k_getpc ();
2358: /* panic, RAM is going to disappear under PC */
2359: ins = get_word (pc + 2);
2360: if ((ins & ~7) == 0x4ed0) {
2361: int reg = ins & 7;
2362: uae_u32 addr = m68k_areg (regs, reg);
2363: write_log ("reset/jmp (ax) combination emulated -> %x\n", addr);
2364: if (addr < 0x80000)
2365: addr += 0xf80000;
2366: m68k_setpc (addr - 2);
2367: return;
2368: }
2369: write_log ("M68K RESET PC=%x, rebooting..\n", pc);
2370: m68k_setpc (ksboot);
2371: }
2372:
2373:
2374: void m68k_setstopped (void)
2375: {
2376: regs.stopped = 1;
2377: /* A traced STOP instruction drops through immediately without
2378: actually stopping. */
2379: if ((regs.spcflags & SPCFLAG_DOTRACE) == 0)
2380: set_special (SPCFLAG_STOP);
2381: else
2382: m68k_resumestopped ();
2383: }
2384:
2385: void m68k_resumestopped (void)
2386: {
2387: if (!regs.stopped)
2388: return;
2389: regs.stopped = 0;
2390: unset_special (SPCFLAG_STOP);
2391: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.