all repos — mgba @ d484c98eba5fc8281ccb16427ee326301e71ad1c

mGBA Game Boy Advance Emulator

Debugger: Add get/set register functions
Vicki Pfau vi@endrift.com
Fri, 13 Oct 2017 00:29:38 -0700
commit

d484c98eba5fc8281ccb16427ee326301e71ad1c

parent

a2447d09e3e0bacaf8e8c0b750fac18f13de4fdf

M include/mgba/debugger/debugger.hinclude/mgba/debugger/debugger.h

@@ -84,6 +84,9 @@ void (*setWatchpoint)(struct mDebuggerPlatform*, uint32_t address, int segment, enum mWatchpointType type);

void (*clearWatchpoint)(struct mDebuggerPlatform*, uint32_t address, int segment); void (*checkBreakpoints)(struct mDebuggerPlatform*); void (*trace)(struct mDebuggerPlatform*, char* out, size_t* length); + + bool (*getRegister)(struct mDebuggerPlatform*, const char* name, int32_t* value); + bool (*setRegister)(struct mDebuggerPlatform*, const char* name, int32_t value); }; struct mDebuggerSymbols;
M include/mgba/internal/debugger/cli-debugger.hinclude/mgba/internal/debugger/cli-debugger.h

@@ -14,6 +14,7 @@ #include <mgba/debugger/debugger.h>

extern const char* ERROR_MISSING_ARGS; extern const char* ERROR_OVERFLOW; +extern const char* ERROR_INVALID_ARGS; struct CLIDebugger;

@@ -51,7 +52,6 @@ bool (*custom)(struct CLIDebuggerSystem*);

void (*disassemble)(struct CLIDebuggerSystem*, struct CLIDebugVector* dv); uint32_t (*lookupIdentifier)(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); - uint32_t (*lookupPlatformIdentifier)(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); void (*printStatus)(struct CLIDebuggerSystem*); struct CLIDebuggerCommandSummary* commands;
M src/arm/debugger/cli-debugger.csrc/arm/debugger/cli-debugger.c

@@ -17,7 +17,6 @@ static void _disassembleArm(struct CLIDebugger*, struct CLIDebugVector*);

static void _disassembleThumb(struct CLIDebugger*, struct CLIDebugVector*); static void _setBreakpointARM(struct CLIDebugger*, struct CLIDebugVector*); static void _setBreakpointThumb(struct CLIDebugger*, struct CLIDebugVector*); -static void _writeRegister(struct CLIDebugger*, struct CLIDebugVector*); static void _disassembleMode(struct CLIDebugger*, struct CLIDebugVector*, enum ExecutionMode mode); static uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode);

@@ -33,7 +32,6 @@ { "disasm/a", _disassembleArm, "Ii", "Disassemble instructions as ARM" },

{ "disasm/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" }, { "disassemble/a", _disassembleArm, "Ii", "Disassemble instructions as ARM" }, { "disassemble/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" }, - { "w/r", _writeRegister, "SI", "Write a register" }, { 0, 0, 0, 0 } };

@@ -145,31 +143,6 @@ }

_printLine(debugger->p, cpu->gprs[ARM_PC] - instructionLength, mode); } -static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - struct CLIDebuggerBackend* be = debugger->backend; - struct ARMCore* cpu = debugger->d.core->cpu; - if (!dv || dv->type != CLIDV_CHAR_TYPE) { - be->printf(be, "%s\n", ERROR_MISSING_ARGS); - return; - } - if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - be->printf(be, "%s\n", ERROR_MISSING_ARGS); - return; - } - char* end; - uint32_t regid = strtoul(&dv->charValue[1], &end, 10); - if (dv->charValue[0] != 'r' || (*end && !isspace(*end)) || regid > ARM_PC) { - be->printf(be, "%s\n", "Unknown register name"); - return; - } - if (regid == ARM_PC) { - be->printf(be, "%s\n", "Cannot write to program counter"); - return; - } - uint32_t value = dv->next->intValue; - cpu->gprs[regid] = value; -} - static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) {

@@ -190,38 +163,9 @@ uint32_t address = dv->intValue;

ARMDebuggerSetSoftwareBreakpoint(debugger->d.platform, address, MODE_THUMB); } -static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) { - struct ARMCore* cpu = debugger->p->d.core->cpu; - if (strcmp(name, "sp") == 0) { - return cpu->gprs[ARM_SP]; - } - if (strcmp(name, "lr") == 0) { - return cpu->gprs[ARM_LR]; - } - if (strcmp(name, "pc") == 0) { - return cpu->gprs[ARM_PC]; - } - if (strcmp(name, "cpsr") == 0) { - return cpu->cpsr.packed; - } - // TODO: test if mode has SPSR - if (strcmp(name, "spsr") == 0) { - return cpu->spsr.packed; - } - if (name[0] == 'r' && name[1] >= '0' && name[1] <= '9') { - int reg = atoi(&name[1]); - if (reg < 16) { - return cpu->gprs[reg]; - } - } - dv->type = CLIDV_ERROR_TYPE; - return 0; -} - void ARMCLIDebuggerCreate(struct CLIDebuggerSystem* debugger) { debugger->printStatus = _printStatus; debugger->disassemble = _disassemble; - debugger->lookupPlatformIdentifier = _lookupPlatformIdentifier; debugger->platformName = "ARM"; debugger->platformCommands = _armCommands; }
M src/arm/debugger/debugger.csrc/arm/debugger/debugger.c

@@ -56,6 +56,8 @@ static void ARMDebuggerClearWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment);

