--- hatari/src/debug/history.c 2019/04/09 08:50:22 1.1 +++ hatari/src/debug/history.c 2019/04/09 08:54:22 1.1.1.3 @@ -1,10 +1,10 @@ /* * Hatari - history.c * - * Copyright (C) 2011 by Eero Tamminen + * Copyright (C) 2011-2013 by Eero Tamminen * - * This file is distributed under the GNU Public License, version 2 or at - * your option any later version. Read the file gpl.txt for details. + * This file is distributed under the GNU General Public License, version 2 + * or at your option any later version. Read the file gpl.txt for details. * * history.c - functions for debugger entry & breakpoint history */ @@ -22,9 +22,9 @@ const char History_fileid[] = "Hatari hi #include "m68000.h" #include "68kDisass.h" -bool bHistoryEnabled; +#define HISTORY_ITEMS_MIN 64 -#define HISTORY_ITEMS 256 +history_type_t HistoryTracking; typedef struct { bool shown:1; @@ -39,16 +39,17 @@ typedef struct { } hist_item_t; static struct { - unsigned idx; /* index to current history item */ - unsigned count; /* how many items of history are collected */ - hist_item_t item[HISTORY_ITEMS]; /* ring-buffer */ + unsigned idx; /* index to current history item */ + unsigned count; /* how many items of history are collected */ + unsigned limit; /* ring-buffer size */ + hist_item_t *item; /* ring-buffer */ } History; /** * Convert debugger entry/breakpoint entry reason to a string */ -const char* History_ReasonStr(debug_reason_t reason) +static const char* History_ReasonStr(debug_reason_t reason) { switch(reason) { case REASON_CPU_EXCEPTION: @@ -70,16 +71,40 @@ const char* History_ReasonStr(debug_reas /** - * Enable/disable history collecting. - * Clear history on disabling as data wouldn't - * then be anymore valid. + * Set what kind of history is collected. + * Clear history if tracking type changes as rest of + * data wouldn't then be anymore valid. */ -void History_Enable(bool enable) +static void History_Enable(history_type_t track, unsigned limit) { - if (!enable) { + const char *msg; + if (track != HistoryTracking || limit != History.limit) { + fprintf(stderr, "Re-allocating & zeroing history due to type/limit change.\n"); + if (History.item) { + free(History.item); + } memset(&History, 0, sizeof(History)); + History.item = calloc(limit, sizeof(History.item[0])); + History.limit = limit; + } + switch (track) { + case HISTORY_TRACK_NONE: + msg = "disabled"; + break; + case HISTORY_TRACK_CPU: + msg = "enabled for CPU"; + break; + case HISTORY_TRACK_DSP: + msg = "enabled for DSP"; + break; + case HISTORY_TRACK_ALL: + msg = "enabled for CPU & DSP"; + break; + default: + msg = "error"; } - bHistoryEnabled = enable; + HistoryTracking = track; + fprintf(stderr, "History tracking %s (max. %d instructions).\n", msg, limit); } /** @@ -88,7 +113,7 @@ void History_Enable(bool enable) static void History_Advance(void) { History.idx++; - History.idx %= HISTORY_ITEMS; + History.idx %= History.limit; History.item[History.idx].valid = true; History.item[History.idx].shown = false; History.item[History.idx].reason = REASON_NONE; @@ -124,7 +149,9 @@ void History_AddDsp(void) */ void History_Mark(debug_reason_t reason) { - History.item[History.idx].reason = reason; + if (History.item) { + History.item[History.idx].reason = reason; + } } /** @@ -135,8 +162,8 @@ void History_Show(Uint32 count) bool show_all; int i; - if (History.count > HISTORY_ITEMS) { - History.count = HISTORY_ITEMS; + if (History.count > History.limit) { + History.count = History.limit; } if (count > History.count) { count = History.count; @@ -157,11 +184,11 @@ void History_Show(Uint32 count) /* even last item already shown, show all again */ show_all = true; } - i = (i + HISTORY_ITEMS - count) % HISTORY_ITEMS; + i = (i + History.limit - count) % History.limit; while (count-- > 0) { i++; - i %= HISTORY_ITEMS; + i %= History.limit; if (!History.item[i].valid) { fprintf(stderr, "ERROR: invalid history item %d!", count); } @@ -172,10 +199,10 @@ void History_Show(Uint32 count) if (History.item[i].for_dsp) { Uint16 pc = History.item[i].pc.dsp; - DSP_DisasmAddress(pc, pc); + DSP_DisasmAddress(stderr, pc, pc); } else { Uint32 dummy; - Disasm(stderr, History.item[i].pc.cpu, &dummy, 1, DISASM_ENGINE_EXT); + Disasm(stderr, History.item[i].pc.cpu, &dummy, 1); } if (History.item[i].reason != REASON_NONE) { fprintf(stderr, "Debugger: *%s*\n", History_ReasonStr(History.item[i].reason)); @@ -183,32 +210,57 @@ void History_Show(Uint32 count) } } +/* + * Readline callback + */ +char *History_Match(const char *text, int state) +{ + static const char* cmds[] = { "cpu", "dsp", "off" }; + return DebugUI_MatchHelper(cmds, ARRAYSIZE(cmds), text, state); +} + /** * Command: Show collected CPU/DSP debugger/breakpoint history */ int History_Parse(int nArgc, char *psArgs[]) { - int count; + int count, limit = 0; - if (nArgc != 2) { - DebugUI_PrintCmdHelp(psArgs[0]); - return DEBUGGER_CMDDONE; + if (nArgc < 2) { + return DebugUI_PrintCmdHelp(psArgs[0]); + } + if (nArgc > 2) { + limit = atoi(psArgs[2]); + } + /* make sure value is valid & positive */ + if (!limit) { + limit = History.limit; + } + if (limit < HISTORY_ITEMS_MIN) { + limit = HISTORY_ITEMS_MIN; } - count = atoi(psArgs[1]); - if (count <= 0 || count > HISTORY_ITEMS) { + + if (count <= 0) { /* no count -> enable or disable? */ if (strcmp(psArgs[1], "on") == 0) { - History_Enable(true); + History_Enable(HISTORY_TRACK_ALL, limit); return DEBUGGER_CMDDONE; } if (strcmp(psArgs[1], "off") == 0) { - History_Enable(false); + History_Enable(HISTORY_TRACK_NONE, limit); + return DEBUGGER_CMDDONE; + } + if (strcmp(psArgs[1], "cpu") == 0) { + History_Enable(HISTORY_TRACK_CPU, limit); + return DEBUGGER_CMDDONE; + } + if (strcmp(psArgs[1], "dsp") == 0) { + History_Enable(HISTORY_TRACK_DSP, limit); return DEBUGGER_CMDDONE; } - fprintf(stderr, "History range is 1-%d!\n", HISTORY_ITEMS); - DebugUI_PrintCmdHelp(psArgs[0]); - return DEBUGGER_CMDDONE; + fprintf(stderr, "History range is 1-\n"); + return DebugUI_PrintCmdHelp(psArgs[0]); } History_Show(count);