all repos — mgba @ 97e4e7a28c3953916c2f02cb6b50bc72914961ca

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
  7#include <stdlib.h>
  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
 26void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) {
 27	debugger->cpu = cpu;
 28	debugger->state = DEBUGGER_PAUSED;
 29	debugger->breakpoints = 0;
 30	debugger->memoryShim.original = cpu->memory;
 31	debugger->memoryShim.p = debugger;
 32	debugger->memoryShim.watchpoints = 0;
 33	if (debugger->init) {
 34		debugger->init(debugger);
 35	}
 36}
 37
 38void ARMDebuggerDeinit(struct ARMDebugger* debugger) {
 39	// TODO: actually call this
 40	debugger->deinit(debugger);
 41}
 42
 43void ARMDebuggerRun(struct ARMDebugger* debugger) {
 44	if (debugger->state == DEBUGGER_EXITING) {
 45		debugger->state = DEBUGGER_RUNNING;
 46	}
 47	while (debugger->state < DEBUGGER_EXITING) {
 48		if (!debugger->breakpoints) {
 49			while (debugger->state == DEBUGGER_RUNNING) {
 50				ARMRun(debugger->cpu);
 51			}
 52		} else {
 53			while (debugger->state == DEBUGGER_RUNNING) {
 54				ARMRun(debugger->cpu);
 55				_checkBreakpoints(debugger);
 56			}
 57		}
 58		switch (debugger->state) {
 59		case DEBUGGER_RUNNING:
 60			break;
 61		case DEBUGGER_PAUSED:
 62			if (debugger->paused) {
 63				debugger->paused(debugger);
 64			} else {
 65				debugger->state = DEBUGGER_RUNNING;
 66			}
 67			break;
 68		case DEBUGGER_EXITING:
 69		case DEBUGGER_SHUTDOWN:
 70			return;
 71		}
 72	}
 73}
 74
 75void ARMDebuggerEnter(struct ARMDebugger* debugger, enum DebuggerEntryReason reason) {
 76	debugger->state = DEBUGGER_PAUSED;
 77	if (debugger->entered) {
 78		debugger->entered(debugger, reason);
 79	}
 80}
 81
 82void ARMDebuggerSetBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
 83	struct DebugBreakpoint* breakpoint = malloc(sizeof(struct DebugBreakpoint));
 84	breakpoint->address = address;
 85	breakpoint->next = debugger->breakpoints;
 86	debugger->breakpoints = breakpoint;
 87}
 88
 89void ARMDebuggerClearBreakpoint(struct ARMDebugger* debugger, uint32_t address) {
 90	struct DebugBreakpoint** previous = &debugger->breakpoints;
 91	struct DebugBreakpoint* breakpoint;
 92	for (; (breakpoint = *previous); previous = &breakpoint->next) {
 93		if (breakpoint->address == address) {
 94			*previous = breakpoint->next;
 95			free(breakpoint);
 96		}
 97	}
 98}
 99
100void ARMDebuggerSetWatchpoint(struct ARMDebugger* debugger, uint32_t address) {
101	if (debugger->cpu->memory != &debugger->memoryShim.d) {
102		ARMDebuggerInstallMemoryShim(debugger);
103	}
104	struct DebugBreakpoint* watchpoint = malloc(sizeof(struct DebugBreakpoint));
105	watchpoint->address = address;
106	watchpoint->next = debugger->memoryShim.watchpoints;
107	debugger->memoryShim.watchpoints = watchpoint;
108}