all repos — mgba @ 768316a8d39665065507a29ccb2ea06ac4a26823

mGBA Game Boy Advance Emulator

src/debugger/memory-debugger.c (view raw)

 1#include "memory-debugger.h"
 2
 3#include "debugger.h"
 4
 5#include <string.h>
 6
 7static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width);
 8
 9#define FIND_DEBUGGER(DEBUGGER, CPU) \
10	{ \
11		DEBUGGER = 0; \
12		int i; \
13		for (i = 0; i < CPU->numComponents; ++i) { \
14			if (CPU->components[i]->id == ARM_DEBUGGER_ID) { \
15				DEBUGGER = (struct ARMDebugger*) cpu->components[i]; \
16				break; \
17			} \
18		} \
19	}
20
21#define CREATE_SHIM(NAME, RETURN, TYPES, ARGS...) \
22	static RETURN ARMDebuggerShim_ ## NAME TYPES { \
23		struct ARMDebugger* debugger; \
24		FIND_DEBUGGER(debugger, cpu); \
25		return debugger->originalMemory.NAME(cpu, ARGS); \
26	}
27
28#define CREATE_WATCHPOINT_SHIM(NAME, WIDTH, RETURN, TYPES, ARGS...) \
29	static RETURN ARMDebuggerShim_ ## NAME TYPES { \
30		struct ARMDebugger* debugger; \
31		FIND_DEBUGGER(debugger, cpu); \
32		if (_checkWatchpoints(debugger->watchpoints, address, WIDTH)) { \
33			ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT); \
34		} \
35		return debugger->originalMemory.NAME(cpu, ARGS); \
36	}
37
38CREATE_WATCHPOINT_SHIM(load32, 4, int32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
39CREATE_WATCHPOINT_SHIM(load16, 2, int16_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
40CREATE_WATCHPOINT_SHIM(loadU16, 2, uint16_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
41CREATE_WATCHPOINT_SHIM(load8, 1, int8_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
42CREATE_WATCHPOINT_SHIM(loadU8, 1, uint8_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
43CREATE_WATCHPOINT_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), address, value, cycleCounter)
44CREATE_WATCHPOINT_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), address, value, cycleCounter)
45CREATE_WATCHPOINT_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), address, value, cycleCounter)
46CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address)
47
48static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width) {
49	width -= 1;
50	for (; watchpoints; watchpoints = watchpoints->next) {
51		if (!((watchpoints->address ^ address) & ~width)) {
52			return true;
53		}
54	}
55	return false;
56}
57
58void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger) {
59	debugger->originalMemory = debugger->cpu->memory;
60	debugger->cpu->memory.store32 = ARMDebuggerShim_store32;
61	debugger->cpu->memory.store16 = ARMDebuggerShim_store16;
62	debugger->cpu->memory.store8 = ARMDebuggerShim_store8;
63	debugger->cpu->memory.load32 = ARMDebuggerShim_load32;
64	debugger->cpu->memory.load16 = ARMDebuggerShim_load16;
65	debugger->cpu->memory.loadU16 = ARMDebuggerShim_loadU16;
66	debugger->cpu->memory.load8 = ARMDebuggerShim_load8;
67	debugger->cpu->memory.loadU8 = ARMDebuggerShim_loadU8;
68	debugger->cpu->memory.setActiveRegion = ARMDebuggerShim_setActiveRegion;
69}
70
71void ARMDebuggerRemoveMemoryShim(struct ARMDebugger* debugger) {
72	debugger->cpu->memory.store32 = debugger->originalMemory.store32;
73	debugger->cpu->memory.store16 = debugger->originalMemory.store16;
74	debugger->cpu->memory.store8 = debugger->originalMemory.store8;
75	debugger->cpu->memory.load32 = debugger->originalMemory.load32;
76	debugger->cpu->memory.load16 = debugger->originalMemory.load16;
77	debugger->cpu->memory.loadU16 = debugger->originalMemory.loadU16;
78	debugger->cpu->memory.load8 = debugger->originalMemory.load8;
79	debugger->cpu->memory.loadU8 = debugger->originalMemory.loadU8;
80	debugger->cpu->memory.setActiveRegion = debugger->originalMemory.setActiveRegion;
81}