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