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