src/lr35902/debugger/debugger.c (view raw)
1/* Copyright (c) 2013-2016 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/debugger.h>
7
8#include <mgba/core/core.h>
9#include <mgba/internal/lr35902/lr35902.h>
10
11DEFINE_VECTOR(LR35902DebugBreakpointList, struct LR35902DebugBreakpoint);
12DEFINE_VECTOR(LR35902DebugWatchpointList, struct LR35902DebugWatchpoint);
13
14static struct LR35902DebugBreakpoint* _lookupBreakpoint(struct LR35902DebugBreakpointList* breakpoints, uint16_t address) {
15 size_t i;
16 for (i = 0; i < LR35902DebugBreakpointListSize(breakpoints); ++i) {
17 if (LR35902DebugBreakpointListGetPointer(breakpoints, i)->address == address) {
18 return LR35902DebugBreakpointListGetPointer(breakpoints, i);
19 }
20 }
21 return 0;
22}
23
24static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
25 struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
26 struct LR35902DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->breakpoints, debugger->cpu->pc);
27 if (!breakpoint) {
28 return;
29 }
30 if (breakpoint->segment >= 0 && debugger->cpu->memory.currentSegment(debugger->cpu, breakpoint->address) != breakpoint->segment) {
31 return;
32 }
33 struct mDebuggerEntryInfo info = {
34 .address = breakpoint->address
35 };
36 mDebuggerEnter(d->p, DEBUGGER_ENTER_BREAKPOINT, &info);
37}
38
39static void LR35902DebuggerInit(void* cpu, struct mDebuggerPlatform* platform);
40static void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform);
41
42static void LR35902DebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info);
43
44static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment);
45static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment);
46static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform*);
47static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform*);
48
49struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void) {
50 struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct LR35902Debugger));
51 platform->entered = LR35902DebuggerEnter;
52 platform->init = LR35902DebuggerInit;
53 platform->deinit = LR35902DebuggerDeinit;
54 platform->setBreakpoint = LR35902DebuggerSetBreakpoint;
55 platform->clearBreakpoint = LR35902DebuggerClearBreakpoint;
56 platform->setWatchpoint = NULL;
57 platform->clearWatchpoint = NULL;
58 platform->checkBreakpoints = LR35902DebuggerCheckBreakpoints;
59 platform->hasBreakpoints = LR35902DebuggerHasBreakpoints;
60 return platform;
61}
62
63void LR35902DebuggerInit(void* cpu, struct mDebuggerPlatform* platform) {
64 struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
65 debugger->cpu = cpu;
66 LR35902DebugBreakpointListInit(&debugger->breakpoints, 0);
67 LR35902DebugWatchpointListInit(&debugger->watchpoints, 0);
68}
69
70void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform) {
71 struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
72 LR35902DebugBreakpointListDeinit(&debugger->breakpoints);
73 LR35902DebugWatchpointListDeinit(&debugger->watchpoints);
74}
75
76static void LR35902DebuggerEnter(struct mDebuggerPlatform* platform, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
77 UNUSED(reason);
78 UNUSED(info);
79 struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
80 struct LR35902Core* cpu = debugger->cpu;
81 cpu->nextEvent = cpu->cycles;
82}
83
84static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) {
85 struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
86 struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListAppend(&debugger->breakpoints);
87 breakpoint->address = address;
88 breakpoint->segment = segment;
89}
90
91static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) {
92 struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
93 struct LR35902DebugBreakpointList* breakpoints = &debugger->breakpoints;
94 size_t i;
95 for (i = 0; i < LR35902DebugBreakpointListSize(breakpoints); ++i) {
96 struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListGetPointer(breakpoints, i);
97 if (breakpoint->address == address && breakpoint->segment == segment) {
98 LR35902DebugBreakpointListShift(breakpoints, i, 1);
99 }
100 }
101}
102
103static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform* d) {
104 struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
105 return LR35902DebugBreakpointListSize(&debugger->breakpoints) || LR35902DebugWatchpointListSize(&debugger->watchpoints);
106}