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