Debugger: Begin GB debugger
Jeffrey Pfau jeffrey@endrift.com
Mon, 25 Apr 2016 22:34:14 -0700
9 files changed,
343 insertions(+),
10 deletions(-)
A
src/gb/cli.c
@@ -0,0 +1,31 @@
+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "cli.h" + +#include "lr35902/cli-debugger.h" + +#ifdef USE_CLI_DEBUGGER + +struct CLIDebuggerCommandSummary _GBCLIDebuggerCommands[] = { + { 0, 0, 0, 0 } +}; + +struct CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore* core) { + UNUSED(core); + struct CLIDebuggerSystem* debugger = malloc(sizeof(struct CLIDebuggerSystem)); + LR35902CLIDebuggerCreate(debugger); + debugger->init = NULL; + debugger->deinit = NULL; + debugger->custom = NULL; + debugger->lookupIdentifier = NULL; + + debugger->name = "Game Boy"; + debugger->commands = _GBCLIDebuggerCommands; + + return debugger; +} + +#endif
A
src/gb/cli.h
@@ -0,0 +1,15 @@
+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef GB_CLI_H +#define GB_CLI_H + +#ifdef USE_CLI_DEBUGGER +#include "debugger/cli-debugger.h" + +struct CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore*); +#endif + +#endif
M
src/gb/core.c
→
src/gb/core.c
@@ -6,8 +6,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "core.h" #include "core/core.h" +#include "gb/cli.h" #include "gb/gb.h" #include "gb/renderers/software.h" +#include "lr35902/debugger.h" #include "util/memory.h" #include "util/patch.h"@@ -15,6 +17,8 @@ struct GBCore {
struct mCore d; struct GBVideoSoftwareRenderer renderer; uint8_t keys; + struct mCPUComponent* components[CPU_COMPONENT_MAX]; + struct mDebuggerPlatform* debuggerPlatform; }; static bool _GBCoreInit(struct mCore* core) {@@ -29,9 +33,11 @@ return false;
} core->cpu = cpu; core->board = gb; + gbcore->debuggerPlatform = NULL; GBCreate(gb); - LR35902SetComponents(cpu, &gb->d, 0, 0); + memset(gbcore->components, 0, sizeof(gbcore->components)); + LR35902SetComponents(cpu, &gb->d, CPU_COMPONENT_MAX, gbcore->components); LR35902Init(cpu); GBVideoSoftwareRendererCreate(&gbcore->renderer);@@ -290,11 +296,49 @@ cpu->memory.store8(cpu, address + 3, value >> 24);
} static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) { - return false; + UNUSED(core); + switch (type) { +#ifdef USE_CLI_DEBUGGER + case DEBUGGER_CLI: + return true; +#endif + default: + return false; + } } static struct mDebuggerPlatform* _GBCoreDebuggerPlatform(struct mCore* core) { - return 0; + struct GBCore* gbcore = (struct GBCore*) core; + if (!gbcore->debuggerPlatform) { + gbcore->debuggerPlatform = LR35902DebuggerPlatformCreate(); + } + return gbcore->debuggerPlatform; +} + +static struct CLIDebuggerSystem* _GBCoreCliDebuggerSystem(struct mCore* core) { +#ifdef USE_CLI_DEBUGGER + return GBCLIDebuggerCreate(core); +#else + UNUSED(core); + return NULL; +#endif +} + +static void _GBCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) { + struct LR35902Core* cpu = core->cpu; + if (core->debugger) { + LR35902HotplugDetach(cpu, CPU_COMPONENT_DEBUGGER); + } + cpu->components[CPU_COMPONENT_DEBUGGER] = &debugger->d; + LR35902HotplugAttach(cpu, CPU_COMPONENT_DEBUGGER); + core->debugger = debugger; +} + +static void _GBCoreDetachDebugger(struct mCore* core) { + struct LR35902Core* cpu = core->cpu; + LR35902HotplugDetach(cpu, CPU_COMPONENT_DEBUGGER); + cpu->components[CPU_COMPONENT_DEBUGGER] = NULL; + core->debugger = NULL; } struct mCore* GBCoreCreate(void) {@@ -347,5 +391,8 @@ core->busWrite16 = _GBCoreBusWrite16;
core->busWrite32 = _GBCoreBusWrite32; core->supportsDebuggerType = _GBCoreSupportsDebuggerType; core->debuggerPlatform = _GBCoreDebuggerPlatform; + core->cliDebuggerSystem = _GBCoreCliDebuggerSystem; + core->attachDebugger = _GBCoreAttachDebugger; + core->detachDebugger = _GBCoreDetachDebugger; return core; }
M
src/gba/core.c
→
src/gba/core.c
@@ -42,7 +42,7 @@ gbacore->debuggerPlatform = NULL;
gbacore->overrides = 0; GBACreate(gba); - // TODO: Restore debugger and cheats + // TODO: Restore cheats memset(gbacore->components, 0, sizeof(gbacore->components)); ARMSetComponents(cpu, &gba->d, CPU_COMPONENT_MAX, gbacore->components); ARMInit(cpu);
M
src/gba/supervisor/cli.c
→
src/gba/supervisor/cli.c
@@ -12,7 +12,6 @@
#ifdef USE_CLI_DEBUGGER static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*); -static void _GBACLIDebuggerDeinit(struct CLIDebuggerSystem*); static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem*); static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);@@ -33,7 +32,7 @@ struct GBACLIDebugger* GBACLIDebuggerCreate(struct mCore* core) {
struct GBACLIDebugger* debugger = malloc(sizeof(struct GBACLIDebugger)); ARMCLIDebuggerCreate(&debugger->d); debugger->d.init = _GBACLIDebuggerInit; - debugger->d.deinit = _GBACLIDebuggerDeinit; + debugger->d.deinit = NULL; debugger->d.custom = _GBACLIDebuggerCustom; debugger->d.lookupIdentifier = _GBACLIDebuggerLookupIdentifier;@@ -49,10 +48,6 @@ static void _GBACLIDebuggerInit(struct CLIDebuggerSystem* debugger) {
struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger; gbaDebugger->frameAdvance = false; -} - -static void _GBACLIDebuggerDeinit(struct CLIDebuggerSystem* debugger) { - UNUSED(debugger); } static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem* debugger) {
A
src/lr35902/cli-debugger.c
@@ -0,0 +1,100 @@
+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "cli-debugger.h" + +#ifdef USE_CLI_DEBUGGER +#include "core/core.h" +#include "debugger/cli-debugger.h" +#include "lr35902/lr35902.h" + +static void _printStatus(struct CLIDebuggerSystem*); + +static struct CLIDebuggerCommandSummary _lr35902Commands[] = { + { 0, 0, 0, 0 } +}; + +static inline void _printFlags(union FlagRegister f) { + printf("[%c%c%c%c]\n", + f.z ? 'Z' : '-', + f.n ? 'N' : '-', + f.h ? 'H' : '-', + f.c ? 'C' : '-'); +} + +static void _printStatus(struct CLIDebuggerSystem* debugger) { + struct LR35902Core* cpu = debugger->p->d.core->cpu; + printf("A: %02X F: %02X (AF: %04X)\n", cpu->a, cpu->f.packed, cpu->af); + printf("B: %02X C: %02X (BC: %04X)\n", cpu->b, cpu->c, cpu->bc); + printf("D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de); + printf("H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl); + printf("PC: %04X SP: %04X\n", cpu->pc, cpu->sp); + _printFlags(cpu->f); +} + +static uint32_t _lookupIdentifier(struct mDebugger* debugger, const char* name, struct CLIDebugVector* dv) { + struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; + struct LR35902Core* cpu = debugger->core->cpu; + if (strcmp(name, "a") == 0) { + return cpu->a; + } + if (strcmp(name, "b") == 0) { + return cpu->b; + } + if (strcmp(name, "c") == 0) { + return cpu->c; + } + if (strcmp(name, "d") == 0) { + return cpu->d; + } + if (strcmp(name, "e") == 0) { + return cpu->e; + } + if (strcmp(name, "h") == 0) { + return cpu->h; + } + if (strcmp(name, "l") == 0) { + return cpu->l; + } + if (strcmp(name, "bc") == 0) { + return cpu->bc; + } + if (strcmp(name, "de") == 0) { + return cpu->de; + } + if (strcmp(name, "hl") == 0) { + return cpu->hl; + } + if (strcmp(name, "af") == 0) { + return cpu->af; + } + if (strcmp(name, "pc") == 0) { + return cpu->pc; + } + if (strcmp(name, "sp") == 0) { + return cpu->pc; + } + if (strcmp(name, "f") == 0) { + return cpu->f.packed; + } + if (cliDebugger->system) { + uint32_t value = cliDebugger->system->lookupIdentifier(cliDebugger->system, name, dv); + if (dv->type != CLIDV_ERROR_TYPE) { + return value; + } + } else { + dv->type = CLIDV_ERROR_TYPE; + } + return 0; +} + +void LR35902CLIDebuggerCreate(struct CLIDebuggerSystem* debugger) { + debugger->printStatus = _printStatus; + debugger->disassemble = NULL; + debugger->platformName = "GB-Z80"; + debugger->platformCommands = NULL; +} + +#endif
A
src/lr35902/cli-debugger.h
@@ -0,0 +1,14 @@
+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef LR35902_CLI_DEBUGGER_H +#define LR35902_CLI_DEBUGGER_H + +#include "util/common.h" + +struct CLIDebuggerSystem; +void LR35902CLIDebuggerCreate(struct CLIDebuggerSystem* debugger); + +#endif
A
src/lr35902/debugger.c
@@ -0,0 +1,101 @@
+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "debugger.h" + +#include "lr35902/lr35902.h" +#include "core/core.h" + +DEFINE_VECTOR(LR35902DebugBreakpointList, struct LR35902DebugBreakpoint); +DEFINE_VECTOR(LR35902DebugWatchpointList, struct LR35902DebugWatchpoint); + +static struct LR35902DebugBreakpoint* _lookupBreakpoint(struct LR35902DebugBreakpointList* breakpoints, uint16_t address) { + size_t i; + for (i = 0; i < LR35902DebugBreakpointListSize(breakpoints); ++i) { + if (LR35902DebugBreakpointListGetPointer(breakpoints, i)->address == address) { + return LR35902DebugBreakpointListGetPointer(breakpoints, i); + } + } + return 0; +} + +static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; + struct LR35902DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->breakpoints, debugger->cpu->pc - 1); + if (!breakpoint) { + return; + } + // TODO: Segments + struct mDebuggerEntryInfo info = { + .address = breakpoint->address + }; + mDebuggerEnter(d->p, DEBUGGER_ENTER_BREAKPOINT, &info); +} + +static void LR35902DebuggerInit(void* cpu, struct mDebuggerPlatform* platform); +static void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform); + +static void LR35902DebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info); + +static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform*, uint32_t address); +static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform*, uint32_t address); +static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform*); +static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform*); + +struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void) { + struct mDebuggerPlatform* platform = malloc(sizeof(struct LR35902Debugger)); + platform->entered = LR35902DebuggerEnter; + platform->init = LR35902DebuggerInit; + platform->deinit = LR35902DebuggerDeinit; + platform->setBreakpoint = LR35902DebuggerSetBreakpoint; + platform->clearBreakpoint = LR35902DebuggerClearBreakpoint; + platform->setWatchpoint = NULL; + platform->clearWatchpoint = NULL; + platform->checkBreakpoints = LR35902DebuggerCheckBreakpoints; + platform->hasBreakpoints = LR35902DebuggerHasBreakpoints; + return platform; +} + +void LR35902DebuggerInit(void* cpu, struct mDebuggerPlatform* platform) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform; + debugger->cpu = cpu; + LR35902DebugBreakpointListInit(&debugger->breakpoints, 0); + LR35902DebugWatchpointListInit(&debugger->watchpoints, 0); +} + +void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform; + LR35902DebugBreakpointListDeinit(&debugger->breakpoints); + LR35902DebugWatchpointListDeinit(&debugger->watchpoints); +} + +static void LR35902DebuggerEnter(struct mDebuggerPlatform* platform, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform; + struct LR35902Core* cpu = debugger->cpu; + cpu->nextEvent = cpu->cycles; +} + +static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform* d, uint32_t address) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; + struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListAppend(&debugger->breakpoints); + breakpoint->address = address; + breakpoint->segment = -1; +} + +static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform* d, uint32_t address) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; + struct LR35902DebugBreakpointList* breakpoints = &debugger->breakpoints; + size_t i; + for (i = 0; i < LR35902DebugBreakpointListSize(breakpoints); ++i) { + if (LR35902DebugBreakpointListGetPointer(breakpoints, i)->address == address) { + LR35902DebugBreakpointListShift(breakpoints, i, 1); + } + } +} + +static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform* d) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; + return LR35902DebugBreakpointListSize(&debugger->breakpoints) || LR35902DebugWatchpointListSize(&debugger->watchpoints); +}
A
src/lr35902/debugger.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "debugger/debugger.h" + +struct LR35902DebugBreakpoint { + uint16_t address; + int segment; +}; + +struct LR35902DebugWatchpoint { + uint16_t address; + int segment; + enum mWatchpointType type; +}; + +DECLARE_VECTOR(LR35902DebugBreakpointList, struct LR35902DebugBreakpoint); +DECLARE_VECTOR(LR35902DebugWatchpointList, struct LR35902DebugWatchpoint); + +struct LR35902Debugger { + struct mDebuggerPlatform d; + struct LR35902Core* cpu; + + struct LR35902DebugBreakpointList breakpoints; + struct LR35902DebugWatchpointList watchpoints; +}; + +struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void);