all repos — mgba @ 39a73ecb95659ef36ec40519acc16e403adc15a2

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
 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}