all repos — mgba @ 6d18b9aea53e8d510d24fc8412ca8dc00b2e738c

mGBA Game Boy Advance Emulator

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

 1/* Copyright (c) 2013-2014 Jeffrey Pfau
 2 *
 3 * This Source Code Form is subject to the terms of the Mozilla Public
 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 6#include "memory-debugger.h"
 7
 8#include "debugger.h"
 9
10#include <string.h>
11
12static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width);
13
14#define FIND_DEBUGGER(DEBUGGER, CPU) \
15	{ \
16		DEBUGGER = 0; \
17		int i; \
18		for (i = 0; i < CPU->numComponents; ++i) { \
19			if (CPU->components[i]->id == ARM_DEBUGGER_ID) { \
20				DEBUGGER = (struct ARMDebugger*) cpu->components[i]; \
21				break; \
22			} \
23		} \
24	}
25
26#define CREATE_SHIM(NAME, RETURN, TYPES, ARGS...) \
27	static RETURN ARMDebuggerShim_ ## NAME TYPES { \
28		struct ARMDebugger* debugger; \
29		FIND_DEBUGGER(debugger, cpu); \
30		return debugger->originalMemory.NAME(cpu, ARGS); \
31	}
32
33#define CREATE_WATCHPOINT_SHIM(NAME, WIDTH, RETURN, TYPES, ARGS...) \
34	static RETURN ARMDebuggerShim_ ## NAME TYPES { \
35		struct ARMDebugger* debugger; \
36		FIND_DEBUGGER(debugger, cpu); \
37		if (_checkWatchpoints(debugger->watchpoints, address, WIDTH)) { \
38			ARMDebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT); \
39		} \
40		return debugger->originalMemory.NAME(cpu, ARGS); \
41	}
42
43CREATE_WATCHPOINT_SHIM(load32, 4, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
44CREATE_WATCHPOINT_SHIM(load16, 2, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
45CREATE_WATCHPOINT_SHIM(load8, 1, uint32_t, (struct ARMCore* cpu, uint32_t address, int* cycleCounter), address, cycleCounter)
46CREATE_WATCHPOINT_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), address, value, cycleCounter)
47CREATE_WATCHPOINT_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), address, value, cycleCounter)
48CREATE_WATCHPOINT_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), address, value, cycleCounter)
49CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address)
50
51static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width) {
52	width -= 1;
53	for (; watchpoints; watchpoints = watchpoints->next) {
54		if (!((watchpoints->address ^ address) & ~width)) {
55			return true;
56		}
57	}
58	return false;
59}
60
61void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger) {
62	debugger->originalMemory = debugger->cpu->memory;
63	debugger->cpu->memory.store32 = ARMDebuggerShim_store32;
64	debugger->cpu->memory.store16 = ARMDebuggerShim_store16;
65	debugger->cpu->memory.store8 = ARMDebuggerShim_store8;
66	debugger->cpu->memory.load32 = ARMDebuggerShim_load32;
67	debugger->cpu->memory.load16 = ARMDebuggerShim_load16;
68	debugger->cpu->memory.load8 = ARMDebuggerShim_load8;
69	debugger->cpu->memory.setActiveRegion = ARMDebuggerShim_setActiveRegion;
70}
71
72void ARMDebuggerRemoveMemoryShim(struct ARMDebugger* debugger) {
73	debugger->cpu->memory.store32 = debugger->originalMemory.store32;
74	debugger->cpu->memory.store16 = debugger->originalMemory.store16;
75	debugger->cpu->memory.store8 = debugger->originalMemory.store8;
76	debugger->cpu->memory.load32 = debugger->originalMemory.load32;
77	debugger->cpu->memory.load16 = debugger->originalMemory.load16;
78	debugger->cpu->memory.load8 = debugger->originalMemory.load8;
79	debugger->cpu->memory.setActiveRegion = debugger->originalMemory.setActiveRegion;
80}