mirror of https://github.com/mgba-emu/mgba.git
Debugger: Move platform-specific flag lookup to mDebuggerPlatform
This commit is contained in:
parent
d55a13c9ba
commit
131b983894
|
@ -10,6 +10,8 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#define INSN_LENGTH_MAX 4
|
||||
|
||||
#include <mgba/core/cpu.h>
|
||||
#include <mgba/core/log.h>
|
||||
#include <mgba-util/table.h>
|
||||
|
@ -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 {
|
||||
|
|
|
@ -13,33 +13,6 @@ CXX_GUARD_START
|
|||
#include <mgba/debugger/debugger.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_BIT(mDebuggerAccessLogRegionFlags, HasExBlock, 0);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -8,13 +8,6 @@
|
|||
#include <mgba/core/core.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
|
||||
|
||||
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,46 +157,16 @@ 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);
|
||||
ex |= info.flagsEx[j];
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue