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