|
|
1.1.1.3 root 1: /*
1.1 root 2: * UAE - The Un*x Amiga Emulator
1.1.1.3 root 3: *
1.1 root 4: * Debugger
1.1.1.3 root 5: *
1.1 root 6: * (c) 1995 Bernd Schmidt
1.1.1.3 root 7: *
1.1 root 8: */
9:
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12:
13: #include <ctype.h>
14: #include <signal.h>
15:
16: #include "config.h"
17: #include "options.h"
1.1.1.10 root 18: #include "threaddep/thread.h"
1.1.1.3 root 19: #include "uae.h"
1.1 root 20: #include "memory.h"
21: #include "custom.h"
22: #include "newcpu.h"
1.1.1.11! root 23: #include "cpu_prefetch.h"
1.1 root 24: #include "debug.h"
25: #include "cia.h"
26: #include "xwin.h"
27: #include "gui.h"
1.1.1.9 root 28: #include "identify.h"
1.1.1.11! root 29: #include "disk.h"
! 30: #include "autoconf.h"
1.1 root 31:
1.1.1.11! root 32: #define console_out printf
! 33: #define console_flush() fflush (stdout)
! 34: #define console_get(BUF, COUNT) fgets (BUF, COUNT, stdin)
! 35:
! 36: static int debugger_active;
! 37: static uaecptr skipaddr_start, skipaddr_end;
! 38: static int skipaddr_doskip;
! 39: static uae_u32 skipins;
1.1 root 40: static int do_skip;
1.1.1.11! root 41: static int debug_rewind;
! 42: static int memwatch_enabled, memwatch_triggered;
! 43: int debugging;
! 44: int exception_debugging;
1.1 root 45:
1.1.1.7 root 46: static FILE *logfile;
47:
1.1.1.4 root 48: void activate_debugger (void)
1.1 root 49: {
1.1.1.7 root 50: if (logfile)
51: fclose (logfile);
52: logfile = 0;
1.1 root 53: do_skip = 0;
54: if (debugger_active)
55: return;
56: debugger_active = 1;
1.1.1.8 root 57: set_special (SPCFLAG_BRK);
1.1 root 58: debugging = 1;
59: }
60:
61: int firsthist = 0;
62: int lasthist = 0;
63: #ifdef NEED_TO_DEBUG_BADLY
64: struct regstruct history[MAX_HIST];
65: union flagu historyf[MAX_HIST];
66: #else
1.1.1.3 root 67: uaecptr history[MAX_HIST];
1.1 root 68: #endif
69:
1.1.1.11! root 70: static char help[] = {
! 71: " HELP for UAE Debugger\n"
! 72: " -----------------------\n\n"
! 73: " g [<address>] Start execution at the current address or <address>\n"
! 74: " c Dump state of the CIA, disk drives and custom registers\n"
! 75: " r Dump state of the CPU\n"
! 76: " m <address> [<lines>] Memory dump starting at <address>\n"
! 77: " d <address> [<lines>] Disassembly starting at <address>\n"
! 78: " t [instructions] Step one or more instructions\n"
! 79: " z Step through one instruction - useful for JSR, DBRA etc\n"
! 80: " f Step forward until PC in RAM\n"
! 81: " f <address> Add/remove breakpoint\n"
! 82: " fi Step forward until PC points to RTS/RTD or RTE\n"
! 83: " fi <opcode> Step forward until PC points to <opcode>\n"
! 84: " fl List breakpoints\n"
! 85: " fd Remove all breakpoints\n"
! 86: " f <addr1> <addr2> Step forward until <addr1> <= PC <= <addr2>\n"
! 87: " e Dump contents of all custom registers\n"
! 88: " i Dump contents of interrupt and trap vectors\n"
! 89: " o <1|2|addr> [<lines>]View memory as Copper instructions\n"
! 90: " O Display bitplane offsets\n"
! 91: " O <plane> <offset> Offset a bitplane\n"
! 92: " H <count> Show PC history <count> instructions\n"
! 93: " M Search for *Tracker sound modules\n"
! 94: " C <value> Search for values like energy or lifes in games\n"
! 95: " W <address> <value> Write into Amiga memory\n"
! 96: " w <num> <address> <length> <R/W/RW> [<value>]\n"
! 97: " Add/remove memory watchpoints\n"
! 98: " wd Enable illegal access logger\n"
! 99: " S <file> <addr> <n> Save a block of Amiga memory\n"
! 100: " s <string>/<values> [<addr>] [<length>]\n"
! 101: " Search for string/bytes\n"
! 102: " T Show exec tasks and their PCs\n"
! 103: " h,? Show this help page\n"
! 104: " q Quit the emulator. You don't want to use this command.\n\n"
! 105: };
! 106:
! 107: static void debug_help (void)
! 108: {
! 109: console_out (help);
! 110: }
! 111:
! 112:
! 113:
1.1.1.4 root 114: static void ignore_ws (char **c)
1.1 root 115: {
116: while (**c && isspace(**c)) (*c)++;
117: }
118:
1.1.1.11! root 119: static uae_u32 readint (char **c);
1.1.1.4 root 120: static uae_u32 readhex (char **c)
1.1 root 121: {
1.1.1.3 root 122: uae_u32 val = 0;
1.1 root 123: char nc;
124:
1.1.1.4 root 125: ignore_ws (c);
1.1.1.11! root 126: if (**c == '!' || **c == '_') {
! 127: (*c)++;
! 128: return readint (c);
! 129: }
1.1.1.4 root 130: while (isxdigit(nc = **c)) {
1.1 root 131: (*c)++;
132: val *= 16;
133: nc = toupper(nc);
134: if (isdigit(nc)) {
135: val += nc - '0';
136: } else {
137: val += nc - 'A' + 10;
138: }
139: }
140: return val;
141: }
142:
1.1.1.9 root 143: static uae_u32 readint (char **c)
144: {
145: uae_u32 val = 0;
146: char nc;
147: int negative = 0;
148:
149: ignore_ws (c);
1.1.1.11! root 150: if (**c == '$') {
! 151: (*c)++;
! 152: return readhex (c);
! 153: }
! 154: if (**c == '0' && toupper((*c)[1]) == 'X') {
! 155: (*c)+= 2;
! 156: return readhex (c);
! 157: }
1.1.1.9 root 158: if (**c == '-')
159: negative = 1, (*c)++;
160: while (isdigit(nc = **c)) {
161: (*c)++;
162: val *= 10;
163: val += nc - '0';
164: }
165: return val * (negative ? -1 : 1);
166: }
167:
1.1.1.4 root 168: static char next_char( char **c)
1.1 root 169: {
1.1.1.4 root 170: ignore_ws (c);
1.1 root 171: return *(*c)++;
172: }
173:
1.1.1.4 root 174: static int more_params (char **c)
1.1 root 175: {
1.1.1.4 root 176: ignore_ws (c);
1.1 root 177: return (**c) != 0;
178: }
179:
1.1.1.11! root 180: static uae_u32 nextaddr (uae_u32 addr)
! 181: {
! 182: if (addr == 0xffffffff) {
! 183: if (currprefs.bogomem_size)
! 184: return 0xc00000 + currprefs.bogomem_size;
! 185: if (currprefs.fastmem_size)
! 186: return 0x200000 + currprefs.fastmem_size;
! 187: return currprefs.chipmem_size;
! 188: }
! 189: if (addr == currprefs.chipmem_size) {
! 190: if (currprefs.fastmem_size)
! 191: return 0x200000;
! 192: else if (currprefs.bogomem_size)
! 193: return 0xc00000;
! 194: return 0xffffffff;
! 195: }
! 196: if (addr == 0x200000 + currprefs.fastmem_size) {
! 197: if (currprefs.bogomem_size)
! 198: return 0xc00000;
! 199: return 0xffffffff;
! 200: }
! 201: if (addr == 0xc00000 + currprefs.bogomem_size)
! 202: return 0xffffffff;
! 203: return addr + 1;
! 204: }
! 205:
1.1.1.4 root 206: static void dumpmem (uaecptr addr, uaecptr *nxmem, int lines)
1.1 root 207: {
1.1.1.11! root 208: char line[80];
! 209: int cols = 8;
! 210: for (;lines--;) {
1.1 root 211: int i;
1.1.1.11! root 212: sprintf (line, "%08lx ", addr);
! 213: for (i = 0; i < cols; i++) {
! 214: uae_u8 b1 = get_byte (addr + 0);
! 215: uae_u8 b2 = get_byte (addr + 1);
! 216: addr += 2;
! 217: sprintf (line + 9 + i * 5, "%02x%02x ", b1, b2);
! 218: line[9 + cols * 5 + 1 + i * 2 + 0] = b1 >= 32 && b1 < 127 ? b1 : '.';
! 219: line[9 + cols * 5 + 1 + i * 2 + 1] = b2 >= 32 && b2 < 127 ? b2 : '.';
! 220: }
! 221: line[9 + cols * 5] = ' ';
! 222: line[9 + cols * 5 + 1 + 2 * cols] = 0;
! 223: console_out (line);
! 224: console_out ("\n");
1.1 root 225: }
226: *nxmem = addr;
227: }
228:
1.1.1.3 root 229: static void foundmod (uae_u32 ptr, char *type)
1.1.1.2 root 230: {
1.1.1.3 root 231: char name[21];
232: uae_u8 *ptr2 = chipmemory + ptr;
233: int i,length;
234:
1.1.1.11! root 235: console_out ("Found possible %s module at 0x%lx.\n", type, ptr);
1.1.1.3 root 236: memcpy (name, ptr2, 20);
237: name[20] = '\0';
238:
239: /* Browse playlist */
240: length = 0;
241: for (i = 0x3b8; i < 0x438; i++)
242: if (ptr2[i] > length)
243: length = ptr2[i];
244:
245: length = (length+1)*1024 + 0x43c;
246:
247: /* Add sample lengths */
248: ptr2 += 0x2A;
1.1.1.4 root 249: for (i = 0; i < 31; i++, ptr2 += 30)
1.1.1.3 root 250: length += 2*((ptr2[0]<<8)+ptr2[1]);
1.1.1.2 root 251:
1.1.1.11! root 252: console_out ("Name \"%s\", Length 0x%lx bytes.\n", name, length);
1.1.1.3 root 253: }
254:
1.1.1.4 root 255: static void modulesearch (void)
1.1.1.3 root 256: {
257: uae_u8 *p = get_real_address (0);
258: uae_u32 ptr;
259:
1.1.1.4 root 260: for (ptr = 0; ptr < allocated_chipmem - 40; ptr += 2, p += 2) {
1.1.1.2 root 261: /* Check for Mahoney & Kaktus */
262: /* Anyone got the format of old 15 Sample (SoundTracker)modules? */
1.1.1.3 root 263: if (ptr >= 0x438 && p[0] == 'M' && p[1] == '.' && p[2] == 'K' && p[3] == '.')
264: foundmod (ptr - 0x438, "ProTracker (31 samples)");
265:
266: if (ptr >= 0x438 && p[0] == 'F' && p[1] == 'L' && p[2] == 'T' && p[3] == '4')
267: foundmod (ptr - 0x438, "Startrekker");
268:
269: if (strncmp ((char *)p, "SMOD", 4) == 0) {
1.1.1.11! root 270: console_out ("Found possible FutureComposer 1.3 module at 0x%lx, length unknown.\n", ptr);
1.1.1.3 root 271: }
272: if (strncmp ((char *)p, "FC14", 4) == 0) {
1.1.1.11! root 273: console_out ("Found possible FutureComposer 1.4 module at 0x%lx, length unknown.\n", ptr);
1.1.1.3 root 274: }
275: if (p[0] == 0x48 && p[1] == 0xe7 && p[4] == 0x61 && p[5] == 0
276: && p[8] == 0x4c && p[9] == 0xdf && p[12] == 0x4e && p[13] == 0x75
277: && p[14] == 0x48 && p[15] == 0xe7 && p[18] == 0x61 && p[19] == 0
278: && p[22] == 0x4c && p[23] == 0xdf && p[26] == 0x4e && p[27] == 0x75) {
1.1.1.11! root 279: console_out ("Found possible Whittaker module at 0x%lx, length unknown.\n", ptr);
1.1.1.3 root 280: }
281: if (p[4] == 0x41 && p[5] == 0xFA) {
282: int i;
283:
284: for (i = 0; i < 0x240; i += 2)
285: if (p[i] == 0xE7 && p[i + 1] == 0x42 && p[i + 2] == 0x41 && p[i + 3] == 0xFA)
286: break;
287: if (i < 0x240) {
288: uae_u8 *p2 = p + i + 4;
289: for (i = 0; i < 0x30; i += 2)
290: if (p2[i] == 0xD1 && p2[i + 1] == 0xFA) {
1.1.1.11! root 291: console_out ("Found possible MarkII module at %lx, length unknown.\n", ptr);
1.1.1.3 root 292: }
293: }
1.1.1.2 root 294: }
295: }
296: }
297:
1.1.1.11! root 298: static void dump_vectors (void)
1.1.1.9 root 299: {
1.1.1.11! root 300: int i = 0, j = 0;
1.1.1.9 root 301:
1.1.1.11! root 302: while (int_labels[i].name || trap_labels[j].name) {
! 303: if (int_labels[i].name) {
! 304: console_out ("$%08X: %s \t $%08X\t", int_labels[i].adr + regs.vbr,
! 305: int_labels[i].name, get_long (int_labels[i].adr + (int_labels[i].adr == 4 ? 0 : regs.vbr)));
! 306: i++;
! 307: } else {
! 308: console_out ("\t\t\t\t");
! 309: }
! 310: if (trap_labels[j].name) {
! 311: console_out("$%08X: %s \t $%08X", trap_labels[j].adr + regs.vbr,
! 312: trap_labels[j].name, get_long (trap_labels[j].adr + regs.vbr));
! 313: j++;
! 314: }
! 315: console_out ("\n");
1.1.1.9 root 316: }
317: }
318:
319: static void disassemble_wait (FILE *file, unsigned long insn)
320: {
1.1.1.11! root 321: int vp, hp, ve, he, bfd, v_mask, h_mask;
1.1.1.9 root 322:
323: vp = (insn & 0xff000000) >> 24;
324: hp = (insn & 0x00fe0000) >> 16;
325: ve = (insn & 0x00007f00) >> 8;
326: he = (insn & 0x000000fe);
1.1.1.11! root 327: bfd = (insn & 0x00008000) >> 15;
1.1.1.9 root 328:
329: /* bit15 can never be masked out*/
330: v_mask = vp & (ve | 0x80);
331: h_mask = hp & he;
332: if (v_mask > 0) {
1.1.1.11! root 333: console_out ("vpos ");
1.1.1.9 root 334: if (ve != 0x7f) {
1.1.1.11! root 335: console_out ("& 0x%02x ", ve);
1.1.1.9 root 336: }
1.1.1.11! root 337: console_out (">= 0x%02x", v_mask);
1.1.1.9 root 338: }
339: if (he > 0) {
340: if (v_mask > 0) {
1.1.1.11! root 341: console_out (" and");
1.1.1.9 root 342: }
1.1.1.11! root 343: console_out (" hpos ");
1.1.1.9 root 344: if (he != 0xfe) {
1.1.1.11! root 345: console_out ("& 0x%02x ", he);
1.1.1.9 root 346: }
1.1.1.11! root 347: console_out (">= 0x%02x", h_mask);
1.1.1.9 root 348: } else {
1.1.1.11! root 349: console_out (", ignore horizontal");
1.1.1.9 root 350: }
351:
1.1.1.11! root 352: console_out (".\n \t; VP %02x, VE %02x; HP %02x, HE %02x; BFD %d\n",
1.1.1.9 root 353: vp, ve, hp, he, bfd);
354: }
355:
356: /* simple decode copper by Mark Cox */
357: static void decode_copper_insn (FILE* file, unsigned long insn, unsigned long addr)
358: {
359: uae_u32 insn_type = insn & 0x00010001;
360: int hpos, vpos;
361: char record[] = " ";
362: if (find_copper_record (addr, &hpos, &vpos)) {
363: sprintf (record, " [%03x %03x]", vpos, hpos);
364: }
365:
1.1.1.11! root 366: console_out ("%08lx: %04lx %04lx%s\t; ", addr, insn >> 16, insn & 0xFFFF, record);
1.1.1.9 root 367:
368: switch (insn_type) {
369: case 0x00010000: /* WAIT insn */
1.1.1.11! root 370: console_out ("Wait for ");
1.1.1.9 root 371: disassemble_wait (file, insn);
372:
373: if (insn == 0xfffffffe)
1.1.1.11! root 374: console_out (" \t; End of Copperlist\n");
1.1.1.9 root 375:
376: break;
377:
378: case 0x00010001: /* SKIP insn */
1.1.1.11! root 379: console_out ("Skip if ");
1.1.1.9 root 380: disassemble_wait (file, insn);
381: break;
382:
383: case 0x00000000:
384: case 0x00000001: /* MOVE insn */
1.1.1.11! root 385: {
! 386: int addr = (insn >> 16) & 0x1fe;
! 387: int i = 0;
! 388: while (custd[i].name) {
! 389: if (custd[i].adr == addr + 0xdff000)
! 390: break;
! 391: i++;
! 392: }
! 393: if (custd[i].name)
! 394: console_out ("%s := 0x%04lx\n", custd[i].name, insn & 0xffff);
! 395: else
! 396: console_out ("%04x := 0x%04lx\n", addr, insn & 0xffff);
! 397: }
1.1.1.9 root 398: break;
399:
400: default:
401: abort ();
402: }
403:
404: }
405:
406:
407: static uaecptr decode_copperlist (FILE* file, uaecptr address, int nolines)
408: {
409: uae_u32 insn;
410: while (nolines-- > 0) {
411: insn = get_long (address);
412: decode_copper_insn (file, insn, address);
413: address += 4;
414: }
415: return address;
416: /* You may wonder why I don't stop this at the end of the copperlist?
417: * Well, often nice things are hidden at the end and it is debatable the actual
418: * values that mean the end of the copperlist */
419: }
420:
421:
1.1.1.4 root 422: /* cheat-search by Holger Jakob */
423: static void cheatsearch (char **c)
424: {
425: uae_u8 *p = get_real_address (0);
426: static uae_u32 *vlist = NULL;
427: uae_u32 ptr;
428: uae_u32 val = 0;
429: uae_u32 type = 0; /* not yet */
430: uae_u32 count = 0;
431: uae_u32 fcount = 0;
432: uae_u32 full = 0;
433:
434: ignore_ws (c);
1.1.1.11! root 435: val = readhex (c);
1.1.1.4 root 436: if (vlist == NULL) {
437: vlist = malloc (256*4);
438: if (vlist != 0) {
439: for (count = 0; count<255; count++)
440: vlist[count] = 0;
441: count = 0;
442: for (ptr = 0; ptr < allocated_chipmem - 40; ptr += 2, p += 2) {
443: if (ptr >= 0x438 && p[3] == (val & 0xff)
444: && p[2] == (val >> 8 & 0xff)
445: && p[1] == (val >> 16 & 0xff)
446: && p[0] == (val >> 24 & 0xff))
447: {
448: if (count < 255) {
449: vlist[count++]=ptr;
1.1.1.11! root 450: console_out ("%08x: %x%x%x%x\n",ptr,p[0],p[1],p[2],p[3]);
1.1.1.4 root 451: } else
452: full = 1;
453: }
454: }
1.1.1.11! root 455: console_out ("Found %d possible addresses with %d\n",count,val);
! 456: console_out ("Now continue with 'g' and use 'C' with a different value\n");
1.1.1.4 root 457: }
458: } else {
459: for (count = 0; count<255; count++) {
460: if (p[vlist[count]+3] == (val & 0xff)
461: && p[vlist[count]+2] == (val>>8 & 0xff)
462: && p[vlist[count]+1] == (val>>16 & 0xff)
463: && p[vlist[count]] == (val>>24 & 0xff))
464: {
465: fcount++;
1.1.1.11! root 466: console_out ("%08x: %x%x%x%x\n", vlist[count], p[vlist[count]],
1.1.1.4 root 467: p[vlist[count]+1], p[vlist[count]+2], p[vlist[count]+3]);
468: }
469: }
1.1.1.11! root 470: console_out ("%d hits of %d found\n",fcount,val);
1.1.1.4 root 471: free (vlist);
472: vlist = NULL;
473: }
474: }
475:
1.1.1.11! root 476: #define BREAKPOINT_TOTAL 8
! 477: struct breakpoint_node {
! 478: uaecptr addr;
! 479: int enabled;
! 480: };
! 481: static struct breakpoint_node bpnodes[BREAKPOINT_TOTAL];
! 482:
! 483: static addrbank **debug_mem_banks;
! 484: #define MEMWATCH_TOTAL 4
! 485: struct memwatch_node {
! 486: uaecptr addr;
! 487: int size;
! 488: int rw;
! 489: uae_u32 val;
! 490: int val_enabled;
! 491: uae_u32 modval;
! 492: int modval_written;
! 493: };
! 494: static struct memwatch_node mwnodes[MEMWATCH_TOTAL];
! 495: static struct memwatch_node mwhit;
! 496:
! 497: static uae_u8 *illgdebug;
! 498: static int illgdebug_break;
! 499: extern int cdtv_enabled, cd32_enabled;
! 500:
! 501: static void illg_init (void)
1.1.1.4 root 502: {
1.1.1.11! root 503: int i;
! 504:
! 505: free (illgdebug);
! 506: illgdebug = xmalloc (0x1000000);
! 507: if (!illgdebug)
! 508: return;
! 509: memset (illgdebug, 3, 0x1000000);
! 510: memset (illgdebug, 0, currprefs.chipmem_size);
! 511: memset (illgdebug + 0xc00000, 0, currprefs.bogomem_size);
! 512: memset (illgdebug + 0x200000, 0, currprefs.fastmem_size);
! 513: i = 0;
! 514: while (custd[i].name) {
! 515: int rw = custd[i].rw;
! 516: illgdebug[custd[i].adr] = rw;
! 517: illgdebug[custd[i].adr + 1] = rw;
! 518: i++;
! 519: }
! 520: for (i = 0; i < 16; i++) { /* CIAs */
! 521: if (i == 11)
! 522: continue;
! 523: illgdebug[0xbfe001 + i * 0x100] = 0;
! 524: illgdebug[0xbfd000 + i * 0x100] = 0;
! 525: }
! 526: memset (illgdebug + 0xf80000, 1, 512 * 1024); /* KS ROM */
! 527: memset (illgdebug + 0xdc0000, 0, 0x3f); /* clock */
! 528: if (cloanto_rom)
! 529: memset (illgdebug + 0xe00000, 1, 512 * 1024);
! 530: #ifdef FILESYS
! 531: if (nr_units (currprefs.mountinfo) > 0) /* filesys "rom" */
! 532: memset (illgdebug + RTAREA_BASE, 1, 0x10000);
! 533: #endif
! 534: }
! 535:
! 536: /* add special custom register check here */
! 537: static void illg_debug_check (uaecptr addr, int rw, int size, uae_u32 val)
! 538: {
! 539: return;
! 540: }
! 541:
! 542: static void illg_debug_do (uaecptr addr, int rw, int size, uae_u32 val)
! 543: {
! 544: uae_u8 mask;
! 545: uae_u32 pc = m68k_getpc ();
! 546: char rws = rw ? 'W' : 'R';
! 547: int i;
! 548:
! 549: for (i = size - 1; i >= 0; i--) {
! 550: uae_u8 v = val >> (i * 8);
! 551: uae_u32 ad = addr + i;
! 552: if (ad >= 0x1000000)
! 553: mask = 3;
! 554: else
! 555: mask = illgdebug[ad];
! 556: if (!mask)
! 557: continue;
! 558: if (mask & 0x80) {
! 559: illg_debug_check (ad, rw, size, val);
! 560: } else if ((mask & 3) == 3) {
! 561: if (rw)
! 562: write_log ("RW: %08.8X=%02.2X %c PC=%08.8X\n", ad, v, rws, pc);
! 563: else
! 564: write_log ("RW: %08.8X %c PC=%08.8X\n", ad, rws, pc);
! 565: if (illgdebug_break)
! 566: activate_debugger ();
! 567: } else if ((mask & 1) && rw) {
! 568: write_log ("RO: %08.8X=%02.2X %c PC=%08.8X\n", ad, v, rws, pc);
! 569: if (illgdebug_break)
! 570: activate_debugger ();
! 571: } else if ((mask & 2) && !rw) {
! 572: write_log ("WO: %08.8X %c PC=%08.8X\n", ad, rws, pc);
! 573: if (illgdebug_break)
! 574: activate_debugger ();
! 575: }
! 576: }
! 577: }
! 578:
! 579: static int debug_mem_off (uaecptr addr)
! 580: {
! 581: return (munge24 (addr) >> 16) & 0xff;
! 582: }
! 583:
! 584: static void memwatch_func (uaecptr addr, int rw, int size, uae_u32 val)
! 585: {
! 586: int i, brk;
! 587:
! 588: if (illgdebug)
! 589: illg_debug_do (addr, rw, size, val);
! 590: addr = munge24 (addr);
! 591: for (i = 0; i < MEMWATCH_TOTAL; i++) {
! 592: uaecptr addr2 = mwnodes[i].addr;
! 593: uaecptr addr3 = addr2 + mwnodes[i].size;
! 594: int rw2 = mwnodes[i].rw;
! 595:
! 596: brk = 0;
! 597: if (mwnodes[i].size == 0)
! 598: continue;
! 599: if (mwnodes[i].val_enabled && mwnodes[i].val != val)
! 600: continue;
! 601: if (rw != rw2 && rw2 < 2)
! 602: continue;
! 603: if (addr >= addr2 && addr < addr3)
! 604: brk = 1;
! 605: if (!brk && size == 2 && (addr + 1 >= addr2 && addr + 1 < addr3))
! 606: brk = 1;
! 607: if (!brk && size == 4 && ((addr + 2 >= addr2 && addr + 2 < addr3) || (addr + 3 >= addr2 && addr + 3 < addr3)))
! 608: brk = 1;
! 609: if (brk && mwnodes[i].modval_written) {
! 610: if (!rw) {
! 611: brk = 0;
! 612: } else if (mwnodes[i].modval_written == 1) {
! 613: mwnodes[i].modval_written = 2;
! 614: mwnodes[i].modval = val;
! 615: brk = 0;
! 616: } else if (mwnodes[i].modval == val) {
! 617: brk = 0;
! 618: }
! 619: }
! 620: if (brk) {
! 621: mwhit.addr = addr;
! 622: mwhit.rw = rw;
! 623: mwhit.size = size;
! 624: mwhit.val = 0;
! 625: if (mwhit.rw)
! 626: mwhit.val = val;
! 627: memwatch_triggered = i + 1;
! 628: debugging = 1;
! 629: set_special (SPCFLAG_BRK);
! 630: break;
! 631: }
! 632: }
! 633: }
! 634:
! 635: static uae_u32 REGPARAM2 debug_lget (uaecptr addr)
! 636: {
! 637: int off = debug_mem_off (addr);
! 638: uae_u32 v;
! 639: v = debug_mem_banks[off]->lget(addr);
! 640: memwatch_func (addr, 0, 4, v);
! 641: return v;
! 642: }
! 643: static uae_u32 REGPARAM2 debug_wget (uaecptr addr)
! 644: {
! 645: int off = debug_mem_off (addr);
! 646: uae_u32 v;
! 647: v = debug_mem_banks[off]->wget(addr);
! 648: memwatch_func (addr, 0, 2, v);
! 649: return v;
! 650: }
! 651: static uae_u32 REGPARAM2 debug_bget (uaecptr addr)
! 652: {
! 653: int off = debug_mem_off (addr);
! 654: uae_u32 v;
! 655: v = debug_mem_banks[off]->bget(addr);
! 656: memwatch_func (addr, 0, 1, v);
! 657: return v;
! 658: }
! 659: static void REGPARAM2 debug_lput (uaecptr addr, uae_u32 v)
! 660: {
! 661: int off = debug_mem_off (addr);
! 662: memwatch_func (addr, 1, 4, v);
! 663: debug_mem_banks[off]->lput(addr, v);
! 664: }
! 665: static void REGPARAM2 debug_wput (uaecptr addr, uae_u32 v)
! 666: {
! 667: int off = debug_mem_off (addr);
! 668: memwatch_func (addr, 1, 2, v);
! 669: debug_mem_banks[off]->wput(addr, v);
! 670: }
! 671: static void REGPARAM2 debug_bput (uaecptr addr, uae_u32 v)
! 672: {
! 673: int off = debug_mem_off (addr);
! 674: memwatch_func (addr, 1, 1, v);
! 675: debug_mem_banks[off]->bput(addr, v);
! 676: }
! 677: static int REGPARAM2 debug_check (uaecptr addr, uae_u32 size)
! 678: {
! 679: return debug_mem_banks[munge24 (addr) >> 16]->check (addr, size);
! 680: }
! 681: static uae_u8 *REGPARAM2 debug_xlate (uaecptr addr)
! 682: {
! 683: return debug_mem_banks[munge24 (addr) >> 16]->xlateaddr (addr);
! 684: }
! 685:
! 686: static void deinitialize_memwatch (void)
! 687: {
! 688: int i;
! 689: addrbank *a1, *a2;
! 690:
! 691: if (!memwatch_enabled)
! 692: return;
! 693: for (i = 0; i < 256; i++) {
! 694: a1 = debug_mem_banks[i];
! 695: a2 = mem_banks[i];
! 696: memcpy (a2, a1, sizeof (addrbank));
! 697: free (a1);
! 698: }
! 699: free (debug_mem_banks);
! 700: debug_mem_banks = 0;
! 701: memwatch_enabled = 0;
! 702: free (illgdebug);
! 703: illgdebug = 0;
! 704: }
! 705:
! 706: static int initialize_memwatch (void)
! 707: {
! 708: int i;
! 709: addrbank *a1, *a2;
! 710:
! 711: if (!currprefs.address_space_24)
! 712: return 0;
! 713: debug_mem_banks = xmalloc (sizeof (addrbank*) * 256);
! 714: for (i = 0; i < 256; i++) {
! 715: a1 = debug_mem_banks[i] = xmalloc (sizeof (addrbank));
! 716: a2 = mem_banks[i];
! 717: memcpy (a1, a2, sizeof (addrbank));
! 718: }
! 719: for (i = 0; i < 256; i++) {
! 720: a2 = mem_banks[i];
! 721: a2->bget = debug_bget;
! 722: a2->wget = debug_wget;
! 723: a2->lget = debug_lget;
! 724: a2->bput = debug_bput;
! 725: a2->wput = debug_wput;
! 726: a2->lput = debug_lput;
! 727: a2->check = debug_check;
! 728: a2->xlateaddr = debug_xlate;
! 729: }
! 730: memwatch_enabled = 1;
! 731: return 1;
! 732: }
! 733:
! 734: static void memwatch_dump (int num)
! 735: {
! 736: int i;
! 737: struct memwatch_node *mwn;
! 738: for (i = 0; i < MEMWATCH_TOTAL; i++) {
! 739: if ((num >= 0 && num == i) || (num < 0)) {
! 740: mwn = &mwnodes[i];
! 741: if (mwn->size == 0)
! 742: continue;
! 743: console_out ("%d: %08.8X - %08.8X (%d) %s",
! 744: i, mwn->addr, mwn->addr + (mwn->size - 1), mwn->size,
! 745: mwn->rw == 0 ? "R" : (mwn->rw == 1 ? "W" : "RW"));
! 746: if (mwn->val_enabled)
! 747: console_out (" =%X", mwn->val);
! 748: if (mwn->modval_written)
! 749: console_out (" =M");
! 750: console_out("\n");
! 751: }
! 752: }
! 753: }
! 754:
! 755: static void memwatch (char **c)
! 756: {
! 757: int num;
! 758: struct memwatch_node *mwn;
1.1.1.4 root 759: char nc;
760:
1.1.1.11! root 761: if (!memwatch_enabled) {
! 762: if (!initialize_memwatch ()) {
! 763: console_out ("Memwatch breakpoints require 24-bit address space\n");
! 764: return;
! 765: }
! 766: console_out ("Memwatch breakpoints enabled\n");
! 767: }
! 768:
! 769: ignore_ws (c);
! 770: if (!more_params (c)) {
! 771: memwatch_dump (-1);
! 772: return;
! 773: }
! 774: nc = next_char (c);
! 775: if (nc == '-') {
! 776: deinitialize_memwatch ();
! 777: console_out ("Memwatch breakpoints disabled\n");
! 778: return;
! 779: }
! 780: if (nc == 'd') {
! 781: if (illgdebug) {
! 782: ignore_ws (c);
! 783: if (more_params (c)) {
! 784: uae_u32 addr = readhex (c);
! 785: uae_u32 len = 1;
! 786: if (more_params (c))
! 787: len = readhex (c);
! 788: write_log ("cleared logging addresses %08.8X - %08.8X\n", addr, addr + len);
! 789: while (len > 0) {
! 790: addr &= 0xffffff;
! 791: illgdebug[addr] = 0;
! 792: addr++;
! 793: len--;
! 794: }
! 795: }
1.1.1.4 root 796: } else {
1.1.1.11! root 797: illg_init ();
! 798: console_out ("Illegal memory access logging enabled\n");
! 799: ignore_ws (c);
! 800: illgdebug_break = 0;
! 801: if (more_params (c))
! 802: illgdebug_break = 1;
1.1.1.4 root 803: }
1.1.1.11! root 804: return;
1.1.1.4 root 805: }
1.1.1.11! root 806: num = nc - '0';
! 807: if (num < 0 || num >= MEMWATCH_TOTAL)
! 808: return;
! 809: mwn = &mwnodes[num];
! 810: mwn->size = 0;
! 811: ignore_ws (c);
! 812: if (!more_params (c)) {
! 813: console_out ("Memwatch %d removed\n", num);
! 814: return;
! 815: }
! 816: mwn->addr = readhex (c);
! 817: mwn->size = 1;
! 818: mwn->rw = 2;
! 819: mwn->val_enabled = 0;
! 820: mwn->modval_written = 0;
! 821: ignore_ws (c);
! 822: if (more_params (c)) {
! 823: mwn->size = readhex (c);
! 824: ignore_ws (c);
! 825: if (more_params (c)) {
! 826: char nc = toupper (next_char (c));
! 827: if (nc == 'W')
! 828: mwn->rw = 1;
! 829: else if (nc == 'R' && toupper(**c) != 'W')
! 830: mwn->rw = 0;
! 831: else if (nc == 'R' && toupper(**c) == 'W')
! 832: next_char (c);
! 833: ignore_ws (c);
! 834: if (more_params (c)) {
! 835: if (toupper(**c) == 'M') {
! 836: mwn->modval_written = 1;
! 837: } else {
! 838: mwn->val = readhex (c);
! 839: mwn->val_enabled = 1;
! 840: }
! 841: }
1.1.1.4 root 842: }
843: }
1.1.1.11! root 844: memwatch_dump (num);
! 845: }
1.1.1.4 root 846:
1.1.1.11! root 847: static void writeintomem (char **c)
! 848: {
! 849: uae_u32 addr = 0;
! 850: uae_u32 val = 0;
! 851: char cc;
! 852:
! 853: ignore_ws(c);
! 854: addr = readhex (c);
! 855: ignore_ws(c);
! 856: val = readhex (c);
! 857: if (val > 0xffff) {
! 858: put_long (addr, val);
! 859: cc = 'L';
! 860: } else if (val > 0xff) {
! 861: put_word (addr, val);
! 862: cc = 'W';
! 863: } else {
! 864: put_byte (addr, val);
! 865: cc = 'B';
! 866: }
! 867: console_out ("Wrote %x (%u) at %08x.%c\n", val, val, addr, cc);
1.1.1.9 root 868: }
869:
870: static void show_exec_tasks (void)
871: {
872: uaecptr execbase = get_long (4);
873: uaecptr taskready = get_long (execbase + 406);
874: uaecptr taskwait = get_long (execbase + 420);
875: uaecptr node, end;
1.1.1.11! root 876: console_out ("execbase at 0x%08lx\n", (unsigned long) execbase);
! 877: console_out ("Current:\n");
1.1.1.9 root 878: node = get_long (execbase + 276);
1.1.1.11! root 879: console_out ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
! 880: console_out ("Ready:\n");
1.1.1.9 root 881: node = get_long (taskready);
882: end = get_long (taskready + 4);
883: while (node) {
1.1.1.11! root 884: console_out ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
1.1.1.9 root 885: node = get_long (node);
886: }
1.1.1.11! root 887: console_out ("Waiting:\n");
1.1.1.9 root 888: node = get_long (taskwait);
889: end = get_long (taskwait + 4);
890: while (node) {
1.1.1.11! root 891: console_out ("%08lx: %08lx %s\n", node, 0, get_real_address (get_long (node + 10)));
1.1.1.9 root 892: node = get_long (node);
893: }
1.1.1.4 root 894: }
1.1.1.7 root 895:
1.1.1.8 root 896: static int trace_same_insn_count;
897: static uae_u8 trace_insn_copy[10];
898: static struct regstruct trace_prev_regs;
1.1.1.11! root 899: static uaecptr nextpc;
1.1 root 900:
1.1.1.11! root 901: static int instruction_breakpoint (char **c)
! 902: {
! 903: struct breakpoint_node *bpn;
! 904: int i;
1.1.1.3 root 905:
1.1.1.11! root 906: if (more_params (c)) {
! 907: char nc = toupper((*c)[0]);
! 908: if (nc == 'I') {
! 909: next_char (c);
! 910: if (more_params (c))
! 911: skipins = readhex (c);
! 912: else
! 913: skipins = 0x10000;
! 914: do_skip = 1;
! 915: skipaddr_doskip = 1;
! 916: return 1;
! 917: } else if (nc == 'D' && (*c)[1] == 0) {
! 918: for (i = 0; i < BREAKPOINT_TOTAL; i++)
! 919: bpnodes[i].enabled = 0;
! 920: console_out ("All breakpoints removed\n");
! 921: return 0;
! 922: } else if (nc == 'L') {
! 923: int got = 0;
! 924: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
! 925: bpn = &bpnodes[i];
! 926: if (!bpn->enabled)
! 927: continue;
! 928: console_out ("%8X ", bpn->addr);
! 929: got = 1;
1.1.1.8 root 930: }
1.1.1.11! root 931: if (!got)
! 932: console_out ("No breakpoints\n");
! 933: else
! 934: console_out ("\n");
! 935: return 0;
1.1.1.8 root 936: }
1.1.1.11! root 937: skipaddr_doskip = 1;
! 938: skipaddr_start = readhex (c);
! 939: if (more_params (c)) {
! 940: skipaddr_end = readhex (c);
! 941: } else {
! 942: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
! 943: bpn = &bpnodes[i];
! 944: if (bpn->enabled && bpn->addr == skipaddr_start) {
! 945: bpn->enabled = 0;
! 946: console_out ("Breakpoint removed\n");
! 947: skipaddr_start = 0xffffffff;
! 948: skipaddr_doskip = 0;
! 949: return 0;
! 950: }
! 951: }
! 952: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
! 953: bpn = &bpnodes[i];
! 954: if (bpn->enabled)
! 955: continue;
! 956: bpn->addr = skipaddr_start;
! 957: bpn->enabled = 1;
! 958: console_out ("Breakpoint added\n");
! 959: skipaddr_start = 0xffffffff;
! 960: skipaddr_doskip = 0;
! 961: break;
! 962: }
! 963: return 0;
! 964: }
! 965: }
! 966: if (skipaddr_start == 0xC0DEDBAD) {
! 967: trace_same_insn_count = 0;
! 968: logfile = fopen ("uae.trace", "w");
1.1.1.8 root 969: memcpy (trace_insn_copy, regs.pc_p, 10);
970: memcpy (&trace_prev_regs, ®s, sizeof regs);
1.1.1.7 root 971: }
1.1.1.11! root 972: do_skip = 1;
! 973: skipaddr_doskip = -1;
! 974: return 1;
! 975: }
1.1.1.7 root 976:
1.1.1.11! root 977: static void savemem (char **cc)
! 978: {
! 979: uae_u8 b;
! 980: uae_u32 src, src2, len, len2;
! 981: char *name;
! 982: FILE *fp;
! 983:
! 984: if (!more_params (cc))
! 985: goto S_argh;
! 986:
! 987: name = *cc;
! 988: while (**cc != '\0' && !isspace (**cc))
! 989: (*cc)++;
! 990: if (!isspace (**cc))
! 991: goto S_argh;
! 992:
! 993: **cc = '\0';
! 994: (*cc)++;
! 995: if (!more_params (cc))
! 996: goto S_argh;
! 997: src2 = src = readhex (cc);
! 998: if (!more_params (cc))
! 999: goto S_argh;
! 1000: len2 = len = readhex (cc);
! 1001: fp = fopen (name, "wb");
! 1002: if (fp == NULL) {
! 1003: console_out ("Couldn't open file '%s'\n", name);
1.1 root 1004: return;
1005: }
1.1.1.11! root 1006: while (len > 0) {
! 1007: b = get_byte (src);
! 1008: src++;
! 1009: len--;
! 1010: if (fwrite (&b, 1, 1, fp) != 1) {
! 1011: console_out ("Error writing file\n");
! 1012: break;
! 1013: }
! 1014: }
! 1015: fclose (fp);
! 1016: if (len == 0)
! 1017: console_out ("Wrote %08X - %08X (%d bytes) to '%s'\n",
! 1018: src2, src2 + len2, len2, name);
! 1019: return;
! 1020: S_argh:
! 1021: console_out ("S-command needs more arguments!\n");
! 1022: }
1.1 root 1023:
1.1.1.11! root 1024: static void searchmem (char **cc)
! 1025: {
! 1026: int i, sslen, got, val, stringmode;
! 1027: uae_u8 ss[256];
! 1028: uae_u32 addr, endaddr;
! 1029: char nc;
! 1030:
! 1031: got = 0;
! 1032: sslen = 0;
! 1033: stringmode = 0;
! 1034: ignore_ws (cc);
! 1035: if (**cc == '"') {
! 1036: stringmode = 1;
! 1037: (*cc)++;
! 1038: while (**cc != '"' && **cc != 0) {
! 1039: ss[sslen++] = tolower (**cc);
! 1040: (*cc)++;
! 1041: }
! 1042: if (**cc != 0)
! 1043: (*cc)++;
! 1044: } else {
! 1045: for (;;) {
! 1046: if (**cc == 32 || **cc == 0)
! 1047: break;
! 1048: nc = toupper (next_char (cc));
! 1049: if (isspace (nc))
! 1050: break;
! 1051: if (isdigit(nc))
! 1052: val = nc - '0';
! 1053: else
! 1054: val = nc - 'A' + 10;
! 1055: if (val < 0 || val > 15)
! 1056: return;
! 1057: val *= 16;
! 1058: if (**cc == 32 || **cc == 0)
! 1059: break;
! 1060: nc = toupper (next_char (cc));
! 1061: if (isspace (nc))
! 1062: break;
! 1063: if (isdigit(nc))
! 1064: val += nc - '0';
! 1065: else
! 1066: val += nc - 'A' + 10;
! 1067: if (val < 0 || val > 255)
! 1068: return;
! 1069: ss[sslen++] = (uae_u8)val;
! 1070: }
! 1071: }
! 1072: if (sslen == 0)
! 1073: return;
! 1074: ignore_ws (cc);
! 1075: addr = 0;
! 1076: endaddr = nextaddr (0xffffffff);
! 1077: if (more_params (cc)) {
! 1078: addr = readhex (cc);
! 1079: if (more_params (cc))
! 1080: endaddr = readhex (cc);
! 1081: }
! 1082: console_out ("Searching from %08x to %08x..\n", addr, endaddr);
! 1083: while (addr < endaddr && addr != 0xffffffff) {
! 1084: for (i = 0; i < sslen; i++) {
! 1085: uae_u8 b = get_byte (addr + i);
! 1086: if (stringmode) {
! 1087: if (tolower (b) != ss[i])
! 1088: break;
! 1089: } else {
! 1090: if (b != ss[i])
! 1091: break;
! 1092: }
! 1093: }
! 1094: if (i == sslen) {
! 1095: got++;
! 1096: console_out (" %08x", addr);
! 1097: if (got > 100) {
! 1098: console_out ("\nMore than 100 results, aborting..");
! 1099: break;
! 1100: }
! 1101: }
! 1102: addr = nextaddr (addr);
1.1 root 1103: }
1.1.1.11! root 1104: if (!got)
! 1105: console_out ("nothing found");
! 1106: console_out ("\n");
! 1107: }
! 1108:
! 1109: static void m68k_modify (char **inptr)
! 1110: {
! 1111: char c1, c2;
! 1112: uae_u32 v;
! 1113:
! 1114: c1 = toupper (next_char (inptr));
! 1115: if (!more_params (inptr))
! 1116: return;
! 1117: c2 = toupper (next_char (inptr));
! 1118: if (c2 < '0' || c2 > '7')
! 1119: return;
! 1120: c2 -= '0';
! 1121: v = readhex (inptr);
! 1122: if (c1 == 'A')
! 1123: regs.regs[8 + c2] = v;
! 1124: else if (c1 == 'D')
! 1125: regs.regs[c2] = v;
! 1126: else if (c1 == 'P' && c2 == 0)
! 1127: regs.irc = v;
! 1128: else if (c1 == 'P' && c2 == 1)
! 1129: regs.ir = v;
! 1130: }
! 1131:
! 1132: static void debug_1 (void)
! 1133: {
! 1134: char input[80];
! 1135: uaecptr nxdis,nxmem,nxcopper;
1.1 root 1136:
1.1.1.7 root 1137: m68k_dumpstate (stdout, &nextpc);
1.1.1.9 root 1138: nxdis = nextpc; nxmem = nxcopper = 0;
1.1 root 1139:
1.1.1.4 root 1140: for (;;) {
1141: char cmd, *inptr;
1.1.1.3 root 1142:
1.1.1.11! root 1143: console_out (">");
! 1144: console_flush ();
! 1145: if (!console_get (input, 80))
! 1146: continue;
1.1 root 1147: inptr = input;
1.1.1.4 root 1148: cmd = next_char (&inptr);
1149: switch (cmd) {
1.1.1.9 root 1150: case 'c': dumpcia (); dumpdisk (); dumpcustom (); break;
1.1.1.11! root 1151: case 'i': dump_vectors (); break;
! 1152: case 'r': if (more_params(&inptr))
! 1153: m68k_modify (&inptr);
! 1154: else
! 1155: m68k_dumpstate (stdout, &nextpc);
! 1156: break;
1.1.1.9 root 1157: case 'M': modulesearch (); break;
1158: case 'C': cheatsearch (&inptr); break;
1159: case 'W': writeintomem (&inptr); break;
1.1.1.11! root 1160: case 'w': memwatch (&inptr); break;
! 1161: case 'S': savemem (&inptr); break;
! 1162: case 's': searchmem (&inptr); break;
1.1.1.9 root 1163: case 'd':
1164: {
1165: uae_u32 daddr;
1166: int count;
1167:
1168: if (more_params(&inptr))
1169: daddr = readhex(&inptr);
1170: else
1171: daddr = nxdis;
1172: if (more_params(&inptr))
1173: count = readhex(&inptr);
1174: else
1175: count = 10;
1176: m68k_disasm (stdout, daddr, &nxdis, count);
1177: }
1178: break;
1179: case 'T': show_exec_tasks (); break;
1.1.1.11! root 1180: case 't':
! 1181: if (more_params (&inptr))
! 1182: skipaddr_doskip = readint (&inptr);
! 1183: if (skipaddr_doskip <= 0 || skipaddr_doskip > 10000)
! 1184: skipaddr_doskip = 1;
! 1185: set_special (SPCFLAG_BRK);
! 1186: exception_debugging = 1;
! 1187: return;
1.1.1.9 root 1188: case 'z':
1.1.1.11! root 1189: skipaddr_start = nextpc;
! 1190: skipaddr_doskip = 1;
1.1 root 1191: do_skip = 1;
1.1.1.11! root 1192: exception_debugging = 1;
1.1 root 1193: return;
1194:
1.1.1.9 root 1195: case 'f':
1.1.1.11! root 1196: if (instruction_breakpoint (&inptr))
! 1197: return;
! 1198: break;
1.1 root 1199:
1.1.1.9 root 1200: case 'q': uae_quit();
1.1.1.3 root 1201: debugger_active = 0;
1202: debugging = 0;
1203: return;
1204:
1.1.1.9 root 1205: case 'g':
1.1.1.11! root 1206: if (more_params (&inptr)) {
1.1 root 1207: m68k_setpc (readhex (&inptr));
1.1.1.11! root 1208: fill_prefetch_slow ();
! 1209: }
1.1 root 1210: debugger_active = 0;
1211: debugging = 0;
1.1.1.11! root 1212: exception_debugging = 0;
1.1 root 1213: return;
1214:
1.1.1.9 root 1215: case 'H':
1216: {
1217: int count;
1218: int temp;
1.1 root 1219: #ifdef NEED_TO_DEBUG_BADLY
1.1.1.9 root 1220: struct regstruct save_regs = regs;
1221: union flagu save_flags = regflags;
1.1 root 1222: #endif
1223:
1.1.1.9 root 1224: if (more_params(&inptr))
1225: count = readhex(&inptr);
1226: else
1227: count = 10;
1228: if (count < 0)
1229: break;
1230: temp = lasthist;
1231: while (count-- > 0 && temp != firsthist) {
1232: if (temp == 0) temp = MAX_HIST-1; else temp--;
1233: }
1234: while (temp != lasthist) {
1.1 root 1235: #ifdef NEED_TO_DEBUG_BADLY
1.1.1.9 root 1236: regs = history[temp];
1237: regflags = historyf[temp];
1238: m68k_dumpstate (NULL);
1.1 root 1239: #else
1.1.1.9 root 1240: m68k_disasm (stdout, history[temp], NULL, 1);
1.1 root 1241: #endif
1.1.1.9 root 1242: if (++temp == MAX_HIST) temp = 0;
1243: }
1.1 root 1244: #ifdef NEED_TO_DEBUG_BADLY
1.1.1.9 root 1245: regs = save_regs;
1246: regflags = save_flags;
1.1 root 1247: #endif
1.1.1.9 root 1248: }
1249: break;
1250: case 'm':
1251: {
1252: uae_u32 maddr; int lines;
1253: if (more_params(&inptr))
1254: maddr = readhex(&inptr);
1255: else
1256: maddr = nxmem;
1257: if (more_params(&inptr))
1258: lines = readhex(&inptr);
1259: else
1.1.1.11! root 1260: lines = 20;
1.1.1.9 root 1261: dumpmem(maddr, &nxmem, lines);
1262: }
1263: break;
1264: case 'o':
1265: {
1266: uae_u32 maddr;
1267: int lines;
1268:
1269: if (more_params(&inptr)) {
1270: maddr = readhex(&inptr);
1271: if (maddr == 1 || maddr == 2)
1272: maddr = get_copper_address (maddr);
1.1 root 1273: }
1.1.1.9 root 1274: else
1275: maddr = nxcopper;
1276:
1277: if (more_params (&inptr))
1278: lines = readhex (&inptr);
1279: else
1.1.1.11! root 1280: lines = 20;
1.1.1.9 root 1281:
1282: nxcopper = decode_copperlist (stdout, maddr, lines);
1.1 root 1283: break;
1.1.1.9 root 1284: }
1285: case 'O':
1286: if (more_params (&inptr)) {
1287: int plane = readint (&inptr);
1288: int offs = readint (&inptr);
1289: if (plane >= 0 && plane < 8)
1.1.1.10 root 1290: bpl_off[plane] = offs;
1.1.1.9 root 1291: } else {
1292: int i;
1293: for (i = 0; i < 8; i++)
1.1.1.11! root 1294: console_out ("Plane %d offset %d\n", i, bpl_off[i]);
1.1.1.3 root 1295: }
1296: break;
1.1.1.9 root 1297: case 'h':
1298: case '?':
1.1.1.11! root 1299: debug_help ();
1.1.1.9 root 1300: break;
1.1 root 1301: }
1302: }
1303: }
1.1.1.11! root 1304:
! 1305: void debug (void)
! 1306: {
! 1307: int i;
! 1308:
! 1309: bogusframe = 1;
! 1310:
! 1311: if (do_skip && skipaddr_start == 0xC0DEDBAD) {
! 1312: #if 0
! 1313: if (trace_same_insn_count > 0) {
! 1314: if (memcmp (trace_insn_copy, regs.pc_p, 10) == 0
! 1315: && memcmp (trace_prev_regs.regs, regs.regs, sizeof regs.regs) == 0)
! 1316: {
! 1317: trace_same_insn_count++;
! 1318: return;
! 1319: }
! 1320: }
! 1321: if (trace_same_insn_count > 1)
! 1322: fprintf (logfile, "[ repeated %d times ]\n", trace_same_insn_count);
! 1323: #endif
! 1324: m68k_dumpstate (logfile, &nextpc);
! 1325: trace_same_insn_count = 1;
! 1326: memcpy (trace_insn_copy, regs.pc_p, 10);
! 1327: memcpy (&trace_prev_regs, ®s, sizeof regs);
! 1328: }
! 1329:
! 1330: if (!memwatch_triggered) {
! 1331: if (do_skip) {
! 1332: uae_u32 pc = munge24 (m68k_getpc());
! 1333: uae_u16 opcode = currprefs.cpu_compatible ? regs.ir : get_word (pc);
! 1334: int bp = 0;
! 1335:
! 1336: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
! 1337: if (!bpnodes[i].enabled)
! 1338: continue;
! 1339: if (bpnodes[i].addr == pc) {
! 1340: bp = 1;
! 1341: console_out ("Breakpoint at %08.8X\n", pc);
! 1342: break;
! 1343: }
! 1344: }
! 1345: if (skipaddr_doskip) {
! 1346: if (skipaddr_start == pc)
! 1347: bp = 1;
! 1348: if (skipins != 0xffffffff) {
! 1349: if (skipins == 0x10000) {
! 1350: if (opcode == 0x4e75 || opcode == 0x4e73 || opcode == 0x4e77)
! 1351: bp = 1;
! 1352: } else if (opcode == skipins)
! 1353: bp = 1;
! 1354: } else if (skipaddr_start == 0xffffffff && skipaddr_doskip < 0) {
! 1355: if ((pc < 0xe00000 || pc >= 0x1000000) && opcode != 0x4ef9)
! 1356: bp = 1;
! 1357: } else if (skipaddr_start == 0xffffffff && skipaddr_doskip > 0) {
! 1358: bp = 1;
! 1359: } else if (skipaddr_end != 0xffffffff) {
! 1360: if (pc >= skipaddr_start && pc < skipaddr_end)
! 1361: bp = 1;
! 1362: }
! 1363: }
! 1364: if (!bp) {
! 1365: set_special (SPCFLAG_BRK);
! 1366: return;
! 1367: }
! 1368: }
! 1369: } else {
! 1370: write_log ("Memwatch %d: break at %08.8X.%c %c %08.8X\n", memwatch_triggered - 1, mwhit.addr,
! 1371: mwhit.size == 1 ? 'B' : (mwhit.size == 2 ? 'W' : 'L'), mwhit.rw ? 'W' : 'R', mwhit.val);
! 1372: memwatch_triggered = 0;
! 1373: }
! 1374: if (skipaddr_doskip > 0) {
! 1375: skipaddr_doskip--;
! 1376: if (skipaddr_doskip > 0) {
! 1377: set_special (SPCFLAG_BRK);
! 1378: return;
! 1379: }
! 1380: }
! 1381:
! 1382: #ifdef NEED_TO_DEBUG_BADLY
! 1383: history[lasthist] = regs;
! 1384: historyf[lasthist] = regflags;
! 1385: #else
! 1386: history[lasthist] = m68k_getpc();
! 1387: #endif
! 1388: if (++lasthist == MAX_HIST) lasthist = 0;
! 1389: if (lasthist == firsthist) {
! 1390: if (++firsthist == MAX_HIST) firsthist = 0;
! 1391: }
! 1392: #if 0
! 1393: inputdevice_unacquire ();
! 1394: pause_sound ();
! 1395: #endif
! 1396: do_skip = 0;
! 1397: skipaddr_start = 0xffffffff;
! 1398: skipaddr_end = 0xffffffff;
! 1399: skipins = 0xffffffff;
! 1400: skipaddr_doskip = 0;
! 1401: exception_debugging = 0;
! 1402: debug_1 ();
! 1403: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
! 1404: if (bpnodes[i].enabled)
! 1405: do_skip = 1;
! 1406: }
! 1407: if (do_skip) {
! 1408: set_special (SPCFLAG_BRK);
! 1409: debugging = 1;
! 1410: }
! 1411: #if 0
! 1412: resume_sound ();
! 1413: inputdevice_acquire ();
! 1414: #endif
! 1415: }
! 1416:
! 1417: int notinrom (void)
! 1418: {
! 1419: if (munge24 (m68k_getpc()) < 0xe0000)
! 1420: return 1;
! 1421: return 0;
! 1422: }
! 1423:
! 1424: const char *debuginfo (int mode)
! 1425: {
! 1426: static char txt[100];
! 1427: uae_u32 pc = m68k_getpc();
! 1428: sprintf (txt, "PC=%08.8X INS=%04.4X %04.4X %04.4X",
! 1429: pc, get_word(pc), get_word(pc+2), get_word(pc+4));
! 1430: return txt;
! 1431: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.