diff --git a/Makefile b/Makefile index c3e8570..3eeff04 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ WARNINGS += -Werror=unused-parameter -Werror=shadow -Werror=switch -Werro WARNINGS_C := -Werror=implicit-function-declaration -Werror=incompatible-pointer-types WARNINGS += -Werror=type-limits WARNINGS_CXX := +WARNINGS_ELFS := -Wno-override-init ifeq ($(CC),gcc) WARNINGS += -Wno-cast-function-type -Wformat-truncation -Wformat-overflow -Wno-nonnull-compare @@ -132,10 +133,10 @@ tests: $(TESTS_ELFS) #### Various Recipes #### build/%.elf: %.c $(STATIC_LIB) - $(CC) -MMD -MP $(CSTD) $(OPTFLAGS) $(IINC) $(WARNINGS) $(WARNINGS_C) $(CFLAGS) -o $@ $< $(LDFLAGS) + $(CC) -MMD -MP $(CSTD) $(OPTFLAGS) $(IINC) $(WARNINGS) $(WARNINGS_C) $(WARNINGS_ELFS) $(CFLAGS) -o $@ $< $(LDFLAGS) build/%.elf: %.cpp $(STATIC_LIB_XX) - $(CXX) -MMD -MP $(CXXSTD) $(OPTFLAGS) $(IINC_XX) $(WARNINGS) $(WARNINGS_CXX) $(CXXFLAGS) -o $@ $< $(LDXXFLAGS) + $(CXX) -MMD -MP $(CXXSTD) $(OPTFLAGS) $(IINC_XX) $(WARNINGS) $(WARNINGS_CXX) $(WARNINGS_ELFS) $(CXXFLAGS) -o $@ $< $(LDXXFLAGS) build/%.a: $(AR) rcs $@ $^ diff --git a/tests/c/instruction_checks/expected_disasm_utils.h b/tests/c/instruction_checks/expected_disasm_utils.h index d95cc25..b357c9c 100644 --- a/tests/c/instruction_checks/expected_disasm_utils.h +++ b/tests/c/instruction_checks/expected_disasm_utils.h @@ -28,10 +28,13 @@ typedef struct TestEntry { uint32_t word; const char *immOverride; const char *expectedStr; + bool gnuMode; } TestEntry; -#define TEST_ENTRY(cat, w, imm, expected) \ - { .category = cat, .word = w, .immOverride = imm, .expectedStr = expected, } +#define TEST_ENTRY(cat, w, imm, expected, ...) \ + { .category = cat, .word = w, .immOverride = imm, .expectedStr = expected, .gnuMode = true, __VA_ARGS__ } + +#define BOOL_STR(x) ((x) ? "true" : "false") typedef struct InstrInitInfo { void (*init)(RabbitizerInstruction *self, uint32_t word, uint32_t vram); @@ -94,6 +97,8 @@ bool check_expected_output(const TestEntry *entry) { size_t immOverrideLength = strlen_null(entry->immOverride); const InstrInitInfo *info = &initInfos[entry->category]; + RabbitizerConfig_Cfg.toolchainTweaks.gnuMode = entry->gnuMode; + check_infos_validity(); info->init(&instr, entry->word, 0); @@ -106,10 +111,12 @@ bool check_expected_output(const TestEntry *entry) { RabbitizerInstruction_disassemble(&instr, buffer, entry->immOverride, immOverrideLength, 0); if (entry->expectedStr == NULL) { - printf("Word '0x%08X' doesn't have a expected str, got '%s'\n", entry->word, buffer); + fprintf(stderr, "Word '0x%08X' doesn't have a expected str, got '%s'\n", entry->word, buffer); + fprintf(stderr, " gnuMode '%s'\n", BOOL_STR(entry->gnuMode)); expected = false; } else if (strcmp(buffer, entry->expectedStr) != 0) { fprintf(stderr, "Error on word '0x%08X'. Expected '%s', got '%s'\n", entry->word, entry->expectedStr, buffer); + fprintf(stderr, " gnuMode '%s'\n", BOOL_STR(entry->gnuMode)); expected = false; } diff --git a/tests/c/instruction_checks/jalr.c b/tests/c/instruction_checks/jalr.c index 0129689..7113a0a 100644 --- a/tests/c/instruction_checks/jalr.c +++ b/tests/c/instruction_checks/jalr.c @@ -17,6 +17,19 @@ int main() { size_t rs; int errorCount = 0; + /** + * Generates and checks all possible jalr combinations. + * + * jalr has 2 syntaxes, one for an explicit return address and another for an implicit one + * (implicit assumes $ra). + * Both syntaxes use an explicit register to jump to. + * + * Since I didn't want to make a TestEntry array with all the 1024 combinations then I'm + * manually checking each part of the disassembled instruction to match what I expect. + * + * Checking all the possible combinations is overkill, but the test is already written, so meh. + */ + for (rs = 0; rs < RAB_REGISTERS_COUNT; rs++) { uint32_t shifted_rs = RAB_INSTR_PACK_rs(0, rs); size_t rd; @@ -42,6 +55,8 @@ int main() { bufferPtr += strlen(INSTR_OPCODE_PREFIX); if (rd == RABBITIZER_REG_GPR_O32_ra) { + /* Implicit return address */ + if (!STR_STARTS_WITH(bufferPtr, rsName)) { fprintf(stderr, "Error in word 0x%08X. Expected '%s', got '%s'\n", new_word, rsName, bufferPtr); errorCount++; @@ -54,6 +69,8 @@ int main() { } } } else { + /* Explicit return address */ + const char *rdName = RabbitizerRegister_getNameGpr(rd); if (!STR_STARTS_WITH(bufferPtr, rdName)) { diff --git a/tests/c/instruction_checks/plain_disassembly.c b/tests/c/instruction_checks/plain_disassembly.c index 27625dc..8e6717a 100644 --- a/tests/c/instruction_checks/plain_disassembly.c +++ b/tests/c/instruction_checks/plain_disassembly.c @@ -9,7 +9,7 @@ #include "expected_disasm_utils.h" -#define TEST_ENTRY_C(word, imm, expected) TEST_ENTRY(RABBITIZER_INSTRCAT_CPU, word, imm, expected) +#define TEST_ENTRY_C(word, imm, expected) TEST_ENTRY(RABBITIZER_INSTRCAT_CPU, word, imm, expected,) const TestEntry entries[] = { TEST_ENTRY_C(0x3C088001, NULL, "lui $t0, 0x8001"), diff --git a/tests/c/instruction_checks/r3000gte_disasm.c b/tests/c/instruction_checks/r3000gte_disasm.c index e62f4c7..31afbca 100644 --- a/tests/c/instruction_checks/r3000gte_disasm.c +++ b/tests/c/instruction_checks/r3000gte_disasm.c @@ -9,7 +9,7 @@ #include "expected_disasm_utils.h" -#define TEST_ENTRY_C(word, imm, expected) TEST_ENTRY(RABBITIZER_INSTRCAT_R3000GTE, word, imm, expected) +#define TEST_ENTRY_C(word, imm, expected) TEST_ENTRY(RABBITIZER_INSTRCAT_R3000GTE, word, imm, expected,) const TestEntry entries[] = { TEST_ENTRY_C(0x4A180001, NULL, "RTPS"), diff --git a/tests/c/instruction_checks/r5900_trunc_cvt.c b/tests/c/instruction_checks/r5900_trunc_cvt.c index 3dfaa13..6ddb277 100644 --- a/tests/c/instruction_checks/r5900_trunc_cvt.c +++ b/tests/c/instruction_checks/r5900_trunc_cvt.c @@ -7,19 +7,15 @@ #include #include +#include "expected_disasm_utils.h" -typedef struct TestEntry { - uint32_t word; - bool gnuMode; - const char *expectedStr; -} TestEntry; - +#define TEST_ENTRY_C(word, gnu, imm, expected) TEST_ENTRY(RABBITIZER_INSTRCAT_R5900, word, imm, expected, .gnuMode=gnu,) const TestEntry entries[] = { - { 0x4600600D, true, ".word 0x4600600D # trunc.w.s $f0, $f12 # 00000000 " }, - { 0x46006024, true, ".word 0x46006024 # cvt.w.s $f0, $f12 # 00000000 " }, - { 0x4600600D, false, "trunc.w.s $f0, $f12" }, - { 0x46006024, false, "cvt.w.s $f0, $f12" }, + TEST_ENTRY_C(0x4600600D, true, NULL, ".word 0x4600600D # trunc.w.s $f0, $f12 # 00000000 "), + TEST_ENTRY_C(0x46006024, true, NULL, ".word 0x46006024 # cvt.w.s $f0, $f12 # 00000000 "), + TEST_ENTRY_C(0x4600600D, false, NULL, "trunc.w.s $f0, $f12"), + TEST_ENTRY_C(0x46006024, false, NULL, "cvt.w.s $f0, $f12"), }; int main() { @@ -27,31 +23,9 @@ int main() { size_t i; for (i = 0; i < ARRAY_COUNT(entries); i++) { - const TestEntry *entry = &entries[i]; - RabbitizerConfig_Cfg.toolchainTweaks.gnuMode = entry->gnuMode; - RabbitizerInstruction instr; - char *buffer; - size_t bufferSize; - - RabbitizerInstructionR5900_init(&instr, entry->word, 0x80000000); - RabbitizerInstructionR5900_processUniqueId(&instr); - - bufferSize = RabbitizerInstruction_getSizeForBuffer(&instr, 0, 0); - buffer = malloc(bufferSize + 1); - assert(buffer != NULL); - - RabbitizerInstruction_disassemble(&instr, buffer, NULL, 0, 0); - - if (entry->expectedStr == NULL) { - printf("Word '0x%08X' gnuMode '%s' doesn't have a expected str, got '%s'\n", entry->word, entry->gnuMode ? "true" : "false", buffer); - errorCount++; - } else if (strcmp(buffer, entry->expectedStr) != 0) { - fprintf(stderr, "Error on word '0x%08X' gnuMode '%s'. Expected '%s', got '%s'\n", entry->word, entry->gnuMode ? "true" : "false", entry->expectedStr, buffer); + if (!check_expected_output(&entries[i])) { errorCount++; } - - free(buffer); - RabbitizerInstructionR5900_destroy(&instr); } return errorCount; diff --git a/tests/c/instruction_checks/r5900_vcallms.c b/tests/c/instruction_checks/r5900_vcallms.c index e11e718..f8d4df3 100644 --- a/tests/c/instruction_checks/r5900_vcallms.c +++ b/tests/c/instruction_checks/r5900_vcallms.c @@ -9,7 +9,7 @@ #include "expected_disasm_utils.h" -#define TEST_ENTRY_C(word, imm, expected) TEST_ENTRY(RABBITIZER_INSTRCAT_R5900, word, imm, expected) +#define TEST_ENTRY_C(word, imm, expected) TEST_ENTRY(RABBITIZER_INSTRCAT_R5900, word, imm, expected,) const TestEntry entries[] = { TEST_ENTRY_C(0x4A000038, NULL, "vcallms 0x0"),