all repos — mgba @ 96ac72fbf9ec3d74d9ee250d821916db70d6171e

mGBA Game Boy Advance Emulator

src/debugger/debugger.c (view raw)

  1/* Copyright (c) 2013-2014 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 "debugger.h"
  7
  8#include "arm.h"
  9
 10#include "memory-debugger.h"
 11
 12const uint32_t ARM_DEBUGGER_ID = 0xDEADBEEF;
 13
 14static void _checkBreakpoints(struct ARMDebugger* debugger) {
 15	struct DebugBreakpoint* breakpoint;
 16	int instructionLength;
 17	enum ExecutionMode mode = debugger->cpu->cpsr.t;
 18	if (mode == MODE_ARM) {
 19		instructionLength = WORD_SIZE_ARM;
 20	} else {
 21		instructionLength = WORD_SIZE_THUMB;
 22	}
 23	for (breakpoint = debugger->breakpoints; breakpoint; breakpoint = breakpoint->next) {
 24		if (breakpoint->address + instructionLength == (uint32_t) debugger->cpu->gprs[ARM_PC]) {
 25			struct DebuggerEntryInfo info = {
 26				.address = breakpoint->address
 27			};
 28			ARMDebuggerEnter(debugger, DEBUGGER_ENTER_BREAKPOINT, &info);
 29			break;
 30		}
 31	}
 32}
 33
 34static void ARMDebuggerInit(struct ARMCore*, struct ARMComponent*);
 35static void ARMDebuggerDeinit(struct ARMComponent*);
 36
 37void ARMDebuggerCreate(struct ARMDebugger* debugger) {
 38	debugger->d.id = ARM_DEBUGGER_ID;
 39	debugger->d.init = ARMDebuggerInit;
 40	debugger->d.deinit = ARMDebuggerDeinit;
 41}
 42
 43void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) {
 44	struct ARMDebugger* debugger = (struct ARMDebugger*) component;
 45	debugger->cpu = cpu;
 46	debugger->state = DEBUGGER_RUNNING;
 47	debugger->breakpoints = 0;
 48	debugger->originalMemory = cpu->memory;
 49	debugger->watchpoints = 0;
 50	if (debugger->init) {
 51		debugger->init(debugger);
 52	}
 53}
 54
 55void ARMDebuggerDeinit(struct ARMComponent* component) {
 56	struct ARMDebugger* debugger = (struct ARMDebugger*) component;
 57	debugger->deinit(debugger);
 58}
 59
 60void ARMDebuggerRun(struct ARMDebugger* debugger) {
 61	switch (debugger->state) {
 62	case DEBUGGER_RUNNING:
 63		if (!debugger->breakpoints && !debugger->watchpoints) {
 64			ARMRunLoop(debugger->cpu);
 65		} else {
 66			ARMRun(debugger->cpu);
 67			_checkBreakpoints(debugger);
 68		}
 69		break;
 70	case DEBUGGER_CUSTOM:
 71		ARMRun(debugger->cpu);
 72		_checkBreakpoints(debugger);
 73		debugger->custom(debugger);
 74		break;
 75	case DEBUGGER_PAUSED:
 76		if (debugger->paused) {
 77			debugger->paused(debugger);
 78		} else {
 79			debugger->state = DEBUGGER_RUNNING;
 80		}
 81		break;
 82	case DEBUGGER_SHUTDOWN:
 83		return;
 84	}
 85}
 86
 87void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) {
 88	debugger->state = DEBUGGER_PAUSED;
 89	if (debugger->entered) {
 90		debugger->entered(debugger, reason, info);
 91	}
 92}
 93
 94void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
 95	struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint));
 96	breakpoint->address = address;
 97	breakpoint->next = debugger->breakpoints;
 98	debugger->breakpoints = breakpoint;
 99}
100
101void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
102	struct DebugBreakpoint** previous = &debugger->breakpoints;
103	struct DebugBreakpoint* breakpoint;
104	for (; (breakpoint = *previous); previous = &breakpoint->next) {
105		if (breakpoint->address == address) {
106			*previous = breakpoint->next;
107			free(breakpoint);
108		}
109	}
110}
111
112void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
113	if (!debugger->watchpoints) {
114		ARMDebuggerInstallMemoryShim(debugger);
115	}
116	struct DebugWatchpoint* watchpoint = malloc(sizeof(struct DebugWatchpoint));
117	watchpoint->address = address;
118	watchpoint->next = debugger->watchpoints;
119	debugger->watchpoints = watchpoint;
120}
121
122void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
123	struct DebugWatchpoint** previous = &debugger->watchpoints;
124	struct DebugWatchpoint* breakpoint;
125	for (; (breakpoint = *previous); previous = &breakpoint->next) {
126		if (breakpoint->address == address) {
127			*previous = breakpoint->next;
128			free(breakpoint);
129		}
130	}
131	if (!debugger->watchpoints) {
132		ARMDebuggerRemoveMemoryShim(debugger);
133	}
134}