static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform*); static bool ARMDebuggerHasBreakpoints(struct mDebuggerPlatform*); static void ARMDebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length); +static bool ARMDebuggerGetRegister(struct mDebuggerPlatform*, const char* name, int32_t* value); +static bool ARMDebuggerSetRegister(struct mDebuggerPlatform*, const char* name, int32_t value); struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) { struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct ARMDebugger));

@@ -69,6 +71,8 @@ platform->clearWatchpoint = ARMDebuggerClearWatchpoint;

platform->checkBreakpoints = ARMDebuggerCheckBreakpoints; platform->hasBreakpoints = ARMDebuggerHasBreakpoints; platform->trace = ARMDebuggerTrace; + platform->getRegister = ARMDebuggerGetRegister; + platform->setRegister = ARMDebuggerSetRegister; return platform; }

@@ -246,3 +250,81 @@ cpu->gprs[8], cpu->gprs[9], cpu->gprs[10], cpu->gprs[11],

cpu->gprs[12], cpu->gprs[13], cpu->gprs[14], cpu->gprs[15], cpu->cpsr.packed, disassembly); } + +bool ARMDebuggerGetRegister(struct mDebuggerPlatform* d, const char* name, int32_t* value) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + struct ARMCore* cpu = debugger->cpu; + + if (strcmp(name, "sp") == 0) { + *value = cpu->gprs[ARM_SP]; + return true; + } + if (strcmp(name, "lr") == 0) { + *value = cpu->gprs[ARM_LR]; + return true; + } + if (strcmp(name, "pc") == 0) { + *value = cpu->gprs[ARM_PC]; + return true; + } + if (strcmp(name, "cpsr") == 0) { + *value = cpu->cpsr.packed; + return true; + } + // TODO: test if mode has SPSR + if (strcmp(name, "spsr") == 0) { + *value = cpu->spsr.packed; + return true; + } + if (name[0] == 'r') { + char* end; + uint32_t reg = strtoul(&name[1], &end, 10); + if (reg <= ARM_PC) { + *value = cpu->gprs[reg]; + return true; + } + } + return false; +} + +bool ARMDebuggerSetRegister(struct mDebuggerPlatform* d, const char* name, int32_t value) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + struct ARMCore* cpu = debugger->cpu; + + if (strcmp(name, "sp") == 0) { + cpu->gprs[ARM_SP] = value; + return true; + } + if (strcmp(name, "lr") == 0) { + cpu->gprs[ARM_LR] = value; + return true; + } + if (strcmp(name, "pc") == 0) { + cpu->gprs[ARM_PC] = value; + int32_t currentCycles = 0; + if (cpu->executionMode == MODE_ARM) { + ARM_WRITE_PC; + } else { + THUMB_WRITE_PC; + } + return true; + } + if (name[0] == 'r') { + char* end; + uint32_t reg = strtoul(&name[1], &end, 10); + if (reg > ARM_PC) { + return false; + } + cpu->gprs[reg] = value; + if (reg == ARM_PC) { + int32_t currentCycles = 0; + if (cpu->executionMode == MODE_ARM) { + ARM_WRITE_PC; + } else { + THUMB_WRITE_PC; + } + } + return true; + } + return false; +}
M src/debugger/cli-debugger.csrc/debugger/cli-debugger.c

