[PATCH] Use history for determining suitable disassembly default address

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


If disassembly starts from program counter (PC), user lacks context on
how the code ended in current position.

Because trying to disassemble instructions from "random" address will
often output incorrect disassembly, this scans execution history for a
valid instruction address that's close enough to PC.

History addresses are valid until overwritten with differently aligned
instructions, which is extremely unlike to happen, so this should be
robust enough to be used always when history is enabled.
---
 doc/debugger.html     | 11 ++++++++--
 doc/release-notes.txt |  2 ++
 src/debug/debugcpu.c  |  3 ++-
 src/debug/debugdsp.c  |  3 ++-
 src/debug/history.c   | 50 +++++++++++++++++++++++++++++++++++++++++++
 src/debug/history.h   |  3 ++-
 6 files changed, 67 insertions(+), 5 deletions(-)

diff --git a/doc/debugger.html b/doc/debugger.html
index 74b4c5b5..a68c1071 100644
--- a/doc/debugger.html
+++ b/doc/debugger.html
@@ -330,6 +330,7 @@ Usage:  d [start address-[end address]]
 </pre>
 <pre>
 &gt; disasm pc
+(PC)
 $00aa6e : 2f08                                 move.l    a0,-(sp)
 $00aa70 : 0241 0fff                            andi.w    #$fff,d1
 $00aa74 : 207c 00fe 78c0                       movea.l   #$fe78c0,a0
@@ -341,8 +342,14 @@ $00aa7e : 4ed0                                 jmp       (a0)
 Both commands accept in addition to numeric addresses also register
 and symbol names, like in above example.  If you don't specify an
 address, the commands continue showing from an address that comes
-after the previously shown data.  "disasm" command default address
-will be reset to PC address every time you re-enter the debugger.
+after the previously shown data.
+</p>
+
+<p>
+"disasm" command default address will be reset to program counter (PC)
+address every time you re-enter the debugger.  If history is enabled
+and it includes addresses just before PC, disassembly will instead
+start from such an address to give more context.
 </p>
 
 <p>
diff --git a/doc/release-notes.txt b/doc/release-notes.txt
index 58880d04..e5315727 100644
--- a/doc/release-notes.txt
+++ b/doc/release-notes.txt
@@ -49,6 +49,8 @@ Emulator:
 - Debugger:
   - Repeat CPU & DSP "step" and "next" commands on Enter
   - Output PC location in CPU & DSP disassembly
+  - With history enabled, default disassembly address to
+    an address in history just before PC, instead of to PC
   - More readable "variables" command output
   - Add "info vme" command
   - Add "scc" and "vme" (VME/SCU reg access) tracing support
diff --git a/src/debug/debugcpu.c b/src/debug/debugcpu.c
index 590d237d..f6cce669 100644
--- a/src/debug/debugcpu.c
+++ b/src/debug/debugcpu.c
@@ -1075,6 +1075,7 @@ int DebugCpu_Init(const dbgcommand_t **table)
  */
 void DebugCpu_InitSession(void)
 {
-	disasm_addr = M68000_GetPC();
+#define MAX_CPU_DISASM_OFFSET 16
+	disasm_addr = History_DisasmAddr(M68000_GetPC(), MAX_CPU_DISASM_OFFSET, false);
 	Profile_CpuStop();
 }
diff --git a/src/debug/debugdsp.c b/src/debug/debugdsp.c
index a702410f..325b28c7 100644
--- a/src/debug/debugdsp.c
+++ b/src/debug/debugdsp.c
@@ -671,6 +671,7 @@ int DebugDsp_Init(const dbgcommand_t **table)
  */
 void DebugDsp_InitSession(void)
 {
-	dsp_disasm_addr = DSP_GetPC();
+#define MAX_DSP_DISASM_OFFSET 8
+	dsp_disasm_addr = (Uint16)History_DisasmAddr(DSP_GetPC(), MAX_DSP_DISASM_OFFSET, true);
 	Profile_DspStop();
 }
diff --git a/src/debug/history.c b/src/debug/history.c
index bc170dd8..b8cfdf49 100644
--- a/src/debug/history.c
+++ b/src/debug/history.c
@@ -13,6 +13,7 @@ const char History_fileid[] = "Hatari history.c";
 #include <assert.h>
 #include <errno.h>
 #include "main.h"
+#include "configuration.h"
 #include "debugui.h"
 #include "debug_priv.h"
 #include "dsp.h"
@@ -157,6 +158,55 @@ void History_Mark(debug_reason_t reason)
 	}
 }
 
+/**
+ * Find lowest address in history that is within range:
+ *   (pc-offset) - pc
+ * where 'offset' is the history disasm offset limit.
+ *
+ * If history has no such address, return given pc value.
+ */
+Uint32 History_DisasmAddr(Uint32 pc, Uint32 offset, bool for_dsp)
+{
+	unsigned int i, count;
+	Uint32 limit, first;
+	int track;
+
+	if (!offset) {
+		return pc;
+	}
+	track = for_dsp ? HISTORY_TRACK_DSP : HISTORY_TRACK_CPU;
+	if (!(track & HistoryTracking)) {
+		return pc;
+	}
+	count = History.count;
+	if (count > History.limit) {
+		count = History.limit;
+	}
+	if (count <= 0) {
+		return pc;
+	}
+	first = pc;
+	limit = pc - offset;
+	i = History.idx;
+	while (count-- > 0) {
+		i++;
+		i %= History.limit;
+		assert(History.item[i].valid);
+		if (History.item[i].for_dsp != for_dsp) {
+			continue;
+		}
+		if (for_dsp) {
+			pc = History.item[i].pc.dsp;
+		} else {
+			pc = History.item[i].pc.cpu;
+		}
+		if (pc >= limit && pc < first) {
+			first = pc;
+		}
+	}
+	return first;
+}
+
 /**
  * Output collected CPU/DSP debugger/breakpoint history
  */
diff --git a/src/debug/history.h b/src/debug/history.h
index e3da1477..93602768 100644
--- a/src/debug/history.h
+++ b/src/debug/history.h
@@ -13,7 +13,7 @@ typedef enum {
 	HISTORY_TRACK_NONE = 0,
 	HISTORY_TRACK_CPU = 1,
 	HISTORY_TRACK_DSP = 2,
-	HISTORY_TRACK_ALL = 3
+	HISTORY_TRACK_ALL = (HISTORY_TRACK_CPU|HISTORY_TRACK_DSP)
 } history_type_t;
 
 extern history_type_t HistoryTracking;
@@ -30,6 +30,7 @@ static inline bool History_TrackDsp(void)
 /* for debugcpu/dsp.c */
 extern void History_AddCpu(void);
 extern void History_AddDsp(void);
+extern Uint32 History_DisasmAddr(Uint32 pc, Uint32 offset, bool for_dsp);
 
 /* for debugInfo.c */
 extern void History_Show(FILE *fp, Uint32 count);
-- 
2.20.1


--------------380DF5505989BFFFA19B963D--



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/