|
|
1.1 ! root 1: /* ! 2: * Hatari - history.c ! 3: * ! 4: * Copyright (C) 2011 by Eero Tamminen ! 5: * ! 6: * This file is distributed under the GNU Public License, version 2 or at ! 7: * your option any later version. Read the file gpl.txt for details. ! 8: * ! 9: * history.c - functions for debugger entry & breakpoint history ! 10: */ ! 11: const char History_fileid[] = "Hatari history.c : " __DATE__ " " __TIME__; ! 12: ! 13: #include <assert.h> ! 14: ! 15: #include "main.h" ! 16: #include "debugui.h" ! 17: #include "debug_priv.h" ! 18: #include "dsp.h" ! 19: #include "dsp_core.h" ! 20: #include "evaluate.h" ! 21: #include "history.h" ! 22: #include "m68000.h" ! 23: #include "68kDisass.h" ! 24: ! 25: bool bHistoryEnabled; ! 26: ! 27: #define HISTORY_ITEMS 256 ! 28: ! 29: typedef struct { ! 30: bool shown:1; ! 31: bool valid:1; ! 32: bool for_dsp:1; ! 33: /* reason for debugger entry/breakpoint hit */ ! 34: debug_reason_t reason:8; ! 35: union { ! 36: Uint16 dsp; ! 37: Uint32 cpu; ! 38: } pc; ! 39: } hist_item_t; ! 40: ! 41: static struct { ! 42: unsigned idx; /* index to current history item */ ! 43: unsigned count; /* how many items of history are collected */ ! 44: hist_item_t item[HISTORY_ITEMS]; /* ring-buffer */ ! 45: } History; ! 46: ! 47: ! 48: /** ! 49: * Convert debugger entry/breakpoint entry reason to a string ! 50: */ ! 51: const char* History_ReasonStr(debug_reason_t reason) ! 52: { ! 53: switch(reason) { ! 54: case REASON_CPU_EXCEPTION: ! 55: return "CPU exception"; ! 56: case REASON_CPU_BREAKPOINT: ! 57: return "CPU breakpoint"; ! 58: case REASON_DSP_BREAKPOINT: ! 59: return "DSP breakpoint"; ! 60: case REASON_CPU_STEPS: ! 61: return "CPU steps"; ! 62: case REASON_DSP_STEPS: ! 63: return "DSP steps"; ! 64: case REASON_USER: ! 65: return "User break"; ! 66: default: ! 67: return "Unknown reason"; ! 68: } ! 69: } ! 70: ! 71: ! 72: /** ! 73: * Enable/disable history collecting. ! 74: * Clear history on disabling as data wouldn't ! 75: * then be anymore valid. ! 76: */ ! 77: void History_Enable(bool enable) ! 78: { ! 79: if (!enable) { ! 80: memset(&History, 0, sizeof(History)); ! 81: } ! 82: bHistoryEnabled = enable; ! 83: } ! 84: ! 85: /** ! 86: * Advance & initialize next history item in ring buffer ! 87: */ ! 88: static void History_Advance(void) ! 89: { ! 90: History.idx++; ! 91: History.idx %= HISTORY_ITEMS; ! 92: History.item[History.idx].valid = true; ! 93: History.item[History.idx].shown = false; ! 94: History.item[History.idx].reason = REASON_NONE; ! 95: History.count++; ! 96: } ! 97: ! 98: /** ! 99: * Add CPU PC to history ! 100: */ ! 101: void History_AddCpu(void) ! 102: { ! 103: Uint32 pc = M68000_GetPC(); ! 104: ! 105: History_Advance(); ! 106: History.item[History.idx].for_dsp = false; ! 107: History.item[History.idx].pc.cpu = pc; ! 108: } ! 109: ! 110: /** ! 111: * Add DSP PC to history ! 112: */ ! 113: void History_AddDsp(void) ! 114: { ! 115: Uint16 pc = DSP_GetPC(); ! 116: ! 117: History_Advance(); ! 118: History.item[History.idx].for_dsp = true; ! 119: History.item[History.idx].pc.dsp = pc; ! 120: } ! 121: ! 122: /** ! 123: * Flag last history entry as debugger entry point, with given reason ! 124: */ ! 125: void History_Mark(debug_reason_t reason) ! 126: { ! 127: History.item[History.idx].reason = reason; ! 128: } ! 129: ! 130: /** ! 131: * Show collected CPU/DSP debugger/breakpoint history ! 132: */ ! 133: void History_Show(Uint32 count) ! 134: { ! 135: bool show_all; ! 136: int i; ! 137: ! 138: if (History.count > HISTORY_ITEMS) { ! 139: History.count = HISTORY_ITEMS; ! 140: } ! 141: if (count > History.count) { ! 142: count = History.count; ! 143: } else { ! 144: if (!count) { ! 145: /* default to all */ ! 146: count = History.count; ! 147: } ! 148: } ! 149: if (count <= 0) { ! 150: fprintf(stderr, "No history items to show.\n"); ! 151: return; ! 152: } ! 153: ! 154: i = History.idx; ! 155: show_all = false; ! 156: if (History.item[i].shown) { ! 157: /* even last item already shown, show all again */ ! 158: show_all = true; ! 159: } ! 160: i = (i + HISTORY_ITEMS - count) % HISTORY_ITEMS; ! 161: ! 162: while (count-- > 0) { ! 163: i++; ! 164: i %= HISTORY_ITEMS; ! 165: if (!History.item[i].valid) { ! 166: fprintf(stderr, "ERROR: invalid history item %d!", count); ! 167: } ! 168: if (History.item[i].shown && !show_all) { ! 169: continue; ! 170: } ! 171: History.item[i].shown = true; ! 172: ! 173: if (History.item[i].for_dsp) { ! 174: Uint16 pc = History.item[i].pc.dsp; ! 175: DSP_DisasmAddress(pc, pc); ! 176: } else { ! 177: Uint32 dummy; ! 178: Disasm(stderr, History.item[i].pc.cpu, &dummy, 1, DISASM_ENGINE_EXT); ! 179: } ! 180: if (History.item[i].reason != REASON_NONE) { ! 181: fprintf(stderr, "Debugger: *%s*\n", History_ReasonStr(History.item[i].reason)); ! 182: } ! 183: } ! 184: } ! 185: ! 186: /** ! 187: * Command: Show collected CPU/DSP debugger/breakpoint history ! 188: */ ! 189: int History_Parse(int nArgc, char *psArgs[]) ! 190: { ! 191: int count; ! 192: ! 193: if (nArgc != 2) { ! 194: DebugUI_PrintCmdHelp(psArgs[0]); ! 195: return DEBUGGER_CMDDONE; ! 196: } ! 197: ! 198: count = atoi(psArgs[1]); ! 199: if (count <= 0 || count > HISTORY_ITEMS) { ! 200: /* no count -> enable or disable? */ ! 201: if (strcmp(psArgs[1], "on") == 0) { ! 202: History_Enable(true); ! 203: return DEBUGGER_CMDDONE; ! 204: } ! 205: if (strcmp(psArgs[1], "off") == 0) { ! 206: History_Enable(false); ! 207: return DEBUGGER_CMDDONE; ! 208: } ! 209: fprintf(stderr, "History range is 1-%d!\n", HISTORY_ITEMS); ! 210: DebugUI_PrintCmdHelp(psArgs[0]); ! 211: return DEBUGGER_CMDDONE; ! 212: } ! 213: ! 214: History_Show(count); ! 215: return DEBUGGER_CMDDONE; ! 216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.