|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Debugger
5: *
6: * (c) 1995 Bernd Schmidt
7: * (c) 2006 Toni Wilen
8: *
9: */
10:
11: #include "sysconfig.h"
12: #include "sysdeps.h"
13:
14: #include "main.h"
15: #include "hatari-glue.h"
16:
17: #include <ctype.h>
18: #include <signal.h>
19:
20: #include "options_cpu.h"
21: //#include "uae.h"
22: #include "memory.h"
23: #include "custom.h"
24: #include "newcpu.h"
25: #include "cpu_prefetch.h"
26: #include "debug.h"
27: //#include "cia.h"
28: //#include "xwin.h"
29: //#include "identify.h"
30: //#include "audio.h"
1.1.1.2 ! root 31: //#include "sounddep/sound.h"
1.1 root 32: //#include "disk.h"
33: #include "savestate.h"
34: //#include "autoconf.h"
35: //#include "akiko.h"
36: //#include "inputdevice.h"
37: //#include "crc32.h"
1.1.1.2 ! root 38: #include "cpummu.h"
1.1 root 39: //#include "rommgr.h"
40: //#include "inputrecord.h"
1.1.1.2 ! root 41: //#include "calc.h"
1.1 root 42: #include "cpummu.h"
43: #include "cpummu030.h"
1.1.1.2 ! root 44: //#include "ar.h"
! 45: //#include "pci.h"
1.1 root 46: //#include "ppc/ppcd.h"
1.1.1.2 ! root 47: //#include "uae/io.h"
1.1 root 48: //#include "uae/ppc.h"
49:
50: #ifdef WINUAE_FOR_HATARI
51: #include "stMemory.h"
52: static int debug_mmu_mode;
53:
54: #else
55: int debugger_active;
56: static uaecptr skipaddr_start, skipaddr_end;
57: static int skipaddr_doskip;
58: static uae_u32 skipins;
59: static int do_skip;
60: static int debug_rewind;
61: static int memwatch_triggered;
62: int memwatch_enabled;
63: int debugging;
64: int exception_debugging;
65: int no_trace_exceptions;
66: int debug_copper = 0;
1.1.1.2 ! root 67: int debug_dma = 0, debug_heatmap = 0;
1.1 root 68: int debug_sprite_mask = 0xff;
69: int debug_illegal = 0;
70: uae_u64 debug_illegal_mask;
71: static int debug_mmu_mode;
72: static bool break_if_enforcer;
73:
74: static uaecptr processptr;
75: static uae_char *processname;
76:
77: static uaecptr debug_copper_pc;
78:
79: extern int audio_channel_mask;
80: extern int inputdevice_logging;
81:
82: void deactivate_debugger (void)
83: {
84: debugger_active = 0;
85: debugging = 0;
86: exception_debugging = 0;
87: processptr = 0;
88: xfree (processname);
89: processname = NULL;
90: }
91:
92: void activate_debugger (void)
93: {
94: do_skip = 0;
95: if (debugger_active)
96: return;
97: debugger_active = 1;
98: set_special (SPCFLAG_BRK);
99: debugging = 1;
100: mmu_triggered = 0;
101: }
102:
103: bool debug_enforcer(void)
104: {
105: if (!break_if_enforcer)
106: return false;
107: activate_debugger();
108: return true;
109: }
110:
111: int firsthist = 0;
112: int lasthist = 0;
113: static struct regstruct history[MAX_HIST];
114:
1.1.1.2 ! root 115: static const TCHAR help[] = {
1.1 root 116: _T(" HELP for UAE Debugger\n")
117: _T(" -----------------------\n\n")
118: _T(" g [<address>] Start execution at the current address or <address>.\n")
119: _T(" c Dump state of the CIA, disk drives and custom registers.\n")
120: _T(" r Dump state of the CPU.\n")
121: _T(" r <reg> <value> Modify CPU registers (Dx,Ax,USP,ISP,VBR,...).\n")
122: _T(" m <address> [<lines>] Memory dump starting at <address>.\n")
123: _T(" d <address> [<lines>] Disassembly starting at <address>.\n")
124: _T(" t [instructions] Step one or more instructions.\n")
125: _T(" z Step through one instruction - useful for JSR, DBRA etc.\n")
126: _T(" f Step forward until PC in RAM (\"boot block finder\").\n")
127: _T(" f <address> Add/remove breakpoint.\n")
128: _T(" fa <address> [<start>] [<end>]\n")
129: _T(" Find effective address <address>.\n")
130: _T(" fi Step forward until PC points to RTS, RTD or RTE.\n")
131: _T(" fi <opcode> Step forward until PC points to <opcode>.\n")
132: _T(" fp \"<name>\"/<addr> Step forward until process <name> or <addr> is active.\n")
133: _T(" fl List breakpoints.\n")
134: _T(" fd Remove all breakpoints.\n")
135: _T(" fs <lines to wait> | <vpos> <hpos> Wait n scanlines/position.\n")
136: _T(" fc <CCKs to wait> Wait n color clocks.\n")
1.1.1.2 ! root 137: _T(" fo <num> <reg> <oper> <val> [<mask> <val2>] Conditional register breakpoint.\n")
! 138: _T(" reg=Dx,Ax,PC,USP,ISP,VBR,SR. oper:!=,==,<,>,>=,<=,-,!- (-=val to val2 range).\n")
1.1 root 139: _T(" f <addr1> <addr2> Step forward until <addr1> <= PC <= <addr2>.\n")
140: _T(" e Dump contents of all custom registers, ea = AGA colors.\n")
141: _T(" i [<addr>] Dump contents of interrupt and trap vectors.\n")
142: _T(" il [<mask>] Exception breakpoint.\n")
143: _T(" o <0-2|addr> [<lines>]View memory as Copper instructions.\n")
144: _T(" od Enable/disable Copper vpos/hpos tracing.\n")
145: _T(" ot Copper single step trace.\n")
146: _T(" ob <addr> Copper breakpoint.\n")
147: _T(" H[H] <cnt> Show PC history (HH=full CPU info) <cnt> instructions.\n")
148: _T(" C <value> Search for values like energy or lifes in games.\n")
149: _T(" Cl List currently found trainer addresses.\n")
150: _T(" D[idxzs <[max diff]>] Deep trainer. i=new value must be larger, d=smaller,\n")
151: _T(" x = must be same, z = must be different, s = restart.\n")
152: _T(" W <address> <values[.x] separated by space> Write into Amiga memory.\n")
153: _T(" W <address> 'string' Write into Amiga memory.\n")
154: _T(" w <num> <address> <length> <R/W/I/F/C> [<value>[.x]] (read/write/opcode/freeze/mustchange).\n")
155: _T(" Add/remove memory watchpoints.\n")
156: _T(" wd [<0-1>] Enable illegal access logger. 1 = enable break.\n")
157: _T(" S <file> <addr> <n> Save a block of Amiga memory.\n")
158: _T(" s \"<string>\"/<values> [<addr>] [<length>]\n")
159: _T(" Search for string/bytes.\n")
160: _T(" T or Tt Show exec tasks and their PCs.\n")
161: _T(" Td,Tl,Tr,Tp,Ts,TS,Ti,TO,TM Show devs, libs, resources, ports, semaphores,\n")
162: _T(" residents, interrupts, doslist and memorylist.\n")
163: _T(" b Step to previous state capture position.\n")
164: _T(" M<a/b/s> <val> Enable or disable audio channels, bitplanes or sprites.\n")
165: _T(" sp <addr> [<addr2][<size>] Dump sprite information.\n")
166: _T(" di <mode> [<track>] Break on disk access. R=DMA read,W=write,RW=both,P=PIO.\n")
167: _T(" Also enables level 1 disk logging.\n")
168: _T(" did <log level> Enable disk logging.\n")
169: _T(" dj [<level bitmask>] Enable joystick/mouse input debugging.\n")
170: _T(" smc [<0-1>] Enable self-modifying code detector. 1 = enable break.\n")
171: _T(" dm Dump current address space map.\n")
172: _T(" v <vpos> [<hpos>] Show DMA data (accurate only in cycle-exact mode).\n")
173: _T(" v [-1 to -4] = enable visual DMA debugger.\n")
1.1.1.2 ! root 174: _T(" vh [<ratio> <lines>] \"Heat map\"\n")
! 175: _T(" ?<value> Hex ($ and 0x)/Bin (%)/Dec (!) converter and calculator.\n")
1.1 root 176: #ifdef _WIN32
177: _T(" x Close debugger.\n")
178: _T(" xx Switch between console and GUI debugger.\n")
179: _T(" mg <address> Memory dump starting at <address> in GUI.\n")
180: _T(" dg <address> Disassembly starting at <address> in GUI.\n")
181: #endif
182: _T(" q Quit the emulator. You don't want to use this command.\n\n")
183: };
184:
185: void debug_help (void)
186: {
187: console_out (help);
188: }
189:
1.1.1.2 ! root 190:
! 191: struct mw_acc {
! 192: uae_u32 mask;
! 193: const TCHAR *name;
! 194: };
! 195:
! 196: static const struct mw_acc memwatch_access_masks[] =
! 197: {
! 198: { MW_MASK_ALL, _T("ALL") },
! 199: { MW_MASK_NONE, _T("NONE") },
! 200: { MW_MASK_ALL & ~(MW_MASK_CPU_I | MW_MASK_CPU_D_R | MW_MASK_CPU_D_W), _T("DMA") },
! 201:
! 202: { MW_MASK_BLITTER_A | MW_MASK_BLITTER_B | MW_MASK_BLITTER_C | MW_MASK_BLITTER_D_N | MW_MASK_BLITTER_D_L | MW_MASK_BLITTER_D_F, _T("BLT") },
! 203: { MW_MASK_BLITTER_D_N | MW_MASK_BLITTER_D_L | MW_MASK_BLITTER_D_F, _T("BLTD") },
! 204:
! 205: { MW_MASK_AUDIO_0 | MW_MASK_AUDIO_1 | MW_MASK_AUDIO_2 | MW_MASK_AUDIO_3, _T("AUD") },
! 206:
! 207: { MW_MASK_BPL_0 | MW_MASK_BPL_1 | MW_MASK_BPL_2 | MW_MASK_BPL_3 |
! 208: MW_MASK_BPL_4 | MW_MASK_BPL_5 | MW_MASK_BPL_6 | MW_MASK_BPL_7, _T("BPL") },
! 209:
! 210: { MW_MASK_SPR_0 | MW_MASK_SPR_1 | MW_MASK_SPR_2 | MW_MASK_SPR_3 |
! 211: MW_MASK_SPR_4 | MW_MASK_SPR_5 | MW_MASK_SPR_6 | MW_MASK_SPR_7, _T("SPR") },
! 212:
! 213: { MW_MASK_CPU_I | MW_MASK_CPU_D_R | MW_MASK_CPU_D_W, _T("CPU") },
! 214: { MW_MASK_CPU_D_R | MW_MASK_CPU_D_W, _T("CPUD") },
! 215: { MW_MASK_CPU_I, _T("CPUI") },
! 216: { MW_MASK_CPU_D_R, _T("CPUDR") },
! 217: { MW_MASK_CPU_D_W, _T("CPUDW") },
! 218:
! 219: { MW_MASK_COPPER, _T("COP") },
! 220:
! 221: { MW_MASK_BLITTER_A, _T("BLTA") },
! 222: { MW_MASK_BLITTER_B, _T("BLTB") },
! 223: { MW_MASK_BLITTER_C, _T("BLTC") },
! 224: { MW_MASK_BLITTER_D_N, _T("BLTDN") },
! 225: { MW_MASK_BLITTER_D_L, _T("BLTDL") },
! 226: { MW_MASK_BLITTER_D_F, _T("BLTDF") },
! 227:
! 228: { MW_MASK_DISK, _T("DSK") },
! 229:
! 230: { MW_MASK_AUDIO_0, _T("AUD0") },
! 231: { MW_MASK_AUDIO_1, _T("AUD1") },
! 232: { MW_MASK_AUDIO_2, _T("AUD2") },
! 233: { MW_MASK_AUDIO_3, _T("AUD3") },
! 234:
! 235: { MW_MASK_BPL_0, _T("BPL0") },
! 236: { MW_MASK_BPL_1, _T("BPL1") },
! 237: { MW_MASK_BPL_2, _T("BPL2") },
! 238: { MW_MASK_BPL_3, _T("BPL3") },
! 239: { MW_MASK_BPL_4, _T("BPL4") },
! 240: { MW_MASK_BPL_5, _T("BPL5") },
! 241: { MW_MASK_BPL_6, _T("BPL6") },
! 242: { MW_MASK_BPL_7, _T("BPL7") },
! 243:
! 244: { MW_MASK_SPR_0, _T("SPR0") },
! 245: { MW_MASK_SPR_1, _T("SPR1") },
! 246: { MW_MASK_SPR_2, _T("SPR2") },
! 247: { MW_MASK_SPR_3, _T("SPR3") },
! 248: { MW_MASK_SPR_4, _T("SPR4") },
! 249: { MW_MASK_SPR_5, _T("SPR5") },
! 250: { MW_MASK_SPR_6, _T("SPR6") },
! 251: { MW_MASK_SPR_7, _T("SPR7") },
! 252:
! 253: { 0, NULL },
! 254: };
! 255:
! 256: static void mw_help(void)
! 257: {
! 258: for (int i = 0; memwatch_access_masks[i].mask; i++) {
! 259: console_out_f(_T("%s "), memwatch_access_masks[i].name);
! 260: }
! 261: console_out_f(_T("\n"));
! 262: }
! 263:
1.1 root 264: static int debug_linecounter;
265: #define MAX_LINECOUNTER 1000
266:
267: static int debug_out (const TCHAR *format, ...)
268: {
269: va_list parms;
270: TCHAR buffer[4000];
271:
272: va_start (parms, format);
273: _vsntprintf (buffer, 4000 - 1, format, parms);
274: va_end (parms);
275:
276: console_out (buffer);
277: if (debug_linecounter < MAX_LINECOUNTER)
278: debug_linecounter++;
279: if (debug_linecounter >= MAX_LINECOUNTER)
280: return 0;
281: return 1;
282: }
283:
284: #endif /* ! WINUAE_FOR_HATARI */
285:
286: uae_u32 get_byte_debug (uaecptr addr)
287: {
288: uae_u32 v = 0xff;
289: if (debug_mmu_mode) {
290: flagtype olds = regs.s;
291: regs.s = (debug_mmu_mode & 4) != 0;
292: TRY(p) {
293: if (currprefs.mmu_model == 68030) {
294: v = mmu030_get_generic (addr, debug_mmu_mode, sz_byte, sz_byte, 0);
295: } else {
296: v = mmu_get_user_byte (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_byte);
297: }
298: } CATCH(p) {
299: } ENDTRY
300: regs.s = olds;
301: } else {
302: #ifndef WINUAE_FOR_HATARI
303: v = get_byte (addr);
304: #else
305: v = STMemory_ReadByte ( addr );
306: #endif
307: }
308: return v;
309: }
310: uae_u32 get_word_debug (uaecptr addr)
311: {
312: uae_u32 v = 0xffff;
313: if (debug_mmu_mode) {
314: flagtype olds = regs.s;
315: regs.s = (debug_mmu_mode & 4) != 0;
316: TRY(p) {
317: if (currprefs.mmu_model == 68030) {
318: v = mmu030_get_generic (addr, debug_mmu_mode, sz_word, sz_word, 0);
319: } else {
320: v = mmu_get_user_word (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_word);
321: }
322: } CATCH(p) {
323: } ENDTRY
324: regs.s = olds;
325: } else {
326: #ifndef WINUAE_FOR_HATARI
327: v = get_word (addr);
328: #else
329: v = STMemory_ReadWord ( addr );
330: #endif
331: }
332: return v;
333: }
334: uae_u32 get_long_debug (uaecptr addr)
335: {
336: uae_u32 v = 0xffffffff;
337: if (debug_mmu_mode) {
338: flagtype olds = regs.s;
339: regs.s = (debug_mmu_mode & 4) != 0;
340: TRY(p) {
341: if (currprefs.mmu_model == 68030) {
342: v = mmu030_get_generic (addr, debug_mmu_mode, sz_long, sz_long, 0);
343: } else {
344: v = mmu_get_user_long (addr, regs.s != 0, (debug_mmu_mode & 1) ? true : false, false, sz_long);
345: }
346: } CATCH(p) {
347: } ENDTRY
348: regs.s = olds;
349: } else {
350: #ifndef WINUAE_FOR_HATARI
351: v = get_long (addr);
352: #else
353: v = STMemory_ReadLong ( addr );
354: #endif
355: }
356: return v;
357: }
358: uae_u32 get_iword_debug (uaecptr addr)
359: {
360: if (debug_mmu_mode) {
361: return get_word_debug (addr);
362: } else {
363: #ifndef WINUAE_FOR_HATARI
364: if (valid_address (addr, 2))
365: return get_word (addr);
366: return 0xffff;
367: #else
368: return get_word_debug (addr);
369: #endif
370: }
371: }
372: uae_u32 get_ilong_debug (uaecptr addr)
373: {
374: if (debug_mmu_mode) {
375: return get_long_debug (addr);
376: } else {
377: #ifndef WINUAE_FOR_HATARI
378: if (valid_address (addr, 4))
379: return get_long (addr);
380: return 0xffffffff;
381: #else
382: return get_long_debug (addr);
383: #endif
384: }
385: }
386:
387: #ifndef WINUAE_FOR_HATARI
1.1.1.2 ! root 388: static int safe_addr (uaecptr addr, int size)
1.1 root 389: {
390: if (debug_mmu_mode) {
391: flagtype olds = regs.s;
392: regs.s = (debug_mmu_mode & 4) != 0;
393: TRY(p) {
394: if (currprefs.mmu_model >= 68040)
395: addr = mmu_translate (addr, regs.s != 0, (debug_mmu_mode & 1), false);
396: else
397: addr = mmu030_translate (addr, regs.s != 0, (debug_mmu_mode & 1), false);
398: } CATCH(p) {
399: return 0;
400: } ENDTRY
401: regs.s = olds;
402: }
403: addrbank *ab = &get_mem_bank (addr);
404: if (!ab)
405: return 0;
406: if (ab->flags & ABFLAG_SAFE)
407: return 1;
408: if (!ab->check (addr, size))
409: return 0;
410: if (ab->flags & (ABFLAG_RAM | ABFLAG_ROM | ABFLAG_ROMIN | ABFLAG_SAFE))
411: return 1;
412: return 0;
413: }
414:
415: static bool iscancel (int counter)
416: {
417: static int cnt;
418:
419: cnt++;
420: if (cnt < counter)
421: return false;
422: cnt = 0;
423: if (!console_isch ())
424: return false;
425: console_getch ();
426: return true;
427: }
428:
429: static bool isoperator(TCHAR **cp)
430: {
431: TCHAR c = **cp;
432: return c == '+' || c == '-' || c == '/' || c == '*' || c == '(' || c == ')';
433: }
434:
435: static void ignore_ws (TCHAR **c)
436: {
437: while (**c && _istspace(**c))
438: (*c)++;
439: }
440: static TCHAR peekchar (TCHAR **c)
441: {
442: return **c;
443: }
444: static TCHAR readchar (TCHAR **c)
445: {
446: TCHAR cc = **c;
447: (*c)++;
448: return cc;
449: }
450: static TCHAR next_char (TCHAR **c)
451: {
452: ignore_ws (c);
453: return *(*c)++;
454: }
455: static TCHAR peek_next_char (TCHAR **c)
456: {
457: TCHAR *pc = *c;
458: return pc[1];
459: }
460: static int more_params (TCHAR **c)
461: {
462: ignore_ws (c);
463: return (**c) != 0;
464: }
465:
466: static uae_u32 readint (TCHAR **c);
467: static uae_u32 readbin (TCHAR **c);
468: static uae_u32 readhex (TCHAR **c);
469:
1.1.1.2 ! root 470: static const TCHAR *debugoper[] = {
! 471: _T("=="),
! 472: _T("!="),
! 473: _T("<="),
! 474: _T(">="),
! 475: _T("<"),
! 476: _T(">"),
! 477: _T("-"),
! 478: _T("!-"),
! 479: NULL
! 480: };
! 481:
! 482: static int getoperidx(TCHAR **c)
! 483: {
! 484: int i;
! 485: TCHAR *p = *c;
! 486: TCHAR tmp[10];
! 487: int extra = 0;
! 488:
! 489: i = 0;
! 490: while (p[i]) {
! 491: tmp[i] = _totupper(p[i]);
! 492: if (i >= sizeof(tmp) / sizeof(TCHAR) - 1)
! 493: break;
! 494: i++;
! 495: }
! 496: tmp[i] = 0;
! 497: if (!_tcsncmp(tmp, _T("!="), 2)) {
! 498: (*c) += 2;
! 499: return BREAKPOINT_CMP_NEQUAL;
! 500: } else if (!_tcsncmp(tmp, _T("=="), 2)) {
! 501: (*c) += 2;
! 502: return BREAKPOINT_CMP_EQUAL;
! 503: } else if (!_tcsncmp(tmp, _T(">="), 2)) {
! 504: (*c) += 2;
! 505: return BREAKPOINT_CMP_LARGER_EQUAL;
! 506: } else if (!_tcsncmp(tmp, _T("<="), 2)) {
! 507: (*c) += 2;
! 508: return BREAKPOINT_CMP_SMALLER_EQUAL;
! 509: } else if (!_tcsncmp(tmp, _T(">"), 1)) {
! 510: (*c) += 1;
! 511: return BREAKPOINT_CMP_LARGER;
! 512: } else if (!_tcsncmp(tmp, _T("<"), 1)) {
! 513: (*c) += 1;
! 514: return BREAKPOINT_CMP_SMALLER;
! 515: } else if (!_tcsncmp(tmp, _T("-"), 1)) {
! 516: (*c) += 1;
! 517: return BREAKPOINT_CMP_RANGE;
! 518: } else if (!_tcsncmp(tmp, _T("!-"), 2)) {
! 519: (*c) += 2;
! 520: return BREAKPOINT_CMP_NRANGE;
! 521: }
! 522: return -1;
! 523: }
! 524:
! 525: static const TCHAR *debugregs[] = {
! 526: _T("D0"),
! 527: _T("D1"),
! 528: _T("D2"),
! 529: _T("D3"),
! 530: _T("D4"),
! 531: _T("D5"),
! 532: _T("D6"),
! 533: _T("D7"),
! 534: _T("A0"),
! 535: _T("A1"),
! 536: _T("A2"),
! 537: _T("A3"),
! 538: _T("A4"),
! 539: _T("A5"),
! 540: _T("A6"),
! 541: _T("A7"),
! 542: _T("PC"),
! 543: _T("USP"),
! 544: _T("MSP"),
! 545: _T("ISP"),
! 546: _T("VBR"),
! 547: _T("SR"),
! 548: _T("CCR"),
! 549: _T("CACR"),
! 550: _T("CAAR"),
! 551: _T("SFC"),
! 552: _T("DFC"),
! 553: _T("TC"),
! 554: _T("ITT0"),
! 555: _T("ITT1"),
! 556: _T("DTT0"),
! 557: _T("DTT1"),
! 558: _T("BUSC"),
! 559: _T("PCR"),
! 560: NULL
! 561: };
! 562:
! 563: static int getregidx(TCHAR **c)
! 564: {
! 565: int i;
! 566: TCHAR *p = *c;
! 567: TCHAR tmp[10];
! 568: int extra = 0;
! 569:
! 570: i = 0;
! 571: while (p[i]) {
! 572: tmp[i] = _totupper(p[i]);
! 573: if (i >= sizeof(tmp) / sizeof(TCHAR) - 1)
! 574: break;
! 575: i++;
! 576: }
! 577: tmp[i] = 0;
! 578: for (int i = 0; debugregs[i]; i++) {
! 579: if (!_tcsncmp(tmp, debugregs[i], _tcslen(debugregs[i]))) {
! 580: (*c) += _tcslen(debugregs[i]);
! 581: return i;
! 582: }
! 583: }
! 584: return -1;
! 585: }
! 586:
! 587: static uae_u32 returnregx(int regid)
! 588: {
! 589: if (regid < BREAKPOINT_REG_PC)
! 590: return regs.regs[regid];
! 591: switch(regid)
! 592: {
! 593: case BREAKPOINT_REG_PC:
! 594: return M68K_GETPC;
! 595: case BREAKPOINT_REG_USP:
! 596: return regs.usp;
! 597: case BREAKPOINT_REG_MSP:
! 598: return regs.msp;
! 599: case BREAKPOINT_REG_ISP:
! 600: return regs.isp;
! 601: case BREAKPOINT_REG_VBR:
! 602: return regs.vbr;
! 603: case BREAKPOINT_REG_SR:
! 604: MakeSR();
! 605: return regs.sr;
! 606: case BREAKPOINT_REG_CCR:
! 607: MakeSR();
! 608: return regs.sr & 31;
! 609: case BREAKPOINT_REG_CACR:
! 610: return regs.cacr;
! 611: case BREAKPOINT_REG_CAAR:
! 612: return regs.caar;
! 613: case BREAKPOINT_REG_SFC:
! 614: return regs.sfc;
! 615: case BREAKPOINT_REG_DFC:
! 616: return regs.dfc;
! 617: case BREAKPOINT_REG_TC:
! 618: if (currprefs.cpu_model == 68030)
! 619: return tc_030;
! 620: return regs.tcr;
! 621: case BREAKPOINT_REG_ITT0:
! 622: if (currprefs.cpu_model == 68030)
! 623: return tt0_030;
! 624: return regs.itt0;
! 625: case BREAKPOINT_REG_ITT1:
! 626: if (currprefs.cpu_model == 68030)
! 627: return tt1_030;
! 628: return regs.itt1;
! 629: case BREAKPOINT_REG_DTT0:
! 630: return regs.dtt0;
! 631: case BREAKPOINT_REG_DTT1:
! 632: return regs.dtt1;
! 633: case BREAKPOINT_REG_BUSC:
! 634: return regs.buscr;
! 635: case BREAKPOINT_REG_PCR:
! 636: return regs.fpcr;
! 637: }
! 638: return 0;
! 639: }
! 640:
1.1 root 641: static int readregx (TCHAR **c, uae_u32 *valp)
642: {
643: int i;
644: uae_u32 addr;
645: TCHAR *p = *c;
646: TCHAR tmp[10];
647: int extra = 0;
648:
649: addr = 0;
650: i = 0;
651: while (p[i]) {
652: tmp[i] = _totupper (p[i]);
653: if (i >= sizeof (tmp) / sizeof (TCHAR) - 1)
654: break;
655: i++;
656: }
657: tmp[i] = 0;
658: if (_totupper (tmp[0]) == 'R') {
659: memmove (tmp, tmp + 1, sizeof (tmp) - sizeof (TCHAR));
660: extra = 1;
661: }
662: if (!_tcsncmp (tmp, _T("USP"), 3)) {
663: addr = regs.usp;
664: (*c) += 3;
665: } else if (!_tcsncmp (tmp, _T("VBR"), 3)) {
666: addr = regs.vbr;
667: (*c) += 3;
668: } else if (!_tcsncmp (tmp, _T("MSP"), 3)) {
669: addr = regs.msp;
670: (*c) += 3;
671: } else if (!_tcsncmp (tmp, _T("ISP"), 3)) {
672: addr = regs.isp;
673: (*c) += 3;
674: } else if (!_tcsncmp (tmp, _T("PC"), 2)) {
675: addr = regs.pc;
676: (*c) += 2;
677: } else if (tmp[0] == 'A' || tmp[0] == 'D') {
678: int reg = 0;
679: if (tmp[0] == 'A')
680: reg += 8;
681: reg += tmp[1] - '0';
682: if (reg < 0 || reg > 15)
683: return 0;
684: addr = regs.regs[reg];
685: (*c) += 2;
686: } else {
687: return 0;
688: }
689: *valp = addr;
690: (*c) += extra;
691: return 1;
692: }
693:
694: static bool readbinx (TCHAR **c, uae_u32 *valp)
695: {
696: uae_u32 val = 0;
697: bool first = true;
698:
699: ignore_ws (c);
700: for (;;) {
701: TCHAR nc = **c;
702: if (nc != '1' && nc != '0') {
703: if (first)
704: return false;
705: break;
706: }
707: first = false;
708: (*c)++;
709: val <<= 1;
710: if (nc == '1')
711: val |= 1;
712: }
713: *valp = val;
714: return true;
715: }
716:
717: static bool readhexx (TCHAR **c, uae_u32 *valp)
718: {
719: uae_u32 val = 0;
720: TCHAR nc;
721:
722: ignore_ws (c);
723: if (!isxdigit (peekchar (c)))
724: return false;
725: while (isxdigit (nc = **c)) {
726: (*c)++;
727: val *= 16;
728: nc = _totupper (nc);
729: if (isdigit (nc)) {
730: val += nc - '0';
731: } else {
732: val += nc - 'A' + 10;
733: }
734: }
735: *valp = val;
736: return true;
737: }
738:
739: static bool readintx (TCHAR **c, uae_u32 *valp)
740: {
741: uae_u32 val = 0;
742: TCHAR nc;
743: int negative = 0;
744:
745: ignore_ws (c);
746: if (**c == '-')
747: negative = 1, (*c)++;
748: if (!isdigit (peekchar (c)))
749: return false;
750: while (isdigit (nc = **c)) {
751: (*c)++;
752: val *= 10;
753: val += nc - '0';
754: }
755: *valp = val * (negative ? -1 : 1);
756: return true;
757: }
758:
759: static int checkvaltype2 (TCHAR **c, uae_u32 *val, TCHAR def)
760: {
761: TCHAR nc;
762:
763: ignore_ws (c);
764: nc = _totupper (**c);
765: if (nc == '!') {
766: (*c)++;
767: return readintx (c, val) ? 1 : 0;
768: }
769: if (nc == '$') {
770: (*c)++;
771: return readhexx (c, val) ? 1 : 0;
772: }
773: if (nc == '0' && _totupper ((*c)[1]) == 'X') {
774: (*c)+= 2;
775: return readhexx (c, val) ? 1 : 0;
776: }
777: if (nc == '%') {
778: (*c)++;
779: return readbinx (c, val) ? 1: 0;
780: }
781: if (nc >= 'A' && nc <= 'Z' && nc != 'A' && nc != 'D') {
782: if (readregx (c, val))
783: return 1;
784: }
785: if (def == '!') {
786: return readintx (c, val) ? -1 : 0;
787: return -1;
788: } else if (def == '$') {
789: return readhexx (c, val) ? -1 : 0;
790: } else if (def == '%') {
791: return readbinx (c, val) ? -1 : 0;
792: }
793: return 0;
794: }
795:
796: static int readsize (int val, TCHAR **c)
797: {
798: TCHAR cc = _totupper (readchar(c));
799: if (cc == 'B')
800: return 1;
801: if (cc == 'W')
802: return 2;
803: if (cc == '3')
804: return 3;
805: if (cc == 'L')
806: return 4;
807: return 0;
808: }
809:
810: static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def)
811: {
812: TCHAR form[256], *p;
813: bool gotop = false;
814: double out;
815:
816: form[0] = 0;
817: *size = 0;
818: p = form;
819: for (;;) {
820: uae_u32 v;
821: if (!checkvaltype2 (cp, &v, def))
822: return 0;
823: *val = v;
824: // stupid but works!
825: _stprintf(p, _T("%u"), v);
826: p += _tcslen (p);
827: if (peekchar (cp) == '.') {
828: readchar (cp);
829: *size = readsize (v, cp);
830: }
831: if (!isoperator (cp))
832: break;
833: gotop = true;
834: *p++= readchar (cp);
835: *p = 0;
836: }
837: if (!gotop) {
838: if (*size == 0) {
839: uae_s32 v = (uae_s32)(*val);
840: if (v > 255 || v < -127) {
841: *size = 2;
842: } else if (v > 65535 || v < -32767) {
843: *size = 4;
844: } else {
845: *size = 1;
846: }
847: }
848: return 1;
849: }
850: if (calc (form, &out)) {
851: *val = (uae_u32)out;
852: if (*size == 0) {
853: uae_s32 v = (uae_s32)(*val);
854: if (v > 255 || v < -127) {
855: *size = 2;
856: } else if (v > 65535 || v < -32767) {
857: *size = 4;
858: } else {
859: *size = 1;
860: }
861: }
862: return 1;
863: }
864: return 0;
865: }
866:
867:
868: static uae_u32 readnum (TCHAR **c, int *size, TCHAR def)
869: {
870: uae_u32 val;
871: if (checkvaltype (c, &val, size, def))
872: return val;
873: return 0;
874: }
875:
876: static uae_u32 readint (TCHAR **c)
877: {
878: int size;
879: return readnum (c, &size, '!');
880: }
881: static uae_u32 readhex (TCHAR **c)
882: {
883: int size;
884: return readnum (c, &size, '$');
885: }
886: static uae_u32 readbin (TCHAR **c)
887: {
888: int size;
889: return readnum (c, &size, '%');
890: }
891: static uae_u32 readint (TCHAR **c, int *size)
892: {
893: return readnum (c, size, '!');
894: }
895: static uae_u32 readhex (TCHAR **c, int *size)
896: {
897: return readnum (c, size, '$');
898: }
899:
900: static int next_string (TCHAR **c, TCHAR *out, int max, int forceupper)
901: {
902: TCHAR *p = out;
903: int startmarker = 0;
904:
905: if (**c == '\"') {
906: startmarker = 1;
907: (*c)++;
908: }
909: *p = 0;
910: while (**c != 0) {
911: if (**c == '\"' && startmarker)
912: break;
913: if (**c == 32 && !startmarker) {
914: ignore_ws (c);
915: break;
916: }
917: *p = next_char (c);
918: if (forceupper)
919: *p = _totupper(*p);
920: *++p = 0;
921: max--;
922: if (max <= 1)
923: break;
924: }
925: return _tcslen (out);
926: }
927:
928: static void converter (TCHAR **c)
929: {
930: uae_u32 v = readint (c);
931: TCHAR s[100];
932: int i;
933:
934: for (i = 0; i < 32; i++)
935: s[i] = (v & (1 << (31 - i))) ? '1' : '0';
936: s[i] = 0;
937: console_out_f (_T("0x%08X = %%%s = %u = %d\n"), v, s, v, (uae_s32)v);
938: }
939:
940: int notinrom (void)
941: {
942: uaecptr pc = munge24 (m68k_getpc ());
943: if (pc < 0x00e00000 || pc > 0x00ffffff)
944: return 1;
945: return 0;
946: }
947:
948: static uae_u32 lastaddr (void)
949: {
1.1.1.2 ! root 950: for (int i = MAX_RAM_BOARDS - 1; i >= 0; i--) {
! 951: if (currprefs.z3fastmem[i].size)
! 952: return z3fastmem_bank[i].start + currprefs.z3fastmem[i].size;
! 953: }
1.1 root 954: if (currprefs.z3chipmem_size)
955: return z3chipmem_bank.start + currprefs.z3chipmem_size;
956: if (currprefs.mbresmem_high_size)
957: return a3000hmem_bank.start + currprefs.mbresmem_high_size;
958: if (currprefs.mbresmem_low_size)
959: return a3000lmem_bank.start + currprefs.mbresmem_low_size;
960: if (currprefs.bogomem_size)
961: return bogomem_bank.start + currprefs.bogomem_size;
1.1.1.2 ! root 962: for (int i = MAX_RAM_BOARDS - 1; i >= 0; i--) {
! 963: if (currprefs.fastmem[i].size)
! 964: return fastmem_bank[i].start + currprefs.fastmem[i].size;
! 965: }
1.1 root 966: return currprefs.chipmem_size;
967: }
968:
969: static uaecptr nextaddr2 (uaecptr addr, int *next)
970: {
971: uaecptr prev, prevx;
972: int size, sizex;
973:
974: if (addr >= lastaddr ()) {
975: *next = -1;
976: return 0xffffffff;
977: }
1.1.1.2 ! root 978: prev = currprefs.z3autoconfig_start + currprefs.z3fastmem[0].size;
! 979: size = currprefs.z3fastmem[1].size;
1.1 root 980:
1.1.1.2 ! root 981: if (currprefs.z3fastmem[0].size) {
1.1 root 982: prevx = prev;
983: sizex = size;
1.1.1.2 ! root 984: size = currprefs.z3fastmem[0].size;
! 985: prev = z3fastmem_bank[0].start;
1.1 root 986: if (addr == prev + size) {
987: *next = prevx + sizex;
988: return prevx;
989: }
990: }
991: if (currprefs.z3chipmem_size) {
992: prevx = prev;
993: sizex = size;
994: size = currprefs.z3chipmem_size;
995: prev = z3chipmem_bank.start;
996: if (addr == prev + size) {
997: *next = prevx + sizex;
998: return prevx;
999: }
1000: }
1001: if (currprefs.mbresmem_high_size) {
1002: sizex = size;
1003: prevx = prev;
1004: size = currprefs.mbresmem_high_size;
1005: prev = a3000hmem_bank.start;
1006: if (addr == prev + size) {
1007: *next = prevx + sizex;
1008: return prevx;
1009: }
1010: }
1011: if (currprefs.mbresmem_low_size) {
1012: prevx = prev;
1013: sizex = size;
1014: size = currprefs.mbresmem_low_size;
1015: prev = a3000lmem_bank.start;
1016: if (addr == prev + size) {
1017: *next = prevx + sizex;
1018: return prevx;
1019: }
1020: }
1021: if (currprefs.bogomem_size) {
1022: sizex = size;
1023: prevx = prev;
1024: size = currprefs.bogomem_size;
1025: prev = bogomem_bank.start;
1026: if (addr == prev + size) {
1027: *next = prevx + sizex;
1028: return prevx;
1029: }
1030: }
1.1.1.2 ! root 1031: if (currprefs.fastmem[0].size) {
1.1 root 1032: sizex = size;
1033: prevx = prev;
1.1.1.2 ! root 1034: size = currprefs.fastmem[0].size;
! 1035: prev = fastmem_bank[0].start;
1.1 root 1036: if (addr == prev + size) {
1037: *next = prevx + sizex;
1038: return prevx;
1039: }
1040: }
1041: sizex = size;
1042: prevx = prev;
1043: size = currprefs.chipmem_size;
1044: if (addr == size) {
1045: *next = prevx + sizex;
1046: return prevx;
1047: }
1048: if (addr == 1)
1049: *next = size;
1050: return addr;
1051: }
1052:
1053: static uaecptr nextaddr (uaecptr addr, uaecptr last, uaecptr *end)
1054: {
1055: static uaecptr old;
1056: int next = last;
1057: if (last && 0) {
1058: if (addr >= last)
1059: return 0xffffffff;
1060: return addr + 1;
1061: }
1062: if (addr == 0xffffffff) {
1063: if (end)
1064: *end = currprefs.chipmem_size;
1065: return 0;
1066: }
1067: if (end)
1068: next = *end;
1069: addr = nextaddr2 (addr + 1, &next);
1070: if (end)
1071: *end = next;
1072: if (old != next) {
1073: if (addr != 0xffffffff)
1074: console_out_f (_T("Scanning.. %08x - %08x (%s)\n"), addr & 0xffffff00, next, get_mem_bank (addr).name);
1075: old = next;
1076: }
1077: #if 0
1078: if (next && addr != 0xffffffff) {
1079: uaecptr xa = addr;
1080: if (xa == 1)
1081: xa = 0;
1082: console_out_f ("%08X -> %08X (%08X)...\n", xa, xa + next - 1, next);
1083: }
1084: #endif
1085: return addr;
1086: }
1087:
1088: uaecptr dumpmem2 (uaecptr addr, TCHAR *out, int osize)
1089: {
1090: int i, cols = 8;
1091: int nonsafe = 0;
1092:
1093: if (osize <= (9 + cols * 5 + 1 + 2 * cols))
1094: return addr;
1095: _stprintf (out, _T("%08X "), addr);
1096: for (i = 0; i < cols; i++) {
1097: uae_u8 b1, b2;
1098: b1 = b2 = 0;
1099: if (safe_addr (addr, 1)) {
1100: b1 = get_byte_debug (addr + 0);
1101: b2 = get_byte_debug (addr + 1);
1102: _stprintf (out + 9 + i * 5, _T("%02X%02X "), b1, b2);
1103: out[9 + cols * 5 + 1 + i * 2 + 0] = b1 >= 32 && b1 < 127 ? b1 : '.';
1104: out[9 + cols * 5 + 1 + i * 2 + 1] = b2 >= 32 && b2 < 127 ? b2 : '.';
1105: } else {
1106: nonsafe++;
1107: _tcscpy (out + 9 + i * 5, _T("**** "));
1108: out[9 + cols * 5 + 1 + i * 2 + 0] = '*';
1109: out[9 + cols * 5 + 1 + i * 2 + 1] = '*';
1110: }
1111: addr += 2;
1112: }
1113: out[9 + cols * 5] = ' ';
1114: out[9 + cols * 5 + 1 + 2 * cols] = 0;
1115: if (nonsafe == cols) {
1116: addrbank *ab = &get_mem_bank (addr);
1117: if (ab->name)
1118: memcpy (out + (9 + 4 + 1) * sizeof (TCHAR), ab->name, _tcslen (ab->name) * sizeof (TCHAR));
1119: }
1120: return addr;
1121: }
1122:
1123: static void dumpmem (uaecptr addr, uaecptr *nxmem, int lines)
1124: {
1125: TCHAR line[MAX_LINEWIDTH + 1];
1126: for (;lines--;) {
1127: addr = dumpmem2 (addr, line, sizeof(line));
1128: debug_out (_T("%s"), line);
1129: if (!debug_out (_T("\n")))
1130: break;
1131: }
1132: *nxmem = addr;
1133: }
1134:
1135: static void dump_custom_regs (int aga)
1136: {
1137: int len, i, j, end;
1138: uae_u8 *p1, *p2, *p3, *p4;
1139:
1140: if (aga) {
1141: dump_aga_custom();
1142: return;
1143: }
1144:
1145: p1 = p2 = save_custom (&len, 0, 1);
1146: p1 += 4; // skip chipset type
1147: for (i = 0; i < 4; i++) {
1148: p4 = p1 + 0xa0 + i * 16;
1149: p3 = save_audio (i, &len, 0);
1150: p4[0] = p3[12];
1151: p4[1] = p3[13];
1152: p4[2] = p3[14];
1153: p4[3] = p3[15];
1154: p4[4] = p3[4];
1155: p4[5] = p3[5];
1156: p4[6] = p3[8];
1157: p4[7] = p3[9];
1158: p4[8] = 0;
1159: p4[9] = p3[1];
1160: p4[10] = p3[10];
1161: p4[11] = p3[11];
1162: free (p3);
1163: }
1164: end = 0;
1165: while (custd[end].name)
1166: end++;
1167: end++;
1168: end /= 2;
1169: for (i = 0; i < end; i++) {
1170: uae_u16 v1, v2;
1171: int addr1, addr2;
1172: j = end + i;
1173: addr1 = custd[i].adr & 0x1ff;
1174: addr2 = custd[j].adr & 0x1ff;
1175: v1 = (p1[addr1 + 0] << 8) | p1[addr1 + 1];
1176: v2 = (p1[addr2 + 0] << 8) | p1[addr2 + 1];
1177: console_out_f (_T("%03X %s\t%04X\t%03X %s\t%04X\n"),
1178: addr1, custd[i].name, v1,
1179: addr2, custd[j].name, v2);
1180: }
1181: free (p2);
1182: }
1183:
1184: static void dump_vectors (uaecptr addr)
1185: {
1186: int i = 0, j = 0;
1187:
1188: if (addr == 0xffffffff)
1189: addr = regs.vbr;
1190:
1191: while (int_labels[i].name || trap_labels[j].name) {
1192: if (int_labels[i].name) {
1193: console_out_f (_T("$%08X %02d: %12s $%08X "), int_labels[i].adr + addr, int_labels[i].adr / 4,
1194: int_labels[i].name, get_long_debug (int_labels[i].adr + addr));
1195: i++;
1196: }
1197: if (trap_labels[j].name) {
1198: console_out_f (_T("$%08X %02d: %12s $%08X"), trap_labels[j].adr + addr, trap_labels[j].adr / 4,
1199: trap_labels[j].name, get_long_debug (trap_labels[j].adr + addr));
1200: j++;
1201: }
1202: console_out (_T("\n"));
1203: }
1204: }
1205:
1206: static void disassemble_wait (FILE *file, unsigned long insn)
1207: {
1208: int vp, hp, ve, he, bfd, v_mask, h_mask;
1209: int doout = 0;
1210:
1211: vp = (insn & 0xff000000) >> 24;
1212: hp = (insn & 0x00fe0000) >> 16;
1213: ve = (insn & 0x00007f00) >> 8;
1214: he = (insn & 0x000000fe);
1215: bfd = (insn & 0x00008000) >> 15;
1216:
1217: /* bit15 can never be masked out*/
1218: v_mask = vp & (ve | 0x80);
1219: h_mask = hp & he;
1220: if (v_mask > 0) {
1221: doout = 1;
1222: console_out (_T("vpos "));
1223: if (ve != 0x7f) {
1224: console_out_f (_T("& 0x%02x "), ve);
1225: }
1226: console_out_f (_T(">= 0x%02x"), v_mask);
1227: }
1228: if (he > 0) {
1229: if (v_mask > 0) {
1230: console_out (_T(" and"));
1231: }
1232: console_out (_T(" hpos "));
1233: if (he != 0xfe) {
1234: console_out_f (_T("& 0x%02x "), he);
1235: }
1236: console_out_f (_T(">= 0x%02x"), h_mask);
1237: } else {
1238: if (doout)
1239: console_out (_T(", "));
1240: console_out (_T(", ignore horizontal"));
1241: }
1242:
1243: console_out_f (_T("\n \t; VP %02x, VE %02x; HP %02x, HE %02x; BFD %d\n"),
1244: vp, ve, hp, he, bfd);
1245: }
1246:
1247: #define NR_COPPER_RECORDS 100000
1248: /* Record copper activity for the debugger. */
1249: struct cop_rec
1250: {
1251: uae_u16 w1, w2;
1252: int hpos, vpos;
1253: int bhpos, bvpos;
1254: uaecptr addr;
1255: };
1256: static struct cop_rec *cop_record[2];
1257: static int nr_cop_records[2], curr_cop_set;
1258:
1259: #define NR_DMA_REC_HPOS 256
1260: #define NR_DMA_REC_VPOS 1000
1261: static struct dma_rec *dma_record[2];
1262: static int dma_record_toggle;
1263:
1264: void record_dma_reset (void)
1265: {
1266: int v, h;
1267: struct dma_rec *dr, *dr2;
1268:
1269: if (!dma_record[0])
1270: return;
1271: dma_record_toggle ^= 1;
1272: dr = dma_record[dma_record_toggle];
1273: for (v = 0; v < NR_DMA_REC_VPOS; v++) {
1274: for (h = 0; h < NR_DMA_REC_HPOS; h++) {
1275: dr2 = &dr[v * NR_DMA_REC_HPOS + h];
1276: memset (dr2, 0, sizeof (struct dma_rec));
1277: dr2->reg = 0xffff;
1278: dr2->addr = 0xffffffff;
1279: }
1280: }
1281: }
1282:
1283: void record_copper_reset (void)
1284: {
1285: /* Start a new set of copper records. */
1286: curr_cop_set ^= 1;
1287: nr_cop_records[curr_cop_set] = 0;
1288: }
1289:
1290: STATIC_INLINE uae_u32 ledcolor (uae_u32 c, uae_u32 *rc, uae_u32 *gc, uae_u32 *bc, uae_u32 *a)
1291: {
1292: uae_u32 v = rc[(c >> 16) & 0xff] | gc[(c >> 8) & 0xff] | bc[(c >> 0) & 0xff];
1293: if (a)
1294: v |= a[255 - ((c >> 24) & 0xff)];
1295: return v;
1296: }
1297:
1298: STATIC_INLINE void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8)
1299: {
1300: if (x <= 0)
1301: return;
1302:
1303: switch (bpp) {
1304: case 1:
1305: buf[x] = (uae_u8)c8;
1306: break;
1307: case 2:
1308: {
1309: uae_u16 *p = (uae_u16*)buf + x;
1310: *p = (uae_u16)c8;
1311: break;
1312: }
1313: case 3:
1314: /* no 24 bit yet */
1315: break;
1316: case 4:
1317: {
1318: uae_u32 *p = (uae_u32*)buf + x;
1319: *p = c8;
1320: break;
1321: }
1322: }
1323: }
1324:
1325: #define lc(x) ledcolor (x, xredcolors, xgreencolors, xbluecolors, NULL)
1326:
1327: static uae_u32 intlevc[] = { 0x000000, 0x444444, 0x008800, 0xffff00, 0x000088, 0x880000, 0xff0000, 0xffffff };
1.1.1.2 ! root 1328: static uae_u8 debug_colors_rgb[DMARECORD_MAX * 4];
! 1329: static uae_u32 debug_colors_l[DMARECORD_MAX];
1.1 root 1330:
1.1.1.2 ! root 1331: static void set_dbg_color(int index, uae_u8 r, uae_u8 g, uae_u8 b)
! 1332: {
! 1333: debug_colors_rgb[index * 4 + 0] = r;
! 1334: debug_colors_rgb[index * 4 + 1] = g;
! 1335: debug_colors_rgb[index * 4 + 2] = b;
! 1336: debug_colors_l[index] = lc((r << 16) | (g << 8) | (b << 0));
! 1337: }
! 1338:
! 1339: static void set_debug_colors(uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors)
! 1340: {
! 1341: set_dbg_color(0, 0x22, 0x22, 0x22);
! 1342: set_dbg_color(DMARECORD_REFRESH, 0x44, 0x44, 0x44);
! 1343: set_dbg_color(DMARECORD_CPU_D, 0xa2, 0x53, 0x42);
! 1344: set_dbg_color(DMARECORD_CPU_I, 0xad, 0x98, 0xd6);
! 1345: set_dbg_color(DMARECORD_COPPER, 0xee, 0xee, 0x00);
! 1346: set_dbg_color(DMARECORD_AUDIO, 0xff, 0x00, 0x00);
! 1347: set_dbg_color(DMARECORD_BLITTER, 0x00, 0x88, 0x88);
! 1348: set_dbg_color(DMARECORD_BLITTER_FILL, 0x00, 0x88, 0xff);
! 1349: set_dbg_color(DMARECORD_BLITTER_LINE, 0x00, 0xff, 0x00);
! 1350: set_dbg_color(DMARECORD_BITPLANE, 0x00, 0x00, 0xff);
! 1351: set_dbg_color(DMARECORD_SPRITE, 0xff, 0x00, 0xff);
! 1352: set_dbg_color(DMARECORD_DISK, 0xff, 0xff, 0xff);
! 1353: }
! 1354:
! 1355: static void debug_draw_cycles (uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors)
1.1 root 1356: {
1357: int y, x, xx, dx, xplus, yplus;
1358: struct dma_rec *dr;
1359: int t;
1360:
1361: if (debug_dma >= 4)
1362: yplus = 2;
1363: else
1364: yplus = 1;
1365: if (debug_dma >= 3)
1366: xplus = 2;
1367: else
1368: xplus = 1;
1369:
1370: t = dma_record_toggle ^ 1;
1371: y = line / yplus - 8;
1372:
1373: if (y < 0)
1374: return;
1375: if (y > maxvpos)
1376: return;
1377: if (y >= height)
1378: return;
1379:
1380: dx = width - xplus * ((maxhpos + 1) & ~1) - 16;
1381:
1382: uae_s8 intlev = 0;
1383: for (x = 0; x < maxhpos; x++) {
1.1.1.2 ! root 1384: uae_u32 c = debug_colors_l[0];
1.1 root 1385: xx = x * xplus + dx;
1386: dr = &dma_record[t][y * NR_DMA_REC_HPOS + x];
1387: if (dr->reg != 0xffff) {
1.1.1.2 ! root 1388: c = debug_colors_l[dr->type];
1.1 root 1389: }
1390: if (dr->intlev > intlev)
1391: intlev = dr->intlev;
1392: putpixel (buf, bpp, xx + 4, c);
1393: if (xplus)
1394: putpixel (buf, bpp, xx + 4 + 1, c);
1395: }
1396: putpixel (buf, bpp, dx + 0, 0);
1397: putpixel (buf, bpp, dx + 1, lc(intlevc[intlev]));
1398: putpixel (buf, bpp, dx + 2, lc(intlevc[intlev]));
1399: putpixel (buf, bpp, dx + 3, 0);
1400: }
1401:
1.1.1.2 ! root 1402: #define HEATMAP_WIDTH 256
! 1403: #define HEATMAP_HEIGHT 256
! 1404: #define HEATMAP_COUNT 32
! 1405: #define HEATMAP_DIV 8
! 1406: static const int max_heatmap = 16 * 1048576; // 16M
! 1407: static uae_u32 *heatmap_debug_colors;
! 1408:
1.1 root 1409: static struct memory_heatmap *heatmap;
1410: struct memory_heatmap
1411: {
1.1.1.2 ! root 1412: uae_u32 mask;
! 1413: uae_u32 cpucnt;
1.1 root 1414: uae_u16 cnt;
1415: uae_u16 type;
1416: };
1417:
1.1.1.2 ! root 1418: static void debug_draw_heatmap(uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors)
! 1419: {
! 1420: struct memory_heatmap *mht = heatmap;
! 1421: int dx = 16;
! 1422: int y = line;
! 1423:
! 1424: if (y < 0 || y >= HEATMAP_HEIGHT)
! 1425: return;
! 1426:
! 1427: mht += y * HEATMAP_WIDTH;
! 1428:
! 1429: for (int x = 0; x < HEATMAP_WIDTH; x++) {
! 1430: uae_u32 c = heatmap_debug_colors[mht->cnt * DMARECORD_MAX + mht->type];
! 1431: //c = heatmap_debug_colors[(HEATMAP_COUNT - 1) * DMARECORD_MAX + DMARECORD_CPU_I];
! 1432: int xx = x + dx;
! 1433: putpixel(buf, bpp, xx, c);
! 1434: if (mht->cnt > 0)
! 1435: mht->cnt--;
! 1436: mht++;
! 1437: }
! 1438: }
! 1439:
! 1440: void debug_draw(uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors)
! 1441: {
! 1442: if (!heatmap_debug_colors) {
! 1443: heatmap_debug_colors = xcalloc(uae_u32, DMARECORD_MAX * HEATMAP_COUNT);
! 1444: set_debug_colors(xredcolors, xgreencolors, xbluecolors);
! 1445: for (int i = 0; i < HEATMAP_COUNT; i++) {
! 1446: uae_u32 *cp = heatmap_debug_colors + i * DMARECORD_MAX;
! 1447: for (int j = 0; j < DMARECORD_MAX; j++) {
! 1448: uae_u8 r = debug_colors_rgb[j * 4 + 0];
! 1449: uae_u8 g = debug_colors_rgb[j * 4 + 1];
! 1450: uae_u8 b = debug_colors_rgb[j * 4 + 2];
! 1451: r = r * i / HEATMAP_COUNT;
! 1452: g = g * i / HEATMAP_COUNT;
! 1453: b = b * i / HEATMAP_COUNT;
! 1454: cp[j] = lc((r << 16) | (g << 8) | (b << 0));
! 1455: }
! 1456: }
! 1457: }
! 1458:
! 1459: if (heatmap) {
! 1460: debug_draw_heatmap(buf, bpp, line, width, height, xredcolors, xgreencolors, xbluecolors);
! 1461: } else {
! 1462: debug_draw_cycles(buf, bpp, line, width, height, xredcolors, xgreencolors, xbluecolors);
! 1463: }
! 1464: }
! 1465:
! 1466: struct heatmapstore
! 1467: {
! 1468: TCHAR *s;
! 1469: double v;
! 1470: };
! 1471:
! 1472: static void heatmap_stats(TCHAR **c)
! 1473: {
! 1474: int range = 95;
! 1475: int maxlines = 30;
! 1476: double max;
! 1477: int maxcnt;
! 1478: uae_u32 mask = MW_MASK_CPU_I;
! 1479: const TCHAR *maskname = NULL;
! 1480:
! 1481: if (more_params(c)) {
! 1482: if (**c == 'c' && peek_next_char(c) == 0) {
! 1483: for (int i = 0; i < max_heatmap / HEATMAP_DIV; i++) {
! 1484: struct memory_heatmap *hm = &heatmap[i];
! 1485: memset(hm, 0, sizeof(struct memory_heatmap));
! 1486: }
! 1487: console_out(_T("heatmap data cleared\n"));
! 1488: return;
! 1489: }
! 1490: if (!isdigit(peek_next_char(c))) {
! 1491: TCHAR str[100];
! 1492: if (next_string(c, str, sizeof str / sizeof (TCHAR), true)) {
! 1493: for (int j = 0; memwatch_access_masks[j].mask; j++) {
! 1494: if (!_tcsicmp(str, memwatch_access_masks[j].name)) {
! 1495: mask = memwatch_access_masks[j].mask;
! 1496: maskname = memwatch_access_masks[j].name;
! 1497: console_out_f(_T("Mask %08x Name %s\n"), mask, maskname);
! 1498: break;
! 1499: }
! 1500: }
! 1501: }
! 1502: if (more_params(c)) {
! 1503: maxlines = readint(c);
! 1504: }
! 1505: } else {
! 1506: range = readint(c);
! 1507: if (more_params(c)) {
! 1508: maxlines = readint(c);
! 1509: }
! 1510: }
! 1511: }
! 1512: if (maxlines <= 0)
! 1513: maxlines = 10000;
! 1514:
! 1515: if (mask != MW_MASK_CPU_I) {
! 1516:
! 1517: int found = -1;
! 1518: int firstaddress = 0;
! 1519: for (int lines = 0; lines < maxlines; lines++) {
! 1520:
! 1521: for (; firstaddress < max_heatmap / HEATMAP_DIV; firstaddress++) {
! 1522: struct memory_heatmap *hm = &heatmap[firstaddress];
! 1523: if (hm->mask & mask)
! 1524: break;
! 1525: }
! 1526:
! 1527: if (firstaddress == max_heatmap / HEATMAP_DIV)
! 1528: return;
! 1529:
! 1530: int lastaddress;
! 1531: for (lastaddress = firstaddress; lastaddress < max_heatmap / HEATMAP_DIV; lastaddress++) {
! 1532: struct memory_heatmap *hm = &heatmap[lastaddress];
! 1533: if (!(hm->mask & mask))
! 1534: break;
! 1535: }
! 1536: lastaddress--;
! 1537:
! 1538: console_out_f(_T("%03d: %08x - %08x %08x (%d) %s\n"),
! 1539: lines,
! 1540: firstaddress * HEATMAP_DIV, lastaddress * HEATMAP_DIV + HEATMAP_DIV - 1,
! 1541: lastaddress * HEATMAP_DIV - firstaddress * HEATMAP_DIV + HEATMAP_DIV - 1,
! 1542: lastaddress * HEATMAP_DIV - firstaddress * HEATMAP_DIV + HEATMAP_DIV - 1,
! 1543: maskname);
! 1544:
! 1545: firstaddress = lastaddress + 1;
! 1546: }
! 1547:
! 1548: } else {
! 1549: #define MAX_HEATMAP_LINES 1000
! 1550: struct heatmapstore linestore[MAX_HEATMAP_LINES] = { 0 };
! 1551: int storecnt = 0;
! 1552: uae_u32 maxlimit = 0xffffffff;
! 1553:
! 1554: max = 0;
! 1555: maxcnt = 0;
! 1556: for (int i = 0; i < max_heatmap / HEATMAP_DIV; i++) {
! 1557: struct memory_heatmap *hm = &heatmap[i];
! 1558: if (hm->cpucnt > 0) {
! 1559: max += hm->cpucnt;
! 1560: maxcnt++;
! 1561: }
! 1562: }
! 1563:
! 1564: if (!maxcnt) {
! 1565: console_out(_T("No CPU accesses found\n"));
! 1566: return;
! 1567: }
! 1568:
! 1569: for (int lines = 0; lines < maxlines; lines++) {
! 1570:
! 1571: int found = -1;
! 1572: int foundcnt = 0;
! 1573:
! 1574: for (int i = 0; i < max_heatmap / HEATMAP_DIV; i++) {
! 1575: struct memory_heatmap *hm = &heatmap[i];
! 1576: if (hm->cpucnt > 0 && hm->cpucnt > foundcnt && hm->cpucnt < maxlimit) {
! 1577: foundcnt = hm->cpucnt;
! 1578: found = i;
! 1579: }
! 1580: }
! 1581: if (found < 0)
! 1582: break;
! 1583:
! 1584: int totalcnt = 0;
! 1585: int cntrange = foundcnt * range / 100;
! 1586: if (cntrange <= 0)
! 1587: cntrange = 1;
! 1588:
! 1589: int lastaddress;
! 1590: for (lastaddress = found; lastaddress < max_heatmap / HEATMAP_DIV; lastaddress++) {
! 1591: struct memory_heatmap *hm = &heatmap[lastaddress];
! 1592: if (hm->cpucnt == 0 || hm->cpucnt < cntrange || hm->cpucnt >= maxlimit)
! 1593: break;
! 1594: totalcnt += hm->cpucnt;
! 1595: }
! 1596: lastaddress--;
! 1597:
! 1598: int firstaddress;
! 1599: for (firstaddress = found - 1; firstaddress >= 0; firstaddress--) {
! 1600: struct memory_heatmap *hm = &heatmap[firstaddress];
! 1601: if (hm->cpucnt == 0 || hm->cpucnt < cntrange || hm->cpucnt >= maxlimit)
! 1602: break;
! 1603: totalcnt += hm->cpucnt;
! 1604: }
! 1605: firstaddress--;
! 1606:
! 1607: firstaddress *= HEATMAP_DIV;
! 1608: lastaddress *= HEATMAP_DIV;
! 1609:
! 1610: TCHAR tmp[100];
! 1611: double pct = totalcnt / max * 100.0;
! 1612: _stprintf(tmp, _T("%03d: %08x - %08x %08x (%d) %.5f%%\n"), lines + 1,
! 1613: firstaddress, lastaddress + HEATMAP_DIV - 1,
! 1614: lastaddress - firstaddress + HEATMAP_DIV - 1,
! 1615: lastaddress - firstaddress + HEATMAP_DIV - 1,
! 1616: pct);
! 1617: linestore[storecnt].s = my_strdup(tmp);
! 1618: linestore[storecnt].v = pct;
! 1619:
! 1620: storecnt++;
! 1621: if (storecnt >= MAX_HEATMAP_LINES)
! 1622: break;
! 1623:
! 1624: maxlimit = foundcnt;
! 1625: }
! 1626:
! 1627: for (int lines1 = 0; lines1 < storecnt; lines1++) {
! 1628: for (int lines2 = lines1 + 1; lines2 < storecnt; lines2++) {
! 1629: if (linestore[lines1].v < linestore[lines2].v) {
! 1630: struct heatmapstore hms;
! 1631: memcpy(&hms, &linestore[lines1], sizeof(struct heatmapstore));
! 1632: memcpy(&linestore[lines1], &linestore[lines2], sizeof(struct heatmapstore));
! 1633: memcpy(&linestore[lines2], &hms, sizeof(struct heatmapstore));
! 1634: }
! 1635: }
! 1636: }
! 1637: for (int lines1 = 0; lines1 < storecnt; lines1++) {
! 1638: console_out(linestore[lines1].s);
! 1639: xfree(linestore[lines1].s);
! 1640: }
! 1641:
! 1642: }
! 1643:
! 1644: }
! 1645:
! 1646: static void free_heatmap(void)
! 1647: {
! 1648: xfree(heatmap);
! 1649: heatmap = NULL;
! 1650: debug_heatmap = 0;
! 1651: }
! 1652:
! 1653: static void init_heatmap(void)
1.1 root 1654: {
1.1.1.2 ! root 1655: if (!heatmap)
! 1656: heatmap = xcalloc(struct memory_heatmap, max_heatmap / HEATMAP_DIV);
1.1 root 1657: }
1658:
1.1.1.2 ! root 1659: static void memwatch_heatmap (uaecptr addr, int rwi, int size, uae_u32 accessmask)
1.1 root 1660: {
1.1.1.2 ! root 1661: if (addr >= max_heatmap || !heatmap)
1.1 root 1662: return;
1.1.1.2 ! root 1663: struct memory_heatmap *hm = &heatmap[addr / HEATMAP_DIV];
! 1664: if (accessmask & MW_MASK_CPU_I) {
! 1665: hm->cpucnt++;
! 1666: }
! 1667: hm->cnt = HEATMAP_COUNT - 1;
! 1668: int type = 0;
! 1669: for (int i = 0; i < 32; i++) {
! 1670: if (accessmask & (1 << i)) {
! 1671: switch (1 << i)
! 1672: {
! 1673: case MW_MASK_BPL_0:
! 1674: case MW_MASK_BPL_1:
! 1675: case MW_MASK_BPL_2:
! 1676: case MW_MASK_BPL_3:
! 1677: case MW_MASK_BPL_4:
! 1678: case MW_MASK_BPL_5:
! 1679: case MW_MASK_BPL_6:
! 1680: case MW_MASK_BPL_7:
! 1681: type = DMARECORD_BITPLANE;
! 1682: break;
! 1683: case MW_MASK_AUDIO_0:
! 1684: case MW_MASK_AUDIO_1:
! 1685: case MW_MASK_AUDIO_2:
! 1686: case MW_MASK_AUDIO_3:
! 1687: type = DMARECORD_AUDIO;
! 1688: break;
! 1689: case MW_MASK_BLITTER_A:
! 1690: case MW_MASK_BLITTER_B:
! 1691: case MW_MASK_BLITTER_C:
! 1692: case MW_MASK_BLITTER_D_N:
! 1693: case MW_MASK_BLITTER_D_F:
! 1694: case MW_MASK_BLITTER_D_L:
! 1695: type = DMARECORD_BLITTER;
! 1696: break;
! 1697: case MW_MASK_COPPER:
! 1698: type = DMARECORD_COPPER;
! 1699: break;
! 1700: case MW_MASK_DISK:
! 1701: type = DMARECORD_DISK;
! 1702: break;
! 1703: case MW_MASK_CPU_I:
! 1704: type = DMARECORD_CPU_I;
! 1705: break;
! 1706: case MW_MASK_CPU_D_R:
! 1707: case MW_MASK_CPU_D_W:
! 1708: type = DMARECORD_CPU_D;
! 1709: break;
! 1710: }
! 1711: }
! 1712: }
! 1713: hm->type = type;
! 1714: hm->mask |= accessmask;
1.1 root 1715: }
1716:
1717: void record_dma_event (int evt, int hpos, int vpos)
1718: {
1719: struct dma_rec *dr;
1720:
1721: if (!dma_record[0])
1722: return;
1723: if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
1724: return;
1725: dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
1726: dr->evt |= evt;
1727: }
1728:
1729: struct dma_rec *record_dma (uae_u16 reg, uae_u16 dat, uae_u32 addr, int hpos, int vpos, int type)
1730: {
1731: struct dma_rec *dr;
1732:
1733: if (!dma_record[0]) {
1734: dma_record[0] = xmalloc (struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
1735: dma_record[1] = xmalloc (struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
1736: dma_record_toggle = 0;
1737: record_dma_reset ();
1738: }
1739: if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
1740: return NULL;
1741:
1742: dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
1743: if (dr->reg != 0xffff) {
1744: write_log (_T("DMA conflict: v=%d h=%d OREG=%04X NREG=%04X\n"), vpos, hpos, dr->reg, reg);
1745: return dr;
1746: }
1747: dr->reg = reg;
1748: dr->dat = dat;
1749: dr->addr = addr;
1750: dr->type = type;
1751: dr->intlev = regs.intmask;
1752: return dr;
1753: }
1754:
1755: static void decode_dma_record (int hpos, int vpos, int toggle, bool logfile)
1756: {
1757: struct dma_rec *dr;
1758: int h, i, maxh, cnt;
1759: uae_u32 cycles;
1760:
1.1.1.2 ! root 1761: if (!dma_record[0] || hpos < 0 || vpos < 0)
1.1 root 1762: return;
1763: dr = &dma_record[dma_record_toggle ^ toggle][vpos * NR_DMA_REC_HPOS];
1764: if (logfile)
1765: write_dlog (_T("Line: %02X %3d HPOS %02X %3d:\n"), vpos, vpos, hpos, hpos);
1766: else
1767: console_out_f (_T("Line: %02X %3d HPOS %02X %3d:\n"), vpos, vpos, hpos, hpos);
1768: h = hpos;
1769: dr += hpos;
1770: maxh = hpos + 80;
1771: if (maxh > maxhpos)
1772: maxh = maxhpos;
1773: cycles = vsync_cycles;
1774: if (toggle)
1775: cycles -= maxvpos * maxhpos * CYCLE_UNIT;
1776: cnt = 0;
1777: while (h < maxh) {
1778: int col = 9;
1779: int cols = 8;
1780: TCHAR l1[81];
1781: TCHAR l2[81];
1782: TCHAR l3[81];
1783: TCHAR l4[81];
1784: TCHAR l5[81];
1785: for (i = 0; i < cols && h < maxh; i++, h++, dr++) {
1786: int cl = i * col, cl2;
1787: int r = dr->reg;
1788: bool longsize = false;
1.1.1.2 ! root 1789: const TCHAR *sr;
1.1 root 1790:
1791: sr = _T(" ");
1792: if (dr->type == DMARECORD_COPPER)
1793: sr = _T("COP ");
1794: else if (dr->type == DMARECORD_BLITTER)
1795: sr = _T("BLT ");
1796: else if (dr->type == DMARECORD_BLITTER_LINE)
1797: sr = _T("BLL ");
1798: else if (dr->type == DMARECORD_REFRESH)
1799: sr = _T("RFS ");
1800: else if (dr->type == DMARECORD_AUDIO)
1801: sr = _T("AUD ");
1802: else if (dr->type == DMARECORD_DISK)
1803: sr = _T("DSK ");
1804: else if (dr->type == DMARECORD_SPRITE)
1805: sr = _T("SPR ");
1806: _stprintf (l1 + cl, _T("[%02X %3d]"), h, h);
1807: _tcscpy (l4 + cl, _T(" "));
1808: if (r != 0xffff) {
1809: if (r & 0x1000) {
1810: if ((r & 0x0100) == 0x0000)
1811: _tcscpy (l2 + cl, _T(" CPU-R "));
1812: else if ((r & 0x0100) == 0x0100)
1813: _tcscpy (l2 + cl, _T(" CPU-W "));
1814: if ((r & 0xff) == 4) {
1815: l2[cl + 7] = 'L';
1816: longsize = true;
1817: }
1818: if ((r & 0xff) == 2)
1819: l2[cl + 7] = 'W';
1820: if ((r & 0xff) == 1)
1821: l2[cl + 7] = 'B';
1822: } else {
1823: _stprintf (l2 + cl, _T("%4s %03X"), sr, r);
1824: }
1825: _stprintf (l3 + cl, longsize ? _T("%08X") : _T(" %04X"), dr->dat);
1826: if (dr->addr != 0xffffffff)
1827: _stprintf (l4 + cl, _T("%08X"), dr->addr & 0x00ffffff);
1828: } else {
1829: _tcscpy (l2 + cl, _T(" "));
1830: _tcscpy (l3 + cl, _T(" "));
1831: }
1832: cl2 = cl;
1833: if (dr->evt & DMA_EVENT_BLITNASTY)
1834: l3[cl2++] = 'N';
1835: if (dr->evt & DMA_EVENT_BLITSTARTFINISH)
1836: l3[cl2++] = 'B';
1837: if (dr->evt & DMA_EVENT_BLITIRQ)
1838: l3[cl2++] = 'b';
1839: if (dr->evt & DMA_EVENT_BPLFETCHUPDATE)
1840: l3[cl2++] = 'p';
1841: if (dr->evt & DMA_EVENT_COPPERWAKE)
1842: l3[cl2++] = 'W';
1843: if (dr->evt & DMA_EVENT_COPPERWANTED)
1844: l3[cl2++] = 'c';
1845: if (dr->evt & DMA_EVENT_CPUIRQ)
1846: l3[cl2++] = 'I';
1847: if (dr->evt & DMA_EVENT_INTREQ)
1848: l3[cl2++] = 'i';
1.1.1.2 ! root 1849: if (dr->evt & DMA_EVENT_SPECIAL)
! 1850: l3[cl2++] = 'X';
1.1 root 1851: _stprintf (l5 + cl, _T("%08X"), cycles + (vpos * maxhpos + (hpos + cnt)) * CYCLE_UNIT);
1852: if (i < cols - 1 && h < maxh - 1) {
1853: l1[cl + col - 1] = 32;
1854: l2[cl + col - 1] = 32;
1855: l3[cl + col - 1] = 32;
1856: l4[cl + col - 1] = 32;
1857: l5[cl + col - 1] = 32;
1858: }
1859: cnt++;
1860: }
1861: if (logfile) {
1862: write_dlog (_T("%s\n"), l1);
1863: write_dlog (_T("%s\n"), l2);
1864: write_dlog (_T("%s\n"), l3);
1865: write_dlog (_T("%s\n"), l4);
1866: write_dlog (_T("%s\n"), l5);
1867: write_dlog (_T("\n"));
1868: } else {
1869: console_out_f (_T("%s\n"), l1);
1870: console_out_f (_T("%s\n"), l2);
1871: console_out_f (_T("%s\n"), l3);
1872: console_out_f (_T("%s\n"), l4);
1873: console_out_f (_T("%s\n"), l5);
1874: console_out_f (_T("\n"));
1875: }
1876: }
1877: }
1878: void log_dma_record (void)
1879: {
1880: if (!input_record && !input_play)
1881: return;
1882: if (!debug_dma)
1883: debug_dma = 1;
1884: decode_dma_record (0, 0, 0, true);
1885: }
1886:
1887: static void init_record_copper(void)
1888: {
1889: if (!cop_record[0]) {
1890: cop_record[0] = xmalloc(struct cop_rec, NR_COPPER_RECORDS);
1891: cop_record[1] = xmalloc(struct cop_rec, NR_COPPER_RECORDS);
1892: }
1893: }
1894:
1895: void record_copper_blitwait (uaecptr addr, int hpos, int vpos)
1896: {
1897: int t = nr_cop_records[curr_cop_set];
1898: init_record_copper();
1899: cop_record[curr_cop_set][t].bhpos = hpos;
1900: cop_record[curr_cop_set][t].bvpos = vpos;
1901: }
1902:
1903: void record_copper (uaecptr addr, uae_u16 word1, uae_u16 word2, int hpos, int vpos)
1904: {
1905: int t = nr_cop_records[curr_cop_set];
1906: init_record_copper();
1907: if (t < NR_COPPER_RECORDS) {
1908: cop_record[curr_cop_set][t].addr = addr;
1909: cop_record[curr_cop_set][t].w1 = word1;
1910: cop_record[curr_cop_set][t].w2 = word2;
1911: cop_record[curr_cop_set][t].hpos = hpos;
1912: cop_record[curr_cop_set][t].vpos = vpos;
1913: cop_record[curr_cop_set][t].bvpos = -1;
1914: nr_cop_records[curr_cop_set] = t + 1;
1915: }
1916: if (debug_copper & 2) { /* trace */
1917: debug_copper &= ~2;
1918: activate_debugger ();
1919: }
1920: if ((debug_copper & 4) && addr >= debug_copper_pc && addr <= debug_copper_pc + 3) {
1921: debug_copper &= ~4;
1922: activate_debugger ();
1923: }
1924: }
1925:
1926: static struct cop_rec *find_copper_records (uaecptr addr)
1927: {
1928: int s = curr_cop_set ^ 1;
1929: int t = nr_cop_records[s];
1930: int i;
1931: for (i = 0; i < t; i++) {
1932: if (cop_record[s][i].addr == addr)
1933: return &cop_record[s][i];
1934: }
1935: return 0;
1936: }
1937:
1938: /* simple decode copper by Mark Cox */
1939: static void decode_copper_insn (FILE* file, uae_u16 mword1, uae_u16 mword2, unsigned long addr)
1940: {
1941: struct cop_rec *cr = NULL;
1942: uae_u32 insn_type, insn;
1943: TCHAR here = ' ';
1944: TCHAR record[] = _T(" ");
1945:
1946: if ((cr = find_copper_records (addr))) {
1947: _stprintf (record, _T(" [%03x %03x]"), cr->vpos, cr->hpos);
1948: insn = (cr->w1 << 16) | cr->w2;
1949: } else {
1950: insn = (mword1 << 16) | mword2;
1951: }
1952:
1953: insn_type = insn & 0x00010001;
1954:
1955: if (get_copper_address (-1) >= addr && get_copper_address(-1) <= addr + 3)
1956: here = '*';
1957:
1958: console_out_f (_T("%c%08x: %04x %04x%s\t;%c "), here, addr, insn >> 16, insn & 0xFFFF, record, insn != ((mword1 << 16) | mword2) ? '!' : ' ');
1959:
1960: switch (insn_type) {
1961: case 0x00010000: /* WAIT insn */
1962: console_out (_T("Wait for "));
1963: disassemble_wait (file, insn);
1964:
1965: if (insn == 0xfffffffe)
1966: console_out (_T(" \t; End of Copperlist\n"));
1967:
1968: break;
1969:
1970: case 0x00010001: /* SKIP insn */
1971: console_out (_T("Skip if "));
1972: disassemble_wait (file, insn);
1973: break;
1974:
1975: case 0x00000000:
1976: case 0x00000001: /* MOVE insn */
1977: {
1978: int addr = (insn >> 16) & 0x1fe;
1979: int i = 0;
1980: while (custd[i].name) {
1981: if (custd[i].adr == addr + 0xdff000)
1982: break;
1983: i++;
1984: }
1985: if (custd[i].name)
1986: console_out_f (_T("%s := 0x%04x\n"), custd[i].name, insn & 0xffff);
1987: else
1988: console_out_f (_T("%04x := 0x%04x\n"), addr, insn & 0xffff);
1989: }
1990: break;
1991:
1992: default:
1993: abort ();
1994: }
1995:
1996: if (cr && cr->bvpos >= 0) {
1997: console_out_f (_T(" BLT [%03x %03x]\n"), cr->bvpos, cr->bhpos);
1998: }
1999: }
2000:
2001: static uaecptr decode_copperlist (FILE* file, uaecptr address, int nolines)
2002: {
2003: while (nolines-- > 0) {
2004: decode_copper_insn (file, chipmem_wget_indirect (address), chipmem_wget_indirect (address + 2), address);
2005: address += 4;
2006: }
2007: return address;
2008: /* You may wonder why I don't stop this at the end of the copperlist?
2009: * Well, often nice things are hidden at the end and it is debatable the actual
2010: * values that mean the end of the copperlist */
2011: }
2012:
2013: static int copper_debugger (TCHAR **c)
2014: {
2015: static uaecptr nxcopper;
2016: uae_u32 maddr;
2017: int lines;
2018:
2019: if (**c == 'd') {
2020: next_char (c);
2021: if (debug_copper)
2022: debug_copper = 0;
2023: else
2024: debug_copper = 1;
2025: console_out_f (_T("Copper debugger %s.\n"), debug_copper ? _T("enabled") : _T("disabled"));
2026: } else if (**c == 't') {
2027: debug_copper = 1|2;
2028: return 1;
2029: } else if (**c == 'b') {
2030: (*c)++;
2031: debug_copper = 1|4;
2032: if (more_params (c)) {
2033: debug_copper_pc = readhex (c);
2034: console_out_f (_T("Copper breakpoint @0x%08x\n"), debug_copper_pc);
2035: } else {
2036: debug_copper &= ~4;
2037: }
2038: } else {
2039: if (more_params (c)) {
2040: maddr = readhex (c);
2041: if (maddr == 1 || maddr == 2)
2042: maddr = get_copper_address (maddr);
2043: else if (maddr == 0)
2044: maddr = get_copper_address (-1);
2045: } else
2046: maddr = nxcopper;
2047:
2048: if (more_params (c))
2049: lines = readhex (c);
2050: else
2051: lines = 20;
2052:
2053: nxcopper = decode_copperlist (stdout, maddr, lines);
2054: }
2055: return 0;
2056: }
2057:
2058: #define MAX_CHEAT_VIEW 100
2059: struct trainerstruct {
2060: uaecptr addr;
2061: int size;
2062: };
2063:
2064: static struct trainerstruct *trainerdata;
2065: static int totaltrainers;
2066:
2067: static void clearcheater(void)
2068: {
2069: if (!trainerdata)
2070: trainerdata = xmalloc(struct trainerstruct, MAX_CHEAT_VIEW);
2071: memset(trainerdata, 0, sizeof (struct trainerstruct) * MAX_CHEAT_VIEW);
2072: totaltrainers = 0;
2073: }
2074: static int addcheater(uaecptr addr, int size)
2075: {
2076: if (totaltrainers >= MAX_CHEAT_VIEW)
2077: return 0;
2078: trainerdata[totaltrainers].addr = addr;
2079: trainerdata[totaltrainers].size = size;
2080: totaltrainers++;
2081: return 1;
2082: }
2083: static void listcheater(int mode, int size)
2084: {
2085: int i, skip;
2086:
2087: if (!trainerdata)
2088: return;
2089: if (mode)
2090: skip = 6;
2091: else
2092: skip = 8;
2093: for(i = 0; i < totaltrainers; i++) {
2094: struct trainerstruct *ts = &trainerdata[i];
2095: uae_u16 b;
2096:
2097: if (size) {
2098: b = get_byte_debug (ts->addr);
2099: } else {
2100: b = get_word_debug (ts->addr);
2101: }
2102: if (mode)
2103: console_out_f (_T("%08X=%04X "), ts->addr, b);
2104: else
2105: console_out_f (_T("%08X "), ts->addr);
2106: if ((i % skip) == skip)
2107: console_out (_T("\n"));
2108: }
2109: }
2110:
2111: static void deepcheatsearch (TCHAR **c)
2112: {
2113: static int first = 1;
2114: static uae_u8 *memtmp;
2115: static int memsize, memsize2;
2116: uae_u8 *p1, *p2;
2117: uaecptr addr, end;
2118: int i, wasmodified, nonmodified;
2119: static int size;
2120: static int inconly, deconly, maxdiff;
2121: int addrcnt, cnt;
2122: TCHAR v;
2123:
2124: v = _totupper (**c);
2125:
2126: if(!memtmp || v == 'S') {
2127: maxdiff = 0x10000;
2128: inconly = 0;
2129: deconly = 0;
2130: size = 1;
2131: }
2132:
2133: if (**c)
2134: (*c)++;
2135: ignore_ws (c);
2136: if ((**c) == '1' || (**c) == '2') {
2137: size = **c - '0';
2138: (*c)++;
2139: }
2140: if (more_params (c))
2141: maxdiff = readint (c);
2142:
2143: if (!memtmp || v == 'S') {
2144: first = 1;
2145: xfree (memtmp);
2146: memsize = 0;
2147: addr = 0xffffffff;
2148: while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
2149: memsize += end - addr;
2150: addr = end - 1;
2151: }
2152: memsize2 = (memsize + 7) / 8;
2153: memtmp = xmalloc (uae_u8, memsize + memsize2);
2154: if (!memtmp)
2155: return;
2156: memset (memtmp + memsize, 0xff, memsize2);
2157: p1 = memtmp;
2158: addr = 0xffffffff;
2159: while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
2160: for (i = addr; i < end; i++)
2161: *p1++ = get_byte_debug (i);
2162: addr = end - 1;
2163: }
2164: console_out (_T("Deep trainer first pass complete.\n"));
2165: return;
2166: }
2167: inconly = deconly = 0;
2168: wasmodified = v == 'X' ? 0 : 1;
2169: nonmodified = v == 'Z' ? 1 : 0;
2170: if (v == 'I')
2171: inconly = 1;
2172: if (v == 'D')
2173: deconly = 1;
2174: p1 = memtmp;
2175: p2 = memtmp + memsize;
2176: addrcnt = 0;
2177: cnt = 0;
2178: addr = 0xffffffff;
2179: while ((addr = nextaddr (addr, 0, NULL)) != 0xffffffff) {
2180: uae_s32 b, b2;
2181: int doremove = 0;
2182: int addroff = addrcnt >> 3;
2183: int addrmask ;
2184:
2185: if (size == 1) {
2186: b = (uae_s8)get_byte_debug (addr);
2187: b2 = (uae_s8)p1[addrcnt];
2188: addrmask = 1 << (addrcnt & 7);
2189: } else {
2190: b = (uae_s16)get_word_debug (addr);
2191: b2 = (uae_s16)((p1[addrcnt] << 8) | p1[addrcnt + 1]);
2192: addrmask = 3 << (addrcnt & 7);
2193: }
2194:
2195: if (p2[addroff] & addrmask) {
2196: if (wasmodified && !nonmodified) {
2197: int diff = b - b2;
2198: if (b == b2)
2199: doremove = 1;
2200: if (abs(diff) > maxdiff)
2201: doremove = 1;
2202: if (inconly && diff < 0)
2203: doremove = 1;
2204: if (deconly && diff > 0)
2205: doremove = 1;
2206: } else if (nonmodified && b == b2) {
2207: doremove = 1;
2208: } else if (!wasmodified && b != b2) {
2209: doremove = 1;
2210: }
2211: if (doremove)
2212: p2[addroff] &= ~addrmask;
2213: else
2214: cnt++;
2215: }
2216: if (size == 1) {
2217: p1[addrcnt] = b;
2218: addrcnt++;
2219: } else {
2220: p1[addrcnt] = b >> 8;
2221: p1[addrcnt + 1] = b >> 0;
2222: addr = nextaddr (addr, 0, NULL);
2223: if (addr == 0xffffffff)
2224: break;
2225: addrcnt += 2;
2226: }
2227: if (iscancel (65536)) {
2228: console_out_f (_T("Aborted at %08X\n"), addr);
2229: break;
2230: }
2231: }
2232:
2233: console_out_f (_T("%d addresses found\n"), cnt);
2234: if (cnt <= MAX_CHEAT_VIEW) {
2235: clearcheater ();
2236: cnt = 0;
2237: addrcnt = 0;
2238: addr = 0xffffffff;
2239: while ((addr = nextaddr(addr, 0, NULL)) != 0xffffffff) {
2240: int addroff = addrcnt >> 3;
2241: int addrmask = (size == 1 ? 1 : 3) << (addrcnt & 7);
2242: if (p2[addroff] & addrmask)
2243: addcheater (addr, size);
2244: addrcnt += size;
2245: cnt++;
2246: }
2247: if (cnt > 0)
2248: console_out (_T("\n"));
2249: listcheater (1, size);
2250: } else {
2251: console_out (_T("Now continue with 'g' and use 'D' again after you have lost another life\n"));
2252: }
2253: }
2254:
2255: /* cheat-search by Toni Wilen (originally by Holger Jakob) */
2256: static void cheatsearch (TCHAR **c)
2257: {
2258: static uae_u8 *vlist;
2259: static int listsize;
2260: static int first = 1;
2261: static int size = 1;
2262: uae_u32 val, memcnt, prevmemcnt;
2263: int i, count, vcnt, memsize;
2264: uaecptr addr, end;
2265:
2266: memsize = 0;
2267: addr = 0xffffffff;
2268: while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
2269: memsize += end - addr;
2270: addr = end - 1;
2271: }
2272:
2273: if (_totupper (**c) == 'L') {
2274: listcheater (1, size);
2275: return;
2276: }
2277: ignore_ws (c);
2278: if (!more_params (c)) {
2279: first = 1;
2280: console_out (_T("Search reset\n"));
2281: xfree (vlist);
2282: listsize = memsize;
2283: vlist = xcalloc (uae_u8, listsize >> 3);
2284: return;
2285: }
2286: if (first)
2287: val = readint (c, &size);
2288: else
2289: val = readint (c);
2290:
2291: if (vlist == NULL) {
2292: listsize = memsize;
2293: vlist = xcalloc (uae_u8, listsize >> 3);
2294: }
2295:
2296: count = 0;
2297: vcnt = 0;
2298:
2299: clearcheater ();
2300: addr = 0xffffffff;
2301: prevmemcnt = memcnt = 0;
2302: while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
2303: if (addr + size < end) {
2304: for (i = 0; i < size; i++) {
2305: int shift = (size - i - 1) * 8;
2306: if (get_byte_debug (addr + i) != ((val >> shift) & 0xff))
2307: break;
2308: }
2309: if (i == size) {
2310: int voffset = memcnt >> 3;
2311: int vmask = 1 << (memcnt & 7);
2312: if (!first) {
2313: while (prevmemcnt < memcnt) {
2314: vlist[prevmemcnt >> 3] &= ~(1 << (prevmemcnt & 7));
2315: prevmemcnt++;
2316: }
2317: if (vlist[voffset] & vmask) {
2318: count++;
2319: addcheater(addr, size);
2320: } else {
2321: vlist[voffset] &= ~vmask;
2322: }
2323: prevmemcnt = memcnt + 1;
2324: } else {
2325: vlist[voffset] |= vmask;
2326: count++;
2327: }
2328: }
2329: }
2330: memcnt++;
2331: if (iscancel (65536)) {
2332: console_out_f (_T("Aborted at %08X\n"), addr);
2333: break;
2334: }
2335: }
2336: if (!first) {
2337: while (prevmemcnt < memcnt) {
2338: vlist[prevmemcnt >> 3] &= ~(1 << (prevmemcnt & 7));
2339: prevmemcnt++;
2340: }
2341: listcheater (0, size);
2342: }
2343: console_out_f (_T("Found %d possible addresses with 0x%X (%u) (%d bytes)\n"), count, val, val, size);
2344: if (count > 0)
2345: console_out (_T("Now continue with 'g' and use 'C' with a different value\n"));
2346: first = 0;
2347: }
2348:
2349: struct breakpoint_node bpnodes[BREAKPOINT_TOTAL];
2350: static addrbank **debug_mem_banks;
2351: static addrbank *debug_mem_area;
2352: struct memwatch_node mwnodes[MEMWATCH_TOTAL];
2353: static struct memwatch_node mwhit;
2354:
2355: static uae_u8 *illgdebug, *illghdebug;
2356: static int illgdebug_break;
2357:
2358: static void illg_free (void)
2359: {
2360: xfree (illgdebug);
2361: illgdebug = NULL;
2362: xfree (illghdebug);
2363: illghdebug = NULL;
2364: }
2365:
2366: static void illg_init (void)
2367: {
2368: int i;
2369: uae_u8 c = 3;
2370: uaecptr addr, end;
2371:
2372: illgdebug = xcalloc (uae_u8, 0x01000000);
2373: illghdebug = xcalloc (uae_u8, 65536);
2374: if (!illgdebug || !illghdebug) {
2375: illg_free();
2376: return;
2377: }
2378: addr = 0xffffffff;
2379: while ((addr = nextaddr (addr, 0, &end)) != 0xffffffff) {
2380: if (end < 0x01000000) {
2381: memset (illgdebug + addr, c, end - addr);
2382: } else {
2383: uae_u32 s = addr >> 16;
2384: uae_u32 e = end >> 16;
2385: memset (illghdebug + s, c, e - s);
2386: }
2387: addr = end - 1;
2388: }
1.1.1.2 ! root 2389: for (int i = 0; i < MAX_RTG_BOARDS; i++) {
! 2390: if (currprefs.rtgboards[i].rtgmem_size)
! 2391: memset (illghdebug + (gfxmem_banks[i]->start >> 16), 3, currprefs.rtgboards[i].rtgmem_size >> 16);
! 2392: }
1.1 root 2393:
2394: i = 0;
2395: while (custd[i].name) {
2396: int rw = custd[i].rw;
2397: illgdebug[custd[i].adr] = rw;
2398: illgdebug[custd[i].adr + 1] = rw;
2399: i++;
2400: }
2401: for (i = 0; i < 16; i++) { /* CIAs */
2402: if (i == 11)
2403: continue;
2404: illgdebug[0xbfe001 + i * 0x100] = c;
2405: illgdebug[0xbfd000 + i * 0x100] = c;
2406: }
2407: memset (illgdebug + 0xf80000, 1, 512 * 1024); /* KS ROM */
2408: memset (illgdebug + 0xdc0000, c, 0x3f); /* clock */
2409: #ifdef CDTV
2410: if (currprefs.cs_cdtvram) {
2411: memset (illgdebug + 0xdc8000, c, 4096); /* CDTV batt RAM */
2412: memset (illgdebug + 0xf00000, 1, 256 * 1024); /* CDTV ext ROM */
2413: }
2414: #endif
2415: #ifdef CD32
2416: if (currprefs.cs_cd32cd) {
2417: memset (illgdebug + AKIKO_BASE, c, AKIKO_BASE_END - AKIKO_BASE);
2418: memset (illgdebug + 0xe00000, 1, 512 * 1024); /* CD32 ext ROM */
2419: }
2420: #endif
2421: if (currprefs.cs_ksmirror_e0)
2422: memset (illgdebug + 0xe00000, 1, 512 * 1024);
2423: if (currprefs.cs_ksmirror_a8)
2424: memset (illgdebug + 0xa80000, 1, 2 * 512 * 1024);
2425: #ifdef FILESYS
2426: if (uae_boot_rom_type) /* filesys "rom" */
2427: memset (illgdebug + rtarea_base, 1, 0x10000);
2428: #endif
2429: if (currprefs.cs_ide > 0)
2430: memset (illgdebug + 0xdd0000, 3, 65536);
2431: }
2432:
2433: /* add special custom register check here */
2434: static void illg_debug_check (uaecptr addr, int rwi, int size, uae_u32 val)
2435: {
2436: return;
2437: }
2438:
2439: static void illg_debug_do (uaecptr addr, int rwi, int size, uae_u32 val)
2440: {
2441: uae_u8 mask;
2442: uae_u32 pc = m68k_getpc ();
2443: int i;
2444:
2445: for (i = size - 1; i >= 0; i--) {
2446: uae_u8 v = val >> (i * 8);
2447: uae_u32 ad = addr + i;
2448: if (ad >= 0x01000000)
2449: mask = illghdebug[ad >> 16];
2450: else
2451: mask = illgdebug[ad];
2452: if ((mask & 3) == 3)
2453: return;
2454: if (mask & 0x80) {
2455: illg_debug_check (ad, rwi, size, val);
2456: } else if ((mask & 3) == 0) {
2457: if (rwi & 2)
2458: console_out_f (_T("W: %08X=%02X PC=%08X\n"), ad, v, pc);
2459: else if (rwi & 1)
2460: console_out_f (_T("R: %08X PC=%08X\n"), ad, pc);
2461: if (illgdebug_break)
2462: activate_debugger ();
2463: } else if (!(mask & 1) && (rwi & 1)) {
2464: console_out_f (_T("RO: %08X=%02X PC=%08X\n"), ad, v, pc);
2465: if (illgdebug_break)
2466: activate_debugger ();
2467: } else if (!(mask & 2) && (rwi & 2)) {
2468: console_out_f (_T("WO: %08X PC=%08X\n"), ad, pc);
2469: if (illgdebug_break)
2470: activate_debugger ();
2471: }
2472: }
2473: }
2474:
2475: static int debug_mem_off (uaecptr *addrp)
2476: {
2477: uaecptr addr = *addrp;
2478: addrbank *ba;
2479: int offset = munge24 (addr) >> 16;
2480: if (!debug_mem_banks)
2481: return offset;
2482: ba = debug_mem_banks[offset];
2483: if (!ba)
2484: return offset;
2485: if (ba->mask || ba->startmask)
2486: addr = (addr & ba->mask) | ba->startmask;
2487: *addrp = addr;
2488: return offset;
2489: }
2490:
2491: struct smc_item {
2492: uae_u32 addr;
2493: uae_u8 cnt;
2494: };
2495:
2496: static int smc_size, smc_mode;
2497: static struct smc_item *smc_table;
2498:
2499: static void smc_free (void)
2500: {
2501: if (smc_table)
2502: console_out (_T("SMCD disabled\n"));
2503: xfree(smc_table);
2504: smc_mode = 0;
2505: smc_table = NULL;
2506: }
2507:
2508: static void initialize_memwatch (int mode);
2509: static void smc_detect_init (TCHAR **c)
2510: {
2511: int v, i;
2512:
2513: ignore_ws (c);
2514: v = readint (c);
2515: smc_free ();
2516: smc_size = 1 << 24;
1.1.1.2 ! root 2517: if (currprefs.z3fastmem[0].size)
! 2518: smc_size = currprefs.z3autoconfig_start + currprefs.z3fastmem[0].size;
1.1 root 2519: smc_size += 4;
2520: smc_table = xmalloc (struct smc_item, smc_size);
2521: if (!smc_table)
2522: return;
2523: for (i = 0; i < smc_size; i++) {
2524: smc_table[i].addr = 0xffffffff;
2525: smc_table[i].cnt = 0;
2526: }
2527: if (!memwatch_enabled)
2528: initialize_memwatch (0);
2529: if (v)
2530: smc_mode = 1;
2531: console_out_f (_T("SMCD enabled. Break=%d\n"), smc_mode);
2532: }
2533:
2534: #define SMC_MAXHITS 8
2535: static void smc_detector (uaecptr addr, int rwi, int size, uae_u32 *valp)
2536: {
2537: int i, hitcnt;
2538: uaecptr hitaddr, hitpc;
2539:
2540: if (!smc_table)
2541: return;
2542: if (addr >= smc_size)
2543: return;
2544: if (rwi == 2) {
2545: for (i = 0; i < size; i++) {
2546: if (smc_table[addr + i].cnt < SMC_MAXHITS) {
2547: smc_table[addr + i].addr = m68k_getpc ();
2548: }
2549: }
2550: return;
2551: }
2552: hitpc = smc_table[addr].addr;
2553: if (hitpc == 0xffffffff)
2554: return;
2555: hitaddr = addr;
2556: hitcnt = 0;
2557: while (addr < smc_size && smc_table[addr].addr != 0xffffffff) {
2558: smc_table[addr++].addr = 0xffffffff;
2559: hitcnt++;
2560: }
2561: if ((hitpc & 0xFFF80000) == 0xF80000)
2562: return;
2563: if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) {
2564: /* ignore single-word unconditional jump instructions
2565: * (instruction prefetch from PC+2 can cause false positives) */
2566: if (regs.irc == 0x4e75 || regs.irc == 4e74 || regs.irc == 0x4e72 || regs.irc == 0x4e77)
2567: return; /* RTS, RTD, RTE, RTR */
2568: if ((regs.irc & 0xff00) == 0x6000 && (regs.irc & 0x00ff) != 0 && (regs.irc & 0x00ff) != 0xff)
2569: return; /* BRA.B */
2570: }
2571: if (hitcnt < 100) {
2572: smc_table[hitaddr].cnt++;
2573: console_out_f (_T("SMC at %08X - %08X (%d) from %08X\n"),
2574: hitaddr, hitaddr + hitcnt, hitcnt, hitpc);
2575: if (smc_mode)
2576: activate_debugger ();
2577: if (smc_table[hitaddr].cnt >= SMC_MAXHITS)
2578: console_out_f (_T("* hit count >= %d, future hits ignored\n"), SMC_MAXHITS);
2579: }
2580: }
2581:
2582: uae_u8 *save_debug_memwatch (int *len, uae_u8 *dstptr)
2583: {
2584: uae_u8 *dstbak, *dst;
2585: int total;
2586:
2587: total = 0;
2588: for (int i = 0; i < MEMWATCH_TOTAL; i++) {
2589: if (mwnodes[i].size > 0)
2590: total++;
2591: }
2592: if (!total)
2593: return NULL;
2594:
2595: if (dstptr)
2596: dstbak = dst = dstptr;
2597: else
2598: dstbak = dst = xmalloc (uae_u8, 1000);
2599: save_u32 (1);
2600: save_u8 (total);
2601: for (int i = 0; i < MEMWATCH_TOTAL; i++) {
2602: struct memwatch_node *m = &mwnodes[i];
2603: if (m->size <= 0)
2604: continue;
2605: save_store_pos ();
2606: save_u8 (i);
2607: save_u8 (m->modval_written);
2608: save_u8 (m->mustchange);
2609: save_u8 (m->frozen);
2610: save_u8 (m->val_enabled);
2611: save_u8 (m->rwi);
2612: save_u32 (m->addr);
2613: save_u32 (m->size);
2614: save_u32 (m->modval);
2615: save_u32 (m->val_mask);
2616: save_u32 (m->val_size);
2617: save_u32 (m->val);
2618: save_u32 (m->pc);
2619: save_u32 (m->access_mask);
2620: save_u32 (m->reg);
2621: save_store_size ();
2622: }
2623: *len = dst - dstbak;
2624: return dstbak;
2625: }
2626:
2627: uae_u8 *restore_debug_memwatch (uae_u8 *src)
2628: {
2629: if (restore_u32 () != 1)
2630: return src;
2631: int total = restore_u8 ();
2632: for (int i = 0; i < total; i++) {
2633: restore_store_pos ();
2634: int idx = restore_u8 ();
2635: struct memwatch_node *m = &mwnodes[idx];
2636: m->modval_written = restore_u8 ();
2637: m->mustchange = restore_u8 ();
2638: m->frozen = restore_u8 ();
2639: m->val_enabled = restore_u8 ();
2640: m->rwi = restore_u8 ();
2641: m->addr = restore_u32 ();
2642: m->size = restore_u32 ();
2643: m->modval = restore_u32 ();
2644: m->val_mask = restore_u32 ();
2645: m->val_size = restore_u32 ();
2646: m->val = restore_u32 ();
2647: m->pc = restore_u32 ();
2648: m->access_mask = restore_u32();
2649: m->reg = restore_u32();
2650: restore_store_size ();
2651: }
2652: return src;
2653: }
2654:
2655: void restore_debug_memwatch_finish (void)
2656: {
2657: for (int i = 0; i < MEMWATCH_TOTAL; i++) {
2658: struct memwatch_node *m = &mwnodes[i];
2659: if (m->size) {
2660: if (!memwatch_enabled)
2661: initialize_memwatch (0);
2662: return;
2663: }
2664: }
2665: }
2666:
2667: static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u32 accessmask, uae_u32 reg)
2668: {
2669: int i, brk;
2670: uae_u32 val = *valp;
2671:
2672: if (illgdebug)
2673: illg_debug_do (addr, rwi, size, val);
2674:
1.1.1.2 ! root 2675: if (heatmap)
! 2676: memwatch_heatmap (addr, rwi, size, accessmask);
1.1 root 2677:
2678: addr = munge24 (addr);
2679: if (smc_table && (rwi >= 2))
2680: smc_detector (addr, rwi, size, valp);
2681: for (i = 0; i < MEMWATCH_TOTAL; i++) {
2682: struct memwatch_node *m = &mwnodes[i];
2683: uaecptr addr2 = m->addr;
2684: uaecptr addr3 = addr2 + m->size;
2685: int rwi2 = m->rwi;
2686: uae_u32 oldval = 0;
2687: int isoldval = 0;
2688:
2689: brk = 0;
2690: if (m->size == 0)
2691: continue;
2692: if (!(rwi & rwi2))
2693: continue;
2694: if (!(m->access_mask & accessmask))
2695: continue;
2696:
2697: if (addr >= addr2 && addr < addr3)
2698: brk = 1;
2699: if (!brk && size == 2 && (addr + 1 >= addr2 && addr + 1 < addr3))
2700: brk = 1;
2701: if (!brk && size == 4 && ((addr + 2 >= addr2 && addr + 2 < addr3) || (addr + 3 >= addr2 && addr + 3 < addr3)))
2702: brk = 1;
2703:
2704: if (!brk)
2705: continue;
2706: if (mem_banks[addr >> 16]->check (addr, size)) {
2707: uae_u8 *p = mem_banks[addr >> 16]->xlateaddr (addr);
2708: if (size == 1)
2709: oldval = p[0];
2710: else if (size == 2)
2711: oldval = (p[0] << 8) | p[1];
2712: else
2713: oldval = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
2714: isoldval = 1;
2715: }
2716:
2717: if (!m->frozen && m->val_enabled) {
2718: int trigger = 0;
2719: uae_u32 mask = m->size == 4 ? 0xffffffff : (1 << (m->size * 8)) - 1;
2720: uae_u32 mval = m->val;
2721: int scnt = size;
2722: for (;;) {
2723: if (((mval & mask) & m->val_mask) == ((val & mask) & m->val_mask))
2724: trigger = 1;
2725: if (mask & 0x80000000)
2726: break;
2727: if (m->size == 1) {
2728: mask <<= 8;
2729: mval <<= 8;
2730: scnt--;
2731: } else if (m->size == 2) {
2732: mask <<= 16;
2733: scnt -= 2;
2734: mval <<= 16;
2735: } else {
2736: scnt -= 4;
2737: }
2738: if (scnt <= 0)
2739: break;
2740: }
2741: if (!trigger)
2742: continue;
2743: }
2744:
2745: if (m->mustchange && rwi == 2 && isoldval) {
2746: if (oldval == *valp)
2747: continue;
2748: }
2749:
2750: if (m->modval_written) {
2751: if (!rwi) {
2752: brk = 0;
2753: } else if (m->modval_written == 1) {
2754: m->modval_written = 2;
2755: m->modval = val;
2756: brk = 0;
2757: } else if (m->modval == val) {
2758: brk = 0;
2759: }
2760: }
2761: if (m->frozen) {
2762: if (m->val_enabled) {
2763: int shift = (addr + size - 1) - (m->addr + m->val_size - 1);
2764: uae_u32 sval;
2765: uae_u32 mask;
2766:
2767: if (m->val_size == 4)
2768: mask = 0xffffffff;
2769: else if (m->val_size == 2)
2770: mask = 0x0000ffff;
2771: else
2772: mask = 0x000000ff;
2773:
2774: sval = m->val;
2775: if (shift < 0) {
2776: shift = -8 * shift;
2777: sval >>= shift;
2778: mask >>= shift;
2779: } else {
2780: shift = 8 * shift;
2781: sval <<= shift;
2782: mask <<= shift;
2783: }
2784: *valp = (sval & mask) | ((*valp) & ~mask);
1.1.1.2 ! root 2785: write_log (_T("%08x %08x %08x %08x %d\n"), addr, m->addr, *valp, mask, shift);
1.1 root 2786: return 1;
2787: }
2788: return 0;
2789: }
2790: // if (!notinrom ())
2791: // return 1;
2792: mwhit.pc = M68K_GETPC;
2793: mwhit.addr = addr;
2794: mwhit.rwi = rwi;
2795: mwhit.size = size;
2796: mwhit.val = 0;
2797: mwhit.access_mask = accessmask;
2798: mwhit.reg = reg;
2799: if (mwhit.rwi & 2)
2800: mwhit.val = val;
2801: memwatch_triggered = i + 1;
2802: debugging = 1;
2803: set_special (SPCFLAG_BRK);
2804: return 1;
2805: }
2806: return 1;
2807: }
2808:
2809: #endif /* WINUAE_FOR_HATARI */
2810: #if 0
2811:
2812: static int mmu_hit (uaecptr addr, int size, int rwi, uae_u32 *v);
2813:
2814: static uae_u32 REGPARAM2 mmu_lget (uaecptr addr)
2815: {
2816: int off = debug_mem_off (&addr);
2817: uae_u32 v = 0;
2818: if (!mmu_hit (addr, 4, 0, &v))
2819: v = debug_mem_banks[off]->lget (addr);
2820: return v;
2821: }
2822: static uae_u32 REGPARAM2 mmu_wget (uaecptr addr)
2823: {
2824: int off = debug_mem_off (&addr);
2825: uae_u32 v = 0;
2826: if (!mmu_hit (addr, 2, 0, &v))
2827: v = debug_mem_banks[off]->wget (addr);
2828: return v;
2829: }
2830: static uae_u32 REGPARAM2 mmu_bget (uaecptr addr)
2831: {
2832: int off = debug_mem_off (&addr);
2833: uae_u32 v = 0;
2834: if (!mmu_hit(addr, 1, 0, &v))
2835: v = debug_mem_banks[off]->bget (addr);
2836: return v;
2837: }
2838: static void REGPARAM2 mmu_lput (uaecptr addr, uae_u32 v)
2839: {
2840: int off = debug_mem_off (&addr);
2841: if (!mmu_hit (addr, 4, 1, &v))
2842: debug_mem_banks[off]->lput (addr, v);
2843: }
2844: static void REGPARAM2 mmu_wput (uaecptr addr, uae_u32 v)
2845: {
2846: int off = debug_mem_off (&addr);
2847: if (!mmu_hit (addr, 2, 1, &v))
2848: debug_mem_banks[off]->wput (addr, v);
2849: }
2850: static void REGPARAM2 mmu_bput (uaecptr addr, uae_u32 v)
2851: {
2852: int off = debug_mem_off (&addr);
2853: if (!mmu_hit (addr, 1, 1, &v))
2854: debug_mem_banks[off]->bput (addr, v);
2855: }
2856:
2857: static uae_u32 REGPARAM2 debug_lget (uaecptr addr)
2858: {
2859: uae_u32 off = debug_mem_off (&addr);
2860: uae_u32 v;
2861: v = debug_mem_banks[off]->lget (addr);
1.1.1.2 ! root 2862: memwatch_func (addr, 1, 4, &v, MW_MASK_CPU_D_R, 0);
1.1 root 2863: return v;
2864: }
2865: static uae_u32 REGPARAM2 mmu_lgeti (uaecptr addr)
2866: {
2867: int off = debug_mem_off (&addr);
2868: uae_u32 v = 0;
2869: if (!mmu_hit (addr, 4, 4, &v))
2870: v = debug_mem_banks[off]->lgeti (addr);
2871: return v;
2872: }
2873: static uae_u32 REGPARAM2 mmu_wgeti (uaecptr addr)
2874: {
2875: int off = debug_mem_off (&addr);
2876: uae_u32 v = 0;
2877: if (!mmu_hit (addr, 2, 4, &v))
2878: v = debug_mem_banks[off]->wgeti (addr);
2879: return v;
2880: }
2881:
2882: static uae_u32 REGPARAM2 debug_wget (uaecptr addr)
2883: {
2884: int off = debug_mem_off (&addr);
2885: uae_u32 v;
2886: v = debug_mem_banks[off]->wget (addr);
1.1.1.2 ! root 2887: memwatch_func (addr, 1, 2, &v, MW_MASK_CPU_D_R, 0);
1.1 root 2888: return v;
2889: }
2890: static uae_u32 REGPARAM2 debug_bget (uaecptr addr)
2891: {
2892: int off = debug_mem_off (&addr);
2893: uae_u32 v;
2894: v = debug_mem_banks[off]->bget (addr);
1.1.1.2 ! root 2895: memwatch_func (addr, 1, 1, &v, MW_MASK_CPU_D_R, 0);
1.1 root 2896: return v;
2897: }
2898: static uae_u32 REGPARAM2 debug_lgeti (uaecptr addr)
2899: {
2900: int off = debug_mem_off (&addr);
2901: uae_u32 v;
2902: v = debug_mem_banks[off]->lgeti (addr);
1.1.1.2 ! root 2903: memwatch_func (addr, 4, 4, &v, MW_MASK_CPU_I, 0);
1.1 root 2904: return v;
2905: }
2906: static uae_u32 REGPARAM2 debug_wgeti (uaecptr addr)
2907: {
2908: int off = debug_mem_off (&addr);
2909: uae_u32 v;
2910: v = debug_mem_banks[off]->wgeti (addr);
1.1.1.2 ! root 2911: memwatch_func (addr, 4, 2, &v, MW_MASK_CPU_I, 0);
1.1 root 2912: return v;
2913: }
2914: static void REGPARAM2 debug_lput (uaecptr addr, uae_u32 v)
2915: {
2916: int off = debug_mem_off (&addr);
1.1.1.2 ! root 2917: if (memwatch_func (addr, 2, 4, &v, MW_MASK_CPU_D_W, 0))
1.1 root 2918: debug_mem_banks[off]->lput (addr, v);
2919: }
2920: static void REGPARAM2 debug_wput (uaecptr addr, uae_u32 v)
2921: {
2922: int off = debug_mem_off (&addr);
1.1.1.2 ! root 2923: if (memwatch_func (addr, 2, 2, &v, MW_MASK_CPU_D_W, 0))
1.1 root 2924: debug_mem_banks[off]->wput (addr, v);
2925: }
2926: static void REGPARAM2 debug_bput (uaecptr addr, uae_u32 v)
2927: {
2928: int off = debug_mem_off (&addr);
1.1.1.2 ! root 2929: if (memwatch_func (addr, 2, 1, &v, MW_MASK_CPU_D_W, 0))
1.1 root 2930: debug_mem_banks[off]->bput (addr, v);
2931: }
2932: static int REGPARAM2 debug_check (uaecptr addr, uae_u32 size)
2933: {
2934: return debug_mem_banks[munge24 (addr) >> 16]->check (addr, size);
2935: }
2936: static uae_u8 *REGPARAM2 debug_xlate (uaecptr addr)
2937: {
2938: return debug_mem_banks[munge24 (addr) >> 16]->xlateaddr (addr);
2939: }
2940:
2941: uae_u16 debug_wputpeekdma_chipset (uaecptr addr, uae_u32 v, uae_u32 mask, int reg)
2942: {
2943: if (!memwatch_enabled)
2944: return v;
2945: addr &= 0x1fe;
2946: addr += 0xdff000;
2947: memwatch_func (addr, 2, 2, &v, mask, reg);
2948: return v;
2949: }
2950: uae_u16 debug_wputpeekdma_chipram (uaecptr addr, uae_u32 v, uae_u32 mask, int reg)
2951: {
2952: if (!memwatch_enabled)
2953: return v;
2954: if (debug_mem_banks[addr >> 16] == NULL)
2955: return v;
2956: if (!currprefs.z3chipmem_size)
2957: addr &= chipmem_bank.mask;
2958: memwatch_func (addr & chipmem_bank.mask, 2, 2, &v, mask, reg);
2959: return v;
2960: }
2961: uae_u16 debug_wgetpeekdma_chipram (uaecptr addr, uae_u32 v, uae_u32 mask, int reg)
2962: {
2963: uae_u32 vv = v;
2964: if (!memwatch_enabled)
2965: return v;
2966: if (debug_mem_banks[addr >> 16] == NULL)
2967: return v;
2968: if (!currprefs.z3chipmem_size)
2969: addr &= chipmem_bank.mask;
2970: memwatch_func (addr, 1, 2, &vv, mask, reg);
2971: return vv;
2972: }
2973:
1.1.1.2 ! root 2974: static void debug_putlpeek (uaecptr addr, uae_u32 v)
1.1 root 2975: {
2976: if (!memwatch_enabled)
2977: return;
1.1.1.2 ! root 2978: memwatch_func (addr, 2, 4, &v, MW_MASK_CPU_D_W, 0);
1.1 root 2979: }
2980: void debug_wputpeek (uaecptr addr, uae_u32 v)
2981: {
2982: if (!memwatch_enabled)
2983: return;
1.1.1.2 ! root 2984: memwatch_func (addr, 2, 2, &v, MW_MASK_CPU_D_W, 0);
1.1 root 2985: }
2986: void debug_bputpeek (uaecptr addr, uae_u32 v)
2987: {
2988: if (!memwatch_enabled)
2989: return;
1.1.1.2 ! root 2990: memwatch_func (addr, 2, 1, &v, MW_MASK_CPU_D_W, 0);
1.1 root 2991: }
2992: void debug_bgetpeek (uaecptr addr, uae_u32 v)
2993: {
2994: uae_u32 vv = v;
2995: if (!memwatch_enabled)
2996: return;
1.1.1.2 ! root 2997: memwatch_func (addr, 1, 1, &vv, MW_MASK_CPU_D_R, 0);
1.1 root 2998: }
2999: void debug_wgetpeek (uaecptr addr, uae_u32 v)
3000: {
3001: uae_u32 vv = v;
3002: if (!memwatch_enabled)
3003: return;
1.1.1.2 ! root 3004: memwatch_func (addr, 1, 2, &vv, MW_MASK_CPU_D_R, 0);
1.1 root 3005: }
3006: void debug_lgetpeek (uaecptr addr, uae_u32 v)
3007: {
3008: uae_u32 vv = v;
3009: if (!memwatch_enabled)
3010: return;
1.1.1.2 ! root 3011: memwatch_func (addr, 1, 4, &vv, MW_MASK_CPU_D_R, 0);
1.1 root 3012: }
3013:
3014: #ifndef WINUAE_FOR_HATARI
3015:
3016: struct membank_store
3017: {
3018: addrbank *addr;
3019: addrbank newbank;
3020: int banknr;
3021: };
3022:
3023: static struct membank_store *membank_stores;
3024: static int membank_total;
3025: #define MEMWATCH_STORE_SLOTS 32
3026:
3027: static void memwatch_reset (void)
3028: {
3029: for (int i = 0; i < membank_total; i++) {
3030: addrbank *ab = debug_mem_banks[i];
3031: if (!ab)
3032: continue;
3033: map_banks_quick (ab, i, 1, 1);
3034: }
3035: for (int i = 0; membank_stores[i].addr; i++) {
3036: struct membank_store *ms = &membank_stores[i];
1.1.1.2 ! root 3037: /* name was allocated in memwatch_remap */
1.1 root 3038: xfree ((char*)ms->newbank.name);
3039: memset (ms, 0, sizeof (struct membank_store));
3040: ms->addr = NULL;
3041: }
3042: memset (debug_mem_banks, 0, membank_total * sizeof (addrbank*));
3043: }
3044:
3045: static void memwatch_remap (uaecptr addr)
3046: {
3047: int mode = 0;
3048: int i;
3049: int banknr;
3050: struct membank_store *ms;
3051: addrbank *bank;
3052: addrbank *newbank = NULL;
3053:
3054: addr &= ~65535;
3055: banknr = addr >> 16;
3056: if (debug_mem_banks[banknr])
3057: return;
3058: bank = mem_banks[banknr];
3059: for (i = 0 ; i < MEMWATCH_STORE_SLOTS; i++) {
3060: ms = &membank_stores[i];
3061: if (ms->addr == NULL)
3062: break;
3063: if (ms->addr == bank) {
3064: newbank = &ms->newbank;
3065: break;
3066: }
3067: }
3068: if (i >= MEMWATCH_STORE_SLOTS)
3069: return;
3070: if (!newbank) {
3071: TCHAR tmp[200];
3072: _stprintf (tmp, _T("%s [D]"), bank->name);
3073: ms->addr = bank;
3074: ms->banknr = banknr;
3075: newbank = &ms->newbank;
1.1.1.2 ! root 3076: memcpy (newbank, bank, sizeof(addrbank));
1.1 root 3077: newbank->bget = mode ? mmu_bget : debug_bget;
3078: newbank->wget = mode ? mmu_wget : debug_wget;
3079: newbank->lget = mode ? mmu_lget : debug_lget;
3080: newbank->bput = mode ? mmu_bput : debug_bput;
3081: newbank->wput = mode ? mmu_wput : debug_wput;
3082: newbank->lput = mode ? mmu_lput : debug_lput;
3083: newbank->check = debug_check;
3084: newbank->xlateaddr = debug_xlate;
3085: newbank->wgeti = mode ? mmu_wgeti : debug_wgeti;
3086: newbank->lgeti = mode ? mmu_lgeti : debug_lgeti;
1.1.1.2 ! root 3087: /* name will be freed by memwatch_reset */
1.1 root 3088: newbank->name = my_strdup (tmp);
3089: if (!newbank->mask)
3090: newbank->mask = -1;
3091: }
3092: debug_mem_banks[banknr] = bank;
3093: map_banks_quick (newbank, banknr, 1, 1);
3094: // map aliases
3095: for (i = 0; i < membank_total; i++) {
3096: uaecptr addr2 = i << 16;
3097: addrbank *ab = &get_mem_bank(addr2);
3098: if (ab != ms->addr)
3099: continue;
3100: if ((addr2 & ab->mask) == (addr & bank->mask)) {
3101: debug_mem_banks[i] = ms->addr;
3102: map_banks_quick (newbank, i, 1, 1);
3103: }
3104: }
3105: }
3106:
3107: static void memwatch_setup (void)
3108: {
3109: memwatch_reset ();
3110: for (int i = 0; i < MEMWATCH_TOTAL; i++) {
3111: struct memwatch_node *m = &mwnodes[i];
3112: uae_u32 size = 0;
3113: if (!m->size)
3114: continue;
3115: while (size < m->size) {
3116: memwatch_remap (m->addr + size);
3117: size += 65536;
3118: }
3119: }
3120: }
3121:
3122: static int deinitialize_memwatch (void)
3123: {
3124: int oldmode;
3125:
3126: if (!memwatch_enabled && !mmu_enabled)
3127: return -1;
3128: memwatch_reset ();
3129: oldmode = mmu_enabled ? 1 : 0;
3130: xfree (debug_mem_banks);
3131: debug_mem_banks = NULL;
3132: xfree (debug_mem_area);
3133: debug_mem_area = NULL;
3134: xfree (membank_stores);
3135: membank_stores = NULL;
3136: memwatch_enabled = 0;
3137: mmu_enabled = 0;
3138: xfree (illgdebug);
3139: illgdebug = 0;
3140: return oldmode;
3141: }
3142:
3143: static void initialize_memwatch (int mode)
3144: {
3145: membank_total = currprefs.address_space_24 ? 256 : 65536;
3146: deinitialize_memwatch ();
3147: debug_mem_banks = xcalloc (addrbank*, membank_total);
3148: debug_mem_area = xcalloc (addrbank, membank_total);
3149: membank_stores = xcalloc (struct membank_store, MEMWATCH_STORE_SLOTS);
3150: #if 0
3151: int i, j, as;
3152: addrbank *a1, *a2, *oa;
3153: oa = NULL;
3154: for (i = 0; i < as; i++) {
3155: a1 = debug_mem_banks[i] = debug_mem_area + i;
3156: a2 = mem_banks[i];
3157: if (a2 != oa) {
3158: for (j = 0; membank_stores[j].addr; j++) {
3159: if (membank_stores[j].addr == a2)
3160: break;
3161: }
3162: if (membank_stores[j].addr == NULL) {
3163: membank_stores[j].addr = a2;
3164: memcpy (&membank_stores[j].store, a2, sizeof (addrbank));
3165: }
3166: }
3167: memcpy (a1, a2, sizeof (addrbank));
3168: }
3169: for (i = 0; i < as; i++) {
3170: a2 = mem_banks[i];
3171: a2->bget = mode ? mmu_bget : debug_bget;
3172: a2->wget = mode ? mmu_wget : debug_wget;
3173: a2->lget = mode ? mmu_lget : debug_lget;
3174: a2->bput = mode ? mmu_bput : debug_bput;
3175: a2->wput = mode ? mmu_wput : debug_wput;
3176: a2->lput = mode ? mmu_lput : debug_lput;
3177: a2->check = debug_check;
3178: a2->xlateaddr = debug_xlate;
3179: a2->wgeti = mode ? mmu_wgeti : debug_wgeti;
3180: a2->lgeti = mode ? mmu_lgeti : debug_lgeti;
3181: }
3182: #endif
3183: if (mode)
3184: mmu_enabled = 1;
3185: else
3186: memwatch_enabled = 1;
3187: }
3188:
3189: int debug_bankchange (int mode)
3190: {
3191: if (mode == -1) {
3192: int v = deinitialize_memwatch ();
3193: if (v < 0)
3194: return -2;
3195: return v;
3196: }
3197: if (mode >= 0) {
3198: initialize_memwatch (mode);
3199: memwatch_setup ();
3200: }
3201: return -1;
3202: }
3203:
3204: addrbank *get_mem_bank_real(uaecptr addr)
3205: {
3206: addrbank *ab = &get_mem_bank(addr);
3207: if (!memwatch_enabled)
3208: return ab;
3209: addrbank *ab2 = debug_mem_banks[addr >> 16];
3210: if (ab2)
3211: return ab2;
3212: return ab;
3213: }
3214:
1.1.1.2 ! root 3215: static const TCHAR *getsizechar (int size)
1.1 root 3216: {
3217: if (size == 4)
3218: return _T(".l");
3219: if (size == 3)
3220: return _T(".3");
3221: if (size == 2)
3222: return _T(".w");
3223: if (size == 1)
3224: return _T(".b");
3225: return _T("");
3226: }
3227:
3228: void memwatch_dump2 (TCHAR *buf, int bufsize, int num)
3229: {
3230: int i;
3231: struct memwatch_node *mwn;
3232:
3233: if (buf)
3234: memset (buf, 0, bufsize * sizeof (TCHAR));
3235: for (i = 0; i < MEMWATCH_TOTAL; i++) {
3236: if ((num >= 0 && num == i) || (num < 0)) {
3237: uae_u32 usedmask = 0;
3238: mwn = &mwnodes[i];
3239: if (mwn->size == 0)
3240: continue;
3241: buf = buf_out (buf, &bufsize, _T("%2d: %08X - %08X (%d) %c%c%c"),
3242: i, mwn->addr, mwn->addr + (mwn->size - 1), mwn->size,
3243: (mwn->rwi & 1) ? 'R' : ' ', (mwn->rwi & 2) ? 'W' : ' ', (mwn->rwi & 4) ? 'I' : ' ');
3244: if (mwn->frozen)
3245: buf = buf_out (buf, &bufsize, _T(" F"));
3246: if (mwn->val_enabled)
3247: buf = buf_out (buf, &bufsize, _T(" =%X%s"), mwn->val, getsizechar (mwn->val_size));
3248: if (mwn->modval_written)
3249: buf = buf_out (buf, &bufsize, _T(" =M"));
3250: if (mwn->mustchange)
3251: buf = buf_out (buf, &bufsize, _T(" C"));
3252: for (int j = 0; memwatch_access_masks[j].mask; j++) {
3253: uae_u32 mask = memwatch_access_masks[j].mask;
3254: if ((mwn->access_mask & mask) == mask && (usedmask & mask) == 0) {
3255: buf = buf_out(buf, &bufsize, _T(" "));
3256: buf = buf_out(buf, &bufsize, memwatch_access_masks[j].name);
3257: usedmask |= mask;
3258: }
3259: }
3260: buf = buf_out (buf, &bufsize, _T("\n"));
3261: }
3262: }
3263: }
3264:
3265: static void memwatch_dump (int num)
3266: {
3267: TCHAR *buf;
3268: int multiplier = num < 0 ? MEMWATCH_TOTAL : 1;
3269:
3270: buf = xmalloc (TCHAR, 50 * multiplier);
3271: if (!buf)
3272: return;
3273: memwatch_dump2 (buf, 50 * multiplier, num);
3274: f_out (stdout, _T("%s"), buf);
3275: xfree (buf);
3276: }
3277:
3278: static void memwatch (TCHAR **c)
3279: {
3280: int num;
3281: struct memwatch_node *mwn;
3282: TCHAR nc, *cp;
3283:
3284: if (!memwatch_enabled) {
3285: initialize_memwatch (0);
3286: console_out (_T("Memwatch breakpoints enabled\n"));
3287: }
3288:
3289: cp = *c;
3290: ignore_ws (c);
3291: if (!more_params (c)) {
3292: memwatch_dump (-1);
3293: return;
3294: }
3295: nc = next_char (c);
3296: if (nc == '-') {
3297: deinitialize_memwatch ();
3298: console_out (_T("Memwatch breakpoints disabled\n"));
3299: return;
3300: }
3301: if (nc == 'd') {
3302: if (illgdebug) {
3303: ignore_ws (c);
3304: if (more_params (c)) {
3305: uae_u32 addr = readhex (c);
3306: uae_u32 len = 1;
3307: if (more_params (c))
3308: len = readhex (c);
3309: console_out_f (_T("Cleared logging addresses %08X - %08X\n"), addr, addr + len);
3310: while (len > 0) {
3311: addr &= 0xffffff;
3312: illgdebug[addr] = 7;
3313: addr++;
3314: len--;
3315: }
3316: } else {
3317: illg_free();
3318: console_out (_T("Illegal memory access logging disabled\n"));
3319: }
3320: } else {
3321: illg_init ();
3322: ignore_ws (c);
3323: illgdebug_break = 0;
3324: if (more_params (c))
3325: illgdebug_break = 1;
3326: console_out_f (_T("Illegal memory access logging enabled. Break=%d\n"), illgdebug_break);
3327: }
3328: return;
3329: }
3330: *c = cp;
3331: num = readint (c);
3332: if (num < 0 || num >= MEMWATCH_TOTAL)
3333: return;
3334: mwn = &mwnodes[num];
3335: mwn->size = 0;
3336: ignore_ws (c);
3337: if (!more_params (c)) {
3338: console_out_f (_T("Memwatch %d removed\n"), num);
3339: memwatch_setup ();
3340: return;
3341: }
3342: mwn->addr = readhex (c);
3343: mwn->size = 1;
3344: mwn->rwi = 7;
3345: mwn->val_enabled = 0;
3346: mwn->val_mask = 0xffffffff;
3347: mwn->val = 0;
3348: mwn->access_mask = 0;
3349: mwn->reg = 0xffffffff;
3350: mwn->frozen = 0;
3351: mwn->modval_written = 0;
3352: ignore_ws (c);
3353: if (more_params (c)) {
3354: mwn->size = readhex (c);
3355: ignore_ws (c);
3356: if (more_params (c)) {
3357: TCHAR *cs = *c;
3358: while (*cs) {
3359: for (int i = 0; memwatch_access_masks[i].mask; i++) {
3360: const TCHAR *n = memwatch_access_masks[i].name;
3361: int len = _tcslen(n);
3362: if (!_tcsnicmp(cs, n, len)) {
3363: if (cs[len] == 0 || cs[len] == 10 || cs[len] == 13) {
3364: mwn->access_mask |= memwatch_access_masks[i].mask;
3365: while (len > 0) {
3366: len--;
3367: cs[len] = ' ';
3368: }
3369: }
3370: }
3371: }
3372: cs++;
3373: }
3374: ignore_ws (c);
3375: if (more_params(c)) {
3376: for (;;) {
3377: TCHAR ncc = peek_next_char(c);
3378: TCHAR nc = _totupper (next_char (c));
3379: if (mwn->rwi == 7)
3380: mwn->rwi = 0;
3381: if (nc == 'F')
3382: mwn->frozen = 1;
3383: if (nc == 'W')
3384: mwn->rwi |= 2;
3385: if (nc == 'I')
3386: mwn->rwi |= 4;
3387: if (nc == 'R')
3388: mwn->rwi |= 1;
3389: if (ncc == ' ')
3390: break;
3391: if (!more_params(c))
3392: break;
3393: }
3394: ignore_ws (c);
3395: }
3396: if (more_params (c)) {
3397: if (_totupper (**c) == 'M') {
3398: mwn->modval_written = 1;
3399: } else if (_totupper (**c) == 'C') {
3400: mwn->mustchange = 1;
3401: } else {
3402: mwn->val = readhex (c, &mwn->val_size);
3403: mwn->val_enabled = 1;
3404: }
3405: }
3406: }
3407: }
3408: if (!mwn->access_mask)
1.1.1.2 ! root 3409: mwn->access_mask = MW_MASK_CPU_D_R | MW_MASK_CPU_D_W | MW_MASK_CPU_I;
1.1 root 3410: if (mwn->frozen && mwn->rwi == 0)
3411: mwn->rwi = 3;
3412: memwatch_setup ();
3413: memwatch_dump (num);
3414: }
3415:
3416: static void writeintomem (TCHAR **c)
3417: {
3418: uae_u32 addr = 0;
3419: uae_u32 val = 0;
3420: TCHAR cc;
3421: int len = 1;
3422:
3423: ignore_ws(c);
3424: addr = readhex (c);
3425:
3426: ignore_ws (c);
3427: if (!more_params (c))
3428: return;
3429: cc = peekchar (c);
3430: if (cc == '\'' || cc == '\"') {
3431: next_char (c);
3432: while (more_params (c)) {
3433: TCHAR str[2];
3434: char *astr;
3435: cc = next_char (c);
3436: if (cc == '\'' || cc == '\"')
3437: break;
3438: str[0] = cc;
3439: str[1] = 0;
3440: astr = ua (str);
3441: put_byte (addr, astr[0]);
3442: xfree (astr);
3443: addr++;
3444: }
3445: } else {
3446: for (;;) {
3447: ignore_ws (c);
3448: if (!more_params (c))
3449: break;
3450: val = readhex (c, &len);
3451:
3452: if (len == 4) {
3453: put_long (addr, val);
3454: cc = 'L';
3455: } else if (len == 2) {
3456: put_word (addr, val);
3457: cc = 'W';
3458: } else if (len == 1) {
3459: put_byte (addr, val);
3460: cc = 'B';
3461: } else {
3462: break;
3463: }
3464: console_out_f (_T("Wrote %X (%u) at %08X.%c\n"), val, val, addr, cc);
3465: addr += len;
3466: }
3467: }
3468: }
3469:
3470: static uae_u8 *dump_xlate (uae_u32 addr)
3471: {
3472: if (!mem_banks[addr >> 16]->check (addr, 1))
3473: return NULL;
3474: return mem_banks[addr >> 16]->xlateaddr (addr);
3475: }
3476:
3477: #if 0
3478: #define UAE_MEMORY_REGIONS_MAX 64
3479: #define UAE_MEMORY_REGION_NAME_LENGTH 64
3480:
3481: #define UAE_MEMORY_REGION_RAM (1 << 0)
3482: #define UAE_MEMORY_REGION_ALIAS (1 << 1)
3483: #define UAE_MEMORY_REGION_MIRROR (1 << 2)
3484:
3485: typedef struct UaeMemoryRegion {
3486: uaecptr start;
3487: int size;
3488: TCHAR name[UAE_MEMORY_REGION_NAME_LENGTH];
3489: TCHAR rom_name[UAE_MEMORY_REGION_NAME_LENGTH];
3490: uaecptr alias;
3491: int flags;
3492: } UaeMemoryRegion;
3493:
3494: typedef struct UaeMemoryMap {
3495: UaeMemoryRegion regions[UAE_MEMORY_REGIONS_MAX];
3496: int num_regions;
3497: } UaeMemoryMap;
3498: #endif
3499:
3500: static void memory_map_dump_3(UaeMemoryMap *map, int log)
3501: {
3502: bool imold;
3503: int i, j, max;
3504: addrbank *a1 = mem_banks[0];
3505: TCHAR txt[256];
3506:
3507: map->num_regions = 0;
3508: imold = currprefs.illegal_mem;
3509: currprefs.illegal_mem = false;
3510: max = currprefs.address_space_24 ? 256 : 65536;
3511: j = 0;
3512: for (i = 0; i < max + 1; i++) {
3513: addrbank *a2 = NULL;
3514: if (i < max)
3515: a2 = mem_banks[i];
3516: if (a1 != a2) {
3517: int k, mirrored, mirrored2, size, size_out;
3518: TCHAR size_ext;
3519: uae_u8 *caddr;
3520: TCHAR tmp[MAX_DPATH];
3521: const TCHAR *name = a1->name;
3522: struct addrbank_sub *sb = a1->sub_banks;
3523: int bankoffset = 0;
3524: int region_size;
3525:
3526: k = j;
3527: caddr = dump_xlate (k << 16);
3528: mirrored = caddr ? 1 : 0;
3529: k++;
3530: while (k < i && caddr) {
1.1.1.2 ! root 3531: if (dump_xlate (k << 16) == caddr) {
1.1 root 3532: mirrored++;
1.1.1.2 ! root 3533: }
1.1 root 3534: k++;
3535: }
3536: mirrored2 = mirrored;
3537: if (mirrored2 == 0)
3538: mirrored2 = 1;
3539:
3540: while (bankoffset < 65536) {
3541: int bankoffset2 = bankoffset;
3542: if (sb) {
3543: uaecptr daddr;
3544: if (!sb->bank)
3545: break;
3546: daddr = (j << 16) | bankoffset;
3547: a1 = get_sub_bank(&daddr);
3548: name = a1->name;
3549: for (;;) {
3550: bankoffset2 += MEMORY_MIN_SUBBANK;
3551: if (bankoffset2 >= 65536)
3552: break;
3553: daddr = (j << 16) | bankoffset2;
3554: addrbank *dab = get_sub_bank(&daddr);
3555: if (dab != a1)
3556: break;
3557: }
3558: sb++;
3559: size = (bankoffset2 - bankoffset) / 1024;
3560: region_size = size * 1024;
3561: } else {
3562: size = (i - j) << (16 - 10);
3563: region_size = ((i - j) << 16) / mirrored2;
3564: }
3565:
3566: if (name == NULL)
3567: name = _T("<none>");
3568:
3569: size_out = size;
3570: size_ext = 'K';
3571: if (j >= 256 && (size_out / mirrored2 >= 1024) && !((size_out / mirrored2) & 1023)) {
3572: size_out /= 1024;
3573: size_ext = 'M';
3574: }
3575: #if 1
3576: _stprintf (txt, _T("%08X %7d%c/%d = %7d%c %s"), (j << 16) | bankoffset, size_out, size_ext,
3577: mirrored, mirrored ? size_out / mirrored : size_out, size_ext, name);
3578: #endif
3579: tmp[0] = 0;
3580: if ((a1->flags & ABFLAG_ROM) && mirrored) {
3581: TCHAR *p = txt + _tcslen (txt);
3582: uae_u32 crc = 0xffffffff;
3583: if (a1->check(((j << 16) | bankoffset), (size * 1024) / mirrored))
3584: crc = get_crc32 (a1->xlateaddr((j << 16) | bankoffset), (size * 1024) / mirrored);
3585: struct romdata *rd = getromdatabycrc (crc);
3586: _stprintf (p, _T(" (%08X)"), crc);
3587: if (rd) {
3588: tmp[0] = '=';
3589: getromname (rd, tmp + 1);
3590: _tcscat (tmp, _T("\n"));
3591: }
3592: }
3593:
3594: if (a1 != &dummy_bank) {
3595: for (int m = 0; m < mirrored2; m++) {
3596: UaeMemoryRegion *r = &map->regions[map->num_regions];
3597: r->start = (j << 16) + bankoffset + region_size * m;
3598: r->size = region_size;
3599: r->flags = 0;
3600: r->memory = NULL;
3601: r->memory = dump_xlate((j << 16) | bankoffset);
3602: if (r->memory)
3603: r->flags |= UAE_MEMORY_REGION_RAM;
3604: /* just to make it easier to spot in debugger */
3605: r->alias = 0xffffffff;
3606: if (m >= 0) {
3607: r->alias = j << 16;
3608: r->flags |= UAE_MEMORY_REGION_ALIAS | UAE_MEMORY_REGION_MIRROR;
3609: }
3610: _stprintf(r->name, _T("%s"), name);
3611: _stprintf(r->rom_name, _T("%s"), tmp);
3612: map->num_regions += 1;
3613: }
3614: }
3615: #if 1
3616: _tcscat (txt, _T("\n"));
3617: if (log > 0)
1.1.1.2 ! root 3618: write_log (_T("%s"), txt);
1.1 root 3619: else if (log == 0)
3620: console_out (txt);
3621: if (tmp[0]) {
3622: if (log > 0)
1.1.1.2 ! root 3623: write_log (_T("%s"), tmp);
1.1 root 3624: else if (log == 0)
3625: console_out (tmp);
3626: }
3627: #endif
3628: if (!sb)
3629: break;
3630: bankoffset = bankoffset2;
3631: }
3632: j = i;
3633: a1 = a2;
3634: }
3635: }
1.1.1.2 ! root 3636: pci_dump(log);
1.1 root 3637: currprefs.illegal_mem = imold;
3638: }
3639:
3640: void uae_memory_map(UaeMemoryMap *map)
3641: {
3642: memory_map_dump_3(map, -1);
3643: }
3644:
3645: static void memory_map_dump_2 (int log)
3646: {
3647: UaeMemoryMap map;
3648: memory_map_dump_3(&map, log);
3649: #if 0
3650: for (int i = 0; i < map.num_regions; i++) {
3651: TCHAR txt[256];
3652: UaeMemoryRegion *r = &map.regions[i];
3653: int size = r->size / 1024;
3654: TCHAR size_ext = 'K';
3655: int mirrored = 1;
3656: int size_out = 0;
3657: _stprintf (txt, _T("%08X %7u%c/%d = %7u%c %s\n"), r->start, size, size_ext,
3658: r->flags & UAE_MEMORY_REGION_RAM, size, size_ext, r->name);
3659: if (log)
3660: write_log (_T("%s"), txt);
3661: else
3662: console_out (txt);
3663: if (r->rom_name[0]) {
3664: if (log)
3665: write_log (_T("%s"), r->rom_name);
3666: else
3667: console_out (r->rom_name);
3668: }
3669: }
3670: #endif
3671: }
3672:
3673: void memory_map_dump (void)
1.1.1.2 ! root 3674: {
! 3675: memory_map_dump_2(1);
1.1 root 3676: }
3677:
3678: STATIC_INLINE uaecptr BPTR2APTR (uaecptr addr)
3679: {
3680: return addr << 2;
3681: }
3682: static TCHAR *BSTR2CSTR (uae_u8 *bstr)
3683: {
3684: TCHAR *s;
3685: char *cstr = xmalloc (char, bstr[0] + 1);
3686: if (cstr) {
3687: memcpy (cstr, bstr + 1, bstr[0]);
3688: cstr[bstr[0]] = 0;
3689: }
3690: s = au (cstr);
3691: xfree (cstr);
3692: return s;
3693: }
3694:
3695: static void print_task_info (uaecptr node, bool nonactive)
3696: {
3697: TCHAR *s;
3698: int process = get_byte_debug (node + 8) == 13 ? 1 : 0;
3699:
3700: console_out_f (_T("%08X: "), node);
3701: s = au ((char*)get_real_address (get_long_debug (node + 10)));
3702: console_out_f (process ? _T("PROCESS '%s'\n") : _T("TASK '%s'\n"), s);
3703: xfree (s);
3704: if (process) {
3705: uaecptr cli = BPTR2APTR (get_long_debug (node + 172));
3706: int tasknum = get_long_debug (node + 140);
3707: if (cli && tasknum) {
3708: uae_u8 *command_bstr = get_real_address (BPTR2APTR (get_long_debug (cli + 16)));
3709: TCHAR *command = BSTR2CSTR (command_bstr);
3710: console_out_f (_T(" [%d, '%s']\n"), tasknum, command);
3711: xfree (command);
3712: } else {
3713: console_out (_T("\n"));
3714: }
3715: }
3716: if (nonactive) {
3717: uae_u32 sigwait = get_long_debug(node + 22);
3718: if (sigwait)
3719: console_out_f(_T(" Waiting signals: %08x\n"), sigwait);
1.1.1.2 ! root 3720: int offset = kickstart_version >= 37 ? 74 : 70;
! 3721: uae_u32 sp = get_long_debug(node + 54) + offset;
1.1 root 3722: uae_u32 pc = get_long_debug(sp);
3723: console_out_f(_T(" SP: %08x PC: %08x\n"), sp, pc);
3724: }
3725: }
3726:
3727: static void show_exec_tasks (void)
3728: {
3729: uaecptr execbase = get_long_debug (4);
3730: uaecptr taskready = execbase + 406;
3731: uaecptr taskwait = execbase + 420;
3732: uaecptr node;
3733: console_out_f (_T("Execbase at 0x%08X\n"), execbase);
3734: console_out (_T("Current:\n"));
3735: node = get_long_debug (execbase + 276);
3736: print_task_info (node, false);
3737: console_out_f (_T("Ready:\n"));
3738: node = get_long_debug (taskready);
3739: while (node && get_long_debug(node)) {
3740: print_task_info (node, true);
3741: node = get_long_debug (node);
3742: }
3743: console_out (_T("Waiting:\n"));
3744: node = get_long_debug (taskwait);
3745: while (node && get_long_debug(node)) {
3746: print_task_info (node, true);
3747: node = get_long_debug (node);
3748: }
3749: }
3750:
3751: static uaecptr get_base (const uae_char *name, int offset)
3752: {
3753: uaecptr v = get_long_debug (4);
3754: addrbank *b = &get_mem_bank(v);
3755:
3756: if (!b || !b->check (v, 400) || !(b->flags & ABFLAG_RAM))
3757: return 0;
3758: v += offset;
1.1.1.2 ! root 3759: while ((v = get_long_debug (v))) {
1.1 root 3760: uae_u32 v2;
3761: uae_u8 *p;
3762: b = &get_mem_bank (v);
3763: if (!b || !b->check (v, 32) || (!(b->flags & ABFLAG_RAM) && !(b->flags & ABFLAG_ROMIN)))
3764: goto fail;
3765: v2 = get_long_debug (v + 10); // name
3766: b = &get_mem_bank (v2);
3767: if (!b || !b->check (v2, 20))
3768: goto fail;
3769: if ((b->flags & ABFLAG_ROM) || (b->flags & ABFLAG_RAM) || (b->flags & ABFLAG_ROMIN)) {
3770: p = b->xlateaddr (v2);
3771: if (!memcmp (p, name, strlen (name) + 1))
3772: return v;
3773: }
3774: }
3775: return 0;
3776: fail:
3777: return 0xffffffff;
3778: }
3779:
3780: static TCHAR *getfrombstr(uaecptr pp)
3781: {
3782: uae_u8 *p = get_real_address ((uaecptr)(pp << 2));
3783: TCHAR *s = xmalloc (TCHAR, p[0] + 1);
3784: return au_copy (s, p[0] + 1, (char*)p + 1);
3785: }
3786:
3787: // read one byte from expansion autoconfig ROM
3788: static void copyromdata(uae_u8 bustype, uaecptr rom, int offset, uae_u8 *out, int size)
3789: {
3790: switch (bustype & 0xc0)
3791: {
3792: case 0x00: // nibble
3793: while (size-- > 0) {
3794: *out++ = (get_byte_debug(rom + offset * 4 + 0) & 0xf0) | ((get_byte_debug(rom + offset * 4 + 2) & 0xf0) >> 4);
3795: offset++;
3796: }
3797: break;
3798: case 0x40: // byte
3799: while (size-- > 0) {
3800: *out++ = get_byte_debug(rom + offset * 2);
3801: offset++;
3802: }
3803: break;
3804: case 0x80: // word
3805: default:
3806: while (size-- > 0) {
3807: *out++ = get_byte_debug(rom + offset);
3808: offset++;
3809: }
3810: break;
3811: }
3812: }
3813:
3814: static void show_exec_lists (TCHAR *t)
3815: {
3816: uaecptr execbase = get_long_debug (4);
3817: uaecptr list = 0, node;
3818: TCHAR c = t[0];
3819:
3820: if (c == 'o' || c == 'O') { // doslist
3821: uaecptr dosbase = get_base ("dos.library", 378);
3822: if (dosbase) {
3823: uaecptr rootnode = get_long_debug (dosbase + 34);
3824: uaecptr dosinfo = get_long_debug (rootnode + 24) << 2;
3825: console_out_f (_T("ROOTNODE: %08x DOSINFO: %08x\n"), rootnode, dosinfo);
3826: uaecptr doslist = get_long_debug (dosinfo + 4) << 2;
3827: while (doslist) {
3828: int type = get_long_debug (doslist + 4);
3829: uaecptr msgport = get_long_debug (doslist + 8);
3830: TCHAR *name = getfrombstr (get_long_debug (doslist + 40));
3831: console_out_f (_T("%08x: %d %08x '%s'\n"), doslist, type, msgport, name);
3832: if (type == 0) {
3833: uaecptr fssm = get_long_debug(doslist + 28) << 2;
3834: console_out_f (_T(" - H=%08x Stack=%5d Pri=%2d Start=%08x Seg=%08x GV=%08x\n"),
3835: get_long_debug (doslist + 16) << 2, get_long_debug (doslist + 20),
3836: get_long_debug (doslist + 24), fssm,
3837: get_long_debug (doslist + 32) << 2, get_long_debug (doslist + 36));
3838: if (fssm >= 0x100 && (fssm & 3) == 0) {
3839: TCHAR *unitname = getfrombstr(get_long_debug(fssm + 4));
3840: console_out_f (_T(" %s:%d %08x\n"), unitname, get_long_debug(fssm), get_long_debug(fssm + 8));
3841: uaecptr de = get_long_debug(fssm + 8) << 2;
3842: if (de) {
3843: console_out_f (_T(" TableSize %u\n"), get_long_debug(de + 0));
3844: console_out_f (_T(" SizeBlock %u\n"), get_long_debug(de + 4));
3845: console_out_f (_T(" SecOrg %u\n"), get_long_debug(de + 8));
3846: console_out_f (_T(" Surfaces %u\n"), get_long_debug(de + 12));
3847: console_out_f (_T(" SectorPerBlock %u\n"), get_long_debug(de + 16));
3848: console_out_f (_T(" BlocksPerTrack %u\n"), get_long_debug(de + 20));
3849: console_out_f (_T(" Reserved %u\n"), get_long_debug(de + 24));
3850: console_out_f (_T(" PreAlloc %u\n"), get_long_debug(de + 28));
3851: console_out_f (_T(" Interleave %u\n"), get_long_debug(de + 32));
3852: console_out_f (_T(" LowCyl %u\n"), get_long_debug(de + 36));
3853: console_out_f (_T(" HighCyl %u (Total %u)\n"), get_long_debug(de + 40), get_long_debug(de + 40) - get_long_debug(de + 36) + 1);
3854: console_out_f (_T(" NumBuffers %u\n"), get_long_debug(de + 44));
3855: console_out_f (_T(" BufMemType 0x%08x\n"), get_long_debug(de + 48));
3856: console_out_f (_T(" MaxTransfer 0x%08x\n"), get_long_debug(de + 52));
3857: console_out_f (_T(" Mask 0x%08x\n"), get_long_debug(de + 56));
3858: console_out_f (_T(" BootPri %d\n"), get_long_debug(de + 60));
3859: console_out_f (_T(" DosType 0x%08x\n"), get_long_debug(de + 64));
3860: }
3861: xfree(unitname);
3862: }
3863: }
3864: xfree (name);
3865: doslist = get_long_debug (doslist) << 2;
3866: }
3867: } else {
3868: console_out_f (_T("can't find dos.library\n"));
3869: }
3870: return;
3871: } else if (c == 'i' || c == 'I') { // interrupts
3872: static const int it[] = { 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0 };
3873: static const int it2[] = { 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 7 };
3874: list = execbase + 84;
3875: for (int i = 0; i < 16; i++) {
1.1.1.2 ! root 3876: console_out_f (_T("%2d %d: %08X\n"), i + 1, it2[i], list);
1.1 root 3877: if (it[i]) {
1.1.1.2 ! root 3878: console_out_f (_T(" [H] %08X\n"), get_long_debug (list));
1.1 root 3879: node = get_long_debug (list + 8);
3880: if (node) {
3881: uae_u8 *addr = get_real_address (get_long_debug (node + 10));
3882: TCHAR *name = addr ? au ((char*)addr) : au("<null>");
1.1.1.2 ! root 3883: console_out_f (_T(" %08X (C=%08X D=%08X) '%s'\n"), node, get_long_debug (list + 4), get_long_debug (list), name);
1.1 root 3884: xfree (name);
3885: }
3886: } else {
3887: int cnt = 0;
3888: node = get_long_debug (list);
3889: node = get_long_debug (node);
3890: while (get_long_debug (node)) {
3891: uae_u8 *addr = get_real_address (get_long_debug (node + 10));
3892: TCHAR *name = addr ? au ((char*)addr) : au("<null>");
1.1.1.2 ! root 3893: uae_s8 pri = get_byte_debug(node + 9);
! 3894: console_out_f (_T(" [S] %08x %+03d (C=%08x D=%08X) '%s'\n"), node, pri, get_long_debug (node + 18), get_long_debug (node + 14), name);
1.1 root 3895: if (i == 4 - 1 || i == 14 - 1) {
3896: if (!_tcsicmp (name, _T("cia-a")) || !_tcsicmp (name, _T("cia-b"))) {
3897: static const TCHAR *ciai[] = { _T("A"), _T("B"), _T("ALRM"), _T("SP"), _T("FLG") };
3898: uaecptr cia = node + 22;
3899: for (int j = 0; j < 5; j++) {
3900: uaecptr ciap = get_long_debug (cia);
3901: console_out_f (_T(" %5s: %08x"), ciai[j], ciap);
3902: if (ciap) {
3903: uae_u8 *addr2 = get_real_address (get_long_debug (ciap + 10));
3904: TCHAR *name2 = addr ? au ((char*)addr2) : au("<null>");
3905: console_out_f (_T(" (C=%08x D=%08X) '%s'"), get_long_debug (ciap + 18), get_long_debug (ciap + 14), name2);
3906: xfree (name2);
3907: }
3908: console_out_f (_T("\n"));
3909: cia += 4;
3910: }
3911: }
3912: }
3913: xfree (name);
3914: node = get_long_debug (node);
3915: cnt++;
3916: }
3917: if (!cnt)
3918: console_out_f (_T(" [S] <none>\n"));
3919: }
3920: list += 12;
3921: }
3922: return;
3923: } else if (c == 'e') { // expansion
3924: uaecptr expbase = get_base("expansion.library", 378);
3925: if (expbase) {
3926: list = get_long_debug(expbase + 60);
3927: while (list && get_long_debug(list)) {
3928: uae_u32 addr = get_long_debug(list + 32);
3929: uae_u16 rom_vector = get_word_debug(list + 16 + 10);
3930: uae_u8 type = get_byte_debug(list + 16 + 0);
3931: console_out_f(_T("%02x %02x %08x %08x %04x %02x %08x %04x (%u/%u)\n"),
3932: type, get_byte_debug(list + 16 + 2),
3933: addr, get_long_debug(list + 36),
3934: get_word_debug(list + 16 + 4), get_byte_debug(list + 16 + 1),
3935: get_long_debug(list + 16 + 6), rom_vector,
3936: get_word_debug(list + 16 + 4), get_byte_debug(list + 16 + 1));
3937: if ((type & 0x10)) {
3938: uae_u8 diagarea[256];
3939: uae_u16 nameoffset;
3940: uaecptr rom = addr + rom_vector;
3941: uae_u8 config = get_byte_debug(rom);
3942: copyromdata(config, rom, 0, diagarea, 16);
3943: nameoffset = (diagarea[8] << 8) | diagarea[9];
3944: console_out_f(_T(" %02x %02x Size %04x Diag %04x Boot %04x Name %04x %04x %04x\n"),
3945: diagarea[0], diagarea[1],
3946: (diagarea[2] << 8) | diagarea[3],
3947: (diagarea[4] << 8) | diagarea[5],
3948: (diagarea[6] << 8) | diagarea[7],
3949: nameoffset,
3950: (diagarea[10] << 8) | diagarea[11],
3951: (diagarea[12] << 8) | diagarea[13]);
3952: if (nameoffset != 0 && nameoffset != 0xffff) {
3953: copyromdata(config, rom, nameoffset, diagarea, 256);
3954: diagarea[sizeof diagarea - 1] = 0;
3955: TCHAR *str = au((char*)diagarea);
3956: console_out_f(_T(" '%s'\n"), str);
3957: xfree(str);
3958: }
3959: }
3960: list = get_long_debug(list);
3961: }
3962: }
1.1.1.2 ! root 3963: return;
1.1 root 3964: } else if (c == 'R') { // residents
3965: list = get_long_debug(execbase + 300);
3966: while (list) {
3967: uaecptr resident = get_long_debug (list);
3968: if (!resident)
3969: break;
3970: if (resident & 0x80000000) {
3971: console_out_f (_T("-> %08X\n"), resident & 0x7fffffff);
3972: list = resident & 0x7fffffff;
3973: continue;
3974: }
3975: uae_u8 *addr;
3976: addr = get_real_address (get_long_debug (resident + 14));
3977: TCHAR *name1 = addr ? au ((char*)addr) : au("<null>");
3978: my_trim (name1);
3979: addr = get_real_address (get_long_debug (resident + 18));
3980: TCHAR *name2 = addr ? au ((char*)addr) : au("<null>");
3981: my_trim (name2);
3982: console_out_f (_T("%08X %08X: %02X %3d %02X %+3.3d '%s' ('%s')\n"),
3983: list, resident,
3984: get_byte_debug (resident + 10), get_byte_debug (resident + 11),
3985: get_byte_debug (resident + 12), (uae_s8)get_byte_debug (resident + 13),
3986: name1, name2);
3987: xfree (name2);
3988: xfree (name1);
3989: list += 4;
3990: }
3991: return;
3992: } else if (c == 'f' || c== 'F') { // filesystem.resource
3993: uaecptr fs = get_base ("FileSystem.resource", 336);
3994: if (fs) {
3995: static const TCHAR *fsnames[] = {
3996: _T("DosType"),
3997: _T("Version"),
3998: _T("PatchFlags"),
3999: _T("Type"),
4000: _T("Task"),
4001: _T("Lock"),
4002: _T("Handler"),
4003: _T("StackSize"),
4004: _T("Priority"),
4005: _T("Startup"),
4006: _T("SegList"),
4007: _T("GlobalVec"),
4008: NULL
4009: };
4010: uae_u8 *addr = get_real_address (get_long_debug (fs + 14));
4011: TCHAR *name = addr ? au ((char*)addr) : au ("<null>");
4012: my_trim (name);
4013: console_out_f (_T("%08x: '%s'\n"), fs, name);
4014: xfree (name);
4015: node = get_long_debug (fs + 18);
4016: while (get_long_debug (node)) {
4017: TCHAR *name = au ((char*)get_real_address (get_long_debug (node + 10)));
4018: my_trim (name);
4019: console_out_f (_T("%08x: '%s'\n"), node, name);
4020: xfree (name);
4021: for (int i = 0; fsnames[i]; i++) {
4022: uae_u32 v = get_long_debug (node + 14 + i * 4);
4023: console_out_f (_T("%16s = %08x %d\n"), fsnames[i], v, v);
4024: }
4025: console_out_f (_T("\n"));
4026: node = get_long_debug (node);
4027: }
4028:
4029: } else {
4030: console_out_f (_T("FileSystem.resource not found.\n"));
4031: }
4032: return;
4033: } else if (c == 'm' || c == 'M') { // memory
4034: list = execbase + 322;
4035: node = get_long_debug (list);
4036: while (get_long_debug (node)) {
4037: TCHAR *name = au ((char*)get_real_address (get_long_debug (node + 10)));
4038: uae_u16 v = get_word_debug (node + 8);
4039: console_out_f (_T("%08x %d %d %s\n"), node, (int)((v >> 8) & 0xff), (uae_s8)(v & 0xff), name);
4040: xfree (name);
4041: console_out_f (_T("Attributes %04x First %08x Lower %08x Upper %08x Free %d\n"),
4042: get_word_debug (node + 14), get_long_debug (node + 16), get_long_debug (node + 20),
4043: get_long_debug (node + 24), get_long_debug (node + 28));
4044: uaecptr mc = get_long_debug (node + 16);
4045: while (mc) {
4046: uae_u32 mc1 = get_long_debug (mc);
4047: uae_u32 mc2 = get_long_debug (mc + 4);
4048: console_out_f (_T(" %08x: %08x-%08x,%08x,%08x (%d)\n"), mc, mc, mc + mc2, mc1, mc2, mc2);
4049: mc = mc1;
4050: }
4051: console_out_f (_T("\n"));
4052: node = get_long_debug (node);
4053: }
4054: return;
4055: }
4056:
4057: bool full = false;
4058: switch (c)
4059: {
4060: case 'r': // resources
4061: list = execbase + 336;
4062: break;
4063: case 'd': // devices
4064: list = execbase + 350;
4065: full = true;
4066: break;
4067: case 'l': // libraries
4068: list = execbase + 378;
4069: full = true;
4070: break;
4071: case 'p': // ports
4072: list = execbase + 392;
4073: break;
4074: case 's': // semaphores
4075: list = execbase + 532;
4076: break;
4077: }
4078: if (list == 0)
4079: return;
4080: node = get_long_debug (list);
4081: while (get_long_debug (node)) {
4082: TCHAR *name = au ((char*)get_real_address (get_long_debug (node + 10)));
4083: uae_u16 v = get_word_debug (node + 8);
4084: console_out_f (_T("%08x %d %d"), node, (int)((v >> 8) & 0xff), (uae_s8)(v & 0xff));
4085: if (full) {
4086: uae_u16 ver = get_word_debug(node + 20);
4087: uae_u16 rev = get_word_debug(node + 22);
4088: uae_u32 op = get_word_debug(node + 32);
4089: console_out_f(_T(" %d.%d %d"), ver, rev, op);
4090: }
4091: console_out_f(_T(" %s"), name);
4092: xfree (name);
4093: if (full) {
4094: uaecptr idstring = get_long_debug(node + 24);
4095: if (idstring) {
4096: name = au((char*)get_real_address(idstring));
4097: console_out_f(_T(" (%s)"), name);
4098: xfree(name);
4099: }
4100: }
4101: console_out_f(_T("\n"));
4102: node = get_long_debug (node);
4103: }
4104: }
4105:
4106: static void breakfunc(uae_u32 v)
4107: {
4108: write_log(_T("Cycle breakpoint hit\n"));
4109: debugging = 1;
4110: set_special (SPCFLAG_BRK);
4111: }
4112:
4113: static int cycle_breakpoint(TCHAR **c)
4114: {
4115: TCHAR nc = (*c)[0];
4116: next_char(c);
4117: if (more_params(c)) {
4118: int count = readint(c);
4119: if (nc == 's') {
4120: if (more_params(c)) {
4121: int hp = readint(c);
4122: if (count >= vpos) {
4123: count = vpos - count;
4124: } else {
4125: count += maxvpos - vpos;
4126: }
4127: count *= maxhpos;
4128: if (hp >= current_hpos()) {
4129: count += hp - current_hpos();
4130: } else {
4131: count += maxhpos - current_hpos();
4132: }
4133: } else {
4134: count *= maxhpos;
4135: }
4136: }
4137: event2_newevent_x(-1, count, 0, breakfunc);
4138: return 1;
4139: }
4140: return 0;
4141: }
4142:
4143: #if 0
4144: static int trace_same_insn_count;
4145: static uae_u8 trace_insn_copy[10];
4146: static struct regstruct trace_prev_regs;
4147: #endif
4148: static uaecptr nextpc;
4149:
4150: int instruction_breakpoint (TCHAR **c)
4151: {
4152: struct breakpoint_node *bpn;
4153: int i;
4154:
4155: if (more_params (c)) {
4156: TCHAR nc = _totupper ((*c)[0]);
1.1.1.2 ! root 4157: if (nc == 'O') {
! 4158: // bpnum register operation value1 [mask value2]
! 4159: next_char(c);
! 4160: if (more_params(c)) {
! 4161: int bpidx = readint(c);
! 4162: if (more_params(c) && bpidx >= 0 && bpidx < BREAKPOINT_TOTAL) {
! 4163: bpn = &bpnodes[bpidx];
! 4164: int regid = getregidx(c);
! 4165: if (regid >= 0) {
! 4166: bpn->type = regid;
! 4167: bpn->mask = 0xffffffff;
! 4168: if (more_params(c)) {
! 4169: int operid = getoperidx(c);
! 4170: if (more_params(c) && operid >= 0) {
! 4171: bpn->oper = operid;
! 4172: bpn->value1 = readhex(c);
! 4173: bpn->enabled = 1;
! 4174: if (more_params(c)) {
! 4175: bpn->mask = readhex(c);
! 4176: if (more_params(c)) {
! 4177: bpn->value2 = readhex(c);
! 4178: }
! 4179: }
! 4180: console_out(_T("Breakpoint added.\n"));
! 4181: }
! 4182: }
! 4183: }
! 4184: }
1.1 root 4185: }
4186: return 0;
4187: } else if (nc == 'I') {
4188: next_char (c);
4189: if (more_params (c))
4190: skipins = readhex (c);
4191: else
4192: skipins = 0x10000;
4193: do_skip = 1;
4194: skipaddr_doskip = 1;
4195: return 1;
4196: } else if (nc == 'D' && (*c)[1] == 0) {
4197: for (i = 0; i < BREAKPOINT_TOTAL; i++)
4198: bpnodes[i].enabled = 0;
1.1.1.2 ! root 4199: console_out(_T("All breakpoints removed.\n"));
! 4200: return 0;
! 4201: } else if (nc == 'R' && (*c)[1] == 0) {
! 4202: if (more_params(c)) {
! 4203: int bpnum = readint(c);
! 4204: if (bpnum >= 0 && bpnum < BREAKPOINT_TOTAL) {
! 4205: bpnodes[bpnum].enabled = 0;
! 4206: console_out_f(_T("Breakpoint %d removed.\n"), bpnum);
! 4207: }
! 4208: }
1.1 root 4209: return 0;
4210: } else if (nc == 'L') {
4211: int got = 0;
4212: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
4213: bpn = &bpnodes[i];
4214: if (!bpn->enabled)
4215: continue;
1.1.1.2 ! root 4216: console_out_f (_T("%d: %s %s %08x [%08x %08x]\n"), i, debugregs[bpn->type], debugoper[bpn->oper], bpn->value1, bpn->mask, bpn->value2);
1.1 root 4217: got = 1;
4218: }
4219: if (!got)
1.1.1.2 ! root 4220: console_out (_T("No breakpoints.\n"));
1.1 root 4221: else
4222: console_out (_T("\n"));
4223: return 0;
4224: }
4225: skipaddr_doskip = 1;
4226: skipaddr_start = readhex (c);
4227: if (more_params (c)) {
4228: skipaddr_end = readhex (c);
4229: } else {
4230: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
4231: bpn = &bpnodes[i];
1.1.1.2 ! root 4232: if (bpn->enabled && bpn->value1 == skipaddr_start) {
1.1 root 4233: bpn->enabled = 0;
1.1.1.2 ! root 4234: console_out (_T("Breakpoint removed.\n"));
1.1 root 4235: skipaddr_start = 0xffffffff;
4236: skipaddr_doskip = 0;
4237: return 0;
4238: }
4239: }
4240: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
4241: bpn = &bpnodes[i];
4242: if (bpn->enabled)
4243: continue;
1.1.1.2 ! root 4244: bpn->value1 = skipaddr_start;
! 4245: bpn->type = BREAKPOINT_REG_PC;
! 4246: bpn->oper = BREAKPOINT_CMP_EQUAL;
1.1 root 4247: bpn->enabled = 1;
1.1.1.2 ! root 4248: console_out (_T("Breakpoint added.\n"));
1.1 root 4249: skipaddr_start = 0xffffffff;
4250: skipaddr_doskip = 0;
4251: break;
4252: }
4253: return 0;
4254: }
4255: }
4256: #if 0
4257: if (skipaddr_start == 0xC0DEDBAD) {
4258: trace_same_insn_count = 0;
4259: logfile = fopen ("uae.trace", "w");
4260: memcpy (trace_insn_copy, regs.pc_p, 10);
4261: memcpy (&trace_prev_regs, ®s, sizeof regs);
4262: }
4263: #endif
4264: do_skip = 1;
4265: skipaddr_doskip = -1;
4266: return 1;
4267: }
4268:
4269: static int process_breakpoint (TCHAR **c)
4270: {
4271: processptr = 0;
4272: xfree (processname);
4273: processname = NULL;
4274: if (!more_params (c))
4275: return 0;
4276: if (**c == '\"') {
4277: TCHAR pn[200];
4278: next_string (c, pn, 200, 0);
4279: processname = ua (pn);
4280: } else {
4281: processptr = readhex (c);
4282: }
4283: do_skip = 1;
4284: skipaddr_doskip = 1;
4285: skipaddr_start = 0;
4286: return 1;
4287: }
4288:
4289: static void savemem (TCHAR **cc)
4290: {
4291: uae_u8 b;
4292: uae_u32 src, src2, len, len2;
4293: TCHAR *name;
4294: FILE *fp;
4295:
4296: if (!more_params (cc))
4297: goto S_argh;
4298:
4299: name = *cc;
4300: while (**cc != '\0' && !isspace (**cc))
4301: (*cc)++;
4302: if (!isspace (**cc))
4303: goto S_argh;
4304:
4305: **cc = '\0';
4306: (*cc)++;
4307: if (!more_params (cc))
4308: goto S_argh;
4309: src2 = src = readhex (cc);
4310: if (!more_params (cc))
4311: goto S_argh;
4312: len2 = len = readhex (cc);
1.1.1.2 ! root 4313: fp = uae_tfopen (name, _T("wb"));
1.1 root 4314: if (fp == NULL) {
4315: console_out_f (_T("Couldn't open file '%s'\n"), name);
4316: return;
4317: }
4318: while (len > 0) {
4319: b = get_byte_debug (src);
4320: src++;
4321: len--;
4322: if (fwrite (&b, 1, 1, fp) != 1) {
4323: console_out (_T("Error writing file\n"));
4324: break;
4325: }
4326: }
4327: fclose (fp);
4328: if (len == 0)
4329: console_out_f (_T("Wrote %08X - %08X (%d bytes) to '%s'\n"),
4330: src2, src2 + len2, len2, name);
4331: return;
4332: S_argh:
4333: console_out (_T("S-command needs more arguments!\n"));
4334: }
4335:
4336: static void searchmem (TCHAR **cc)
4337: {
4338: int i, sslen, got, val, stringmode;
4339: uae_u8 ss[256];
4340: uae_u32 addr, endaddr;
4341: TCHAR nc;
4342:
4343: got = 0;
4344: sslen = 0;
4345: stringmode = 0;
4346: ignore_ws (cc);
4347: if (**cc == '"') {
4348: stringmode = 1;
4349: (*cc)++;
4350: while (**cc != '"' && **cc != 0) {
4351: ss[sslen++] = tolower (**cc);
4352: (*cc)++;
4353: }
4354: if (**cc != 0)
4355: (*cc)++;
4356: } else {
4357: for (;;) {
4358: if (**cc == 32 || **cc == 0)
4359: break;
4360: nc = _totupper (next_char (cc));
4361: if (isspace (nc))
4362: break;
4363: if (isdigit(nc))
4364: val = nc - '0';
4365: else
4366: val = nc - 'A' + 10;
4367: if (val < 0 || val > 15)
4368: return;
4369: val *= 16;
4370: if (**cc == 32 || **cc == 0)
4371: break;
4372: nc = _totupper (next_char (cc));
4373: if (isspace (nc))
4374: break;
4375: if (isdigit(nc))
4376: val += nc - '0';
4377: else
4378: val += nc - 'A' + 10;
4379: if (val < 0 || val > 255)
4380: return;
4381: ss[sslen++] = (uae_u8)val;
4382: }
4383: }
4384: if (sslen == 0)
4385: return;
4386: ignore_ws (cc);
4387: addr = 0;
4388: endaddr = lastaddr ();
4389: if (more_params (cc)) {
4390: addr = readhex (cc);
4391: if (more_params (cc))
4392: endaddr = readhex (cc);
4393: }
4394: console_out_f (_T("Searching from %08X to %08X..\n"), addr, endaddr);
4395: while ((addr = nextaddr (addr, endaddr, NULL)) != 0xffffffff) {
4396: if (addr == endaddr)
4397: break;
4398: for (i = 0; i < sslen; i++) {
4399: uae_u8 b = get_byte_debug (addr + i);
4400: if (stringmode) {
4401: if (tolower (b) != ss[i])
4402: break;
4403: } else {
4404: if (b != ss[i])
4405: break;
4406: }
4407: }
4408: if (i == sslen) {
4409: got++;
4410: console_out_f (_T(" %08X"), addr);
4411: if (got > 100) {
4412: console_out (_T("\nMore than 100 results, aborting.."));
4413: break;
4414: }
4415: }
4416: if (iscancel (65536)) {
4417: console_out_f (_T("Aborted at %08X\n"), addr);
4418: break;
4419: }
4420: }
4421: if (!got)
4422: console_out (_T("nothing found"));
4423: console_out (_T("\n"));
4424: }
4425:
4426: static int staterecorder (TCHAR **cc)
4427: {
4428: #if 0
4429: TCHAR nc;
4430:
4431: if (!more_params (cc)) {
4432: if (savestate_dorewind (1)) {
4433: debug_rewind = 1;
4434: return 1;
4435: }
4436: return 0;
4437: }
4438: nc = next_char (cc);
4439: if (nc == 'l') {
4440: savestate_listrewind ();
4441: return 0;
4442: }
4443: #endif
4444: return 0;
4445: }
4446:
4447: static int debugtest_modes[DEBUGTEST_MAX];
4448: static const TCHAR *debugtest_names[] = {
4449: _T("Blitter"), _T("Keyboard"), _T("Floppy")
4450: };
4451:
4452: void debugtest (enum debugtest_item di, const TCHAR *format, ...)
4453: {
4454: va_list parms;
4455: TCHAR buffer[1000];
4456:
4457: if (!debugtest_modes[di])
4458: return;
4459: va_start (parms, format);
4460: _vsntprintf (buffer, 1000 - 1, format, parms);
4461: va_end (parms);
4462: write_log (_T("%s PC=%08X: %s\n"), debugtest_names[di], M68K_GETPC, buffer);
4463: if (debugtest_modes[di] == 2)
4464: activate_debugger ();
4465: }
4466:
4467: static void debugtest_set (TCHAR **inptr)
4468: {
4469: int i, val, val2;
4470: ignore_ws (inptr);
4471:
4472: val2 = 1;
4473: if (!more_params (inptr)) {
4474: for (i = 0; i < DEBUGTEST_MAX; i++)
4475: debugtest_modes[i] = 0;
4476: console_out (_T("All debugtests disabled\n"));
4477: return;
4478: }
4479: val = readint (inptr);
4480: if (more_params (inptr)) {
4481: val2 = readint (inptr);
4482: if (val2 > 0)
4483: val2 = 2;
4484: }
4485: if (val < 0) {
4486: for (i = 0; i < DEBUGTEST_MAX; i++)
4487: debugtest_modes[i] = val2;
4488: console_out (_T("All debugtests enabled\n"));
4489: return;
4490: }
4491: if (val >= 0 && val < DEBUGTEST_MAX) {
4492: if (debugtest_modes[val])
4493: debugtest_modes[val] = 0;
4494: else
4495: debugtest_modes[val] = val2;
4496: console_out_f (_T("Debugtest '%s': %s. break = %s\n"),
4497: debugtest_names[val], debugtest_modes[val] ? _T("on") :_T("off"), val2 == 2 ? _T("on") : _T("off"));
4498: }
4499: }
4500:
4501: static void debug_sprite (TCHAR **inptr)
4502: {
4503: uaecptr saddr, addr, addr2;
4504: int xpos, xpos_ecs;
4505: int ypos, ypos_ecs;
4506: int ypose, ypose_ecs;
4507: int attach;
4508: uae_u64 w1, w2, ww1, ww2;
4509: int size = 1, width;
4510: int ecs, sh10;
4511: int y, i;
4512: TCHAR tmp[80];
4513: int max = 2;
4514:
4515: addr2 = 0;
4516: ignore_ws (inptr);
4517: addr = readhex (inptr);
4518: ignore_ws (inptr);
4519: if (more_params (inptr))
4520: size = readhex (inptr);
4521: if (size != 1 && size != 2 && size != 4) {
4522: addr2 = size;
4523: ignore_ws (inptr);
4524: if (more_params (inptr))
4525: size = readint (inptr);
4526: if (size != 1 && size != 2 && size != 4)
4527: size = 1;
4528: }
4529: for (;;) {
4530: ecs = 0;
4531: sh10 = 0;
4532: saddr = addr;
4533: width = size * 16;
4534: w1 = get_word_debug (addr);
4535: w2 = get_word_debug (addr + size * 2);
4536: console_out_f (_T(" %06X "), addr);
4537: for (i = 0; i < size * 2; i++)
4538: console_out_f (_T("%04X "), get_word_debug (addr + i * 2));
4539: console_out_f (_T("\n"));
4540:
4541: ypos = w1 >> 8;
4542: xpos = w1 & 255;
4543: ypose = w2 >> 8;
4544: attach = (w2 & 0x80) ? 1 : 0;
4545: if (w2 & 4)
4546: ypos |= 256;
4547: if (w2 & 2)
4548: ypose |= 256;
4549: ypos_ecs = ypos;
4550: ypose_ecs = ypose;
4551: if (w2 & 0x40)
4552: ypos_ecs |= 512;
4553: if (w2 & 0x20)
4554: ypose_ecs |= 512;
4555: xpos <<= 1;
4556: if (w2 & 0x01)
4557: xpos |= 1;
4558: xpos_ecs = xpos << 2;
4559: if (w2 & 0x10)
4560: xpos_ecs |= 2;
4561: if (w2 & 0x08)
4562: xpos_ecs |= 1;
4563: if (w2 & (0x40 | 0x20 | 0x10 | 0x08))
4564: ecs = 1;
4565: if (w1 & 0x80)
4566: sh10 = 1;
4567: if (ypose < ypos)
4568: ypose += 256;
4569:
4570: for (y = ypos; y < ypose; y++) {
4571: int x;
4572: addr += size * 4;
4573: if (addr2)
4574: addr2 += size * 4;
4575: if (size == 1) {
4576: w1 = get_word_debug (addr);
4577: w2 = get_word_debug (addr + 2);
4578: if (addr2) {
4579: ww1 = get_word_debug (addr2);
4580: ww2 = get_word_debug (addr2 + 2);
4581: }
4582: } else if (size == 2) {
4583: w1 = get_long_debug (addr);
4584: w2 = get_long_debug (addr + 4);
4585: if (addr2) {
4586: ww1 = get_long_debug (addr2);
4587: ww2 = get_long_debug (addr2 + 4);
4588: }
4589: } else if (size == 4) {
4590: w1 = get_long_debug (addr + 0);
4591: w2 = get_long_debug (addr + 8);
4592: w1 <<= 32;
4593: w2 <<= 32;
4594: w1 |= get_long_debug (addr + 4);
4595: w2 |= get_long_debug (addr + 12);
4596: if (addr2) {
4597: ww1 = get_long_debug (addr2 + 0);
4598: ww2 = get_long_debug (addr2 + 8);
4599: ww1 <<= 32;
4600: ww2 <<= 32;
4601: ww1 |= get_long_debug (addr2 + 4);
4602: ww2 |= get_long_debug (addr2 + 12);
4603: }
4604: }
4605: width = size * 16;
4606: for (x = 0; x < width; x++) {
4607: int v1 = w1 & 1;
4608: int v2 = w2 & 1;
4609: int v = v1 * 2 + v2;
4610: w1 >>= 1;
4611: w2 >>= 1;
4612: if (addr2) {
4613: int vv1 = ww1 & 1;
4614: int vv2 = ww2 & 1;
4615: int vv = vv1 * 2 + vv2;
4616: vv1 >>= 1;
4617: vv2 >>= 1;
4618: v *= 4;
4619: v += vv;
4620: tmp[width - (x + 1)] = v >= 10 ? 'A' + v - 10 : v + '0';
4621: } else {
4622: tmp[width - (x + 1)] = v + '0';
4623: }
4624: }
4625: tmp[width] = 0;
4626: console_out_f (_T("%3d %06X %s\n"), y, addr, tmp);
4627: }
4628:
4629: console_out_f (_T("Sprite address %08X, width = %d\n"), saddr, size * 16);
4630: console_out_f (_T("OCS: StartX=%d StartY=%d EndY=%d\n"), xpos, ypos, ypose);
4631: console_out_f (_T("ECS: StartX=%d (%d.%d) StartY=%d EndY=%d%s\n"), xpos_ecs, xpos_ecs / 4, xpos_ecs & 3, ypos_ecs, ypose_ecs, ecs ? _T(" (*)") : _T(""));
4632: console_out_f (_T("Attach: %d. AGA SSCAN/SH10 bit: %d\n"), attach, sh10);
4633:
4634: addr += size * 4;
4635: if (get_word_debug (addr) == 0 && get_word_debug (addr + size * 4) == 0)
4636: break;
4637: max--;
4638: if (max <= 0)
4639: break;
4640: }
4641:
4642: }
4643:
4644: int debug_write_memory_16 (uaecptr addr, uae_u16 v)
4645: {
4646: addrbank *ad;
4647:
4648: ad = &get_mem_bank (addr);
4649: if (ad) {
4650: ad->wput (addr, v);
4651: return 1;
4652: }
4653: return -1;
4654: }
4655: int debug_write_memory_8 (uaecptr addr, uae_u8 v)
4656: {
4657: addrbank *ad;
4658:
4659: ad = &get_mem_bank (addr);
4660: if (ad) {
4661: ad->bput (addr, v);
4662: return 1;
4663: }
4664: return -1;
4665: }
4666: int debug_peek_memory_16 (uaecptr addr)
4667: {
4668: addrbank *ad;
4669:
4670: ad = &get_mem_bank (addr);
4671: if (ad->flags & (ABFLAG_RAM | ABFLAG_ROM | ABFLAG_ROMIN | ABFLAG_SAFE))
4672: return ad->wget (addr);
4673: if (ad == &custom_bank) {
4674: addr &= 0x1fe;
4675: return (ar_custom[addr + 0] << 8) | ar_custom[addr + 1];
4676: }
4677: return -1;
4678: }
4679: int debug_read_memory_16 (uaecptr addr)
4680: {
4681: addrbank *ad;
4682:
4683: ad = &get_mem_bank (addr);
4684: if (ad)
4685: return ad->wget (addr);
4686: return -1;
4687: }
4688: int debug_read_memory_8 (uaecptr addr)
4689: {
4690: addrbank *ad;
4691:
4692: ad = &get_mem_bank (addr);
4693: if (ad)
4694: return ad->bget (addr);
4695: return -1;
4696: }
4697:
4698: static void disk_debug (TCHAR **inptr)
4699: {
4700: TCHAR parm[10];
4701: int i;
4702:
4703: if (**inptr == 'd') {
4704: (*inptr)++;
4705: ignore_ws (inptr);
4706: disk_debug_logging = readint (inptr);
4707: console_out_f (_T("Disk logging level %d\n"), disk_debug_logging);
4708: return;
4709: }
4710: disk_debug_mode = 0;
4711: disk_debug_track = -1;
4712: ignore_ws (inptr);
4713: if (!next_string (inptr, parm, sizeof (parm) / sizeof (TCHAR), 1))
4714: goto end;
4715: for (i = 0; i < _tcslen(parm); i++) {
4716: if (parm[i] == 'R')
4717: disk_debug_mode |= DISK_DEBUG_DMA_READ;
4718: if (parm[i] == 'W')
4719: disk_debug_mode |= DISK_DEBUG_DMA_WRITE;
4720: if (parm[i] == 'P')
4721: disk_debug_mode |= DISK_DEBUG_PIO;
4722: }
4723: if (more_params(inptr))
4724: disk_debug_track = readint (inptr);
4725: if (disk_debug_track < 0 || disk_debug_track > 2 * 83)
4726: disk_debug_track = -1;
4727: if (disk_debug_logging == 0)
4728: disk_debug_logging = 1;
4729: end:
4730: console_out_f (_T("Disk breakpoint mode %c%c%c track %d\n"),
4731: disk_debug_mode & DISK_DEBUG_DMA_READ ? 'R' : '-',
4732: disk_debug_mode & DISK_DEBUG_DMA_WRITE ? 'W' : '-',
4733: disk_debug_mode & DISK_DEBUG_PIO ? 'P' : '-',
4734: disk_debug_track);
4735: }
4736:
4737: static void find_ea (TCHAR **inptr)
4738: {
4739: uae_u32 ea, sea, dea;
4740: uaecptr addr, end;
4741: int hits = 0;
4742:
4743: addr = 0;
4744: end = lastaddr ();
4745: ea = readhex (inptr);
4746: if (more_params(inptr)) {
4747: addr = readhex (inptr);
4748: if (more_params(inptr))
4749: end = readhex (inptr);
4750: }
4751: console_out_f (_T("Searching from %08X to %08X\n"), addr, end);
4752: while((addr = nextaddr (addr, end, &end)) != 0xffffffff) {
4753: if ((addr & 1) == 0 && addr + 6 <= end) {
4754: sea = 0xffffffff;
4755: dea = 0xffffffff;
4756: m68k_disasm_ea (addr, NULL, 1, &sea, &dea);
4757: if (ea == sea || ea == dea) {
4758: m68k_disasm (addr, NULL, 1);
4759: hits++;
4760: if (hits > 100) {
4761: console_out_f (_T("Too many hits. End addr = %08X\n"), addr);
4762: break;
4763: }
4764: }
4765: if (iscancel (65536)) {
4766: console_out_f (_T("Aborted at %08X\n"), addr);
4767: break;
4768: }
4769: }
4770: }
4771: }
4772:
4773: static void m68k_modify (TCHAR **inptr)
4774: {
4775: uae_u32 v;
4776: TCHAR parm[10];
4777: TCHAR c1, c2;
4778: int i;
4779:
4780: if (!next_string (inptr, parm, sizeof (parm) / sizeof (TCHAR), 1))
4781: return;
4782: c1 = _totupper (parm[0]);
4783: c2 = 99;
4784: if (c1 == 'A' || c1 == 'D' || c1 == 'P') {
4785: c2 = _totupper (parm[1]);
4786: if (isdigit (c2))
4787: c2 -= '0';
4788: else
4789: c2 = 99;
4790: }
4791: v = readhex (inptr);
4792: if (c1 == 'A' && c2 < 8)
4793: regs.regs[8 + c2] = v;
4794: else if (c1 == 'D' && c2 < 8)
4795: regs.regs[c2] = v;
4796: else if (c1 == 'P' && c2 == 0)
4797: regs.irc = v;
4798: else if (c1 == 'P' && c2 == 1)
4799: regs.ir = v;
4800: else if (!_tcscmp (parm, _T("SR"))) {
4801: regs.sr = v;
4802: MakeFromSR ();
4803: } else if (!_tcscmp (parm, _T("CCR"))) {
4804: regs.sr = (regs.sr & ~31) | (v & 31);
4805: MakeFromSR ();
4806: } else if (!_tcscmp (parm, _T("USP"))) {
4807: regs.usp = v;
4808: } else if (!_tcscmp (parm, _T("ISP"))) {
4809: regs.isp = v;
4810: } else if (!_tcscmp (parm, _T("PC"))) {
4811: m68k_setpc (v);
4812: fill_prefetch ();
4813: } else {
4814: for (i = 0; m2cregs[i].regname; i++) {
4815: if (!_tcscmp (parm, m2cregs[i].regname))
4816: val_move2c2 (m2cregs[i].regno, v);
4817: }
4818: }
4819: }
4820:
4821: static void ppc_disasm(uaecptr addr, uaecptr *nextpc, int cnt)
4822: {
4823: PPCD_CB disa;
4824:
4825: while(cnt-- > 0) {
4826: uae_u32 instr = get_long_debug(addr);
4827: disa.pc = addr;
4828: disa.instr = instr;
4829: PPCDisasm(&disa);
4830: TCHAR *mnemo = au(disa.mnemonic);
4831: TCHAR *ops = au(disa.operands);
4832: console_out_f(_T("%08X %08X %-12s%-30s\n"), addr, instr, mnemo, ops);
4833: xfree(ops);
4834: xfree(mnemo);
4835: addr += 4;
4836: }
4837: if (nextpc)
4838: *nextpc = addr;
4839: }
4840:
4841: static uaecptr nxdis, nxmem;
4842: static bool ppcmode;
4843:
1.1.1.2 ! root 4844: static bool debug_line (TCHAR *input)
1.1 root 4845: {
4846: TCHAR cmd, *inptr;
4847: uaecptr addr;
4848:
4849: inptr = input;
4850: cmd = next_char (&inptr);
4851:
4852: switch (cmd)
4853: {
1.1.1.2 ! root 4854: case 'c': dumpcia (); dumpdisk (_T("DEBUG")); dumpcustom (); break;
1.1 root 4855: case 'i':
4856: {
4857: if (*inptr == 'l') {
4858: next_char (&inptr);
4859: if (more_params (&inptr)) {
4860: debug_illegal_mask = readhex (&inptr);
1.1.1.2 ! root 4861: if (more_params(&inptr))
! 4862: debug_illegal_mask |= ((uae_u64)readhex(&inptr)) << 32;
1.1 root 4863: } else {
4864: debug_illegal_mask = debug_illegal ? 0 : -1;
4865: debug_illegal_mask &= ~((uae_u64)255 << 24); // mask interrupts
4866: }
1.1.1.2 ! root 4867: console_out_f (_T("Exception breakpoint mask: %08X %08X\n"), (uae_u32)(debug_illegal_mask >> 32), (uae_u32)debug_illegal_mask);
1.1 root 4868: debug_illegal = debug_illegal_mask ? 1 : 0;
4869: } else {
4870: addr = 0xffffffff;
4871: if (more_params (&inptr))
4872: addr = readhex (&inptr);
4873: dump_vectors (addr);
4874: }
4875: break;
4876: }
4877: case 'e': dump_custom_regs (tolower(*inptr) == 'a'); break;
4878: case 'r':
4879: {
4880: if (*inptr == 'c')
4881: m68k_dumpcache ();
4882: else if (more_params(&inptr))
4883: m68k_modify (&inptr);
4884: else
4885: m68k_dumpstate (&nextpc);
4886: }
4887: break;
4888: case 'D': deepcheatsearch (&inptr); break;
4889: case 'C': cheatsearch (&inptr); break;
4890: case 'W': writeintomem (&inptr); break;
4891: case 'w': memwatch (&inptr); break;
4892: case 'S': savemem (&inptr); break;
4893: case 's':
4894: if (*inptr == 'c') {
4895: screenshot (1, 1);
4896: } else if (*inptr == 'p') {
4897: inptr++;
4898: debug_sprite (&inptr);
4899: } else if (*inptr == 'm') {
4900: if (*(inptr + 1) == 'c') {
4901: next_char (&inptr);
4902: next_char (&inptr);
4903: if (!smc_table)
4904: smc_detect_init (&inptr);
4905: else
4906: smc_free ();
4907: }
4908: } else {
4909: searchmem (&inptr);
4910: }
4911: break;
4912: case 'd':
4913: {
4914: if (*inptr == 'i') {
4915: next_char (&inptr);
4916: disk_debug (&inptr);
4917: } else if (*inptr == 'j') {
4918: inptr++;
4919: inputdevice_logging = 1 | 2;
4920: if (more_params (&inptr))
4921: inputdevice_logging = readint (&inptr);
4922: console_out_f (_T("Input logging level %d\n"), inputdevice_logging);
4923: } else if (*inptr == 'm') {
4924: memory_map_dump_2 (0);
4925: } else if (*inptr == 't') {
4926: next_char (&inptr);
4927: debugtest_set (&inptr);
4928: #ifdef _WIN32
4929: } else if (*inptr == 'g') {
4930: extern void update_disassembly (uae_u32);
4931: next_char (&inptr);
4932: if (more_params (&inptr))
4933: update_disassembly (readhex (&inptr));
4934: #endif
4935: } else {
4936: uae_u32 daddr;
4937: int count;
4938: if (*inptr == 'p') {
4939: ppcmode = true;
4940: next_char(&inptr);
4941: } else if(*inptr == 'o') {
4942: ppcmode = false;
4943: next_char(&inptr);
4944: }
4945: if (more_params (&inptr))
4946: daddr = readhex (&inptr);
4947: else
4948: daddr = nxdis;
4949: if (more_params (&inptr))
4950: count = readhex (&inptr);
4951: else
4952: count = 10;
4953: if (ppcmode) {
4954: ppc_disasm(daddr, &nxdis, count);
4955: } else {
4956: m68k_disasm (daddr, &nxdis, count);
4957: }
4958: }
4959: }
4960: break;
4961: case 'T':
4962: if (inptr[0] == 't' || inptr[0] == 0)
4963: show_exec_tasks ();
4964: else
4965: show_exec_lists (&inptr[0]);
4966: break;
4967: case 't':
4968: no_trace_exceptions = 0;
4969: if (*inptr != 't') {
4970: if (more_params (&inptr))
4971: skipaddr_doskip = readint (&inptr);
4972: if (skipaddr_doskip <= 0 || skipaddr_doskip > 10000)
4973: skipaddr_doskip = 1;
4974: } else {
4975: no_trace_exceptions = 1;
4976: }
4977: set_special (SPCFLAG_BRK);
4978: exception_debugging = 1;
4979: return true;
4980: case 'z':
4981: skipaddr_start = nextpc;
4982: skipaddr_doskip = 1;
4983: do_skip = 1;
4984: exception_debugging = 1;
4985: return true;
4986:
4987: case 'f':
4988: if (inptr[0] == 'a') {
4989: next_char (&inptr);
4990: find_ea (&inptr);
4991: } else if (inptr[0] == 'p') {
4992: inptr++;
4993: if (process_breakpoint (&inptr))
4994: return true;
4995: } else if (inptr[0] == 'c' || inptr[0] == 's') {
4996: if (cycle_breakpoint(&inptr))
4997: return true;
4998: } else if (inptr[0] == 'e' && inptr[1] == 'n') {
4999: break_if_enforcer = break_if_enforcer ? false : true;
5000: console_out_f(_T("Break when enforcer hit: %s\n"), break_if_enforcer ? _T("enabled") : _T("disabled"));
5001: } else {
5002: if (instruction_breakpoint (&inptr))
5003: return true;
5004: }
5005: break;
5006:
5007: case 'q':
5008: uae_quit();
5009: deactivate_debugger();
5010: return true;
5011:
5012: case 'g':
5013: if (more_params (&inptr)) {
5014: m68k_setpc (readhex (&inptr));
5015: fill_prefetch ();
5016: }
5017: deactivate_debugger();
5018: return true;
5019:
5020: case 'x':
5021: if (_totupper(inptr[0]) == 'X') {
5022: debugger_change(-1);
5023: } else {
5024: deactivate_debugger();
5025: close_console();
5026: return true;
5027: }
5028: break;
5029:
5030: case 'H':
5031: {
5032: int count, temp, badly, skip;
5033: uae_u32 addr = 0;
5034: uae_u32 oldpc = m68k_getpc ();
5035: struct regstruct save_regs = regs;
5036:
5037: badly = 0;
5038: if (inptr[0] == 'H') {
5039: badly = 1;
5040: inptr++;
5041: }
5042:
5043: if (more_params(&inptr))
5044: count = readint (&inptr);
5045: else
5046: count = 10;
5047: if (count > 1000) {
5048: addr = count;
5049: count = MAX_HIST;
5050: }
5051: if (count < 0)
5052: break;
5053: skip = count;
5054: if (more_params (&inptr))
5055: skip = count - readint (&inptr);
5056:
5057: temp = lasthist;
5058: while (count-- > 0 && temp != firsthist) {
5059: if (temp == 0)
5060: temp = MAX_HIST - 1;
5061: else
5062: temp--;
5063: }
5064: while (temp != lasthist) {
5065: regs = history[temp];
5066: if (history[temp].pc == addr || addr == 0) {
5067: m68k_setpc (history[temp].pc);
5068: if (badly) {
5069: m68k_dumpstate (NULL);
5070: } else {
5071: console_out_f(_T("%2d "), history[temp].intmask ? history[temp].intmask : (history[temp].s ? -1 : 0));
5072: m68k_disasm (history[temp].pc, NULL, 1);
5073: }
5074: if (addr && history[temp].pc == addr)
5075: break;
5076: }
5077: if (skip-- < 0)
5078: break;
5079: if (++temp == MAX_HIST)
5080: temp = 0;
5081: }
5082: regs = save_regs;
5083: m68k_setpc (oldpc);
5084: }
5085: break;
5086: case 'M':
5087: if (more_params (&inptr)) {
5088: switch (next_char (&inptr))
5089: {
5090: case 'a':
5091: if (more_params (&inptr))
5092: audio_channel_mask = readhex (&inptr);
5093: console_out_f (_T("Audio mask = %02X\n"), audio_channel_mask);
5094: break;
5095: case 's':
5096: if (more_params (&inptr))
5097: debug_sprite_mask = readhex (&inptr);
5098: console_out_f (_T("Sprite mask: %02X\n"), debug_sprite_mask);
5099: break;
5100: case 'b':
5101: if (more_params (&inptr)) {
5102: debug_bpl_mask = readhex (&inptr) & 0xff;
5103: if (more_params (&inptr))
5104: debug_bpl_mask_one = readhex (&inptr) & 0xff;
5105: notice_screen_contents_lost ();
5106: }
5107: console_out_f (_T("Bitplane mask: %02X (%02X)\n"), debug_bpl_mask, debug_bpl_mask_one);
5108: break;
5109: }
5110: }
5111: break;
5112: case 'm':
5113: {
5114: uae_u32 maddr;
5115: int lines;
5116: #ifdef _WIN32
5117: if (*inptr == 'g') {
5118: extern void update_memdump (uae_u32);
5119: next_char (&inptr);
5120: if (more_params (&inptr))
5121: update_memdump (readhex (&inptr));
5122: break;
5123: }
5124: #endif
5125: if (*inptr == 'm' && inptr[1] == 'u') {
5126: if (currprefs.mmu_model) {
5127: inptr += 2;
5128: if (more_params (&inptr))
5129: debug_mmu_mode = readint (&inptr);
5130: else
5131: debug_mmu_mode = 0;
5132: console_out_f (_T("MMU translation function code = %d\n"), debug_mmu_mode);
5133: }
5134: break;
5135: }
5136: if (more_params (&inptr)) {
5137: maddr = readhex (&inptr);
5138: } else {
5139: maddr = nxmem;
5140: }
5141: if (more_params (&inptr))
5142: lines = readhex (&inptr);
5143: else
5144: lines = 20;
5145: dumpmem (maddr, &nxmem, lines);
5146: }
5147: break;
5148: case 'v':
5149: case 'V':
5150: {
5151: int v1 = vpos, v2 = 0;
1.1.1.2 ! root 5152: if (*inptr == 'h') {
! 5153: inptr++;
! 5154: if (more_params(&inptr) && *inptr == '?') {
! 5155: mw_help();
! 5156: } else if (!heatmap) {
! 5157: debug_heatmap = 1;
! 5158: init_heatmap();
! 5159: if (more_params(&inptr)) {
! 5160: v1 = readint(&inptr);
! 5161: if (v1 < 0) {
! 5162: debug_heatmap = 2;
! 5163: }
! 5164: }
! 5165: TCHAR buf[200];
! 5166: TCHAR *pbuf;
! 5167: _stprintf(buf, _T("0 dff000 200 NONE"));
! 5168: pbuf = buf;
! 5169: memwatch(&pbuf);
! 5170: _stprintf(buf, _T("1 0 %08x NONE"), currprefs.chipmem_size);
! 5171: pbuf = buf;
! 5172: memwatch(&pbuf);
! 5173: if (currprefs.bogomem_size) {
! 5174: _stprintf(buf, _T("2 c00000 %08x NONE"), currprefs.bogomem_size);
! 5175: pbuf = buf;
! 5176: memwatch(&pbuf);
! 5177: }
! 5178: console_out_f(_T("Heatmap enabled\n"));
! 5179: } else {
! 5180: if (*inptr == 'd') {
! 5181: console_out_f(_T("Heatmap disabled\n"));
! 5182: free_heatmap();
! 5183: } else {
! 5184: heatmap_stats(&inptr);
! 5185: }
! 5186: }
1.1 root 5187: } else {
1.1.1.2 ! root 5188: if (more_params(&inptr) && *inptr == '?') {
! 5189: mw_help();
! 5190: } else {
! 5191: free_heatmap();
! 5192: if (more_params (&inptr))
! 5193: v1 = readint (&inptr);
! 5194: if (more_params (&inptr))
! 5195: v2 = readint (&inptr);
! 5196: if (debug_dma) {
! 5197: decode_dma_record (v2, v1, cmd == 'v', false);
! 5198: } else {
! 5199: debug_dma = v1 < 0 ? -v1 : 1;
! 5200: console_out_f (_T("DMA debugger enabled, mode=%d.\n"), debug_dma);
! 5201: }
! 5202: }
1.1 root 5203: }
5204: }
5205: break;
5206: case 'o':
5207: {
5208: if (copper_debugger (&inptr)) {
5209: debugger_active = 0;
5210: debugging = 0;
5211: return true;
5212: }
5213: break;
5214: }
5215: case 'O':
5216: break;
5217: case 'b':
5218: if (staterecorder (&inptr))
5219: return true;
5220: break;
5221: case 'U':
5222: if (currprefs.mmu_model && more_params (&inptr)) {
5223: int i;
5224: uaecptr addrl = readhex (&inptr);
5225: uaecptr addrp;
5226: console_out_f (_T("%08X translates to:\n"), addrl);
5227: for (i = 0; i < 4; i++) {
5228: bool super = (i & 2) != 0;
5229: bool data = (i & 1) != 0;
5230: console_out_f (_T("S%dD%d="), super, data);
5231: TRY(prb) {
5232: if (currprefs.mmu_model >= 68040)
5233: addrp = mmu_translate (addrl, super, data, false);
5234: else
5235: addrp = mmu030_translate (addrl, super, data, false);
5236: console_out_f (_T("%08X"), addrp);
5237: TRY(prb2) {
5238: if (currprefs.mmu_model >= 68040)
5239: addrp = mmu_translate (addrl, super, data, true);
5240: else
5241: addrp = mmu030_translate (addrl, super, data, true);
5242: console_out_f (_T(" RW"));
5243: } CATCH(prb2) {
5244: console_out_f (_T(" RO"));
5245: } ENDTRY
5246: } CATCH(prb) {
5247: console_out_f (_T("***********"));
5248: } ENDTRY
5249: console_out_f (_T(" "));
5250: }
5251: console_out_f (_T("\n"));
5252: }
5253: break;
5254: case 'h':
5255: case '?':
5256: if (more_params (&inptr))
5257: converter (&inptr);
5258: else
5259: debug_help ();
5260: break;
5261: }
5262: return false;
5263: }
5264:
5265: static void debug_1 (void)
5266: {
5267: TCHAR input[MAX_LINEWIDTH];
5268:
5269: m68k_dumpstate (&nextpc);
5270: nxdis = nextpc; nxmem = 0;
5271: debugger_active = 1;
5272:
5273: for (;;) {
5274: int v;
5275:
5276: if (!debugger_active)
5277: return;
5278: update_debug_info ();
5279: console_out (_T(">"));
5280: console_flush ();
5281: debug_linecounter = 0;
5282: v = console_get (input, MAX_LINEWIDTH);
5283: if (v < 0)
5284: return;
5285: if (v == 0)
5286: continue;
5287: if (debug_line (input))
5288: return;
5289: }
5290: }
5291:
5292: static void addhistory (void)
5293: {
5294: uae_u32 pc = m68k_getpc ();
5295: // if (!notinrom())
5296: // return;
5297: history[lasthist] = regs;
5298: history[lasthist].pc = m68k_getpc ();
5299: if (++lasthist == MAX_HIST)
5300: lasthist = 0;
5301: if (lasthist == firsthist) {
5302: if (++firsthist == MAX_HIST) firsthist = 0;
5303: }
5304: }
5305:
5306: static void debug_continue(void)
5307: {
5308: set_special (SPCFLAG_BRK);
5309: }
5310:
5311:
5312: void debug (void)
5313: {
5314: int i;
5315: int wasactive;
5316:
5317: if (savestate_state)
5318: return;
5319:
5320: bogusframe = 1;
5321: addhistory ();
5322:
5323: #if 0
5324: if (do_skip && skipaddr_start == 0xC0DEDBAD) {
5325: if (trace_same_insn_count > 0) {
5326: if (memcmp (trace_insn_copy, regs.pc_p, 10) == 0
5327: && memcmp (trace_prev_regs.regs, regs.regs, sizeof regs.regs) == 0)
5328: {
5329: trace_same_insn_count++;
5330: return;
5331: }
5332: }
5333: if (trace_same_insn_count > 1)
5334: fprintf (logfile, "[ repeated %d times ]\n", trace_same_insn_count);
5335: m68k_dumpstate (logfile, &nextpc);
5336: trace_same_insn_count = 1;
5337: memcpy (trace_insn_copy, regs.pc_p, 10);
5338: memcpy (&trace_prev_regs, ®s, sizeof regs);
5339: }
5340: #endif
5341:
5342: if (!memwatch_triggered) {
5343: if (do_skip) {
5344: uae_u32 pc;
5345: uae_u16 opcode;
5346: int bp = 0;
5347:
5348: pc = munge24 (m68k_getpc ());
5349: opcode = currprefs.cpu_model < 68020 && (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) ? regs.ir : get_word_debug (pc);
5350:
5351: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
1.1.1.2 ! root 5352: struct breakpoint_node *bpn = &bpnodes[i];
! 5353: if (!bpn->enabled)
1.1 root 5354: continue;
1.1.1.2 ! root 5355: if (bpn->type == BREAKPOINT_REG_PC) {
! 5356: if (bpn->value1 == pc) {
! 5357: bp = 1;
! 5358: console_out_f (_T("Breakpoint at %08X\n"), pc);
! 5359: break;
! 5360: }
! 5361: } else if (bpn->type >= 0 && bpn->type < BREAKPOINT_REG_END) {
! 5362: uae_u32 value1 = bpn->value1 & bpn->mask;
! 5363: uae_u32 value2 = bpn->value2 & bpn->mask;
! 5364: uae_u32 cval = returnregx(bpn->type) & bpn->mask;
! 5365: switch (bpn->oper)
! 5366: {
! 5367: case BREAKPOINT_CMP_EQUAL:
! 5368: if (cval == value1)
! 5369: bp = i + 1;
! 5370: break;
! 5371: case BREAKPOINT_CMP_NEQUAL:
! 5372: if (cval != value1)
! 5373: bp = i + 1;
! 5374: break;
! 5375: case BREAKPOINT_CMP_SMALLER:
! 5376: if (cval <= value1)
! 5377: bp = i + 1;
! 5378: break;
! 5379: case BREAKPOINT_CMP_LARGER:
! 5380: if (cval >= value1)
! 5381: bp = i + 1;
! 5382: break;
! 5383: case BREAKPOINT_CMP_RANGE:
! 5384: if (cval >= value1 && cval <= value2)
! 5385: bp = i + 1;
! 5386: break;
! 5387: case BREAKPOINT_CMP_NRANGE:
! 5388: if (cval <= value1 || cval >= value2)
! 5389: bp = i + 1;
! 5390: break;
! 5391: }
1.1 root 5392: }
5393: }
5394:
5395: if (skipaddr_doskip) {
5396: if (skipaddr_start == pc)
1.1.1.2 ! root 5397: bp = -1;
1.1 root 5398: if ((processptr || processname) && notinrom()) {
5399: uaecptr execbase = get_long_debug (4);
5400: uaecptr activetask = get_long_debug (execbase + 276);
5401: int process = get_byte_debug (activetask + 8) == 13 ? 1 : 0;
5402: char *name = (char*)get_real_address (get_long_debug (activetask + 10));
5403: if (process) {
5404: uaecptr cli = BPTR2APTR(get_long_debug (activetask + 172));
5405: uaecptr seglist = 0;
5406:
5407: uae_char *command = NULL;
5408: if (cli) {
5409: if (processname)
5410: command = (char*)get_real_address (BPTR2APTR(get_long_debug (cli + 16)));
5411: seglist = BPTR2APTR(get_long_debug (cli + 60));
5412: } else {
5413: seglist = BPTR2APTR(get_long_debug (activetask + 128));
5414: seglist = BPTR2APTR(get_long_debug (seglist + 12));
5415: }
5416: if (activetask == processptr || (processname && (!stricmp (name, processname) || (command && command[0] && !strnicmp (command + 1, processname, command[0]) && processname[command[0]] == 0)))) {
5417: while (seglist) {
5418: uae_u32 size = get_long_debug (seglist - 4) - 4;
5419: if (pc >= (seglist + 4) && pc < (seglist + size)) {
5420: bp = 1;
5421: break;
5422: }
5423: seglist = BPTR2APTR(get_long_debug (seglist));
5424: }
5425: }
5426: }
5427: } else if (skipins != 0xffffffff) {
5428: if (skipins == 0x10000) {
5429: if (opcode == 0x4e75 || opcode == 0x4e73 || opcode == 0x4e77)
1.1.1.2 ! root 5430: bp = -1;
1.1 root 5431: } else if (opcode == skipins)
1.1.1.2 ! root 5432: bp = -1;
1.1 root 5433: } else if (skipaddr_start == 0xffffffff && skipaddr_doskip < 0) {
5434: if ((pc < 0xe00000 || pc >= 0x1000000) && opcode != 0x4ef9)
1.1.1.2 ! root 5435: bp = -1;
1.1 root 5436: } else if (skipaddr_start == 0xffffffff && skipaddr_doskip > 0) {
1.1.1.2 ! root 5437: bp = -1;
1.1 root 5438: } else if (skipaddr_end != 0xffffffff) {
5439: if (pc >= skipaddr_start && pc < skipaddr_end)
1.1.1.2 ! root 5440: bp = -1;
1.1 root 5441: }
5442: }
5443: if (!bp) {
5444: debug_continue();
5445: return;
5446: }
1.1.1.2 ! root 5447: if (bp > 0)
! 5448: console_out_f(_T("Breakpoint %d triggered.\n"), bp - 1);
1.1 root 5449: }
5450: } else {
5451: console_out_f (_T("Memwatch %d: break at %08X.%c %c%c%c %08X PC=%08X "), memwatch_triggered - 1, mwhit.addr,
5452: mwhit.size == 1 ? 'B' : (mwhit.size == 2 ? 'W' : 'L'),
5453: (mwhit.rwi & 1) ? 'R' : ' ', (mwhit.rwi & 2) ? 'W' : ' ', (mwhit.rwi & 4) ? 'I' : ' ',
5454: mwhit.val, mwhit.pc);
5455: for (i = 0; memwatch_access_masks[i].mask; i++) {
5456: if (mwhit.access_mask == memwatch_access_masks[i].mask)
5457: console_out_f (_T("%s (%03x)\n"), memwatch_access_masks[i].name, mwhit.reg);
5458: }
5459: memwatch_triggered = 0;
5460: }
5461: if (skipaddr_doskip > 0) {
5462: skipaddr_doskip--;
5463: if (skipaddr_doskip > 0) {
5464: debug_continue();
5465: return;
5466: }
5467: }
5468:
5469: wasactive = ismouseactive ();
5470: #ifdef WITH_PPC
5471: uae_ppc_pause(1);
5472: #endif
5473: inputdevice_unacquire ();
5474: pause_sound ();
5475: setmouseactive (0);
5476: activate_console ();
5477: do_skip = 0;
5478: skipaddr_start = 0xffffffff;
5479: skipaddr_end = 0xffffffff;
5480: skipins = 0xffffffff;
5481: skipaddr_doskip = 0;
5482: exception_debugging = 0;
5483: debug_rewind = 0;
5484: processptr = 0;
5485: #if 0
5486: if (!currprefs.statecapture) {
5487: changed_prefs.statecapture = currprefs.statecapture = 1;
5488: savestate_init ();
5489: }
5490: #endif
5491: debug_1 ();
5492: if (!debug_rewind && !currprefs.cachesize
5493: #ifdef FILESYS
5494: && nr_units () == 0
5495: #endif
5496: ) {
5497: savestate_capture (1);
5498: }
5499: for (i = 0; i < BREAKPOINT_TOTAL; i++) {
5500: if (bpnodes[i].enabled)
5501: do_skip = 1;
5502: }
5503: if (do_skip) {
5504: set_special (SPCFLAG_BRK);
5505: debugging = -1;
5506: }
5507: resume_sound ();
5508: inputdevice_acquire (TRUE);
5509: #ifdef WITH_PPC
5510: uae_ppc_pause(0);
5511: #endif
5512: setmouseactive (wasactive ? 2 : 0);
5513: }
5514:
5515: const TCHAR *debuginfo (int mode)
5516: {
5517: static TCHAR txt[100];
5518: uae_u32 pc = M68K_GETPC;
5519: _stprintf (txt, _T("PC=%08X INS=%04X %04X %04X"),
5520: pc, get_word_debug (pc), get_word_debug (pc + 2), get_word_debug (pc + 4));
5521: return txt;
5522: }
5523:
5524: #endif /* WINUAE_FOR_HATARI */
5525:
5526: void mmu_disasm (uaecptr pc, int lines)
5527: {
5528: debug_mmu_mode = regs.s ? 6 : 2;
5529: m68k_dumpstate (0xffffffff, NULL);
5530: m68k_disasm (pc, NULL, lines);
5531: }
5532:
5533: static int mmu_logging;
5534:
5535: #define MMU_PAGE_SHIFT 16
5536:
5537: struct mmudata {
5538: uae_u32 flags;
5539: uae_u32 addr;
5540: uae_u32 len;
5541: uae_u32 remap;
5542: uae_u32 p_addr;
5543: };
5544:
5545: static struct mmudata *mmubanks;
5546: static uae_u32 mmu_struct, mmu_callback, mmu_regs;
5547: static uae_u32 mmu_fault_bank_addr, mmu_fault_addr;
5548: static int mmu_fault_size, mmu_fault_rw;
5549: static int mmu_slots;
5550: static struct regstruct mmur;
5551:
5552: struct mmunode {
5553: struct mmudata *mmubank;
5554: struct mmunode *next;
5555: };
5556: static struct mmunode **mmunl;
5557: extern regstruct mmu_backup_regs;
5558:
5559: #define MMU_READ_U (1 << 0)
5560: #define MMU_WRITE_U (1 << 1)
5561: #define MMU_READ_S (1 << 2)
5562: #define MMU_WRITE_S (1 << 3)
5563: #define MMU_READI_U (1 << 4)
5564: #define MMU_READI_S (1 << 5)
5565:
5566: #define MMU_MAP_READ_U (1 << 8)
5567: #define MMU_MAP_WRITE_U (1 << 9)
5568: #define MMU_MAP_READ_S (1 << 10)
5569: #define MMU_MAP_WRITE_S (1 << 11)
5570: #define MMU_MAP_READI_U (1 << 12)
5571: #define MMU_MAP_READI_S (1 << 13)
5572:
5573: void mmu_do_hit (void)
5574: {
5575: int i;
5576: uaecptr p;
5577: uae_u32 pc;
5578:
5579: mmu_triggered = 0;
5580: pc = m68k_getpc ();
5581: p = mmu_regs + 18 * 4;
5582: put_long (p, pc);
5583: regs = mmu_backup_regs;
5584: regs.intmask = 7;
5585: regs.t0 = regs.t1 = 0;
5586: if (!regs.s) {
5587: regs.usp = m68k_areg (regs, 7);
5588: if (currprefs.cpu_model >= 68020)
5589: m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
5590: else
5591: m68k_areg (regs, 7) = regs.isp;
5592: regs.s = 1;
5593: }
5594: MakeSR ();
5595: m68k_setpc (mmu_callback);
5596: fill_prefetch ();
5597:
5598: if (currprefs.cpu_model > 68000) {
5599: for (i = 0 ; i < 9; i++) {
5600: m68k_areg (regs, 7) -= 4;
5601: put_long (m68k_areg (regs, 7), 0);
5602: }
5603: m68k_areg (regs, 7) -= 4;
5604: put_long (m68k_areg (regs, 7), mmu_fault_addr);
5605: m68k_areg (regs, 7) -= 2;
5606: put_word (m68k_areg (regs, 7), 0); /* WB1S */
5607: m68k_areg (regs, 7) -= 2;
5608: put_word (m68k_areg (regs, 7), 0); /* WB2S */
5609: m68k_areg (regs, 7) -= 2;
5610: put_word (m68k_areg (regs, 7), 0); /* WB3S */
5611: m68k_areg (regs, 7) -= 2;
5612: put_word (m68k_areg (regs, 7),
5613: (mmu_fault_rw ? 0 : 0x100) | (mmu_fault_size << 5)); /* SSW */
5614: m68k_areg (regs, 7) -= 4;
5615: put_long (m68k_areg (regs, 7), mmu_fault_bank_addr);
5616: m68k_areg (regs, 7) -= 2;
5617: put_word (m68k_areg (regs, 7), 0x7002);
5618: }
5619: m68k_areg (regs, 7) -= 4;
5620: put_long (m68k_areg (regs, 7), get_long_debug (p - 4));
5621: m68k_areg (regs, 7) -= 2;
5622: put_word (m68k_areg (regs, 7), mmur.sr);
5623: #ifdef JIT
5624: set_special(SPCFLAG_END_COMPILE);
5625: #endif
5626: }
5627:
5628: static void mmu_do_hit_pre (struct mmudata *md, uaecptr addr, int size, int rwi, uae_u32 v)
5629: {
5630: uae_u32 p, pc;
5631: int i;
5632:
5633: mmur = regs;
5634: pc = m68k_getpc ();
5635: if (mmu_logging)
5636: console_out_f (_T("MMU: hit %08X SZ=%d RW=%d V=%08X PC=%08X\n"), addr, size, rwi, v, pc);
5637:
5638: p = mmu_regs;
5639: put_long (p, 0); p += 4;
5640: for (i = 0; i < 16; i++) {
5641: put_long (p, regs.regs[i]);
5642: p += 4;
5643: }
5644: put_long (p, pc); p += 4;
5645: put_long (p, 0); p += 4;
5646: put_long (p, regs.usp); p += 4;
5647: put_long (p, regs.isp); p += 4;
5648: put_long (p, regs.msp); p += 4;
5649: put_word (p, regs.sr); p += 2;
5650: put_word (p, (size << 1) | ((rwi & 2) ? 1 : 0)); /* size and rw */ p += 2;
5651: put_long (p, addr); /* fault address */ p += 4;
5652: put_long (p, md->p_addr); /* bank address */ p += 4;
5653: put_long (p, v); p += 4;
5654: mmu_fault_addr = addr;
5655: mmu_fault_bank_addr = md->p_addr;
5656: mmu_fault_size = size;
5657: mmu_fault_rw = rwi;
5658: mmu_triggered = 1;
5659: }
5660:
5661: static int mmu_hit (uaecptr addr, int size, int rwi, uae_u32 *v)
5662: {
5663: int s, trig;
5664: uae_u32 flags;
5665: struct mmudata *md;
5666: struct mmunode *mn;
5667:
5668: if (mmu_triggered)
5669: return 1;
5670:
5671: mn = mmunl[addr >> MMU_PAGE_SHIFT];
5672: if (mn == NULL)
5673: return 0;
5674:
5675: s = regs.s;
5676: while (mn) {
5677: md = mn->mmubank;
5678: if (addr >= md->addr && addr < md->addr + md->len) {
5679: flags = md->flags;
5680: if (flags & (MMU_MAP_READ_U | MMU_MAP_WRITE_U | MMU_MAP_READ_S | MMU_MAP_WRITE_S | MMU_MAP_READI_U | MMU_MAP_READI_S)) {
5681: trig = 0;
5682: if (!s && (flags & MMU_MAP_READ_U) && (rwi & 1))
5683: trig = 1;
5684: if (!s && (flags & MMU_MAP_WRITE_U) && (rwi & 2))
5685: trig = 1;
5686: if (s && (flags & MMU_MAP_READ_S) && (rwi & 1))
5687: trig = 1;
5688: if (s && (flags & MMU_MAP_WRITE_S) && (rwi & 2))
5689: trig = 1;
5690: if (!s && (flags & MMU_MAP_READI_U) && (rwi & 4))
5691: trig = 1;
5692: if (s && (flags & MMU_MAP_READI_S) && (rwi & 4))
5693: trig = 1;
5694: if (trig) {
5695: uaecptr maddr = md->remap + (addr - md->addr);
5696: if (maddr == addr) /* infinite mmu hit loop? no thanks.. */
5697: return 1;
5698: if (mmu_logging)
5699: console_out_f (_T("MMU: remap %08X -> %08X SZ=%d RW=%d\n"), addr, maddr, size, rwi);
5700: if ((rwi & 2)) {
5701: switch (size)
5702: {
5703: case 4:
5704: put_long (maddr, *v);
5705: break;
5706: case 2:
5707: put_word (maddr, *v);
5708: break;
5709: case 1:
5710: put_byte (maddr, *v);
5711: break;
5712: }
5713: } else {
5714: switch (size)
5715: {
5716: case 4:
5717: *v = get_long_debug (maddr);
5718: break;
5719: case 2:
5720: *v = get_word_debug (maddr);
5721: break;
5722: case 1:
5723: *v = get_byte_debug (maddr);
5724: break;
5725: }
5726: }
5727: return 1;
5728: }
5729: }
5730: if (flags & (MMU_READ_U | MMU_WRITE_U | MMU_READ_S | MMU_WRITE_S | MMU_READI_U | MMU_READI_S)) {
5731: trig = 0;
5732: if (!s && (flags & MMU_READ_U) && (rwi & 1))
5733: trig = 1;
5734: if (!s && (flags & MMU_WRITE_U) && (rwi & 2))
5735: trig = 1;
5736: if (s && (flags & MMU_READ_S) && (rwi & 1))
5737: trig = 1;
5738: if (s && (flags & MMU_WRITE_S) && (rwi & 2))
5739: trig = 1;
5740: if (!s && (flags & MMU_READI_U) && (rwi & 4))
5741: trig = 1;
5742: if (s && (flags & MMU_READI_S) && (rwi & 4))
5743: trig = 1;
5744: if (trig) {
5745: mmu_do_hit_pre (md, addr, size, rwi, *v);
5746: return 1;
5747: }
5748: }
5749: }
5750: mn = mn->next;
5751: }
5752: return 0;
5753: }
5754:
1.1.1.2 ! root 5755: #ifdef JIT
! 5756:
1.1 root 5757: static void mmu_free_node(struct mmunode *mn)
5758: {
5759: if (!mn)
5760: return;
5761: mmu_free_node (mn->next);
5762: xfree (mn);
5763: }
5764:
5765: static void mmu_free(void)
5766: {
5767: struct mmunode *mn;
5768: int i;
5769:
5770: for (i = 0; i < mmu_slots; i++) {
5771: mn = mmunl[i];
5772: mmu_free_node (mn);
5773: }
5774: xfree (mmunl);
5775: mmunl = NULL;
5776: xfree (mmubanks);
5777: mmubanks = NULL;
5778: }
5779:
1.1.1.2 ! root 5780: #endif
! 5781:
1.1 root 5782: static int getmmubank(struct mmudata *snptr, uaecptr p)
5783: {
5784: snptr->flags = get_long_debug (p);
5785: if (snptr->flags == 0xffffffff)
5786: return 1;
5787: snptr->addr = get_long_debug (p + 4);
5788: snptr->len = get_long_debug (p + 8);
5789: snptr->remap = get_long_debug (p + 12);
5790: snptr->p_addr = p;
5791: return 0;
5792: }
5793:
5794: int mmu_init(int mode, uaecptr parm, uaecptr parm2)
5795: {
5796: uaecptr p, p2, banks;
5797: int size;
5798: struct mmudata *snptr;
5799: struct mmunode *mn;
5800: #ifdef JIT
1.1.1.2 ! root 5801: static int wasjit;
1.1 root 5802: if (currprefs.cachesize) {
5803: wasjit = currprefs.cachesize;
5804: changed_prefs.cachesize = 0;
5805: console_out (_T("MMU: JIT disabled\n"));
1.1.1.2 ! root 5806: check_prefs_changed_comp(false);
1.1 root 5807: }
5808: if (mode == 0) {
5809: if (mmu_enabled) {
5810: mmu_free ();
5811: deinitialize_memwatch ();
5812: console_out (_T("MMU: disabled\n"));
5813: changed_prefs.cachesize = wasjit;
5814: }
5815: mmu_logging = 0;
5816: return 1;
5817: }
5818: #endif
5819:
5820: if (mode == 1) {
5821: if (!mmu_enabled)
5822: return 0xffffffff;
5823: return mmu_struct;
5824: }
5825:
5826: p = parm;
5827: mmu_struct = p;
5828: if (get_long_debug (p) != 1) {
5829: console_out_f (_T("MMU: version mismatch %d <> %d\n"), get_long_debug (p), 1);
5830: return 0;
5831: }
5832: p += 4;
5833: mmu_logging = get_long_debug (p) & 1;
5834: p += 4;
5835: mmu_callback = get_long_debug (p);
5836: p += 4;
5837: mmu_regs = get_long_debug (p);
5838: p += 4;
5839:
5840: if (mode == 3) {
5841: int off;
5842: uaecptr addr = get_long_debug (parm2 + 4);
5843: if (!mmu_enabled)
5844: return 0;
5845: off = addr >> MMU_PAGE_SHIFT;
5846: mn = mmunl[off];
5847: while (mn) {
5848: if (mn->mmubank->p_addr == parm2) {
5849: getmmubank(mn->mmubank, parm2);
5850: if (mmu_logging)
5851: console_out_f (_T("MMU: bank update %08X: %08X - %08X %08X\n"),
5852: mn->mmubank->flags, mn->mmubank->addr, mn->mmubank->len + mn->mmubank->addr,
5853: mn->mmubank->remap);
5854: }
5855: mn = mn->next;
5856: }
5857: return 1;
5858: }
5859:
5860: mmu_slots = 1 << ((currprefs.address_space_24 ? 24 : 32) - MMU_PAGE_SHIFT);
5861: mmunl = xcalloc (struct mmunode*, mmu_slots);
5862: size = 1;
5863: p2 = get_long_debug (p);
5864: while (get_long_debug (p2) != 0xffffffff) {
5865: p2 += 16;
5866: size++;
5867: }
5868: p = banks = get_long_debug (p);
5869: snptr = mmubanks = xmalloc (struct mmudata, size);
5870: for (;;) {
5871: int off;
5872: if (getmmubank(snptr, p))
5873: break;
5874: p += 16;
5875: off = snptr->addr >> MMU_PAGE_SHIFT;
5876: if (mmunl[off] == NULL) {
5877: mn = mmunl[off] = xcalloc (struct mmunode, 1);
5878: } else {
5879: mn = mmunl[off];
5880: while (mn->next)
5881: mn = mn->next;
5882: mn = mn->next = xcalloc (struct mmunode, 1);
5883: }
5884: mn->mmubank = snptr;
5885: snptr++;
5886: }
5887:
5888: initialize_memwatch (1);
5889: console_out_f (_T("MMU: enabled, %d banks, CB=%08X S=%08X BNK=%08X SF=%08X, %d*%d\n"),
5890: size - 1, mmu_callback, parm, banks, mmu_regs, mmu_slots, 1 << MMU_PAGE_SHIFT);
5891: set_special (SPCFLAG_BRK);
5892: return 1;
5893: }
5894:
5895: void debug_parser (const TCHAR *cmd, TCHAR *out, uae_u32 outsize)
5896: {
5897: TCHAR empty[2] = { 0 };
5898: TCHAR *input = my_strdup (cmd);
5899: if (out == NULL && outsize == 0) {
5900: setconsolemode (empty, 1);
5901: } else if (out != NULL && outsize > 0) {
5902: out[0] = 0;
5903: setconsolemode (out, outsize);
5904: }
5905: debug_line (input);
5906: setconsolemode (NULL, 0);
5907: xfree (input);
5908: }
5909:
5910: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.