all repos — mgba @ f2134880898dd3ceaba7945c992c8ff34e245682

mGBA Game Boy Advance Emulator

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

 1/* Copyright (c) 2013-2017 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 <mgba/internal/lr35902/debugger/memory-debugger.h>
 7
 8#include <mgba/internal/debugger/parser.h>
 9#include <mgba/internal/lr35902/debugger/debugger.h>
10
11#include <mgba-util/math.h>
12
13#include <string.h>
14
15static bool _checkWatchpoints(struct LR35902Debugger* debugger, uint16_t address, struct mDebuggerEntryInfo* info, enum mWatchpointType type, uint8_t newValue);
16
17#define FIND_DEBUGGER(DEBUGGER, CPU) \
18	do { \
19		DEBUGGER = 0; \
20		size_t i; \
21		for (i = 0; i < CPU->numComponents; ++i) { \
22			if (CPU->components[i]->id == DEBUGGER_ID) { \
23				DEBUGGER = (struct LR35902Debugger*) ((struct mDebugger*) cpu->components[i])->platform; \
24				goto debuggerFound; \
25			} \
26		} \
27		abort(); \
28		debuggerFound: break; \
29	} while(0)
30
31#define CREATE_WATCHPOINT_SHIM(NAME, RW, VALUE, RETURN, TYPES, ...) \
32	static RETURN DebuggerShim_ ## NAME TYPES { \
33		struct LR35902Debugger* debugger; \
34		FIND_DEBUGGER(debugger, cpu); \
35		struct mDebuggerEntryInfo info; \
36		if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_ ## RW, VALUE)) { \
37			mDebuggerEnter(debugger->d.p, DEBUGGER_ENTER_WATCHPOINT, &info); \
38		} \
39		return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \
40	}
41
42CREATE_WATCHPOINT_SHIM(load8, READ, 0, uint8_t, (struct LR35902Core* cpu, uint16_t address), address)
43CREATE_WATCHPOINT_SHIM(store8, WRITE, value, void, (struct LR35902Core* cpu, uint16_t address, int8_t value), address, value)
44
45static bool _checkWatchpoints(struct LR35902Debugger* debugger, uint16_t address, struct mDebuggerEntryInfo* info, enum mWatchpointType type, uint8_t newValue) {
46	struct mWatchpoint* watchpoint;
47	size_t i;
48	for (i = 0; i < mWatchpointListSize(&debugger->watchpoints); ++i) {
49		watchpoint = mWatchpointListGetPointer(&debugger->watchpoints, i);
50		if (watchpoint->address == address && (watchpoint->segment < 0 || watchpoint->segment == debugger->originalMemory.currentSegment(debugger->cpu, address)) && watchpoint->type & type) {
51			if (watchpoint->condition) {
52				int32_t value;
53				int segment;
54				if (!mDebuggerEvaluateParseTree(debugger->d.p, watchpoint->condition, &value, &segment) || !(value || segment >= 0)) {
55					return false;
56				}
57			}
58			info->type.wp.oldValue = debugger->originalMemory.load8(debugger->cpu, address);
59			info->type.wp.newValue = newValue;
60			info->address = address;
61			info->type.wp.watchType = watchpoint->type;
62			info->type.wp.accessType = type;
63			return true;
64		}
65	}
66	return false;
67}
68
69void LR35902DebuggerInstallMemoryShim(struct LR35902Debugger* debugger) {
70	debugger->originalMemory = debugger->cpu->memory;
71	debugger->cpu->memory.store8 = DebuggerShim_store8;
72	debugger->cpu->memory.load8 = DebuggerShim_load8;
73}
74
75void LR35902DebuggerRemoveMemoryShim(struct LR35902Debugger* debugger) {
76	debugger->cpu->memory.store8 = debugger->originalMemory.store8;
77	debugger->cpu->memory.load8 = debugger->originalMemory.load8;
78}