diff --git a/src/platform/test/rom-test-main.c b/src/platform/test/rom-test-main.c index afec63935..17d162622 100644 --- a/src/platform/test/rom-test-main.c +++ b/src/platform/test/rom-test-main.c @@ -31,50 +31,37 @@ struct RomTestOpts { int exitSwiImmediate; - unsigned int returnCodeRegister; + char* returnCodeRegister; }; static void _romTestShutdown(int signal); static bool _parseRomTestOpts(struct mSubParser* parser, int option, const char* arg); static bool _parseSwi(const char* regStr, int* oSwi); -static bool _parseNamedRegister(const char* regStr, unsigned int* oRegister); + +static bool _romTestCheckResiger(void); + +static struct mCore* core; static bool _dispatchExiting = false; static int _exitCode = 0; static struct mStandardLogger _logger; +static void _romTestCallback(void* context); #ifdef M_CORE_GBA -static void _romTestSwi3Callback(void* context); - static void _romTestSwi16(struct ARMCore* cpu, int immediate); static void _romTestSwi32(struct ARMCore* cpu, int immediate); static int _exitSwiImmediate; -static unsigned int _returnCodeRegister; +static char* _returnCodeRegister; void (*_armSwi16)(struct ARMCore* cpu, int immediate); void (*_armSwi32)(struct ARMCore* cpu, int immediate); #endif -#ifdef M_CORE_GB -enum GBReg { - GB_REG_A = 16, - GB_REG_F, - GB_REG_B, - GB_REG_C, - GB_REG_D, - GB_REG_E, - GB_REG_H, - GB_REG_L -}; - -static void _romTestGBCallback(void* context); -#endif - int main(int argc, char * argv[]) { signal(SIGINT, _romTestShutdown); - struct RomTestOpts romTestOpts = { 3, 0 }; + struct RomTestOpts romTestOpts = { 3, NULL }; struct mSubParser subparser = { .usage = ROM_TEST_USAGE, .parse = _parseRomTestOpts, @@ -95,7 +82,7 @@ int main(int argc, char * argv[]) { version(argv[0]); return 0; } - struct mCore* core = mCoreFind(args.fname); + core = mCoreFind(args.fname); if (!core) { return 1; } @@ -112,21 +99,21 @@ int main(int argc, char * argv[]) { bool cleanExit = false; struct mCoreCallbacks callbacks = {0}; - callbacks.context = core; + + _returnCodeRegister = romTestOpts.returnCodeRegister; + if (!_romTestCheckResiger()) { + goto loadError; + } + switch (core->platform(core)) { #ifdef M_CORE_GBA case mPLATFORM_GBA: ((struct GBA*) core->board)->hardCrash = false; - if (romTestOpts.returnCodeRegister >= 16) { - goto loadError; - } - _exitSwiImmediate = romTestOpts.exitSwiImmediate; - _returnCodeRegister = romTestOpts.returnCodeRegister; if (_exitSwiImmediate == 3) { // Hook into SWI 3 (shutdown) - callbacks.shutdown = _romTestSwi3Callback; + callbacks.shutdown = _romTestCallback; core->addCoreCallbacks(core, &callbacks); } else { // Custom SWI hooks @@ -139,13 +126,7 @@ int main(int argc, char * argv[]) { #endif #ifdef M_CORE_GB case mPLATFORM_GB: - if (romTestOpts.returnCodeRegister < GB_REG_A) { - goto loadError; - } - - _returnCodeRegister = romTestOpts.returnCodeRegister; - - callbacks.shutdown = _romTestGBCallback; + callbacks.shutdown = _romTestCallback; core->addCoreCallbacks(core, &callbacks); break; #endif @@ -195,6 +176,9 @@ loadError: mStandardLoggerDeinit(&_logger); mCoreConfigDeinit(&core->config); core->deinit(core); + if (_returnCodeRegister) { + free(_returnCodeRegister); + } return cleanExit ? _exitCode : 1; } @@ -204,16 +188,62 @@ static void _romTestShutdown(int signal) { _dispatchExiting = true; } -#ifdef M_CORE_GBA -static void _romTestSwi3Callback(void* context) { - struct mCore* core = context; - _exitCode = ((struct GBA*) core->board)->cpu->regs.gprs[_returnCodeRegister]; +static bool _romTestCheckResiger(void) { + if (!_returnCodeRegister) { + return true; + } + + const struct mCoreRegisterInfo* registers; + const struct mCoreRegisterInfo* reg = NULL; + size_t regCount = core->listRegisters(core, ®isters); + size_t i; + for (i = 0; i < regCount; ++i) { + if (strcasecmp(_returnCodeRegister, registers[i].name) == 0) { + reg = ®isters[i]; + break; + } + if (registers[i].aliases) { + size_t j; + for (j = 0; registers[i].aliases[j]; ++j) { + if (strcasecmp(_returnCodeRegister, registers[i].aliases[j]) == 0) { + reg = ®isters[i]; + break; + } + } + if (reg) { + break; + } + } + } + if (!reg) { + return false; + } + + if (reg->width > 4) { + return false; + } + + if (reg->type != mCORE_REGISTER_GPR) { + return false; + } + + if (reg->mask != 0xFFFFFFFFU >> (4 - reg->width) * 8) { + return false; + } + + return true; +} + +static void _romTestCallback(void* context) { + UNUSED(context); + core->readRegister(core, _returnCodeRegister, &_exitCode); _dispatchExiting = true; } +#ifdef M_CORE_GBA static void _romTestSwi16(struct ARMCore* cpu, int immediate) { if (immediate == _exitSwiImmediate) { - _exitCode = cpu->regs.gprs[_returnCodeRegister]; + core->readRegister(core, _returnCodeRegister, &_exitCode); _dispatchExiting = true; return; } @@ -222,7 +252,7 @@ static void _romTestSwi16(struct ARMCore* cpu, int immediate) { static void _romTestSwi32(struct ARMCore* cpu, int immediate) { if (immediate == _exitSwiImmediate) { - _exitCode = cpu->regs.gprs[_returnCodeRegister]; + core->readRegister(core, _returnCodeRegister, &_exitCode); _dispatchExiting = true; return; } @@ -230,41 +260,6 @@ static void _romTestSwi32(struct ARMCore* cpu, int immediate) { } #endif -#ifdef M_CORE_GB -static void _romTestGBCallback(void* context) { - struct mCore* core = context; - struct SM83Core* cpu = core->cpu; - - switch (_returnCodeRegister) { - case GB_REG_A: - _exitCode = cpu->a; - break; - case GB_REG_B: - _exitCode = cpu->b; - break; - case GB_REG_C: - _exitCode = cpu->c; - break; - case GB_REG_D: - _exitCode = cpu->d; - break; - case GB_REG_E: - _exitCode = cpu->e; - break; - case GB_REG_F: - _exitCode = cpu->f.packed; - break; - case GB_REG_H: - _exitCode = cpu->h; - break; - case GB_REG_L: - _exitCode = cpu->l; - break; - } - _dispatchExiting = true; -} -#endif - static bool _parseRomTestOpts(struct mSubParser* parser, int option, const char* arg) { struct RomTestOpts* opts = parser->opts; errno = 0; @@ -272,7 +267,8 @@ static bool _parseRomTestOpts(struct mSubParser* parser, int option, const char* case 'S': return _parseSwi(arg, &opts->exitSwiImmediate); case 'R': - return _parseNamedRegister(arg, &opts->returnCodeRegister); + opts->returnCodeRegister = strdup(arg); + return true; default: return false; } @@ -287,72 +283,3 @@ static bool _parseSwi(const char* swiStr, int* oSwi) { *oSwi = swi; return true; } - -static bool _parseNamedRegister(const char* regStr, unsigned int* oRegister) { -#ifdef M_CORE_GB - static const enum GBReg gbMapping[] = { - ['a' - 'a'] = GB_REG_A, - ['b' - 'a'] = GB_REG_B, - ['c' - 'a'] = GB_REG_C, - ['d' - 'a'] = GB_REG_D, - ['e' - 'a'] = GB_REG_E, - ['f' - 'a'] = GB_REG_F, - ['h' - 'a'] = GB_REG_H, - ['l' - 'a'] = GB_REG_L, - }; -#endif - - switch (regStr[0]) { - case 'r': - case 'R': - ++regStr; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - break; -#ifdef M_CORE_GB - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - case 'h': - case 'l': - if (regStr[1] != '\0') { - return false; - } - *oRegister = gbMapping[regStr[0] - 'a']; - break; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - case 'H': - case 'L': - if (regStr[1] != '\0') { - return false; - } - *oRegister = gbMapping[regStr[0] - 'A']; - return true; -#endif - } - - char* parseEnd; - unsigned long regId = strtoul(regStr, &parseEnd, 10); - if (errno || regId > 15 || *parseEnd) { - return false; - } - *oRegister = regId; - return true; -}