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