@@ -26,6 +26,7 @@ #endif

const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share const char* ERROR_OVERFLOW = "Arguments overflow"; +const char* ERROR_INVALID_ARGS = "Invalid arguments"; #if !defined(NDEBUG) && !defined(_WIN32) static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*);

@@ -51,6 +52,7 @@ static void _setWriteWatchpoint(struct CLIDebugger*, struct CLIDebugVector*);

static void _trace(struct CLIDebugger*, struct CLIDebugVector*); static void _writeByte(struct CLIDebugger*, struct CLIDebugVector*); static void _writeHalfword(struct CLIDebugger*, struct CLIDebugVector*); +static void _writeRegister(struct CLIDebugger*, struct CLIDebugVector*); static void _writeWord(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*);

@@ -92,6 +94,7 @@ { "trace", _trace, "I", "Trace a fixed number of instructions" },

{ "w", _setWatchpoint, "I", "Set a watchpoint" }, { "w/1", _writeByte, "II", "Write a byte at a specified offset" }, { "w/2", _writeHalfword, "II", "Write a halfword at a specified offset" }, + { "w/r", _writeRegister, "SI", "Write a register" }, { "w/4", _writeWord, "II", "Write a word at a specified offset" }, { "watch", _setWatchpoint, "I", "Set a watchpoint" }, { "watch/r", _setReadWatchpoint, "I", "Set a read watchpoint" },

@@ -273,12 +276,12 @@ debugger->backend->printf(debugger->backend, " 0x%08X\n", value);

} static void _writeByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - if (!dv || dv->type != CLIDV_INT_TYPE) { + if (!dv || !dv->next) { debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } - if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); + if (dv->type != CLIDV_INT_TYPE || dv->next->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); return; } uint32_t address = dv->intValue;

@@ -295,12 +298,12 @@ }

} static void _writeHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - if (!dv || dv->type != CLIDV_INT_TYPE) { + if (!dv || !dv->next) { debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } - if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); + if (dv->type != CLIDV_INT_TYPE || dv->next->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); return; } uint32_t address = dv->intValue;

@@ -316,13 +319,27 @@ debugger->d.core->busWrite16(debugger->d.core, address, value);

} } +static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + if (!dv || !dv->next) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); + return; + } + if (dv->type != CLIDV_CHAR_TYPE || dv->next->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + return; + } + if (!debugger->d.platform->setRegister(debugger->d.platform, dv->charValue, dv->next->intValue)) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); + } +} + static void _writeWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - if (!dv || dv->type != CLIDV_INT_TYPE) { + if (!dv || !dv->next) { debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } - if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); + if (dv->type != CLIDV_INT_TYPE || dv->next->type != CLIDV_INT_TYPE) { + debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS); return; } uint32_t address = dv->intValue;

@@ -559,12 +576,10 @@ #endif

if (debugger->core->symbolTable && mDebuggerSymbolLookup(debugger->core->symbolTable, name, &dv->intValue, &dv->segmentValue)) { return; } - value = cliDebugger->system->lookupPlatformIdentifier(cliDebugger->system, name, dv); - if (dv->type != CLIDV_ERROR_TYPE) { - dv->intValue = value; + dv->type = CLIDV_INT_TYPE; + if (debugger->platform->getRegister(debugger->platform, name, &dv->intValue)) { return; } - dv->type = CLIDV_INT_TYPE; value = cliDebugger->system->lookupIdentifier(cliDebugger->system, name, dv); if (dv->type != CLIDV_ERROR_TYPE) { dv->intValue = value;
M src/lr35902/debugger/cli-debugger.csrc/lr35902/debugger/cli-debugger.c

@@ -100,58 +100,9 @@ _printFlags(be, cpu->f);

_printLine(debugger->p, cpu->pc, cpu->memory.currentSegment(cpu, cpu->pc)); } -static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) { - struct LR35902Core* cpu = debugger->p->d.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->sp; - } - if (strcmp(name, "f") == 0) { - return cpu->f.packed; - } - dv->type = CLIDV_ERROR_TYPE; - return 0; -} - void LR35902CLIDebuggerCreate(struct CLIDebuggerSystem* debugger) { debugger->printStatus = _printStatus; debugger->disassemble = _disassemble; - debugger->lookupPlatformIdentifier = _lookupPlatformIdentifier; debugger->platformName = "GB-Z80"; debugger->platformCommands = _lr35902Commands; }
M src/lr35902/debugger/debugger.csrc/lr35902/debugger/debugger.c

