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