Debugger: Move platform-specific flag lookup to mDebuggerPlatform

This commit is contained in:
Vicki Pfau 2023-09-07 00:12:02 -07:00
parent d55a13c9ba
commit 131b983894
7 changed files with 128 additions and 99 deletions

View File

@ -10,6 +10,8 @@
CXX_GUARD_START CXX_GUARD_START
#define INSN_LENGTH_MAX 4
#include <mgba/core/cpu.h> #include <mgba/core/cpu.h>
#include <mgba/core/log.h> #include <mgba/core/log.h>
#include <mgba-util/table.h> #include <mgba-util/table.h>
@ -19,6 +21,38 @@ mLOG_DECLARE_CATEGORY(DEBUGGER);
extern const uint32_t DEBUGGER_ID; 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 { enum mDebuggerType {
DEBUGGER_NONE = 0, DEBUGGER_NONE = 0,
DEBUGGER_CUSTOM, DEBUGGER_CUSTOM,
@ -109,6 +143,14 @@ struct mWatchpoint {
struct ParseTree* condition; 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(mBreakpointList, struct mBreakpoint);
DECLARE_VECTOR(mWatchpointList, struct mWatchpoint); DECLARE_VECTOR(mWatchpointList, struct mWatchpoint);
DECLARE_VECTOR(mDebuggerModuleList, struct mDebuggerModule*); DECLARE_VECTOR(mDebuggerModuleList, struct mDebuggerModule*);
@ -161,6 +203,8 @@ struct mDebuggerPlatform {
enum mStackTraceMode (*getStackTraceMode)(struct mDebuggerPlatform*); enum mStackTraceMode (*getStackTraceMode)(struct mDebuggerPlatform*);
void (*setStackTraceMode)(struct mDebuggerPlatform*, enum mStackTraceMode mode); void (*setStackTraceMode)(struct mDebuggerPlatform*, enum mStackTraceMode mode);
bool (*updateStackTrace)(struct mDebuggerPlatform* d); bool (*updateStackTrace)(struct mDebuggerPlatform* d);
void (*nextInstructionInfo)(struct mDebuggerPlatform* d, struct mDebuggerInstructionInfo* info);
}; };
struct mDebugger { struct mDebugger {

View File

@ -13,33 +13,6 @@ CXX_GUARD_START
#include <mgba/debugger/debugger.h> #include <mgba/debugger/debugger.h>
#include <mgba-util/vector.h> #include <mgba-util/vector.h>
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_BITFIELD(mDebuggerAccessLogRegionFlags, uint64_t);
DECL_BIT(mDebuggerAccessLogRegionFlags, HasExBlock, 0); DECL_BIT(mDebuggerAccessLogRegionFlags, HasExBlock, 0);

View File

@ -106,6 +106,7 @@ struct SM83InstructionInfo {
size_t SM83Decode(uint8_t opcode, struct SM83InstructionInfo* info); size_t SM83Decode(uint8_t opcode, struct SM83InstructionInfo* info);
int SM83Disassemble(struct SM83InstructionInfo* info, uint16_t pc, char* buffer, int blen); int SM83Disassemble(struct SM83InstructionInfo* info, uint16_t pc, char* buffer, int blen);
int SM83InstructionLength(uint8_t opcode);
CXX_GUARD_END CXX_GUARD_END

View File

@ -246,6 +246,7 @@ static void ARMDebuggerFrameFormatRegisters(struct mStackFrame* frame, char* out
static enum mStackTraceMode ARMDebuggerGetStackTraceMode(struct mDebuggerPlatform*); static enum mStackTraceMode ARMDebuggerGetStackTraceMode(struct mDebuggerPlatform*);
static void ARMDebuggerSetStackTraceMode(struct mDebuggerPlatform*, enum mStackTraceMode); static void ARMDebuggerSetStackTraceMode(struct mDebuggerPlatform*, enum mStackTraceMode);
static bool ARMDebuggerUpdateStackTrace(struct mDebuggerPlatform* d); static bool ARMDebuggerUpdateStackTrace(struct mDebuggerPlatform* d);
static void ARMDebuggerNextInstructionInfo(struct mDebuggerPlatform* d, struct mDebuggerInstructionInfo*);
struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) { struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) {
struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct ARMDebugger)); struct mDebuggerPlatform* platform = (struct mDebuggerPlatform*) malloc(sizeof(struct ARMDebugger));
@ -263,6 +264,7 @@ struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) {
platform->getStackTraceMode = ARMDebuggerGetStackTraceMode; platform->getStackTraceMode = ARMDebuggerGetStackTraceMode;
platform->setStackTraceMode = ARMDebuggerSetStackTraceMode; platform->setStackTraceMode = ARMDebuggerSetStackTraceMode;
platform->updateStackTrace = ARMDebuggerUpdateStackTrace; platform->updateStackTrace = ARMDebuggerUpdateStackTrace;
platform->nextInstructionInfo = ARMDebuggerNextInstructionInfo;
return platform; return platform;
} }
@ -551,3 +553,27 @@ static bool ARMDebuggerUpdateStackTrace(struct mDebuggerPlatform* d) {
return false; 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
}

View File

@ -8,13 +8,6 @@
#include <mgba/core/core.h> #include <mgba/core/core.h>
#include <mgba-util/vfs.h> #include <mgba-util/vfs.h>
#ifdef M_CORE_GBA
#include <mgba/internal/arm/isa-inlines.h>
#endif
#ifdef M_CORE_GB
#include <mgba/internal/sm83/sm83.h>
#endif
#define DEFAULT_MAX_REGIONS 20 #define DEFAULT_MAX_REGIONS 20
const char mAL_MAGIC[] = "mAL\1"; const char mAL_MAGIC[] = "mAL\1";
@ -143,42 +136,20 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum
static void _mDebuggerAccessLoggerCallback(struct mDebuggerModule* debugger) { static void _mDebuggerAccessLoggerCallback(struct mDebuggerModule* debugger) {
struct mDebuggerAccessLogger* logger = (struct mDebuggerAccessLogger*) debugger; struct mDebuggerAccessLogger* logger = (struct mDebuggerAccessLogger*) debugger;
struct mCore* core = logger->d.p->core; struct mDebuggerInstructionInfo info;
enum mPlatform platform = core->platform(core); logger->d.p->platform->nextInstructionInfo(logger->d.p->platform, &info);
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;
}
size_t i; size_t i;
for (i = 0; i < mDebuggerAccessLogRegionListSize(&logger->regions); ++i) { for (i = 0; i < mDebuggerAccessLogRegionListSize(&logger->regions); ++i) {
struct mDebuggerAccessLogRegion* region = mDebuggerAccessLogRegionListGetPointer(&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; continue;
} }
size_t offset = address - region->start; size_t offset = info.address - region->start;
if (segment > 0) { if (info.segment > 0) {
uint32_t segmentSize = region->end - region->segmentStart; uint32_t segmentSize = region->end - region->segmentStart;
offset %= segmentSize; offset %= segmentSize;
offset += segmentSize * segment; offset += segmentSize * info.segment;
} }
if (offset >= region->size) { if (offset >= region->size) {
@ -186,46 +157,16 @@ static void _mDebuggerAccessLoggerCallback(struct mDebuggerModule* debugger) {
} }
size_t j; 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] = 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) { if (region->blockEx) {
uint16_t ex;
LOAD_16LE(ex, 0, &region->blockEx[offset + j]); LOAD_16LE(ex, 0, &region->blockEx[offset + j]);
ex = mDebuggerAccessLogFlagsExFillExecuteARM(ex); ex |= info.flagsEx[j];
STORE_16LE(ex, 0, &region->blockEx[offset + j]); STORE_16LE(ex, 0, &region->blockEx[offset + j]);
} }
} else {
region->block[offset + j] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset]);
if (region->blockEx) {
uint16_t ex;
LOAD_16LE(ex, 0, &region->blockEx[offset + j]);
ex = mDebuggerAccessLogFlagsExFillExecuteThumb(ex);
STORE_16LE(ex, 0, &region->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, &region->blockEx[offset + j]);
ex = mDebuggerAccessLogFlagsExFillExecuteOpcode(ex);
STORE_16LE(ex, 0, &region->blockEx[offset + j]);
}
break;
#endif
case mPLATFORM_NONE:
return;
}
} }
} }
} }