@@ -50,6 +50,8 @@ static void LR35902DebuggerClearWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment);

static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform*); static bool LR35902DebuggerHasBreakpoints(struct mDebuggerPlatform*); static void LR35902DebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length); +static bool LR35902DebuggerGetRegister(struct mDebuggerPlatform*, const char* name, int32_t* value); +static bool LR35902DebuggerSetRegister(struct mDebuggerPlatform*, const char* name, int32_t value); struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void) { struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct LR35902Debugger));

@@ -63,6 +65,8 @@ platform->clearWatchpoint = LR35902DebuggerClearWatchpoint;

platform->checkBreakpoints = LR35902DebuggerCheckBreakpoints; platform->hasBreakpoints = LR35902DebuggerHasBreakpoints; platform->trace = LR35902DebuggerTrace; + platform->getRegister = LR35902DebuggerGetRegister; + platform->setRegister = LR35902DebuggerSetRegister; return platform; }

@@ -168,3 +172,131 @@ cpu->a, cpu->f.packed, cpu->b, cpu->c,

cpu->d, cpu->e, cpu->h, cpu->l, cpu->sp, cpu->pc, disassembly); } + +bool LR35902DebuggerGetRegister(struct mDebuggerPlatform* d, const char* name, int32_t* value) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; + struct LR35902Core* cpu = debugger->cpu; + + if (strcmp(name, "a") == 0) { + *value = cpu->a; + return true; + } + if (strcmp(name, "b") == 0) { + *value = cpu->b; + return true; + } + if (strcmp(name, "c") == 0) { + *value = cpu->c; + return true; + } + if (strcmp(name, "d") == 0) { + *value = cpu->d; + return true; + } + if (strcmp(name, "e") == 0) { + *value = cpu->e; + return true; + } + if (strcmp(name, "h") == 0) { + *value = cpu->h; + return true; + } + if (strcmp(name, "l") == 0) { + *value = cpu->l; + return true; + } + if (strcmp(name, "bc") == 0) { + *value = cpu->bc; + return true; + } + if (strcmp(name, "de") == 0) { + *value = cpu->de; + return true; + } + if (strcmp(name, "hl") == 0) { + *value = cpu->hl; + return true; + } + if (strcmp(name, "af") == 0) { + *value = cpu->af; + return true; + } + if (strcmp(name, "pc") == 0) { + *value = cpu->pc; + return true; + } + if (strcmp(name, "sp") == 0) { + *value = cpu->sp; + return true; + } + if (strcmp(name, "f") == 0) { + *value = cpu->f.packed; + return true; + } + return false; +} + +bool LR35902DebuggerSetRegister(struct mDebuggerPlatform* d, const char* name, int32_t value) { + struct LR35902Debugger* debugger = (struct LR35902Debugger*) d; + struct LR35902Core* cpu = debugger->cpu; + + if (strcmp(name, "a") == 0) { + cpu->a = value; + return true; + } + if (strcmp(name, "b") == 0) { + cpu->b = value; + return true; + } + if (strcmp(name, "c") == 0) { + cpu->c = value; + return true; + } + if (strcmp(name, "d") == 0) { + cpu->d = value; + return true; + } + if (strcmp(name, "e") == 0) { + cpu->e = value; + return true; + } + if (strcmp(name, "h") == 0) { + cpu->h = value; + return true; + } + if (strcmp(name, "l") == 0) { + cpu->l = value; + return true; + } + if (strcmp(name, "bc") == 0) { + cpu->bc = value; + return true; + } + if (strcmp(name, "de") == 0) { + cpu->de = value; + return true; + } + if (strcmp(name, "hl") == 0) { + cpu->hl = value; + return true; + } + if (strcmp(name, "af") == 0) { + cpu->af = value; + cpu->f.packed &= 0xF0; + return true; + } + if (strcmp(name, "pc") == 0) { + cpu->pc = value; + cpu->memory.setActiveRegion(cpu, cpu->pc); + return true; + } + if (strcmp(name, "sp") == 0) { + cpu->sp = value; + return true; + } + if (strcmp(name, "f") == 0) { + cpu->f.packed = value & 0xF0; + return true; + } + return false; +}