Test: Use core register API instead of hardcoding

This commit is contained in:
Vicki Pfau 2022-07-09 04:34:39 -07:00
parent 8c2f2a8649
commit 5ad8907acb
1 changed files with 74 additions and 147 deletions

View File

@ -31,50 +31,37 @@
struct RomTestOpts { struct RomTestOpts {
int exitSwiImmediate; int exitSwiImmediate;
unsigned int returnCodeRegister; char* returnCodeRegister;
}; };
static void _romTestShutdown(int signal); static void _romTestShutdown(int signal);
static bool _parseRomTestOpts(struct mSubParser* parser, int option, const char* arg); static bool _parseRomTestOpts(struct mSubParser* parser, int option, const char* arg);
static bool _parseSwi(const char* regStr, int* oSwi); 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 bool _dispatchExiting = false;
static int _exitCode = 0; static int _exitCode = 0;
static struct mStandardLogger _logger; static struct mStandardLogger _logger;
static void _romTestCallback(void* context);
#ifdef M_CORE_GBA #ifdef M_CORE_GBA
static void _romTestSwi3Callback(void* context);
static void _romTestSwi16(struct ARMCore* cpu, int immediate); static void _romTestSwi16(struct ARMCore* cpu, int immediate);
static void _romTestSwi32(struct ARMCore* cpu, int immediate); static void _romTestSwi32(struct ARMCore* cpu, int immediate);
static int _exitSwiImmediate; static int _exitSwiImmediate;
static unsigned int _returnCodeRegister; static char* _returnCodeRegister;
void (*_armSwi16)(struct ARMCore* cpu, int immediate); void (*_armSwi16)(struct ARMCore* cpu, int immediate);
void (*_armSwi32)(struct ARMCore* cpu, int immediate); void (*_armSwi32)(struct ARMCore* cpu, int immediate);
#endif #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[]) { int main(int argc, char * argv[]) {
signal(SIGINT, _romTestShutdown); signal(SIGINT, _romTestShutdown);
struct RomTestOpts romTestOpts = { 3, 0 }; struct RomTestOpts romTestOpts = { 3, NULL };
struct mSubParser subparser = { struct mSubParser subparser = {
.usage = ROM_TEST_USAGE, .usage = ROM_TEST_USAGE,
.parse = _parseRomTestOpts, .parse = _parseRomTestOpts,
@ -95,7 +82,7 @@ int main(int argc, char * argv[]) {
version(argv[0]); version(argv[0]);
return 0; return 0;
} }
struct mCore* core = mCoreFind(args.fname); core = mCoreFind(args.fname);
if (!core) { if (!core) {
return 1; return 1;
} }
@ -112,21 +99,21 @@ int main(int argc, char * argv[]) {
bool cleanExit = false; bool cleanExit = false;
struct mCoreCallbacks callbacks = {0}; struct mCoreCallbacks callbacks = {0};
callbacks.context = core;
_returnCodeRegister = romTestOpts.returnCodeRegister;
if (!_romTestCheckResiger()) {
goto loadError;
}
switch (core->platform(core)) { switch (core->platform(core)) {
#ifdef M_CORE_GBA #ifdef M_CORE_GBA
case mPLATFORM_GBA: case mPLATFORM_GBA:
((struct GBA*) core->board)->hardCrash = false; ((struct GBA*) core->board)->hardCrash = false;
if (romTestOpts.returnCodeRegister >= 16) {
goto loadError;
}
_exitSwiImmediate = romTestOpts.exitSwiImmediate; _exitSwiImmediate = romTestOpts.exitSwiImmediate;
_returnCodeRegister = romTestOpts.returnCodeRegister;
if (_exitSwiImmediate == 3) { if (_exitSwiImmediate == 3) {
// Hook into SWI 3 (shutdown) // Hook into SWI 3 (shutdown)
callbacks.shutdown = _romTestSwi3Callback; callbacks.shutdown = _romTestCallback;
core->addCoreCallbacks(core, &callbacks); core->addCoreCallbacks(core, &callbacks);
} else { } else {
// Custom SWI hooks // Custom SWI hooks
@ -139,13 +126,7 @@ int main(int argc, char * argv[]) {
#endif #endif
#ifdef M_CORE_GB #ifdef M_CORE_GB
case mPLATFORM_GB: case mPLATFORM_GB:
if (romTestOpts.returnCodeRegister < GB_REG_A) { callbacks.shutdown = _romTestCallback;
goto loadError;
}
_returnCodeRegister = romTestOpts.returnCodeRegister;
callbacks.shutdown = _romTestGBCallback;
core->addCoreCallbacks(core, &callbacks); core->addCoreCallbacks(core, &callbacks);
break; break;
#endif #endif
@ -195,6 +176,9 @@ loadError:
mStandardLoggerDeinit(&_logger); mStandardLoggerDeinit(&_logger);
mCoreConfigDeinit(&core->config); mCoreConfigDeinit(&core->config);
core->deinit(core); core->deinit(core);
if (_returnCodeRegister) {
free(_returnCodeRegister);
}
return cleanExit ? _exitCode : 1; return cleanExit ? _exitCode : 1;
} }
@ -204,16 +188,62 @@ static void _romTestShutdown(int signal) {
_dispatchExiting = true; _dispatchExiting = true;
} }
#ifdef M_CORE_GBA static bool _romTestCheckResiger(void) {
static void _romTestSwi3Callback(void* context) { if (!_returnCodeRegister) {
struct mCore* core = context; return true;
_exitCode = ((struct GBA*) core->board)->cpu->regs.gprs[_returnCodeRegister]; }
const struct mCoreRegisterInfo* registers;
const struct mCoreRegisterInfo* reg = NULL;
size_t regCount = core->listRegisters(core, &registers);
size_t i;
for (i = 0; i < regCount; ++i) {
if (strcasecmp(_returnCodeRegister, registers[i].name) == 0) {
reg = &registers[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 = &registers[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; _dispatchExiting = true;
} }
#ifdef M_CORE_GBA
static void _romTestSwi16(struct ARMCore* cpu, int immediate) { static void _romTestSwi16(struct ARMCore* cpu, int immediate) {
if (immediate == _exitSwiImmediate) { if (immediate == _exitSwiImmediate) {
_exitCode = cpu->regs.gprs[_returnCodeRegister]; core->readRegister(core, _returnCodeRegister, &_exitCode);
_dispatchExiting = true; _dispatchExiting = true;
return; return;
} }
@ -222,7 +252,7 @@ static void _romTestSwi16(struct ARMCore* cpu, int immediate) {
static void _romTestSwi32(struct ARMCore* cpu, int immediate) { static void _romTestSwi32(struct ARMCore* cpu, int immediate) {
if (immediate == _exitSwiImmediate) { if (immediate == _exitSwiImmediate) {
_exitCode = cpu->regs.gprs[_returnCodeRegister]; core->readRegister(core, _returnCodeRegister, &_exitCode);
_dispatchExiting = true; _dispatchExiting = true;
return; return;
} }
@ -230,41 +260,6 @@ static void _romTestSwi32(struct ARMCore* cpu, int immediate) {
} }
#endif #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) { static bool _parseRomTestOpts(struct mSubParser* parser, int option, const char* arg) {
struct RomTestOpts* opts = parser->opts; struct RomTestOpts* opts = parser->opts;
errno = 0; errno = 0;
@ -272,7 +267,8 @@ static bool _parseRomTestOpts(struct mSubParser* parser, int option, const char*
case 'S': case 'S':
return _parseSwi(arg, &opts->exitSwiImmediate); return _parseSwi(arg, &opts->exitSwiImmediate);
case 'R': case 'R':
return _parseNamedRegister(arg, &opts->returnCodeRegister); opts->returnCodeRegister = strdup(arg);
return true;
default: default:
return false; return false;
} }
@ -287,72 +283,3 @@ static bool _parseSwi(const char* swiStr, int* oSwi) {
*oSwi = swi; *oSwi = swi;
return true; 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;
}