View File

@ -74,6 +74,7 @@ static void SM83DebuggerListWatchpoints(struct mDebuggerPlatform*, struct mDebug
static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform*); static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform*);
static bool SM83DebuggerHasBreakpoints(struct mDebuggerPlatform*); static bool SM83DebuggerHasBreakpoints(struct mDebuggerPlatform*);
static void SM83DebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length); static void SM83DebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length);
static void SM83DebuggerNextInstructionInfo(struct mDebuggerPlatform* d, struct mDebuggerInstructionInfo* info);
struct mDebuggerPlatform* SM83DebuggerPlatformCreate(void) { struct mDebuggerPlatform* SM83DebuggerPlatformCreate(void) {
struct SM83Debugger* platform = malloc(sizeof(struct SM83Debugger)); struct SM83Debugger* platform = malloc(sizeof(struct SM83Debugger));
@ -91,6 +92,7 @@ struct mDebuggerPlatform* SM83DebuggerPlatformCreate(void) {
platform->d.getStackTraceMode = NULL; platform->d.getStackTraceMode = NULL;
platform->d.setStackTraceMode = NULL; platform->d.setStackTraceMode = NULL;
platform->d.updateStackTrace = NULL; platform->d.updateStackTrace = NULL;
platform->d.nextInstructionInfo = SM83DebuggerNextInstructionInfo;
platform->printStatus = NULL; platform->printStatus = NULL;
return &platform->d; 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->d, cpu->e, cpu->h, cpu->l,
cpu->sp, cpu->memory.currentSegment(cpu, cpu->pc), cpu->pc, disassembly); 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]);
}
}

View File

@ -582,3 +582,27 @@ int SM83Disassemble(struct SM83InstructionInfo* info, uint16_t pc, char* buffer,
buffer[blen - 1] = '\0'; buffer[blen - 1] = '\0';
return total; 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];
}