/debug.cpp
C++ | 7823 lines | 7210 code | 509 blank | 104 comment | 2449 complexity | cf330f5eec37f77f7e4a85245c01a51d MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * UAE - The Un*x Amiga Emulator
- *
- * Debugger
- *
- * (c) 1995 Bernd Schmidt
- * (c) 2006 Toni Wilen
- *
- */
- #include "sysconfig.h"
- #include "sysdeps.h"
- #include <ctype.h>
- #include <signal.h>
- #include "options.h"
- #include "uae.h"
- #include "memory.h"
- #include "custom.h"
- #include "newcpu.h"
- #include "cpu_prefetch.h"
- #include "debug.h"
- #include "disasm.h"
- #include "debugmem.h"
- #include "cia.h"
- #include "xwin.h"
- #include "identify.h"
- #include "audio.h"
- #include "sounddep/sound.h"
- #include "disk.h"
- #include "savestate.h"
- #include "autoconf.h"
- #include "akiko.h"
- #include "inputdevice.h"
- #include "crc32.h"
- #include "cpummu.h"
- #include "rommgr.h"
- #include "inputrecord.h"
- #include "calc.h"
- #include "cpummu.h"
- #include "cpummu030.h"
- #include "ar.h"
- #include "pci.h"
- #include "ppc/ppcd.h"
- #include "uae/io.h"
- #include "uae/ppc.h"
- #include "drawing.h"
- #include "devices.h"
- #include "blitter.h"
- #include "ini.h"
- #include "readcpu.h"
- #include "cputbl.h"
- #include "keybuf.h"
- static int trace_mode;
- static uae_u32 trace_param[3];
- int debugger_active;
- static int debug_rewind;
- static int memwatch_triggered;
- static int inside_debugger;
- int debugger_used;
- int memwatch_access_validator;
- int memwatch_enabled;
- int debugging;
- int exception_debugging;
- int no_trace_exceptions;
- int debug_copper = 0;
- int debug_dma = 0, debug_heatmap = 0;
- int debug_sprite_mask = 0xff;
- int debug_illegal = 0;
- uae_u64 debug_illegal_mask;
- static int debug_mmu_mode;
- static bool break_if_enforcer;
- static uaecptr debug_pc;
- static int trace_cycles;
- static int last_hpos1, last_hpos2;
- static int last_vpos1, last_vpos2;
- static int last_frame = -1;
- static uae_u32 last_cycles1, last_cycles2;
- static uaecptr processptr;
- static uae_char *processname;
- static uaecptr debug_copper_pc;
- extern int audio_channel_mask;
- extern int inputdevice_logging;
- static void debug_cycles(void)
- {
- trace_cycles = 1;
- last_cycles2 = get_cycles();
- last_vpos2 = vpos;
- last_hpos2 = current_hpos();
- }
- void deactivate_debugger (void)
- {
- inside_debugger = 0;
- debugger_active = 0;
- debugging = 0;
- exception_debugging = 0;
- processptr = 0;
- xfree (processname);
- processname = NULL;
- debugmem_enable();
- debug_pc = 0xffffffff;
- keybuf_ignore_next_release();
- }
- void activate_debugger (void)
- {
- disasm_init();
- if (isfullscreen() > 0)
- return;
- debugger_load_libraries();
- debugger_used = 1;
- inside_debugger = 1;
- debug_pc = 0xffffffff;
- trace_mode = 0;
- if (debugger_active) {
- // already in debugger but some break point triggered
- // during disassembly etc..
- return;
- }
- debug_cycles();
- debugger_active = 1;
- set_special (SPCFLAG_BRK);
- debugging = 1;
- mmu_triggered = 0;
- debugmem_disable();
- }
- void activate_debugger_new(void)
- {
- activate_debugger();
- debug_pc = M68K_GETPC;
- }
- void activate_debugger_new_pc(uaecptr pc, int len)
- {
- activate_debugger();
- trace_mode = TRACE_RANGE_PC;
- trace_param[0] = pc;
- trace_param[1] = pc + len;
- }
- bool debug_enforcer(void)
- {
- if (!break_if_enforcer)
- return false;
- activate_debugger();
- return true;
- }
- int firsthist = 0;
- int lasthist = 0;
- struct cpuhistory {
- struct regstruct regs;
- int fp, vpos, hpos;
- };
- static struct cpuhistory history[MAX_HIST];
- static const TCHAR help[] = {
- _T(" HELP for UAE Debugger\n")
- _T(" -----------------------\n\n")
- _T(" g [<address>] Start execution at the current address or <address>.\n")
- _T(" c Dump state of the CIA, disk drives and custom registers.\n")
- _T(" r Dump state of the CPU.\n")
- _T(" r <reg> <value> Modify CPU registers (Dx,Ax,USP,ISP,VBR,...).\n")
- _T(" rc[d] Show CPU instruction or data cache contents.\n")
- _T(" m <address> [<lines>] Memory dump starting at <address>.\n")
- _T(" a <address> Assembler.\n")
- _T(" d <address> [<lines>] Disassembly starting at <address>.\n")
- _T(" t [instructions] Step one or more instructions.\n")
- _T(" z Step through one instruction - useful for JSR, DBRA etc.\n")
- _T(" f Step forward until PC in RAM (\"boot block finder\").\n")
- _T(" f <address> Add/remove breakpoint.\n")
- _T(" fa <address> [<start>] [<end>]\n")
- _T(" Find effective address <address>.\n")
- _T(" fi Step forward until PC points to RTS, RTD or RTE.\n")
- _T(" fi <opcode> [<w2>] [<w3>] Step forward until PC points to <opcode>.\n")
- _T(" fp \"<name>\"/<addr> Step forward until process <name> or <addr> is active.\n")
- _T(" fl List breakpoints.\n")
- _T(" fd Remove all breakpoints.\n")
- _T(" fs <lines to wait> | <vpos> <hpos> Wait n scanlines/position.\n")
- _T(" fc <CCKs to wait> Wait n color clocks.\n")
- _T(" fo <num> <reg> <oper> <val> [<mask> <val2>] Conditional register breakpoint.\n")
- _T(" reg=Dx,Ax,PC,USP,ISP,VBR,SR. oper:!=,==,<,>,>=,<=,-,!- (-=val to val2 range).\n")
- _T(" f <addr1> <addr2> Step forward until <addr1> <= PC <= <addr2>.\n")
- _T(" e[x] Dump contents of all custom registers, ea = AGA colors.\n")
- _T(" i [<addr>] Dump contents of interrupt and trap vectors.\n")
- _T(" il [<mask>] Exception breakpoint.\n")
- _T(" o <0-2|addr> [<lines>]View memory as Copper instructions.\n")
- _T(" od Enable/disable Copper vpos/hpos tracing.\n")
- _T(" ot Copper single step trace.\n")
- _T(" ob <addr> Copper breakpoint.\n")
- _T(" H[H] <cnt> Show PC history (HH=full CPU info) <cnt> instructions.\n")
- _T(" C <value> Search for values like energy or lifes in games.\n")
- _T(" Cl List currently found trainer addresses.\n")
- _T(" D[idxzs <[max diff]>] Deep trainer. i=new value must be larger, d=smaller,\n")
- _T(" x = must be same, z = must be different, s = restart.\n")
- _T(" W <addr> <values[.x] separated by space> Write into Amiga memory.\n")
- _T(" W <addr> 'string' Write into Amiga memory.\n")
- _T(" Wf <addr> <endaddr> <bytes or string like above>, fill memory.\n")
- _T(" Wc <addr> <endaddr> <destaddr>, copy memory.\n")
- _T(" w <num> <address> <length> <R/W/I> <F/C/L/N> [<value>[.x]] (read/write/opcode) (freeze/mustchange/logonly/nobreak).\n")
- _T(" Add/remove memory watchpoints.\n")
- _T(" wd [<0-1>] Enable illegal access logger. 1 = enable break.\n")
- _T(" L <file> <addr> [<n>] Load a block of Amiga memory.\n")
- _T(" S <file> <addr> <n> Save a block of Amiga memory.\n")
- _T(" s \"<string>\"/<values> [<addr>] [<length>]\n")
- _T(" Search for string/bytes.\n")
- _T(" T or Tt Show exec tasks and their PCs.\n")
- _T(" Td,Tl,Tr,Tp,Ts,TS,Ti,TO,TM,Tf Show devs, libs, resources, ports, semaphores,\n")
- _T(" residents, interrupts, doslist, memorylist, fsres.\n")
- _T(" b Step to previous state capture position.\n")
- _T(" M<a/b/s> <val> Enable or disable audio channels, bitplanes or sprites.\n")
- _T(" sp <addr> [<addr2][<size>] Dump sprite information.\n")
- _T(" di <mode> [<track>] Break on disk access. R=DMA read,W=write,RW=both,P=PIO.\n")
- _T(" Also enables level 1 disk logging.\n")
- _T(" did <log level> Enable disk logging.\n")
- _T(" dj [<level bitmask>] Enable joystick/mouse input debugging.\n")
- _T(" smc [<0-1>] Enable self-modifying code detector. 1 = enable break.\n")
- _T(" dm Dump current address space map.\n")
- _T(" v <vpos> [<hpos>] Show DMA data (accurate only in cycle-exact mode).\n")
- _T(" v [-1 to -4] = enable visual DMA debugger.\n")
- _T(" vh [<ratio> <lines>] \"Heat map\"\n")
- _T(" I <custom event> Send custom event string\n")
- _T(" ?<value> Hex ($ and 0x)/Bin (%)/Dec (!) converter and calculator.\n")
- #ifdef _WIN32
- _T(" x Close debugger.\n")
- _T(" xx Switch between console and GUI debugger.\n")
- _T(" mg <address> Memory dump starting at <address> in GUI.\n")
- _T(" dg <address> Disassembly starting at <address> in GUI.\n")
- #endif
- _T(" q Quit the emulator. You don't want to use this command.\n\n")
- };
- void debug_help (void)
- {
- console_out (help);
- }
- struct mw_acc {
- uae_u32 mask;
- const TCHAR *name;
- };
- static const struct mw_acc memwatch_access_masks[] =
- {
- { MW_MASK_ALL, _T("ALL") },
- { MW_MASK_NONE, _T("NONE") },
- { MW_MASK_ALL & ~(MW_MASK_CPU_I | MW_MASK_CPU_D_R | MW_MASK_CPU_D_W), _T("DMA") },
- { 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") },
- { MW_MASK_BLITTER_D_N | MW_MASK_BLITTER_D_L | MW_MASK_BLITTER_D_F, _T("BLTD") },
- { MW_MASK_AUDIO_0 | MW_MASK_AUDIO_1 | MW_MASK_AUDIO_2 | MW_MASK_AUDIO_3, _T("AUD") },
- { MW_MASK_BPL_0 | MW_MASK_BPL_1 | MW_MASK_BPL_2 | MW_MASK_BPL_3 |
- MW_MASK_BPL_4 | MW_MASK_BPL_5 | MW_MASK_BPL_6 | MW_MASK_BPL_7, _T("BPL") },
- { MW_MASK_SPR_0 | MW_MASK_SPR_1 | MW_MASK_SPR_2 | MW_MASK_SPR_3 |
- MW_MASK_SPR_4 | MW_MASK_SPR_5 | MW_MASK_SPR_6 | MW_MASK_SPR_7, _T("SPR") },
- { MW_MASK_CPU_I | MW_MASK_CPU_D_R | MW_MASK_CPU_D_W, _T("CPU") },
- { MW_MASK_CPU_D_R | MW_MASK_CPU_D_W, _T("CPUD") },
- { MW_MASK_CPU_I, _T("CPUI") },
- { MW_MASK_CPU_D_R, _T("CPUDR") },
- { MW_MASK_CPU_D_W, _T("CPUDW") },
- { MW_MASK_COPPER, _T("COP") },
- { MW_MASK_BLITTER_A, _T("BLTA") },
- { MW_MASK_BLITTER_B, _T("BLTB") },
- { MW_MASK_BLITTER_C, _T("BLTC") },
- { MW_MASK_BLITTER_D_N, _T("BLTDN") },
- { MW_MASK_BLITTER_D_L, _T("BLTDL") },
- { MW_MASK_BLITTER_D_F, _T("BLTDF") },
- { MW_MASK_DISK, _T("DSK") },
- { MW_MASK_AUDIO_0, _T("AUD0") },
- { MW_MASK_AUDIO_1, _T("AUD1") },
- { MW_MASK_AUDIO_2, _T("AUD2") },
- { MW_MASK_AUDIO_3, _T("AUD3") },
- { MW_MASK_BPL_0, _T("BPL0") },
- { MW_MASK_BPL_1, _T("BPL1") },
- { MW_MASK_BPL_2, _T("BPL2") },
- { MW_MASK_BPL_3, _T("BPL3") },
- { MW_MASK_BPL_4, _T("BPL4") },
- { MW_MASK_BPL_5, _T("BPL5") },
- { MW_MASK_BPL_6, _T("BPL6") },
- { MW_MASK_BPL_7, _T("BPL7") },
- { MW_MASK_SPR_0, _T("SPR0") },
- { MW_MASK_SPR_1, _T("SPR1") },
- { MW_MASK_SPR_2, _T("SPR2") },
- { MW_MASK_SPR_3, _T("SPR3") },
- { MW_MASK_SPR_4, _T("SPR4") },
- { MW_MASK_SPR_5, _T("SPR5") },
- { MW_MASK_SPR_6, _T("SPR6") },
- { MW_MASK_SPR_7, _T("SPR7") },
- { 0, NULL },
- };
- static void mw_help(void)
- {
- for (int i = 0; memwatch_access_masks[i].mask; i++) {
- console_out_f(_T("%s "), memwatch_access_masks[i].name);
- }
- console_out_f(_T("\n"));
- }
- static int debug_linecounter;
- #define MAX_LINECOUNTER 1000
- static int debug_out (const TCHAR *format, ...)
- {
- va_list parms;
- TCHAR buffer[4000];
- va_start (parms, format);
- _vsntprintf (buffer, 4000 - 1, format, parms);
- va_end (parms);
- console_out (buffer);
- if (debug_linecounter < MAX_LINECOUNTER)
- debug_linecounter++;
- if (debug_linecounter >= MAX_LINECOUNTER)
- return 0;
- return 1;
- }
- uae_u32 get_byte_debug (uaecptr addr)
- {
- uae_u32 v = 0xff;
- if (debug_mmu_mode) {
- flagtype olds = regs.s;
- regs.s = (debug_mmu_mode & 4) != 0;
- TRY(p) {
- if (currprefs.mmu_model == 68030) {
- v = mmu030_get_generic (addr, debug_mmu_mode, sz_byte, MMU030_SSW_SIZE_B);
- } else {
- if (debug_mmu_mode & 1) {
- bool odd = (addr & 1) != 0;
- addr &= ~1;
- v = mmu_get_iword(addr, sz_byte);
- if (!odd)
- v >>= 8;
- } else {
- v = mmu_get_user_byte (addr, regs.s != 0, false, sz_byte, false);
- }
- }
- } CATCH(p) {
- } ENDTRY
- regs.s = olds;
- } else {
- v = get_byte (addr);
- }
- return v;
- }
- uae_u32 get_word_debug (uaecptr addr)
- {
- uae_u32 v = 0xffff;
- if (debug_mmu_mode) {
- flagtype olds = regs.s;
- regs.s = (debug_mmu_mode & 4) != 0;
- TRY(p) {
- if (currprefs.mmu_model == 68030) {
- v = mmu030_get_generic (addr, debug_mmu_mode, sz_word, MMU030_SSW_SIZE_W);
- } else {
- if (debug_mmu_mode & 1) {
- v = mmu_get_iword(addr, sz_word);
- } else {
- v = mmu_get_user_word (addr, regs.s != 0, false, sz_word, false);
- }
- }
- } CATCH(p) {
- } ENDTRY
- regs.s = olds;
- } else {
- v = get_word (addr);
- }
- return v;
- }
- uae_u32 get_long_debug (uaecptr addr)
- {
- uae_u32 v = 0xffffffff;
- if (debug_mmu_mode) {
- flagtype olds = regs.s;
- regs.s = (debug_mmu_mode & 4) != 0;
- TRY(p) {
- if (currprefs.mmu_model == 68030) {
- v = mmu030_get_generic (addr, debug_mmu_mode, sz_long, MMU030_SSW_SIZE_L);
- } else {
- if (debug_mmu_mode & 1) {
- v = mmu_get_ilong(addr, sz_long);
- } else {
- v = mmu_get_user_long (addr, regs.s != 0, false, sz_long, false);
- }
- }
- } CATCH(p) {
- } ENDTRY
- regs.s = olds;
- } else {
- v = get_long (addr);
- }
- return v;
- }
- uae_u32 get_iword_debug (uaecptr addr)
- {
- if (debug_mmu_mode) {
- return get_word_debug (addr);
- } else {
- if (valid_address (addr, 2))
- return get_word (addr);
- return 0xffff;
- }
- }
- uae_u32 get_ilong_debug (uaecptr addr)
- {
- if (debug_mmu_mode) {
- return get_long_debug (addr);
- } else {
- if (valid_address (addr, 4))
- return get_long (addr);
- return 0xffffffff;
- }
- }
- uae_u8 *get_real_address_debug(uaecptr addr)
- {
- if (debug_mmu_mode) {
- flagtype olds = regs.s;
- TRY(p) {
- if (currprefs.mmu_model >= 68040)
- addr = mmu_translate(addr, 0, regs.s != 0, (debug_mmu_mode & 1), false, 0);
- else
- addr = mmu030_translate(addr, regs.s != 0, (debug_mmu_mode & 1), false);
- } CATCH(p) {
- } ENDTRY
- }
- return get_real_address(addr);
- }
- int debug_safe_addr (uaecptr addr, int size)
- {
- if (debug_mmu_mode) {
- flagtype olds = regs.s;
- regs.s = (debug_mmu_mode & 4) != 0;
- TRY(p) {
- if (currprefs.mmu_model >= 68040)
- addr = mmu_translate (addr, 0, regs.s != 0, (debug_mmu_mode & 1), false, size);
- else
- addr = mmu030_translate (addr, regs.s != 0, (debug_mmu_mode & 1), false);
- } CATCH(p) {
- STOPTRY;
- return 0;
- } ENDTRY
- regs.s = olds;
- }
- addrbank *ab = &get_mem_bank (addr);
- if (!ab)
- return 0;
- if (ab->flags & ABFLAG_SAFE)
- return 1;
- if (!ab->check (addr, size))
- return 0;
- if (ab->flags & (ABFLAG_RAM | ABFLAG_ROM | ABFLAG_ROMIN | ABFLAG_SAFE))
- return 1;
- return 0;
- }
- static bool iscancel (int counter)
- {
- static int cnt;
- cnt++;
- if (cnt < counter)
- return false;
- cnt = 0;
- if (!console_isch ())
- return false;
- console_getch ();
- return true;
- }
- static bool isoperator(TCHAR **cp)
- {
- TCHAR c = **cp;
- return c == '+' || c == '-' || c == '/' || c == '*' || c == '(' || c == ')';
- }
- static void ignore_ws (TCHAR **c)
- {
- while (**c && _istspace(**c))
- (*c)++;
- }
- static TCHAR peekchar (TCHAR **c)
- {
- return **c;
- }
- static TCHAR readchar (TCHAR **c)
- {
- TCHAR cc = **c;
- (*c)++;
- return cc;
- }
- static TCHAR next_char(TCHAR **c)
- {
- ignore_ws (c);
- return *(*c)++;
- }
- static TCHAR next_char2(TCHAR **c)
- {
- return *(*c)++;
- }
- static TCHAR peek_next_char (TCHAR **c)
- {
- TCHAR *pc = *c;
- return pc[1];
- }
- static int more_params(TCHAR **c)
- {
- ignore_ws(c);
- return (**c) != 0;
- }
- static int more_params2(TCHAR **c)
- {
- return (**c) != 0;
- }
- static uae_u32 readint (TCHAR **c);
- static uae_u32 readbin (TCHAR **c);
- static uae_u32 readhex (TCHAR **c);
- static const TCHAR *debugoper[] = {
- _T("=="),
- _T("!="),
- _T("<="),
- _T(">="),
- _T("<"),
- _T(">"),
- _T("-"),
- _T("!-"),
- NULL
- };
- static int getoperidx(TCHAR **c)
- {
- int i;
- TCHAR *p = *c;
- TCHAR tmp[10];
- int extra = 0;
- i = 0;
- while (p[i]) {
- tmp[i] = _totupper(p[i]);
- if (i >= sizeof(tmp) / sizeof(TCHAR) - 1)
- break;
- i++;
- }
- tmp[i] = 0;
- if (!_tcsncmp(tmp, _T("!="), 2)) {
- (*c) += 2;
- return BREAKPOINT_CMP_NEQUAL;
- } else if (!_tcsncmp(tmp, _T("=="), 2)) {
- (*c) += 2;
- return BREAKPOINT_CMP_EQUAL;
- } else if (!_tcsncmp(tmp, _T(">="), 2)) {
- (*c) += 2;
- return BREAKPOINT_CMP_LARGER_EQUAL;
- } else if (!_tcsncmp(tmp, _T("<="), 2)) {
- (*c) += 2;
- return BREAKPOINT_CMP_SMALLER_EQUAL;
- } else if (!_tcsncmp(tmp, _T(">"), 1)) {
- (*c) += 1;
- return BREAKPOINT_CMP_LARGER;
- } else if (!_tcsncmp(tmp, _T("<"), 1)) {
- (*c) += 1;
- return BREAKPOINT_CMP_SMALLER;
- } else if (!_tcsncmp(tmp, _T("-"), 1)) {
- (*c) += 1;
- return BREAKPOINT_CMP_RANGE;
- } else if (!_tcsncmp(tmp, _T("!-"), 2)) {
- (*c) += 2;
- return BREAKPOINT_CMP_NRANGE;
- }
- return -1;
- }
- static const TCHAR *debugregs[] = {
- _T("D0"),
- _T("D1"),
- _T("D2"),
- _T("D3"),
- _T("D4"),
- _T("D5"),
- _T("D6"),
- _T("D7"),
- _T("A0"),
- _T("A1"),
- _T("A2"),
- _T("A3"),
- _T("A4"),
- _T("A5"),
- _T("A6"),
- _T("A7"),
- _T("PC"),
- _T("USP"),
- _T("MSP"),
- _T("ISP"),
- _T("VBR"),
- _T("SR"),
- _T("CCR"),
- _T("CACR"),
- _T("CAAR"),
- _T("SFC"),
- _T("DFC"),
- _T("TC"),
- _T("ITT0"),
- _T("ITT1"),
- _T("DTT0"),
- _T("DTT1"),
- _T("BUSC"),
- _T("PCR"),
- NULL
- };
- static int getregidx(TCHAR **c)
- {
- int i;
- TCHAR *p = *c;
- TCHAR tmp[10];
- int extra = 0;
- i = 0;
- while (p[i]) {
- tmp[i] = _totupper(p[i]);
- if (i >= sizeof(tmp) / sizeof(TCHAR) - 1)
- break;
- i++;
- }
- tmp[i] = 0;
- for (int i = 0; debugregs[i]; i++) {
- if (!_tcsncmp(tmp, debugregs[i], _tcslen(debugregs[i]))) {
- (*c) += _tcslen(debugregs[i]);
- return i;
- }
- }
- return -1;
- }
- static uae_u32 returnregx(int regid)
- {
- if (regid < BREAKPOINT_REG_PC)
- return regs.regs[regid];
- switch(regid)
- {
- case BREAKPOINT_REG_PC:
- return M68K_GETPC;
- case BREAKPOINT_REG_USP:
- return regs.usp;
- case BREAKPOINT_REG_MSP:
- return regs.msp;
- case BREAKPOINT_REG_ISP:
- return regs.isp;
- case BREAKPOINT_REG_VBR:
- return regs.vbr;
- case BREAKPOINT_REG_SR:
- MakeSR();
- return regs.sr;
- case BREAKPOINT_REG_CCR:
- MakeSR();
- return regs.sr & 31;
- case BREAKPOINT_REG_CACR:
- return regs.cacr;
- case BREAKPOINT_REG_CAAR:
- return regs.caar;
- case BREAKPOINT_REG_SFC:
- return regs.sfc;
- case BREAKPOINT_REG_DFC:
- return regs.dfc;
- case BREAKPOINT_REG_TC:
- if (currprefs.cpu_model == 68030)
- return tc_030;
- return regs.tcr;
- case BREAKPOINT_REG_ITT0:
- if (currprefs.cpu_model == 68030)
- return tt0_030;
- return regs.itt0;
- case BREAKPOINT_REG_ITT1:
- if (currprefs.cpu_model == 68030)
- return tt1_030;
- return regs.itt1;
- case BREAKPOINT_REG_DTT0:
- return regs.dtt0;
- case BREAKPOINT_REG_DTT1:
- return regs.dtt1;
- case BREAKPOINT_REG_BUSC:
- return regs.buscr;
- case BREAKPOINT_REG_PCR:
- return regs.fpcr;
- }
- return 0;
- }
- static int readregx (TCHAR **c, uae_u32 *valp)
- {
- int i;
- uae_u32 addr;
- TCHAR *p = *c;
- TCHAR tmp[10], *tp;
- int extra = 0;
- addr = 0;
- i = 0;
- while (p[i]) {
- tmp[i] = _totupper (p[i]);
- if (i >= sizeof (tmp) / sizeof (TCHAR) - 1)
- break;
- i++;
- }
- tmp[i] = 0;
- tp = tmp;
- if (_totupper (tmp[0]) == 'R') {
- tp = tmp + 1;
- extra = 1;
- }
- if (!_tcsncmp (tp, _T("USP"), 3)) {
- addr = regs.usp;
- (*c) += 3;
- } else if (!_tcsncmp (tp, _T("VBR"), 3)) {
- addr = regs.vbr;
- (*c) += 3;
- } else if (!_tcsncmp (tp, _T("MSP"), 3)) {
- addr = regs.msp;
- (*c) += 3;
- } else if (!_tcsncmp (tp, _T("ISP"), 3)) {
- addr = regs.isp;
- (*c) += 3;
- } else if (!_tcsncmp (tp, _T("PC"), 2)) {
- addr = regs.pc;
- (*c) += 2;
- } else if (tp[0] == 'A' || tp[0] == 'D') {
- int reg = 0;
- if (tp[0] == 'A')
- reg += 8;
- reg += tp[1] - '0';
- if (reg < 0 || reg > 15)
- return 0;
- addr = regs.regs[reg];
- (*c) += 2;
- } else {
- return 0;
- }
- *valp = addr;
- (*c) += extra;
- return 1;
- }
- static bool readbinx (TCHAR **c, uae_u32 *valp)
- {
- uae_u32 val = 0;
- bool first = true;
- ignore_ws (c);
- for (;;) {
- TCHAR nc = **c;
- if (nc != '1' && nc != '0') {
- if (first)
- return false;
- break;
- }
- first = false;
- (*c)++;
- val <<= 1;
- if (nc == '1')
- val |= 1;
- }
- *valp = val;
- return true;
- }
- static bool readhexx (TCHAR **c, uae_u32 *valp)
- {
- uae_u32 val = 0;
- TCHAR nc;
- ignore_ws (c);
- if (!isxdigit (peekchar (c)))
- return false;
- while (isxdigit (nc = **c)) {
- (*c)++;
- val *= 16;
- nc = _totupper (nc);
- if (isdigit (nc)) {
- val += nc - '0';
- } else {
- val += nc - 'A' + 10;
- }
- }
- *valp = val;
- return true;
- }
- static bool readintx (TCHAR **c, uae_u32 *valp)
- {
- uae_u32 val = 0;
- TCHAR nc;
- int negative = 0;
- ignore_ws (c);
- if (**c == '-')
- negative = 1, (*c)++;
- if (!isdigit (peekchar (c)))
- return false;
- while (isdigit (nc = **c)) {
- (*c)++;
- val *= 10;
- val += nc - '0';
- }
- *valp = val * (negative ? -1 : 1);
- return true;
- }
- static int checkvaltype2 (TCHAR **c, uae_u32 *val, TCHAR def)
- {
- TCHAR nc;
- ignore_ws (c);
- nc = _totupper (**c);
- if (nc == '!') {
- (*c)++;
- return readintx (c, val) ? 1 : 0;
- }
- if (nc == '$') {
- (*c)++;
- return readhexx (c, val) ? 1 : 0;
- }
- if (nc == '0' && _totupper ((*c)[1]) == 'X') {
- (*c)+= 2;
- return readhexx (c, val) ? 1 : 0;
- }
- if (nc == '%') {
- (*c)++;
- return readbinx (c, val) ? 1: 0;
- }
- if (nc >= 'A' && nc <= 'Z' && nc != 'A' && nc != 'D') {
- if (readregx (c, val))
- return 1;
- }
- TCHAR name[256];
- name[0] = 0;
- for (int i = 0; i < sizeof name / sizeof(TCHAR) - 1; i++) {
- nc = (*c)[i];
- if (nc == 0 || nc == ' ')
- break;
- name[i] = nc;
- name[i + 1] = 0;
- }
- if (name[0]) {
- TCHAR *np = name;
- if (*np == '#')
- np++;
- if (debugmem_get_symbol_value(np, val)) {
- (*c) += _tcslen(name);
- return 1;
- }
- }
- if (def == '!') {
- return readintx (c, val) ? -1 : 0;
- } else if (def == '$') {
- return readhexx (c, val) ? -1 : 0;
- } else if (def == '%') {
- return readbinx (c, val) ? -1 : 0;
- }
- return 0;
- }
- static int readsize (int val, TCHAR **c)
- {
- TCHAR cc = _totupper (readchar(c));
- if (cc == 'B')
- return 1;
- if (cc == 'W')
- return 2;
- if (cc == '3')
- return 3;
- if (cc == 'L')
- return 4;
- return 0;
- }
- static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def)
- {
- TCHAR form[256], *p;
- bool gotop = false;
- double out;
- form[0] = 0;
- if (size)
- *size = 0;
- p = form;
- for (;;) {
- uae_u32 v;
- if (!checkvaltype2 (cp, &v, def))
- return 0;
- *val = v;
- // stupid but works!
- _stprintf(p, _T("%u"), v);
- p += _tcslen (p);
- if (peekchar (cp) == '.') {
- readchar (cp);
- if (size)
- *size = readsize (v, cp);
- }
- if (!isoperator (cp))
- break;
- gotop = true;
- *p++= readchar (cp);
- *p = 0;
- }
- if (!gotop) {
- if (size && *size == 0) {
- uae_s32 v = (uae_s32)(*val);
- if (v > 65535 || v < -32767) {
- *size = 4;
- } else if (v > 255 || v < -127) {
- *size = 2;
- } else {
- *size = 1;
- }
- }
- return 1;
- }
- if (calc (form, &out)) {
- *val = (uae_u32)out;
- if (size && *size == 0) {
- uae_s32 v = (uae_s32)(*val);
- if (v > 255 || v < -127) {
- *size = 2;
- } else if (v > 65535 || v < -32767) {
- *size = 4;
- } else {
- *size = 1;
- }
- }
- return 1;
- }
- return 0;
- }
- static uae_u32 readnum (TCHAR **c, int *size, TCHAR def)
- {
- uae_u32 val;
- if (checkvaltype (c, &val, size, def))
- return val;
- return 0;
- }
- static uae_u32 readint (TCHAR **c)
- {
- int size;
- return readnum (c, &size, '!');
- }
- static uae_u32 readhex (TCHAR **c)
- {
- int size;
- return readnum (c, &size, '$');
- }
- static uae_u32 readbin (TCHAR **c)
- {
- int size;
- return readnum (c, &size, '%');
- }
- static uae_u32 readint (TCHAR **c, int *size)
- {
- return readnum (c, size, '!');
- }
- static uae_u32 readhex (TCHAR **c, int *size)
- {
- return readnum (c, size, '$');
- }
- static int next_string (TCHAR **c, TCHAR *out, int max, int forceupper)
- {
- TCHAR *p = out;
- int startmarker = 0;
- if (**c == '\"') {
- startmarker = 1;
- (*c)++;
- }
- *p = 0;
- while (**c != 0) {
- if (**c == '\"' && startmarker)
- break;
- if (**c == 32 && !startmarker) {
- ignore_ws (c);
- break;
- }
- *p = next_char (c);
- if (forceupper)
- *p = _totupper(*p);
- *++p = 0;
- max--;
- if (max <= 1)
- break;
- }
- return _tcslen (out);
- }
- static void converter (TCHAR **c)
- {
- uae_u32 v = readint (c);
- TCHAR s[100];
- int i;
- for (i = 0; i < 32; i++)
- s[i] = (v & (1 << (31 - i))) ? '1' : '0';
- s[i] = 0;
- console_out_f (_T("0x%08X = %%%s = %u = %d\n"), v, s, v, (uae_s32)v);
- }
- int notinrom (void)
- {
- uaecptr pc = munge24 (m68k_getpc ());
- if (pc < 0x00e00000 || pc > 0x00ffffff)
- return 1;
- return 0;
- }
- static uae_u32 lastaddr (void)
- {
- int lastbank = currprefs.address_space_24 ? 255 : 65535;
- for (int i = lastbank; i >= 0; i--) {
- addrbank *ab = get_mem_bank_real(i << 16);
- if (ab->baseaddr && (ab->flags & ABFLAG_RAM)) {
- return (i + 1) << 16;
- }
- }
- return 0;
- }
- static uaecptr nextaddr (uaecptr addr, uaecptr last, uaecptr *endp, bool verbose)
- {
- addrbank *ab;
- int lastbank = currprefs.address_space_24 ? 255 : 65535;
- if (addr != 0xffffffff) {
- addrbank *ab2 = get_mem_bank_real(addr);
- addr++;
- ab = get_mem_bank_real(addr);
- if (ab->baseaddr && (ab->flags & ABFLAG_RAM) && ab == ab2)
- return addr;
- } else {
- addr = 0;
- }
- while (addr < (lastbank << 16)) {
- ab = get_mem_bank_real(addr);
- if (ab->baseaddr && (ab->flags & ABFLAG_RAM))
- break;
- addr += 65536;
- }
- if (addr >= (lastbank << 16)) {
- if (endp)
- *endp = 0xffffffff;
- return 0xffffffff;
- }
- uaecptr start = addr;
- while (addr <= (lastbank << 16)) {
- addrbank *ab2 = get_mem_bank_real(addr);
- if ((last && last != 0xffffffff && addr >= last) || !ab2->baseaddr || !(ab2->flags & ABFLAG_RAM) || ab != ab2) {
- if (endp)
- *endp = addr;
- break;
- }
- addr += 65536;
- }
- if (verbose) {
- console_out_f(_T("Scanning.. %08x - %08x (%s)\n"), start, addr, get_mem_bank(start).name);
- }
- return start;
- }
- uaecptr dumpmem2 (uaecptr addr, TCHAR *out, int osize)
- {
- int i, cols = 8;
- int nonsafe = 0;
- if (osize <= (9 + cols * 5 + 1 + 2 * cols))
- return addr;
- _stprintf (out, _T("%08X "), addr);
- for (i = 0; i < cols; i++) {
- uae_u8 b1, b2;
- b1 = b2 = 0;
- if (debug_safe_addr (addr, 1)) {
- b1 = get_byte_debug (addr + 0);
- b2 = get_byte_debug (addr + 1);
- _stprintf (out + 9 + i * 5, _T("%02X%02X "), b1, b2);
- out[9 + cols * 5 + 1 + i * 2 + 0] = b1 >= 32 && b1 < 127 ? b1 : '.';
- out[9 + cols * 5 + 1 + i * 2 + 1] = b2 >= 32 && b2 < 127 ? b2 : '.';
- } else {
- nonsafe++;
- _tcscpy (out + 9 + i * 5, _T("**** "));
- out[9 + cols * 5 + 1 + i * 2 + 0] = '*';
- out[9 + cols * 5 + 1 + i * 2 + 1] = '*';
- }
- addr += 2;
- }
- out[9 + cols * 5] = ' ';
- out[9 + cols * 5 + 1 + 2 * cols] = 0;
- if (nonsafe == cols) {
- addrbank *ab = &get_mem_bank (addr);
- if (ab->name)
- memcpy (out + (9 + 4 + 1) * sizeof (TCHAR), ab->name, _tcslen (ab->name) * sizeof (TCHAR));
- }
- return addr;
- }
- static void dumpmem (uaecptr addr, uaecptr *nxmem, int lines)
- {
- TCHAR line[MAX_LINEWIDTH + 1];
- for (;lines--;) {
- addr = dumpmem2 (addr, line, sizeof(line));
- debug_out (_T("%s"), line);
- if (!debug_out (_T("\n")))
- break;
- }
- *nxmem = addr;
- }
- static void dump_custom_regs(bool aga, bool ext)
- {
- int len;
- uae_u8 *p1, *p2, *p3, *p4;
- TCHAR extra1[256], extra2[256];
- extra1[0] = 0;
- extra2[0] = 0;
- if (aga) {
- dump_aga_custom();
- return;
- }
- p1 = p2 = save_custom (&len, 0, 1);
- p1 += 4; // skip chipset type
- for (int i = 0; i < 4; i++) {
- p4 = p1 + 0xa0 + i * 16;
- p3 = save_audio (i, &len, 0);
- p4[0] = p3[12];
- p4[1] = p3[13];
- p4[2] = p3[14];
- p4[3] = p3[15];
- p4[4] = p3[4];
- p4[5] = p3[5];
- p4[6] = p3[8];
- p4[7] = p3[9];
- p4[8] = 0;
- p4[9] = p3[1];
- p4[10] = p3[10];
- p4[11] = p3[11];
- free (p3);
- }
- int total = 0;
- int i = 0;
- while (custd[i].name) {
- if (!(custd[i].special & CD_NONE))
- total++;
- i++;
- }
- int cnt1 = 0;
- int cnt2 = 0;
- i = 0;
- while (i < total / 2 + 1) {
- for (;;) {
- cnt2++;
- if (!(custd[cnt2].special & CD_NONE))
- break;
- }
- i++;
- }
- for (int i = 0; i < total / 2 + 1; i++) {
- uae_u16 v1, v2;
- int addr1, addr2;
- addr1 = custd[cnt1].adr & 0x1ff;
- addr2 = custd[cnt2].adr & 0x1ff;
- v1 = (p1[addr1 + 0] << 8) | p1[addr1 + 1];
- v2 = (p1[addr2 + 0] << 8) | p1[addr2 + 1];
- if (ext) {
- struct custom_store *cs;
- cs = &custom_storage[addr1 >> 1];
- _stprintf(extra1, _T("\t%04X %08X %s"), cs->value, cs->pc & ~1, (cs->pc & 1) ? _T("COP") : _T("CPU"));
- cs = &custom_storage[addr2 >> 1];
- _stprintf(extra2, _T("\t%04X %08X %s"), cs->value, cs->pc & ~1, (cs->pc & 1) ? _T("COP") : _T("CPU"));
- }
- console_out_f (_T("%03X %s\t%04X%s\t%03X %s\t%04X%s\n"),
- addr1, custd[cnt1].name, v1, extra1,
- addr2, custd[cnt2].name, v2, extra2);
- for (;;) {
- cnt1++;
- if (!(custd[cnt1].special & CD_NONE))
- break;
- }
- for (;;) {
- cnt2++;
- if (!(custd[cnt2].special & CD_NONE))
- break;
- }
- }
- xfree(p2);
- }
- static void dump_vectors (uaecptr addr)
- {
- int i = 0, j = 0;
- if (addr == 0xffffffff)
- addr = regs.vbr;
- while (int_labels[i].name || trap_labels[j].name) {
- if (int_labels[i].name) {
- console_out_f (_T("$%08X %02d: %12s $%08X "), int_labels[i].adr + addr, int_labels[i].adr / 4,
- int_labels[i].name, get_long_debug (int_labels[i].adr + addr));
- i++;
- }
- if (trap_labels[j].name) {
- console_out_f (_T("$%08X %02d: %12s $%08X"), trap_labels[j].adr + addr, trap_labels[j].adr / 4,
- trap_labels[j].name, get_long_debug (trap_labels[j].adr + addr));
- j++;
- }
- console_out (_T("\n"));
- }
- }
- static void disassemble_wait (FILE *file, unsigned long insn)
- {
- int vp, hp, ve, he, bfd, v_mask, h_mask;
- int doout = 0;
- vp = (insn & 0xff000000) >> 24;
- hp = (insn & 0x00fe0000) >> 16;
- ve = (insn & 0x00007f00) >> 8;
- he = (insn & 0x000000fe);
- bfd = (insn & 0x00008000) >> 15;
- /* bit15 can never be masked out*/
- v_mask = vp & (ve | 0x80);
- h_mask = hp & he;
- if (v_mask > 0) {
- doout = 1;
- console_out (_T("vpos "));
- if (ve != 0x7f) {
- console_out_f (_T("& 0x%02x "), ve);
- }
- console_out_f (_T(">= 0x%02x"), v_mask);
- }
- if (he > 0) {
- if (v_mask > 0) {
- console_out (_T(" and"));
- }
- console_out (_T(" hpos "));
- if (he != 0xfe) {
- console_out_f (_T("& 0x%02x "), he);
- }
- console_out_f (_T(">= 0x%02x"), h_mask);
- } else {
- if (doout)
- console_out (_T(", "));
- console_out (_T(", ignore horizontal"));
- }
- console_out_f (_T("\n \t; VP %02x, VE %02x; HP %02x, HE %02x; BFD %d\n"),
- vp, ve, hp, he, bfd);
- }
- #define NR_COPPER_RECORDS 100000
- /* Record copper activity for the debugger. */
- struct cop_rec
- {
- uae_u16 w1, w2;
- int hpos, vpos;
- int bhpos, bvpos;
- uaecptr addr, nextaddr;
- };
- static struct cop_rec *cop_record[2];
- static int nr_cop_records[2], curr_cop_set, selected_cop_set;
- #define NR_DMA_REC_HPOS 256
- #define NR_DMA_REC_VPOS 1000
- static struct dma_rec *dma_record[2];
- static int dma_record_toggle, dma_record_frame[2];
- void record_dma_reset (void)
- {
- int v, h;
- struct dma_rec *dr, *dr2;
- if (!dma_record[0])
- return;
- dma_record_toggle ^= 1;
- dr = dma_record[dma_record_toggle];
- for (v = 0; v < NR_DMA_REC_VPOS; v++) {
- for (h = 0; h < NR_DMA_REC_HPOS; h++) {
- dr2 = &dr[v * NR_DMA_REC_HPOS + h];
- memset (dr2, 0, sizeof (struct dma_rec));
- dr2->reg = 0xffff;
- dr2->cf_reg = 0xffff;
- dr2->addr = 0xffffffff;
- }
- }
- }
- void record_copper_reset (void)
- {
- /* Start a new set of copper records. */
- curr_cop_set ^= 1;
- nr_cop_records[curr_cop_set] = 0;
- }
- STATIC_INLINE uae_u32 ledcolor (uae_u32 c, uae_u32 *rc, uae_u32 *gc, uae_u32 *bc, uae_u32 *a)
- {
- uae_u32 v = rc[(c >> 16) & 0xff] | gc[(c >> 8) & 0xff] | bc[(c >> 0) & 0xff];
- if (a)
- v |= a[255 - ((c >> 24) & 0xff)];
- return v;
- }
- STATIC_INLINE void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8)
- {
- if (x <= 0)
- return;
- switch (bpp) {
- case 1:
- buf[x] = (uae_u8)c8;
- break;
- case 2:
- {
- uae_u16 *p = (uae_u16*)buf + x;
- *p = (uae_u16)c8;
- break;
- }
- case 3:
- /* no 24 bit yet */
- break;
- case 4:
- {
- uae_u32 *p = (uae_u32*)buf + x;
- *p = c8;
- break;
- }
- }
- }
- #define lc(x) ledcolor (x, xredcolors, xgreencolors, xbluecolors, NULL)
- #define DMARECORD_SUBITEMS 8
- struct dmadebug
- {
- uae_u32 l[DMARECORD_SUBITEMS];
- uae_u8 r, g, b;
- bool enabled;
- int max;
- const TCHAR *name;
- };
- static uae_u32 intlevc[] = { 0x000000, 0x444444, 0x008800, 0xffff00, 0x000088, 0x880000, 0xff0000, 0xffffff };
- static struct dmadebug debug_colors[DMARECORD_MAX];
- static bool debug_colors_set;
- static void set_dbg_color(int index, int extra, uae_u8 r, uae_u8 g, uae_u8 b, int max, const TCHAR *name)
- {
- if (extra == 0) {
- debug_colors[index].r = r;
- debug_colors[index].g = g;
- debug_colors[index].b = b;
- debug_colors[index].enabled = true;
- }
- if (name != NULL)
- debug_colors[index].name = name;
- if (max > 0)
- debug_colors[index].max = max;
- debug_colors[index].l[extra] = lc((r << 16) | (g << 8) | (b << 0));
- }
- static void set_debug_colors(void)
- {
- if (debug_colors_set)
- return;
- debug_colors_set = true;
- set_dbg_color(0, 0, 0x22, 0x22, 0x22, 1, _T("-"));
- set_dbg_color(DMARECORD_REFRESH, 0, 0x44, 0x44, 0x44, 4, _T("Refresh"));
- set_dbg_color(DMARECORD_CPU, 0, 0xa2, 0x53, 0x42, 2, _T("CPU")); // code
- set_dbg_color(DMARECORD_COPPER, 0, 0xee, 0xee, 0x00, 3, _T("Copper"));
- set_dbg_color(DMARECORD_AUDIO, 0, 0xff, 0x00, 0x00, 4, _T("Audio"));
- set_dbg_color(DMARECORD_BLITTER, 0, 0x00, 0x88, 0x88, 2, _T("Blitter"));
- set_dbg_color(DMARECORD_BITPLANE, 0, 0x00, 0x00, 0xff, 8, _T("Bitplane"));
- set_dbg_color(DMARECORD_SPRITE, 0, 0xff, 0x00, 0xff, 8, _T("Sprite"));
- set_dbg_color(DMARECORD_DISK, 0, 0xff, 0xff, 0xff, 3, _T("Disk"));
- for (int i = 0; i < DMARECORD_MAX; i++) {
- for (int j = 1; j < DMARECORD_SUBITEMS; j++) {
- debug_colors[i].l[j] = debug_colors[i].l[0];
- }
- }
- set_dbg_color(DMARECORD_CPU, 1, 0xad, 0x98, 0xd6, 0, NULL); // data
- set_dbg_color(DMARECORD_COPPER, 1, 0xaa, 0xaa, 0x22, 0, NULL); // wait
- set_dbg_color(DMARECORD_COPPER, 2, 0x66, 0x66, 0x44, 0, NULL); // special
- set_dbg_color(DMARECORD_BLITTER, 1, 0x00, 0x88, 0xff, 0, NULL); // fill
- set_dbg_color(DMARECORD_BLITTER, 2, 0x00, 0xff, 0x00, 0, NULL); // line
- }
- 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)
- {
- int y, x, xx, dx, xplus, yplus;
- struct dma_rec *dr;
- int t;
- if (debug_dma >= 4)
- yplus = 2;
- else
- yplus = 1;
- if (debug_dma >= 5)
- xplus = 3;
- else if (debug_dma >= 3)
- xplus = 2;
- else
- xplus = 1;
- t = dma_record_toggle ^ 1;
- y = line / yplus;
- if (yplus < 2)
- y -= 8;
- if (y < 0)
- return;
- if (y > maxvpos)
- return;
- if (y >= height)
- return;
- dx = width - xplus * ((maxhpos + 1) & ~1) - 16;
- uae_s8 intlev = 0;
- for (x = 0; x < maxhpos; x++) {
- uae_u32 c = debug_colors[0].l[0];
- xx = x * xplus + dx;
- dr = &dma_record[t][y * NR_DMA_REC_HPOS + x];
- if (dr->reg != 0xffff && debug_colors[dr->type].enabled) {
- c = debug_colors[dr->type].l[dr->extra];
- }
- if (dr->intlev > intlev)
- intlev = dr->intlev;
- putpixel (buf, bpp, xx + 4, c);
- if (xplus)
- putpixel (buf, bpp, xx + 4 + 1, c);
- if (debug_dma >= 6)
- putpixel (buf, bpp, xx + 4 + 2, c);
- }
- putpixel (buf, bpp, dx + 0, 0);
- putpixel (buf, bpp, dx + 1, lc(intlevc[intlev]));
- putpixel (buf, bpp, dx + 2, lc(intlevc[intlev]));
- putpixel (buf, bpp, dx + 3, 0);
- }
- #define HEATMAP_WIDTH 256
- #define HEATMAP_HEIGHT 256
- #define HEATMAP_COUNT 32
- #define HEATMAP_DIV 8
- static const int max_heatmap = 16 * 1048576; // 16M
- static uae_u32 *heatmap_debug_colors;
- static struct memory_heatmap *heatmap;
- struct memory_heatmap
- {
- uae_u32 mask;
- uae_u32 cpucnt;
- uae_u16 cnt;
- uae_u16 type, extra;
- };
- 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)
- {
- struct memory_heatmap *mht = heatmap;
- int dx = 16;
- int y = line;
- if (y < 0 || y >= HEATMAP_HEIGHT)
- return;
- mht += y * HEATMAP_WIDTH;
- for (int x = 0; x < HEATMAP_WIDTH; x++) {
- uae_u32 c = heatmap_debug_colors[mht->cnt * DMARECORD_MAX + mht->type];
- //c = heatmap_debug_colors[(HEATMAP_COUNT - 1) * DMARECORD_MAX + DMARECORD_CPU_I];
- int xx = x + dx;
- putpixel(buf, bpp, xx, c);
- if (mht->cnt > 0)
- mht->cnt--;
- mht++;
- }
- }
- void debug_draw(uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors)
- {
- if (!heatmap_debug_colors) {
- heatmap_debug_colors = xcalloc(uae_u32, DMARECORD_MAX * HEATMAP_COUNT);
- set_debug_colors();
- for (int i = 0; i < HEATMAP_COUNT; i++) {
- uae_u32 *cp = heatmap_debug_colors + i * DMARECORD_MAX;
- for (int j = 0; j < DMARECORD_MAX; j++) {
- uae_u8 r = debug_colors[j].r;
- uae_u8 g = debug_colors[j].g;
- uae_u8 b = debug_colors[j].b;
- r = r * i / HEATMAP_COUNT;
- g = g * i / HEATMAP_COUNT;
- b = b * i / HEATMAP_COUNT;
- cp[j] = lc((r << 16) | (g << 8) | (b << 0));
- }
- }
- }
- if (heatmap) {
- debug_draw_heatmap(buf, bpp, line, width, height, xredcolors, xgreencolors, xbluecolors);
- } else if (dma_record[0]) {
- debug_draw_cycles(buf, bpp, line, width, height, xredcolors, xgreencolors, xbluecolors);
- }
- }
- struct heatmapstore
- {
- TCHAR *s;
- double v;
- };
- static void heatmap_stats(TCHAR **c)
- {
- int range = 95;
- int maxlines = 30;
- double max;
- int maxcnt;
- uae_u32 mask = MW_MASK_CPU_I;
- const TCHAR *maskname = NULL;
- if (more_params(c)) {
- if (**c == 'c' && peek_next_char(c) == 0) {
- for (int i = 0; i < max_heatmap / HEATMAP_DIV; i++) {
- struct memory_heatmap *hm = &heatmap[i];
- memset(hm, 0, sizeof(struct memory_heatmap));
- }
- console_out(_T("heatmap data cleared\n"));
- return;
- }
- if (!isdigit(peek_next_char(c))) {
- TCHAR str[100];
- if (next_string(c, str, sizeof str / sizeof (TCHAR), true)) {
- for (int j = 0; memwatch_access_masks[j].mask; j++) {
- if (!_tcsicmp(str, memwatch_access_masks[j].name)) {
- mask = memwatch_access_masks[j].mask;
- maskname = memwatch_access_masks[j].name;
- console_out_f(_T("Mask %08x Name %s\n"), mask, maskname);
- break;
- }
- }
- }
- if (more_params(c)) {
- maxlines = readint(c);
- }
- } else {
- range = readint(c);
- if (more_params(c)) {
- maxlines = readint(c);
- }
- }
- }
- if (maxlines <= 0)
- maxlines = 10000;
- if (mask != MW_MASK_CPU_I) {
- int found = -1;
- int firstaddress = 0;
- for (int lines = 0; lines < maxlines; lines++) {
- for (; firstaddress < max_heatmap / HEATMAP_DIV; firstaddress++) {
- struct memory_heatmap *hm = &heatmap[firstaddress];
- if (hm->mask & mask)
- break;
- }
- if (firstaddress == max_heatmap / HEATMAP_DIV)
- return;
- int lastaddress;
- for (lastaddress = firstaddress; lastaddress < max_heatmap / HEATMAP_DIV; lastaddress++) {
- struct memory_heatmap *hm = &heatmap[lastaddress];
- if (!(hm->mask & mask))
- break;
- }
- lastaddress--;
- console_out_f(_T("%03d: %08x - %08x %08x (%d) %s\n"),
- lines,
- firstaddress * HEATMAP_DIV, lastaddress * HEATMAP_DIV + HEATMAP_DIV - 1,
- lastaddress * HEATMAP_DIV - firstaddress * HEATMAP_DIV + HEATMAP_DIV - 1,
- lastaddress * HEATMAP_DIV - firstaddress * HEATMAP_DIV + HEATMAP_DIV - 1,
- maskname);
- firstaddress = lastaddress + 1;
- }
- } else {
- #define MAX_HEATMAP_LINES 1000
- struct heatmapstore linestore[MAX_HEATMAP_LINES] = { 0 };
- int storecnt = 0;
- uae_u32 maxlimit = 0xffffffff;
- max = 0;
- maxcnt = 0;
- for (int i = 0; i < max_heatmap / HEATMAP_DIV; i++) {
- struct memory_heatmap *hm = &heatmap[i];
- if (hm->cpucnt > 0) {
- max += hm->cpucnt;
- maxcnt++;
- }
- }
- if (!maxcnt) {
- console_out(_T("No CPU accesses found\n"));
- return;
- }
- for (int lines = 0; lines < maxlines; lines++) {
- int found = -1;
- int foundcnt = 0;
- for (int i = 0; i < max_heatmap / HEATMAP_DIV; i++) {
- struct memory_heatmap *hm = &heatmap[i];
- if (hm->cpucnt > 0 && hm->cpucnt > foundcnt && hm->cpucnt < maxlimit) {
- foundcnt = hm->cpucnt;
- found = i;
- }
- }
- if (found < 0)
- break;
- int totalcnt = 0;
- int cntrange = foundcnt * range / 100;
- if (cntrange <= 0)
- cntrange = 1;
- int lastaddress;
- for (lastaddress = found; lastaddress < max_heatmap / HEATMAP_DIV; lastaddress++) {
- struct memory_heatmap *hm = &heatmap[lastaddress];
- if (hm->cpucnt == 0 || hm->cpucnt < cntrange || hm->cpucnt >= maxlimit)
- break;
- totalcnt += hm->cpucnt;
- }
- lastaddress--;
- int firstaddress;
- for (firstaddress = found - 1; firstaddress >= 0; firstaddress--) {
- struct memory_heatmap *hm = &heatmap[firstaddress];
- if (hm->cpucnt == 0 || hm->cpucnt < cntrange || hm->cpucnt >= maxlimit)
- break;
- totalcnt += hm->cpucnt;
- }
- firstaddress--;
- firstaddress *= HEATMAP_DIV;
- lastaddress *= HEATMAP_DIV;
- TCHAR tmp[100];
- double pct = totalcnt / max * 100.0;
- _stprintf(tmp, _T("%03d: %08x - %08x %08x (%d) %.5f%%\n"), lines + 1,
- firstaddress, lastaddress + HEATMAP_DIV - 1,
- lastaddress - firstaddress + HEATMAP_DIV - 1,
- lastaddress - firstaddress + HEATMAP_DIV - 1,
- pct);
- linestore[storecnt].s = my_strdup(tmp);
- linestore[storecnt].v = pct;
- storecnt++;
- if (storecnt >= MAX_HEATMAP_LINES)
- break;
- maxlimit = foundcnt;
- }
- for (int lines1 = 0; lines1 < storecnt; lines1++) {
- for (int lines2 = lines1 + 1; lines2 < storecnt; lines2++) {
- if (linestore[lines1].v < linestore[lines2].v) {
- struct heatmapstore hms;
- memcpy(&hms, &linestore[lines1], sizeof(struct heatmapstore));
- memcpy(&linestore[lines1], &linestore[lines2], sizeof(struct heatmapstore));
- memcpy(&linestore[lines2], &hms, sizeof(struct heatmapstore));
- }
- }
- }
- for (int lines1 = 0; lines1 < storecnt; lines1++) {
- console_out(linestore[lines1].s);
- xfree(linestore[lines1].s);
- }
- }
- }
- static void free_heatmap(void)
- {
- xfree(heatmap);
- heatmap = NULL;
- debug_heatmap = 0;
- }
- static void init_heatmap(void)
- {
- if (!heatmap)
- heatmap = xcalloc(struct memory_heatmap, max_heatmap / HEATMAP_DIV);
- }
- static void memwatch_heatmap (uaecptr addr, int rwi, int size, uae_u32 accessmask)
- {
- if (addr >= max_heatmap || !heatmap)
- return;
- struct memory_heatmap *hm = &heatmap[addr / HEATMAP_DIV];
- if (accessmask & MW_MASK_CPU_I) {
- hm->cpucnt++;
- }
- hm->cnt = HEATMAP_COUNT - 1;
- int type = 0;
- int extra = 0;
- for (int i = 0; i < 32; i++) {
- if (accessmask & (1 << i)) {
- switch (1 << i)
- {
- case MW_MASK_BPL_0:
- case MW_MASK_BPL_1:
- case MW_MASK_BPL_2:
- case MW_MASK_BPL_3:
- case MW_MASK_BPL_4:
- case MW_MASK_BPL_5:
- case MW_MASK_BPL_6:
- case MW_MASK_BPL_7:
- type = DMARECORD_BITPLANE;
- break;
- case MW_MASK_AUDIO_0:
- case MW_MASK_AUDIO_1:
- case MW_MASK_AUDIO_2:
- case MW_MASK_AUDIO_3:
- type = DMARECORD_AUDIO;
- break;
- case MW_MASK_BLITTER_A:
- case MW_MASK_BLITTER_B:
- case MW_MASK_BLITTER_C:
- case MW_MASK_BLITTER_D_N:
- case MW_MASK_BLITTER_D_F:
- case MW_MASK_BLITTER_D_L:
- type = DMARECORD_BLITTER;
- break;
- case MW_MASK_COPPER:
- type = DMARECORD_COPPER;
- break;
- case MW_MASK_DISK:
- type = DMARECORD_DISK;
- break;
- case MW_MASK_CPU_I:
- type = DMARECORD_CPU;
- break;
- case MW_MASK_CPU_D_R:
- case MW_MASK_CPU_D_W:
- type = DMARECORD_CPU;
- extra = 1;
- break;
- }
- }
- }
- hm->type = type;
- hm->extra = extra;
- hm->mask |= accessmask;
- }
- void record_dma_event (uae_u32 evt, int hpos, int vpos)
- {
- struct dma_rec *dr;
- if (!dma_record[0])
- return;
- if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
- return;
- dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
- dr->evt |= evt;
- }
- void record_dma_replace(int hpos, int vpos, int type, int extra)
- {
- struct dma_rec *dr;
- if (!dma_record[0])
- return;
- if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
- return;
- dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
- if (dr->reg == 0xffff) {
- write_log(_T("DMA record replace without old data!\n"));
- return;
- }
- if (dr->type != type) {
- write_log(_T("DMA record replace type change %d -> %d!\n"), dr->type, type);
- return;
- }
- dr->extra = extra;
- }
- static void dma_conflict(int vpos, int hpos, struct dma_rec *dr, int reg, bool write)
- {
- write_log(_T("DMA conflict %c: v=%d h=%d OREG=%04X NREG=%04X\n"), write ? 'W' : 'R', vpos, hpos, dr->reg, reg);
- }
- void record_dma_write(uae_u16 reg, uae_u32 dat, uae_u32 addr, int hpos, int vpos, int type, int extra)
- {
- struct dma_rec *dr;
- if (!dma_record[0]) {
- dma_record[0] = xmalloc(struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
- dma_record[1] = xmalloc(struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
- dma_record_toggle = 0;
- record_dma_reset();
- dma_record_frame[0] = -1;
- dma_record_frame[1] = -1;
- }
- if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
- return;
- dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
- dma_record_frame[dma_record_toggle] = timeframes;
- if (dr->reg != 0xffff) {
- dr->cf_reg = reg;
- dr->cf_dat = dat;
- dr->cf_addr = addr;
- dma_conflict(vpos, hpos, dr, reg, false);
- return;
- }
- dr->reg = reg;
- dr->dat = dat;
- dr->addr = addr;
- dr->type = type;
- dr->extra = extra;
- dr->intlev = regs.intmask;
- dr->size = 2;
- last_dma_rec = dr;
- }
- struct dma_rec *last_dma_rec;
- void record_dma_read_value(uae_u32 v)
- {
- if (last_dma_rec) {
- if (last_dma_rec->cf_reg != 0xffff) {
- last_dma_rec->cf_dat = v;
- } else {
- last_dma_rec->dat = v;
- }
- last_dma_rec->size = 2;
- }
- }
- void record_dma_read_value_wide(uae_u64 v, bool quad)
- {
- if (last_dma_rec) {
- if (last_dma_rec->cf_reg != 0xffff) {
- last_dma_rec->cf_dat = v;
- } else {
- last_dma_rec->dat = v;
- }
- last_dma_rec->size = quad ? 8 : 4;
- }
- }
- void record_dma_read(uae_u16 reg, uae_u32 addr, int hpos, int vpos, int type, int extra)
- {
- struct dma_rec *dr;
- if (!dma_record[0]) {
- dma_record[0] = xmalloc (struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
- dma_record[1] = xmalloc (struct dma_rec, NR_DMA_REC_HPOS * NR_DMA_REC_VPOS);
- dma_record_toggle = 0;
- record_dma_reset ();
- dma_record_frame[0] = -1;
- dma_record_frame[1] = -1;
- }
- if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS)
- return;
- dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
- dma_record_frame[dma_record_toggle] = timeframes;
- if (dr->reg != 0xffff) {
- if (dr->reg != reg) {
- dma_conflict(vpos, hpos, dr, reg, false);
- dr->cf_reg = reg;
- dr->cf_addr = addr;
- }
- return;
- }
- dr->reg = reg;
- dr->dat = 0;
- dr->addr = addr;
- dr->type = type;
- dr->extra = extra;
- dr->intlev = regs.intmask;
- last_dma_rec = dr;
- }
- 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)
- {
- int longsize = dr->size;
- bool got = false;
- int r = dr->reg;
- int regsize = 3;
- const TCHAR *sr;
- int br = dr->extra & 7;
- int chcnt = -1;
- TCHAR srtext[10];
- bool extra64 = false;
- uae_u32 extraval;
- bool noval = false;
- if (l1)
- l1[0] = 0;
- if (l2)
- l2[0] = 0;
- if (l3)
- l3[0] = 0;
- if (l4)
- l4[0] = 0;
- if (l5)
- l5[0] = 0;
- if (dr->type != 0 || dr->reg != 0xffff || dr->evt)
- got = true;
- sr = _T(" ");
- if (dr->type == DMARECORD_COPPER) {
- if (dr->extra == 3)
- sr = _T("COPW");
- else
- sr = _T("COP ");
- } else if (dr->type == DMARECORD_BLITTER) {
- if (dr->extra & 0x20) {
- if (br == 0)
- sr = _T("BLL-A");
- if (br == 1)
- sr = _T("BLL-B");
- if (br == 2)
- sr = _T("BLL-C");
- if (br == 3)
- sr = _T("BLL-D");
- } else if (dr->extra & 0x10) {
- if (br == 0)
- sr = _T("BLF-A");
- if (br == 1)
- sr = _T("BLF-B");
- if (br == 2)
- sr = _T("BLF-C");
- if (br == 3)
- sr = _T("BLF-D");
- } else {
- if (br == 0)
- sr = _T("BLT-A");
- if (br == 1)
- sr = _T("BLT-B");
- if (br == 2)
- sr = _T("BLT-C");
- if (br == 3)
- sr = _T("BLT-D");
- }
- regsize = 2;
- } else if (dr->type == DMARECORD_REFRESH) {
- sr = _T("RFS");
- chcnt = br;
- noval = true;
- } else if (dr->type == DMARECORD_AUDIO) {
- sr = _T("AUD");
- chcnt = br;
- } else if (dr->type == DMARECORD_DISK) {
- sr = _T("DSK");
- chcnt = br;
- } else if (dr->type == DMARECORD_SPRITE) {
- sr = _T("SPR");
- chcnt = br;
- } else if (dr->type == DMARECORD_BITPLANE) {
- sr = _T("BPL");
- chcnt = br + 1;
- }
- if (dr->cf_reg != 0xffff) {
- _stprintf(srtext, _T("!%03x "), dr->cf_reg);
- chcnt = -1;
- } else {
- _tcscpy(srtext, sr);
- }
- _stprintf (l1, _T("[%02X %3d]"), hpos, hpos);
- if (l4) {
- _tcscpy (l4, _T(" "));
- }
- if (r != 0xffff) {
- if (r & 0x1000) {
- if ((r & 0x0100) == 0x0000)
- _tcscpy (l2, _T("CPU-R "));
- else if ((r & 0x0100) == 0x0100)
- _tcscpy (l2, _T("CPU-W "));
- if ((r & 0xff) == 4) {
- l2[5] = 'L';
- longsize = 4;
- }
- if ((r & 0xff) == 2)
- l2[5] = 'W';
- if ((r & 0xff) == 1)
- l2[5] = 'B';
- } else {
- if (chcnt >= 0) {
- if (regsize == 3)
- _stprintf(l2, _T("%3s%d %03X"), srtext, chcnt, r);
- else
- _stprintf(l2, _T("%4s%d %02X"), srtext, chcnt, r);
- } else {
- if (regsize == 3)
- _stprintf(l2, _T("%4s %03X"), srtext, r);
- else
- _stprintf(l2, _T("%5s %02X"), srtext, r);
- }
- }
- if (l3 && !noval) {
- uae_u64 v = dr->dat;
- if (longsize == 4) {
- _stprintf(l3, _T("%08X"), (uae_u32)v);
- } else if (longsize == 8) {
- _stprintf(l3, _T("%08X"), (uae_u32)(v >> 32));
- extra64 = true;
- extraval = (uae_u32)v;
- } else {
- _stprintf(l3, _T(" %04X"), (uae_u32)(v & 0xffff));
- }
- }
- if (l4 && dr->addr != 0xffffffff)
- _stprintf (l4, _T("%08X"), dr->addr & 0x00ffffff);
- } else {
- _tcscpy (l2, _T(" "));
- if (l3) {
- _tcscpy (l3, _T(" "));
- }
- }
- if (l3) {
- int cl2 = 0;
- if (dr->evt & DMA_EVENT_BLITFINALD)
- l3[cl2++] = 'D';
- if (dr->evt & DMA_EVENT_BLITSTARTFINISH)
- l3[cl2++] = 'B';
- if (dr->evt & DMA_EVENT_CPUBLITTERSTEAL)
- l3[cl2++] = 's';
- if (dr->evt & DMA_EVENT_CPUBLITTERSTOLEN)
- l3[cl2++] = 'S';
- if (dr->evt & DMA_EVENT_BLITIRQ)
- l3[cl2++] = 'b';
- if (dr->evt & DMA_EVENT_BPLFETCHUPDATE)
- l3[cl2++] = 'p';
- if (dr->evt & (DMA_EVENT_COPPERWAKE | DMA_EVENT_COPPERSKIP))
- l3[cl2++] = 'W';
- if (dr->evt & DMA_EVENT_NOONEGETS) {
- l3[cl2++] = '#';
- } else if (dr->evt & DMA_EVENT_COPPERWANTED) {
- l3[cl2++] = 'c';
- }
- if (dr->evt & DMA_EVENT_CPUIRQ)
- l3[cl2++] = 'I';
- if (dr->evt & DMA_EVENT_INTREQ)
- l3[cl2++] = 'i';
- if (dr->evt & DMA_EVENT_SPECIAL)
- l3[cl2++] = 'X';
- if (dr->evt & DMA_EVENT_DDFSTRT)
- l3[cl2++] = '0';
- if (dr->evt & DMA_EVENT_DDFSTOP)
- l3[cl2++] = '1';
- if (dr->evt & DMA_EVENT_DDFSTOP2)
- l3[cl2++] = '2';
- if (dr->evt & DMA_EVENT_HDIWS) {
- l3[cl2++] = '(';
- }
- if (dr->evt & DMA_EVENT_HDIWE) {
- l3[cl2++] = ')';
- }
- if (dr->evt & DMA_EVENT_HBS) {
- l3[cl2++] = '[';
- }
- if (dr->evt & DMA_EVENT_HBE) {
- l3[cl2++] = ']';
- }
- if (dr->evt & DMA_EVENT_HSS) {
- l3[cl2++] = '{';
- }
- if (dr->evt & DM…
Large files files are truncated, but you can click here to view the full file