mirror of https://github.com/mgba-emu/mgba.git
Core: Migrate register access API from debugger into core
This commit is contained in:
parent
6f09085676
commit
87738ba8f3
|
@ -135,6 +135,10 @@ struct mCore {
|
|||
size_t (*listMemoryBlocks)(const struct mCore*, const struct mCoreMemoryBlock**);
|
||||
void* (*getMemoryBlock)(struct mCore*, size_t id, size_t* sizeOut);
|
||||
|
||||
size_t (*listRegisters)(const struct mCore*, const struct mCoreRegisterInfo**);
|
||||
bool (*readRegister)(const struct mCore*, const char* name, void* out);
|
||||
bool (*writeRegister)(struct mCore*, const char* name, const void* in);
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
bool (*supportsDebuggerType)(struct mCore*, enum mDebuggerType);
|
||||
struct mDebuggerPlatform* (*debuggerPlatform)(struct mCore*);
|
||||
|
|
|
@ -286,6 +286,21 @@ struct mCoreMemoryBlock {
|
|||
uint32_t segmentStart;
|
||||
};
|
||||
|
||||
enum mCoreRegisterType {
|
||||
mCORE_REGISTER_GPR = 0,
|
||||
mCORE_REGISTER_FPR,
|
||||
mCORE_REGISTER_FLAGS,
|
||||
mCORE_REGISTER_SIMD,
|
||||
};
|
||||
|
||||
struct mCoreRegisterInfo {
|
||||
const char* name;
|
||||
const char** aliases;
|
||||
unsigned width;
|
||||
uint32_t mask;
|
||||
enum mCoreRegisterType type;
|
||||
};
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -118,8 +118,6 @@ 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);
|
||||
bool (*lookupIdentifier)(struct mDebuggerPlatform*, const char* name, int32_t* value, int* segment);
|
||||
|
||||
uint32_t (*getStackTraceMode)(struct mDebuggerPlatform*);
|
||||
|
|
|
@ -242,8 +242,6 @@ static bool ARMDebuggerHasBreakpoints(struct mDebuggerPlatform*);
|
|||
static void ARMDebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length);
|
||||
static void ARMDebuggerFormatRegisters(struct ARMRegisterFile* regs, char* out, size_t* length);
|
||||
static void ARMDebuggerFrameFormatRegisters(struct mStackFrame* frame, 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);
|
||||
static uint32_t ARMDebuggerGetStackTraceMode(struct mDebuggerPlatform*);
|
||||
static void ARMDebuggerSetStackTraceMode(struct mDebuggerPlatform*, uint32_t);
|
||||
static bool ARMDebuggerUpdateStackTrace(struct mDebuggerPlatform* d);
|
||||
|
@ -261,8 +259,6 @@ struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) {
|
|||
platform->checkBreakpoints = ARMDebuggerCheckBreakpoints;
|
||||
platform->hasBreakpoints = ARMDebuggerHasBreakpoints;
|
||||
platform->trace = ARMDebuggerTrace;
|
||||
platform->getRegister = ARMDebuggerGetRegister;
|
||||
platform->setRegister = ARMDebuggerSetRegister;
|
||||
platform->getStackTraceMode = ARMDebuggerGetStackTraceMode;
|
||||
platform->setStackTraceMode = ARMDebuggerSetStackTraceMode;
|
||||
platform->updateStackTrace = ARMDebuggerUpdateStackTrace;
|
||||
|
@ -511,82 +507,6 @@ static void ARMDebuggerFrameFormatRegisters(struct mStackFrame* frame, char* out
|
|||
ARMDebuggerFormatRegisters(frame->regs, out, length);
|
||||
}
|
||||
|
||||
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;
|
||||
if (cpu->executionMode == MODE_ARM) {
|
||||
ARMWritePC(cpu);
|
||||
} else {
|
||||
ThumbWritePC(cpu);
|
||||
}
|
||||
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) {
|
||||
if (cpu->executionMode == MODE_ARM) {
|
||||
ARMWritePC(cpu);
|
||||
} else {
|
||||
ThumbWritePC(cpu);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t ARMDebuggerGetStackTraceMode(struct mDebuggerPlatform* d) {
|
||||
struct ARMDebugger* debugger = (struct ARMDebugger*) d;
|
||||
return debugger->stackTraceMode;
|
||||
|
|
|
@ -452,7 +452,7 @@ static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector*
|
|||
debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS);
|
||||
return;
|
||||
}
|
||||
if (!debugger->d.platform->setRegister(debugger->d.platform, dv->charValue, dv->next->intValue)) {
|
||||
if (!debugger->d.core->writeRegister(debugger->d.core, dv->charValue, &dv->next->intValue)) {
|
||||
debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ bool mDebuggerLookupIdentifier(struct mDebugger* debugger, const char* name, int
|
|||
if (debugger->core->lookupIdentifier(debugger->core, name, value, segment)) {
|
||||
return true;
|
||||
}
|
||||
if (debugger->platform && debugger->platform->getRegister(debugger->platform, name, value)) {
|
||||
if (debugger->platform && debugger->core->readRegister(debugger->core, name, value)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
155
src/gb/core.c
155
src/gb/core.c
|
@ -60,6 +60,23 @@ static const struct mCoreMemoryBlock _GBCMemoryBlocks[] = {
|
|||
{ GB_BASE_HRAM, "hram", "HRAM", "High RAM", GB_BASE_HRAM, GB_BASE_HRAM + GB_SIZE_HRAM, GB_SIZE_HRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||
};
|
||||
|
||||
static const struct mCoreRegisterInfo _GBRegisters[] = {
|
||||
{ "b", NULL, 1, 0xFF, mCORE_REGISTER_GPR },
|
||||
{ "c", NULL, 1, 0xFF, mCORE_REGISTER_GPR },
|
||||
{ "d", NULL, 1, 0xFF, mCORE_REGISTER_GPR },
|
||||
{ "e", NULL, 1, 0xFF, mCORE_REGISTER_GPR },
|
||||
{ "h", NULL, 1, 0xFF, mCORE_REGISTER_GPR },
|
||||
{ "l", NULL, 1, 0xFF, mCORE_REGISTER_GPR },
|
||||
{ "a", NULL, 1, 0xFF, mCORE_REGISTER_GPR },
|
||||
{ "f", NULL, 1, 0xF0, mCORE_REGISTER_GPR },
|
||||
{ "bc", NULL, 2, 0xFFFF, mCORE_REGISTER_GPR },
|
||||
{ "de", NULL, 2, 0xFFFF, mCORE_REGISTER_GPR },
|
||||
{ "hl", NULL, 2, 0xFFFF, mCORE_REGISTER_GPR },
|
||||
{ "af", NULL, 2, 0xFFF0, mCORE_REGISTER_GPR },
|
||||
{ "pc", NULL, 2, 0xFFFF, mCORE_REGISTER_GPR },
|
||||
{ "sp", NULL, 2, 0xFFFF, mCORE_REGISTER_GPR },
|
||||
};
|
||||
|
||||
struct mVideoLogContext;
|
||||
struct GBCore {
|
||||
struct mCore d;
|
||||
|
@ -837,6 +854,141 @@ void* _GBGetMemoryBlock(struct mCore* core, size_t id, size_t* sizeOut) {
|
|||
}
|
||||
}
|
||||
|
||||
static size_t _GBCoreListRegisters(const struct mCore* core, const struct mCoreRegisterInfo** list) {
|
||||
UNUSED(core);
|
||||
*list = _GBRegisters;
|
||||
return sizeof(_GBRegisters) / sizeof(*_GBRegisters);
|
||||
}
|
||||
|
||||
static bool _GBCoreReadRegister(const struct mCore* core, const char* name, void* out) {
|
||||
struct SM83Core* cpu = core->cpu;
|
||||
uint16_t* value16 = out;
|
||||
uint8_t* value8 = out;
|
||||
|
||||
if (strcmp(name, "b") == 0) {
|
||||
*value8 = cpu->b;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "c") == 0) {
|
||||
*value8 = cpu->c;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "d") == 0) {
|
||||
*value8 = cpu->d;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "e") == 0) {
|
||||
*value8 = cpu->e;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "a") == 0) {
|
||||
*value8 = cpu->a;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "f") == 0) {
|
||||
*value8 = cpu->f.packed;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "h") == 0) {
|
||||
*value8 = cpu->h;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "l") == 0) {
|
||||
*value8 = cpu->l;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "bc") == 0) {
|
||||
*value16 = cpu->bc;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "de") == 0) {
|
||||
*value16 = cpu->de;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "hl") == 0) {
|
||||
*value16 = cpu->hl;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "af") == 0) {
|
||||
*value16 = cpu->af;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "pc") == 0) {
|
||||
*value16 = cpu->pc;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "sp") == 0) {
|
||||
*value16 = cpu->sp;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool _GBCoreWriteRegister(struct mCore* core, const char* name, const void* in) {
|
||||
struct SM83Core* cpu = core->cpu;
|
||||
uint32_t value = *(uint32_t*) in;
|
||||
|
||||
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, "a") == 0) {
|
||||
cpu->a = value;
|
||||
return true;
|
||||
}
|
||||
if (strcmp(name, "f") == 0) {
|
||||
cpu->f.packed = value & 0xF0;
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
|
||||
UNUSED(core);
|
||||
|
@ -1117,6 +1269,9 @@ struct mCore* GBCoreCreate(void) {
|
|||
core->rawWrite32 = _GBCoreRawWrite32;
|
||||
core->listMemoryBlocks = _GBListMemoryBlocks;
|
||||
core->getMemoryBlock = _GBGetMemoryBlock;
|
||||
core->listRegisters = _GBCoreListRegisters;
|
||||
core->readRegister = _GBCoreReadRegister;
|
||||
core->writeRegister = _GBCoreWriteRegister;
|
||||
#ifdef USE_DEBUGGERS
|
||||
core->supportsDebuggerType = _GBCoreSupportsDebuggerType;
|
||||
core->debuggerPlatform = _GBCoreDebuggerPlatform;
|
||||
|
|
170
src/gba/core.c
170
src/gba/core.c
|
@ -8,6 +8,7 @@
|
|||
#include <mgba/core/core.h>
|
||||
#include <mgba/core/log.h>
|
||||
#include <mgba/internal/arm/debugger/debugger.h>
|
||||
#include <mgba/internal/arm/isa-inlines.h>
|
||||
#include <mgba/internal/debugger/symbols.h>
|
||||
#include <mgba/internal/gba/cheats.h>
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
|
@ -32,6 +33,7 @@
|
|||
#include <mgba-util/memory.h>
|
||||
#include <mgba-util/patch.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
#include <errno.h>
|
||||
|
||||
static const struct mCoreChannelInfo _GBAVideoLayers[] = {
|
||||
{ GBA_LAYER_BG0, "bg0", "Background 0", NULL },
|
||||
|
@ -127,6 +129,32 @@ static const struct mCoreMemoryBlock _GBAMemoryBlocksEEPROM[] = {
|
|||
{ REGION_CART_SRAM_MIRROR, "eeprom", "EEPROM", "EEPROM (8kiB)", 0, SIZE_CART_EEPROM, SIZE_CART_EEPROM, mCORE_MEMORY_RW },
|
||||
};
|
||||
|
||||
static const struct mCoreRegisterInfo _GBARegisters[] = {
|
||||
{ "r0", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r1", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r2", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r3", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r4", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r5", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r6", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r7", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r8", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r9", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r10", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r11", NULL, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "r12", (const char*[]) { "ip", NULL }, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "sp", (const char*[]) { "r13", NULL }, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "lr", (const char*[]) { "r14", NULL }, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "pc", (const char*[]) { "r15", NULL }, 4, 0xFFFFFFFF, mCORE_REGISTER_GPR },
|
||||
{ "cpsr", NULL, 4, 0xF00000FF, mCORE_REGISTER_FLAGS },
|
||||
{ "spsr", NULL, 4, 0xF00000FF, mCORE_REGISTER_FLAGS },
|
||||
{ "spsr_irq", NULL, 4, 0xF00000FF, mCORE_REGISTER_FLAGS },
|
||||
{ "spsr_fiq", NULL, 4, 0xF00000FF, mCORE_REGISTER_FLAGS },
|
||||
{ "spsr_svc", NULL, 4, 0xF00000FF, mCORE_REGISTER_FLAGS },
|
||||
{ "spsr_abt", NULL, 4, 0xF00000FF, mCORE_REGISTER_FLAGS },
|
||||
{ "spsr_und", NULL, 4, 0xF00000FF, mCORE_REGISTER_FLAGS },
|
||||
};
|
||||
|
||||
struct mVideoLogContext;
|
||||
|
||||
#define CPU_COMPONENT_AUDIO_MIXER CPU_COMPONENT_MISC_1
|
||||
|
@ -839,7 +867,7 @@ static void _GBACoreRawWrite32(struct mCore* core, uint32_t address, int segment
|
|||
GBAPatch32(cpu, address, value, NULL);
|
||||
}
|
||||
|
||||
size_t _GBAListMemoryBlocks(const struct mCore* core, const struct mCoreMemoryBlock** blocks) {
|
||||
size_t _GBACoreListMemoryBlocks(const struct mCore* core, const struct mCoreMemoryBlock** blocks) {
|
||||
const struct GBA* gba = core->board;
|
||||
switch (gba->memory.savedata.type) {
|
||||
case SAVEDATA_SRAM:
|
||||
|
@ -860,7 +888,7 @@ size_t _GBAListMemoryBlocks(const struct mCore* core, const struct mCoreMemoryBl
|
|||
}
|
||||
}
|
||||
|
||||
void* _GBAGetMemoryBlock(struct mCore* core, size_t id, size_t* sizeOut) {
|
||||
void* _GBACoreGetMemoryBlock(struct mCore* core, size_t id, size_t* sizeOut) {
|
||||
struct GBA* gba = core->board;
|
||||
switch (id) {
|
||||
default:
|
||||
|
@ -900,6 +928,137 @@ void* _GBAGetMemoryBlock(struct mCore* core, size_t id, size_t* sizeOut) {
|
|||
}
|
||||
}
|
||||
|
||||
static size_t _GBACoreListRegisters(const struct mCore* core, const struct mCoreRegisterInfo** list) {
|
||||
UNUSED(core);
|
||||
*list = _GBARegisters;
|
||||
return sizeof(_GBARegisters) / sizeof(*_GBARegisters);
|
||||
}
|
||||
|
||||
static bool _GBACoreReadRegister(const struct mCore* core, const char* name, void* out) {
|
||||
struct ARMCore* cpu = core->cpu;
|
||||
int32_t* value = out;
|
||||
switch (name[0]) {
|
||||
case 'r':
|
||||
case 'R':
|
||||
++name;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
if (strcmp(name, "cpsr") == 0 || strcmp(name, "CPSR") == 0) {
|
||||
*value = cpu->cpsr.packed;
|
||||
_ARMReadCPSR(cpu);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 'i':
|
||||
case 'I':
|
||||
if (strcmp(name, "ip") == 0 || strcmp(name, "IP") == 0) {
|
||||
*value = cpu->gprs[12];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 's':
|
||||
case 'S':
|
||||
if (strcmp(name, "sp") == 0 || strcmp(name, "SP") == 0) {
|
||||
*value = cpu->gprs[ARM_SP];
|
||||
return true;
|
||||
}
|
||||
// TODO: SPSR
|
||||
return false;
|
||||
case 'l':
|
||||
case 'L':
|
||||
if (strcmp(name, "lr") == 0 || strcmp(name, "LR") == 0) {
|
||||
*value = cpu->gprs[ARM_LR];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 'p':
|
||||
case 'P':
|
||||
if (strcmp(name, "pc") == 0 || strcmp(name, "PC") == 0) {
|
||||
*value = cpu->gprs[ARM_PC];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
char* parseEnd;
|
||||
errno = 0;
|
||||
unsigned long regId = strtoul(name, &parseEnd, 10);
|
||||
if (errno || regId > 15 || *parseEnd) {
|
||||
return false;
|
||||
}
|
||||
*value = cpu->gprs[regId];
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _GBACoreWriteRegister(struct mCore* core, const char* name, const void* in) {
|
||||
struct ARMCore* cpu = core->cpu;
|
||||
int32_t value = *(const int32_t*) in;
|
||||
switch (name[0]) {
|
||||
case 'r':
|
||||
case 'R':
|
||||
++name;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
if (strcmp(name, "cpsr") == 0) {
|
||||
cpu->cpsr.packed = value & 0xF00000FF;
|
||||
_ARMReadCPSR(cpu);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 'i':
|
||||
case 'I':
|
||||
if (strcmp(name, "ip") == 0 || strcmp(name, "IP") == 0) {
|
||||
cpu->gprs[12] = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 's':
|
||||
case 'S':
|
||||
if (strcmp(name, "sp") == 0 || strcmp(name, "SP") == 0) {
|
||||
cpu->gprs[ARM_SP] = value;
|
||||
return true;
|
||||
}
|
||||
// TODO: SPSR
|
||||
return false;
|
||||
case 'l':
|
||||
case 'L':
|
||||
if (strcmp(name, "lr") == 0 || strcmp(name, "LR") == 0) {
|
||||
cpu->gprs[ARM_LR] = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case 'p':
|
||||
case 'P':
|
||||
if (strcmp(name, "pc") == 0 || strcmp(name, "PC") == 0) {
|
||||
name = "15";
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
char* parseEnd;
|
||||
errno = 0;
|
||||
unsigned long regId = strtoul(name, &parseEnd, 10);
|
||||
if (errno || regId > 15 || *parseEnd) {
|
||||
return false;
|
||||
}
|
||||
cpu->gprs[regId] = value;
|
||||
if (regId == ARM_PC) {
|
||||
if (cpu->cpsr.t) {
|
||||
ThumbWritePC(cpu);
|
||||
} else {
|
||||
ARMWritePC(cpu);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_DEBUGGERS
|
||||
static bool _GBACoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
|
||||
UNUSED(core);
|
||||
|
@ -1233,8 +1392,11 @@ struct mCore* GBACoreCreate(void) {
|
|||
core->rawWrite8 = _GBACoreRawWrite8;
|
||||
core->rawWrite16 = _GBACoreRawWrite16;
|
||||
core->rawWrite32 = _GBACoreRawWrite32;
|
||||
core->listMemoryBlocks = _GBAListMemoryBlocks;
|
||||
core->getMemoryBlock = _GBAGetMemoryBlock;
|
||||
core->listMemoryBlocks = _GBACoreListMemoryBlocks;
|
||||
core->getMemoryBlock = _GBACoreGetMemoryBlock;
|
||||
core->listRegisters = _GBACoreListRegisters;
|
||||
core->readRegister = _GBACoreReadRegister;
|
||||
core->writeRegister = _GBACoreWriteRegister;
|
||||
#ifdef USE_DEBUGGERS
|
||||
core->supportsDebuggerType = _GBACoreSupportsDebuggerType;
|
||||
core->debuggerPlatform = _GBACoreDebuggerPlatform;
|
||||
|
|
|
@ -72,8 +72,6 @@ static void SM83DebuggerListWatchpoints(struct mDebuggerPlatform*, struct mWatch
|
|||
static void SM83DebuggerCheckBreakpoints(struct mDebuggerPlatform*);
|
||||
static bool SM83DebuggerHasBreakpoints(struct mDebuggerPlatform*);
|
||||
static void SM83DebuggerTrace(struct mDebuggerPlatform*, char* out, size_t* length);
|
||||
static bool SM83DebuggerGetRegister(struct mDebuggerPlatform*, const char* name, int32_t* value);
|
||||
static bool SM83DebuggerSetRegister(struct mDebuggerPlatform*, const char* name, int32_t value);
|
||||
|
||||
struct mDebuggerPlatform* SM83DebuggerPlatformCreate(void) {
|
||||
struct SM83Debugger* platform = malloc(sizeof(struct SM83Debugger));
|
||||
|
@ -88,8 +86,6 @@ struct mDebuggerPlatform* SM83DebuggerPlatformCreate(void) {
|
|||
platform->d.checkBreakpoints = SM83DebuggerCheckBreakpoints;
|
||||
platform->d.hasBreakpoints = SM83DebuggerHasBreakpoints;
|
||||
platform->d.trace = SM83DebuggerTrace;
|
||||
platform->d.getRegister = SM83DebuggerGetRegister;
|
||||
platform->d.setRegister = SM83DebuggerSetRegister;
|
||||
platform->d.getStackTraceMode = NULL;
|
||||
platform->d.setStackTraceMode = NULL;
|
||||
platform->d.updateStackTrace = NULL;
|
||||
|
@ -227,131 +223,3 @@ 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);
|
||||
}
|
||||
|
||||
bool SM83DebuggerGetRegister(struct mDebuggerPlatform* d, const char* name, int32_t* value) {
|
||||
struct SM83Debugger* debugger = (struct SM83Debugger*) d;
|
||||
struct SM83Core* 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 SM83DebuggerSetRegister(struct mDebuggerPlatform* d, const char* name, int32_t value) {
|
||||
struct SM83Debugger* debugger = (struct SM83Debugger*) d;
|
||||
struct SM83Core* 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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue