diff --git a/include/mgba/debugger/debugger.h b/include/mgba/debugger/debugger.h index 761fbf9ac..eb69faaf4 100644 --- a/include/mgba/debugger/debugger.h +++ b/include/mgba/debugger/debugger.h @@ -10,6 +10,8 @@ CXX_GUARD_START +#define INSN_LENGTH_MAX 4 + #include #include #include @@ -19,6 +21,38 @@ mLOG_DECLARE_CATEGORY(DEBUGGER); extern const uint32_t DEBUGGER_ID; +DECL_BITFIELD(mDebuggerAccessLogFlags, uint8_t); +DECL_BIT(mDebuggerAccessLogFlags, Read, 0); +DECL_BIT(mDebuggerAccessLogFlags, Write, 1); +DECL_BIT(mDebuggerAccessLogFlags, Execute, 2); +DECL_BIT(mDebuggerAccessLogFlags, Abort, 3); +DECL_BIT(mDebuggerAccessLogFlags, Access8, 4); +DECL_BIT(mDebuggerAccessLogFlags, Access16, 5); +DECL_BIT(mDebuggerAccessLogFlags, Access32, 6); +DECL_BIT(mDebuggerAccessLogFlags, Access64, 7); + +DECL_BITFIELD(mDebuggerAccessLogFlagsEx, uint16_t); +DECL_BIT(mDebuggerAccessLogFlagsEx, AccessProgram, 0); +DECL_BIT(mDebuggerAccessLogFlagsEx, AccessDMA, 1); +DECL_BIT(mDebuggerAccessLogFlagsEx, AccessSystem, 2); +DECL_BIT(mDebuggerAccessLogFlagsEx, AccessDecompress, 3); +DECL_BIT(mDebuggerAccessLogFlagsEx, AccessCopy, 4); + +DECL_BIT(mDebuggerAccessLogFlagsEx, ErrorIllegalOpcode, 8); +DECL_BIT(mDebuggerAccessLogFlagsEx, ErrorAccessRead, 9); +DECL_BIT(mDebuggerAccessLogFlagsEx, ErrorAccessWrite, 10); +DECL_BIT(mDebuggerAccessLogFlagsEx, ErrorAccessExecute, 11); +DECL_BIT(mDebuggerAccessLogFlagsEx, Private0, 12); +DECL_BIT(mDebuggerAccessLogFlagsEx, Private1, 13); +DECL_BIT(mDebuggerAccessLogFlagsEx, Private2, 14); +DECL_BIT(mDebuggerAccessLogFlagsEx, Private3, 15); + +DECL_BIT(mDebuggerAccessLogFlagsEx, ExecuteARM, 14); +DECL_BIT(mDebuggerAccessLogFlagsEx, ExecuteThumb, 15); + +DECL_BIT(mDebuggerAccessLogFlagsEx, ExecuteOpcode, 14); +DECL_BIT(mDebuggerAccessLogFlagsEx, ExecuteOperand, 15); + enum mDebuggerType { DEBUGGER_NONE = 0, DEBUGGER_CUSTOM, @@ -109,6 +143,14 @@ struct mWatchpoint { struct ParseTree* condition; }; +struct mDebuggerInstructionInfo { + uint32_t address; + int segment; + unsigned width; + mDebuggerAccessLogFlags flags[INSN_LENGTH_MAX]; + mDebuggerAccessLogFlagsEx flagsEx[INSN_LENGTH_MAX]; +}; + DECLARE_VECTOR(mBreakpointList, struct mBreakpoint); DECLARE_VECTOR(mWatchpointList, struct mWatchpoint); DECLARE_VECTOR(mDebuggerModuleList, struct mDebuggerModule*); @@ -161,6 +203,8 @@ struct mDebuggerPlatform { enum mStackTraceMode (*getStackTraceMode)(struct mDebuggerPlatform*); void (*setStackTraceMode)(struct mDebuggerPlatform*, enum mStackTraceMode mode); bool (*updateStackTrace)(struct mDebuggerPlatform* d); + + void (*nextInstructionInfo)(struct mDebuggerPlatform* d, struct mDebuggerInstructionInfo* info); }; struct mDebugger { diff --git a/include/mgba/internal/debugger/access-logger.h b/include/mgba/internal/debugger/access-logger.h index e25450386..26186ac20 100644 --- a/include/mgba/internal/debugger/access-logger.h +++ b/include/mgba/internal/debugger/access-logger.h @@ -13,33 +13,6 @@ CXX_GUARD_START #include #include -DECL_BITFIELD(mDebuggerAccessLogFlags, uint8_t); -DECL_BIT(mDebuggerAccessLogFlags, Read, 0); -DECL_BIT(mDebuggerAccessLogFlags, Write, 1); -DECL_BIT(mDebuggerAccessLogFlags, Execute, 2); -DECL_BIT(mDebuggerAccessLogFlags, Abort, 3); -DECL_BIT(mDebuggerAccessLogFlags, Access8, 4); -DECL_BIT(mDebuggerAccessLogFlags, Access16, 5); -DECL_BIT(mDebuggerAccessLogFlags, Access32, 6); -DECL_BIT(mDebuggerAccessLogFlags, Access64, 7); - -DECL_BITFIELD(mDebuggerAccessLogFlagsEx, uint16_t); -DECL_BIT(mDebuggerAccessLogFlagsEx, AccessProgram, 0); -DECL_BIT(mDebuggerAccessLogFlagsEx, AccessDMA, 1); -DECL_BIT(mDebuggerAccessLogFlagsEx, AccessSystem, 2); -DECL_BIT(mDebuggerAccessLogFlagsEx, AccessDecompress, 3); -DECL_BIT(mDebuggerAccessLogFlagsEx, AccessCopy, 4); -DECL_BIT(mDebuggerAccessLogFlagsEx, ErrorIllegalOpcode, 8); -DECL_BIT(mDebuggerAccessLogFlagsEx, ErrorAccessRead, 9); -DECL_BIT(mDebuggerAccessLogFlagsEx, ErrorAccessWrite, 10); -DECL_BIT(mDebuggerAccessLogFlagsEx, ErrorAccessExecute, 11); - -DECL_BIT(mDebuggerAccessLogFlagsEx, ExecuteARM, 14); -DECL_BIT(mDebuggerAccessLogFlagsEx, ExecuteThumb, 15); - -DECL_BIT(mDebuggerAccessLogFlagsEx, ExecuteOpcode, 14); -DECL_BIT(mDebuggerAccessLogFlagsEx, ExecuteOperand, 15); - DECL_BITFIELD(mDebuggerAccessLogRegionFlags, uint64_t); DECL_BIT(mDebuggerAccessLogRegionFlags, HasExBlock, 0); diff --git a/include/mgba/internal/sm83/decoder.h b/include/mgba/internal/sm83/decoder.h index 14104ef48..2e3761bc0 100644 --- a/include/mgba/internal/sm83/decoder.h +++ b/include/mgba/internal/sm83/decoder.h @@ -106,6 +106,7 @@ struct SM83InstructionInfo { size_t SM83Decode(uint8_t opcode, struct SM83InstructionInfo* info); int SM83Disassemble(struct SM83InstructionInfo* info, uint16_t pc, char* buffer, int blen); +int SM83InstructionLength(uint8_t opcode); CXX_GUARD_END diff --git a/src/arm/debugger/debugger.c b/src/arm/debugger/debugger.c index aa3c6d94c..8fe474258 100644 --- a/src/arm/debugger/debugger.c +++ b/src/arm/debugger/debugger.c @@ -246,6 +246,7 @@ static void ARMDebuggerFrameFormatRegisters(struct mStackFrame* frame, char* out static enum mStackTraceMode ARMDebuggerGetStackTraceMode(struct mDebuggerPlatform*); static void ARMDebuggerSetStackTraceMode(struct mDebuggerPlatform*, enum mStackTraceMode); static bool ARMDebuggerUpdateStackTrace(struct mDebuggerPlatform* d); +static void ARMDebuggerNextInstructionInfo(struct mDebuggerPlatform* d, struct mDebuggerInstructionInfo*); struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) { struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct ARMDebugger)); @@ -263,6 +264,7 @@ struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) { platform->getStackTraceMode = ARMDebuggerGetStackTraceMode; platform->setStackTraceMode = ARMDebuggerSetStackTraceMode; platform->updateStackTrace = ARMDebuggerUpdateStackTrace; + platform->nextInstructionInfo = ARMDebuggerNextInstructionInfo; return platform; } @@ -551,3 +553,27 @@ static bool ARMDebuggerUpdateStackTrace(struct mDebuggerPlatform* d) { return false; } } + +static void ARMDebuggerNextInstructionInfo(struct mDebuggerPlatform* d, struct mDebuggerInstructionInfo* info) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + info->width = _ARMInstructionLength(debugger->cpu); + info->address = debugger->cpu->gprs[ARM_PC] - info->width; + info->segment = 0; + if (debugger->cpu->executionMode == MODE_ARM) { + info->flags[0] = mDebuggerAccessLogFlagsFillAccess32(0); + info->flags[1] = mDebuggerAccessLogFlagsFillAccess32(0); + info->flags[2] = mDebuggerAccessLogFlagsFillAccess32(0); + info->flags[3] = mDebuggerAccessLogFlagsFillAccess32(0); + info->flagsEx[0] = mDebuggerAccessLogFlagsExFillExecuteARM(0); + info->flagsEx[1] = mDebuggerAccessLogFlagsExFillExecuteARM(0); + info->flagsEx[2] = mDebuggerAccessLogFlagsExFillExecuteARM(0); + info->flagsEx[3] = mDebuggerAccessLogFlagsExFillExecuteARM(0); + } else { + info->flags[0] = mDebuggerAccessLogFlagsFillAccess16(0); + info->flags[1] = mDebuggerAccessLogFlagsFillAccess16(0); + info->flagsEx[0] = mDebuggerAccessLogFlagsExFillExecuteThumb(0); + info->flagsEx[1] = mDebuggerAccessLogFlagsExFillExecuteThumb(0); + } + + // TODO Access types +} diff --git a/src/debugger/access-logger.c b/src/debugger/access-logger.c index 2f9c93817..41c780c4e 100644 --- a/src/debugger/access-logger.c +++ b/src/debugger/access-logger.c @@ -8,13 +8,6 @@ #include #include -#ifdef M_CORE_GBA -#include -#endif -#ifdef M_CORE_GB -#include -#endif - #define DEFAULT_MAX_REGIONS 20 const char mAL_MAGIC[] = "mAL\1"; @@ -143,42 +136,20 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum static void _mDebuggerAccessLoggerCallback(struct mDebuggerModule* debugger) { struct mDebuggerAccessLogger* logger = (struct mDebuggerAccessLogger*) debugger; - struct mCore* core = logger->d.p->core; - enum mPlatform platform = core->platform(core); - uint32_t address; - int segment = -1; - unsigned width = 1; - - switch (platform) { - // TODO: Move to debugger->platform -#ifdef M_CORE_GBA - case mPLATFORM_GBA: - address = ((struct ARMCore*) core->cpu)->gprs[ARM_PC]; - width = ((struct ARMCore*) core->cpu)->executionMode == MODE_THUMB ? 2 : 4; - address -= width; - break; -#endif -#ifdef M_CORE_GB - case mPLATFORM_GB: - address = ((struct SM83Core*) core->cpu)->regs.pc; - segment = ((struct SM83Core*) core->cpu)->memory.currentSegment(core->cpu, address); - break; -#endif - case mPLATFORM_NONE: - return; - } + struct mDebuggerInstructionInfo info; + logger->d.p->platform->nextInstructionInfo(logger->d.p->platform, &info); size_t i; for (i = 0; i < mDebuggerAccessLogRegionListSize(&logger->regions); ++i) { struct mDebuggerAccessLogRegion* region = mDebuggerAccessLogRegionListGetPointer(&logger->regions, i); - if (address < region->start || address >= region->end) { + if (info.address < region->start || info.address >= region->end) { continue; } - size_t offset = address - region->start; - if (segment > 0) { + size_t offset = info.address - region->start; + if (info.segment > 0) { uint32_t segmentSize = region->end - region->segmentStart; offset %= segmentSize; - offset += segmentSize * segment; + offset += segmentSize * info.segment; } if (offset >= region->size) { @@ -186,45 +157,15 @@ static void _mDebuggerAccessLoggerCallback(struct mDebuggerModule* debugger) { } size_t j; - for (j = 0; j < width; ++j) { + for (j = 0; j < info.width; ++j) { + uint16_t ex = 0; region->block[offset + j] = mDebuggerAccessLogFlagsFillExecute(region->block[offset + j]); + region->block[offset + j] |= info.flags[j]; - switch (platform) { - // TODO: Move to debugger->platform -#ifdef M_CORE_GBA - case mPLATFORM_GBA: - if (((struct ARMCore*) core->cpu)->executionMode == MODE_ARM) { - region->block[offset + j] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + j]); - if (region->blockEx) { - uint16_t ex; - LOAD_16LE(ex, 0, ®ion->blockEx[offset + j]); - ex = mDebuggerAccessLogFlagsExFillExecuteARM(ex); - STORE_16LE(ex, 0, ®ion->blockEx[offset + j]); - } - } else { - region->block[offset + j] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset]); - if (region->blockEx) { - uint16_t ex; - LOAD_16LE(ex, 0, ®ion->blockEx[offset + j]); - ex = mDebuggerAccessLogFlagsExFillExecuteThumb(ex); - STORE_16LE(ex, 0, ®ion->blockEx[offset + j]); - } - } - break; -#endif -#ifdef M_CORE_GB - case mPLATFORM_GB: - region->block[offset + j] = mDebuggerAccessLogFlagsFillAccess8(region->block[offset + j]); - if (region->blockEx) { - uint16_t ex; - LOAD_16LE(ex, 0, ®ion->blockEx[offset + j]); - ex = mDebuggerAccessLogFlagsExFillExecuteOpcode(ex); - STORE_16LE(ex, 0, ®ion->blockEx[offset + j]); - } - break; -#endif - case mPLATFORM_NONE: - return; + if (region->blockEx) { + LOAD_16LE(ex, 0, ®ion->blockEx[offset + j]); + ex |= info.flagsEx[j]; + STORE_16LE(ex, 0, ®ion->blockEx[offset + j]); } } } diff --git a/src/sm83/debugger/debugger.c b/src/sm83/debugger/debugger.c index d24a75463..162b044df 100644 --- a/src/sm83/debugger/debugger.c +++ b/src/sm83/debugger/debugger.c @@ -74,6 +74,7 @@ static void SM83DebuggerListWatchpoints(struct mDebuggerPlatform*, struct mDebug static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform*); static bool SM83DebuggerHasBreakpoints(struct mDebuggerPlatform*); static void SM83DebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length); +static void SM83DebuggerNextInstructionInfo(struct mDebuggerPlatform* d, struct mDebuggerInstructionInfo* info); struct mDebuggerPlatform* SM83DebuggerPlatformCreate(void) { struct SM83Debugger* platform = malloc(sizeof(struct SM83Debugger)); @@ -91,6 +92,7 @@ struct mDebuggerPlatform* SM83DebuggerPlatformCreate(void) { platform->d.getStackTraceMode = NULL; platform->d.setStackTraceMode = NULL; platform->d.updateStackTrace = NULL; + platform->d.nextInstructionInfo = SM83DebuggerNextInstructionInfo; platform->printStatus = NULL; return &platform->d; } @@ -244,3 +246,21 @@ static void SM83DebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t* le cpu->d, cpu->e, cpu->h, cpu->l, cpu->sp, cpu->memory.currentSegment(cpu, cpu->pc), cpu->pc, disassembly); } + +static void SM83DebuggerNextInstructionInfo(struct mDebuggerPlatform* d, struct mDebuggerInstructionInfo* info) { + struct SM83Debugger* debugger = (struct SM83Debugger*) d; + info->address = debugger->cpu->pc; + uint8_t opcode = debugger->cpu->memory.cpuLoad8(debugger->cpu, info->address); + info->width = SM83InstructionLength(opcode); + info->segment = debugger->cpu->memory.currentSegment(debugger->cpu, info->address); + info->flags[0] = mDebuggerAccessLogFlagsFillAccess8(0); + info->flags[1] = mDebuggerAccessLogFlagsFillAccess8(0); + info->flags[2] = mDebuggerAccessLogFlagsFillAccess8(0); + info->flagsEx[0] = mDebuggerAccessLogFlagsExFillExecuteOpcode(0); + info->flagsEx[1] = mDebuggerAccessLogFlagsExFillExecuteOperand(0); + info->flagsEx[2] = mDebuggerAccessLogFlagsExFillExecuteOperand(0); + if (info->width == 0) { + info->width = 1; + info->flagsEx[0] = mDebuggerAccessLogFlagsExFillErrorIllegalOpcode(info->flagsEx[0]); + } +} diff --git a/src/sm83/decoder.c b/src/sm83/decoder.c index 819576c26..552187327 100644 --- a/src/sm83/decoder.c +++ b/src/sm83/decoder.c @@ -582,3 +582,27 @@ int SM83Disassemble(struct SM83InstructionInfo* info, uint16_t pc, char* buffer, buffer[blen - 1] = '\0'; return total; } + +static int _sm83Widths[256] = { + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 0 */ 1, 3, 1, 1, 1, 1, 2, 1, 3, 1, 1, 1, 1, 1, 2, 1, + /* 1 */ 2, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, + /* 2 */ 2, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, + /* 3 */ 2, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, + /* 4 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 5 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 6 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 7 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 8 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 9 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* A */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* B */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* C */ 1, 1, 3, 3, 3, 1, 2, 1, 1, 1, 3, 2, 3, 3, 2, 1, + /* D */ 1, 1, 3, 0, 3, 1, 2, 1, 1, 1, 3, 0, 3, 0, 2, 1, + /* E */ 2, 1, 1, 0, 0, 1, 2, 1, 2, 1, 3, 0, 0, 0, 2, 1, + /* F */ 2, 1, 1, 1, 0, 1, 2, 1, 2, 1, 3, 1, 0, 0, 2, 1, +}; + +int SM83InstructionLength(uint8_t opcode) { + return _sm83Widths[opcode]; +}