all repos — mgba @ 727fcb94aa79e287f1518eec498e9701b19ca44a

mGBA Game Boy Advance Emulator

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#include <mgba/internal/lr35902/debugger/memory-debugger.h>
 11
 12DEFINE_VECTOR(LR35902DebugBreakpointList, struct LR35902DebugBreakpoint);
 13DEFINE_VECTOR(LR35902DebugWatchpointList, struct LR35902DebugWatchpoint);
 14
 15static struct LR35902DebugBreakpoint* _lookupBreakpoint(struct LR35902DebugBreakpointList* breakpoints, uint16_t address) {
 16	size_t i;
 17	for (i = 0; i < LR35902DebugBreakpointListSize(breakpoints); ++i) {
 18		if (LR35902DebugBreakpointListGetPointer(breakpoints, i)->address == address) {
 19			return LR35902DebugBreakpointListGetPointer(breakpoints, i);
 20		}
 21	}
 22	return 0;
 23}
 24
 25static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
 26	struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
 27	struct LR35902DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->breakpoints, debugger->cpu->pc);
 28	if (!breakpoint) {
 29		return;
 30	}
 31	if (breakpoint->segment >= 0 && debugger->cpu->memory.currentSegment(debugger->cpu, breakpoint->address) != breakpoint->segment) {
 32		return;
 33	}
 34	struct mDebuggerEntryInfo info = {
 35		.address = breakpoint->address
 36	};
 37	mDebuggerEnter(d->p, DEBUGGER_ENTER_BREAKPOINT, &info);
 38}
 39
 40static void LR35902DebuggerInit(void* cpu, struct mDebuggerPlatform* platform);
 41static void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform);
 42
 43static void LR35902DebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info);
 44
 45static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment);
 46static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment);
 47static void LR35902DebuggerSetWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment, enum mWatchpointType type);
 48static void LR35902DebuggerClearWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment);
 49static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform*);
 50static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform*);
 51
 52struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void) {
 53	struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct LR35902Debugger));
 54	platform->entered = LR35902DebuggerEnter;
 55	platform->init = LR35902DebuggerInit;
 56	platform->deinit = LR35902DebuggerDeinit;
 57	platform->setBreakpoint = LR35902DebuggerSetBreakpoint;
 58	platform->clearBreakpoint = LR35902DebuggerClearBreakpoint;
 59	platform->setWatchpoint = LR35902DebuggerSetWatchpoint;
 60	platform->clearWatchpoint = LR35902DebuggerClearWatchpoint;
 61	platform->checkBreakpoints = LR35902DebuggerCheckBreakpoints;
 62	platform->hasBreakpoints = LR35902DebuggerHasBreakpoints;
 63	return platform;
 64}
 65
 66void LR35902DebuggerInit(void* cpu, struct mDebuggerPlatform* platform) {
 67	struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
 68	debugger->cpu = cpu;
 69	LR35902DebugBreakpointListInit(&debugger->breakpoints, 0);
 70	LR35902DebugWatchpointListInit(&debugger->watchpoints, 0);
 71}
 72
 73void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform) {
 74	struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
 75	LR35902DebugBreakpointListDeinit(&debugger->breakpoints);
 76	LR35902DebugWatchpointListDeinit(&debugger->watchpoints);
 77}
 78
 79static void LR35902DebuggerEnter(struct mDebuggerPlatform* platform, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
 80	UNUSED(reason);
 81	UNUSED(info);
 82	struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
 83	struct LR35902Core* cpu = debugger->cpu;
 84	cpu->nextEvent = cpu->cycles;
 85
 86	if (debugger->d.p->entered) {
 87		debugger->d.p->entered(debugger->d.p, reason, info);
 88	}
 89}
 90
 91static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) {
 92	struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
 93	struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListAppend(&debugger->breakpoints);
 94	breakpoint->address = address;
 95	breakpoint->segment = segment;
 96}
 97
 98static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) {
 99	struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
100	struct LR35902DebugBreakpointList* breakpoints = &debugger->breakpoints;
101	size_t i;
102	for (i = 0; i < LR35902DebugBreakpointListSize(breakpoints); ++i) {
103		struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListGetPointer(breakpoints, i);
104		if (breakpoint->address == address && breakpoint->segment == segment) {
105			LR35902DebugBreakpointListShift(breakpoints, i, 1);
106		}
107	}
108}
109
110static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform* d) {
111	struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
112	return LR35902DebugBreakpointListSize(&debugger->breakpoints) || LR35902DebugWatchpointListSize(&debugger->watchpoints);
113}
114
115static void LR35902DebuggerSetWatchpoint(struct mDebuggerPlatform* d, uint32_t address, int segment, enum mWatchpointType type) {
116	struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
117	if (!LR35902DebugWatchpointListSize(&debugger->watchpoints)) {
118		LR35902DebuggerInstallMemoryShim(debugger);
119	}
120	struct LR35902DebugWatchpoint* watchpoint = LR35902DebugWatchpointListAppend(&debugger->watchpoints);
121	watchpoint->address = address;
122	watchpoint->type = type;
123	watchpoint->segment = segment;
124}
125
126static void LR35902DebuggerClearWatchpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) {
127	struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
128	struct LR35902DebugWatchpointList* watchpoints = &debugger->watchpoints;
129	size_t i;
130	for (i = 0; i < LR35902DebugWatchpointListSize(watchpoints); ++i) {
131		struct LR35902DebugWatchpoint* watchpoint = LR35902DebugWatchpointListGetPointer(watchpoints, i);
132		if (watchpoint->address == address && watchpoint->segment == segment) {
133			LR35902DebugWatchpointListShift(watchpoints, i, 1);
134		}
135	}
136	if (!LR35902DebugWatchpointListSize(&debugger->watchpoints)) {
137		LR35902DebuggerRemoveMemoryShim(debugger);
138	}
139}