all repos — mgba @ f25821524d79469e3589ab23340d7e6b4ae6a27f

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			ARMDebuggerEnter(debugger, DEBUGGER_ENTER_BREAKPOINT);
 26			break;
 27		}
 28	}
 29}
 30
 31static void ARMDebuggerInit(struct ARMCore*, struct ARMComponent*);
 32static void ARMDebuggerDeinit(struct ARMComponent*);
 33
 34void ARMDebuggerCreate(struct ARMDebugger* debugger) {
 35	debugger->d.id = ARM_DEBUGGER_ID;
 36	debugger->d.init = ARMDebuggerInit;
 37	debugger->d.deinit = ARMDebuggerDeinit;
 38}
 39
 40void ARMDebuggerInit(struct ARMCore* cpu, struct ARMComponent* component) {
 41	struct ARMDebugger* debugger = (struct ARMDebugger*) component;
 42	debugger->cpu = cpu;
 43	debugger->state = DEBUGGER_RUNNING;
 44	debugger->breakpoints = 0;
 45	debugger->originalMemory = cpu->memory;
 46	debugger->watchpoints = 0;
 47	if (debugger->init) {
 48		debugger->init(debugger);
 49	}
 50}
 51
 52void ARMDebuggerDeinit(struct ARMComponent* component) {
 53	struct ARMDebugger* debugger = (struct ARMDebugger*) component;
 54	debugger->deinit(debugger);
 55}
 56
 57void ARMDebuggerRun(struct ARMDebugger* debugger) {
 58	if (debugger->state == DEBUGGER_EXITING) {
 59		debugger->state = DEBUGGER_RUNNING;
 60	}
 61	while (debugger->state < DEBUGGER_EXITING) {
 62		if (!debugger->breakpoints && !debugger->watchpoints) {
 63			while (debugger->state == DEBUGGER_RUNNING) {
 64				ARMRunLoop(debugger->cpu);
 65			}
 66		} else if (!debugger->breakpoints) {
 67			while (debugger->state == DEBUGGER_RUNNING) {
 68				ARMRun(debugger->cpu);
 69			}
 70		} else {
 71			while (debugger->state == DEBUGGER_RUNNING) {
 72				ARMRun(debugger->cpu);
 73				_checkBreakpoints(debugger);
 74			}
 75		}
 76		switch (debugger->state) {
 77		case DEBUGGER_RUNNING:
 78			break;
 79		case DEBUGGER_CUSTOM:
 80			while (debugger->state == DEBUGGER_CUSTOM) {
 81				ARMRun(debugger->cpu);
 82				_checkBreakpoints(debugger);
 83				debugger->custom(debugger);
 84			}
 85			break;
 86		case DEBUGGER_PAUSED:
 87			if (debugger->paused) {
 88				debugger->paused(debugger);
 89			} else {
 90				debugger->state = DEBUGGER_RUNNING;
 91			}
 92			break;
 93		case DEBUGGER_EXITING:
 94		case DEBUGGER_SHUTDOWN:
 95			return;
 96		}
 97	}
 98}
 99
100void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason reason) {
101	debugger->state = DEBUGGER_PAUSED;
102	if (debugger->entered) {
103		debugger->entered(debugger, reason);
104	}
105}
106
107void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
108	struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint));
109	breakpoint->address = address;
110	breakpoint->next = debugger->breakpoints;
111	debugger->breakpoints = breakpoint;
112}
113
114void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
115	struct DebugBreakpoint** previous = &debugger->breakpoints;
116	struct DebugBreakpoint* breakpoint;
117	for (; (breakpoint = *previous); previous = &breakpoint->next) {
118		if (breakpoint->address == address) {
119			*previous = breakpoint->next;
120			free(breakpoint);
121		}
122	}
123}
124
125void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
126	if (!debugger->watchpoints) {
127		ARMDebuggerInstallMemoryShim(debugger);
128	}
129	struct DebugBreakpoint* watchpoint = malloc(sizeof(struct DebugBreakpoint));
130	watchpoint->address = address;
131	watchpoint->next = debugger->watchpoints;
132	debugger->watchpoints = watchpoint;
133}
134
135void ARMDebuggerClearWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
136	struct DebugBreakpoint** previous = &debugger->watchpoints;
137	struct DebugBreakpoint* breakpoint;
138	for (; (breakpoint = *previous); previous = &breakpoint->next) {
139		if (breakpoint->address == address) {
140			*previous = breakpoint->next;
141			free(breakpoint);
142		}
143	}
144	if (!debugger->watchpoints) {
145		ARMDebuggerRemoveMemoryShim(debugger);
146	}
147}