Debugger: Add get/set register functions
@@ -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;
@@ -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;
@@ -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; }
@@ -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; +}
@@ -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;
@@ -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; }
@@ -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; +}