all repos — mgba @ 7a4ca414e5c7f5fc0c28739b1008f0096528aa70

mGBA Game Boy Advance Emulator

src/debugger/debugger.c (view raw)

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