blob: f157bea00dbccb1eb3e9b94a1c366fc5d9f50658 [file] [edit]
#include "fadec.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEST_FMTREG(exp, ...) test_fmtreg(#__VA_ARGS__, exp, __VA_ARGS__)
static unsigned test_fmtreg(const char* str, const char* exp, FdRegType ty,
FdReg idx, unsigned sizelog) {
char fmt[16];
unsigned len = fd_format_reg(ty, idx, sizelog, fmt);
if (!strcmp(fmt, exp) && len == strlen(fmt))
return 0;
printf("Failed fd_format_reg case: \"%s\" != \"%s\" (%s)\n", exp, fmt, str);
return 1;
}
int main(void) {
unsigned failed = 0;
failed += TEST_FMTREG("al", FD_RT_GPL, FD_REG_AX, 0);
failed += TEST_FMTREG("ah", FD_RT_GPH, FD_REG_AH, 0);
failed += TEST_FMTREG("ax", FD_RT_GPL, FD_REG_AX, 1);
failed += TEST_FMTREG("eax", FD_RT_GPL, FD_REG_AX, 2);
failed += TEST_FMTREG("rax", FD_RT_GPL, FD_REG_AX, 3);
failed += TEST_FMTREG("xmm0", FD_RT_VEC, FD_REG_R0, 3);
failed += TEST_FMTREG("xmm0", FD_RT_VEC, FD_REG_R0, 4);
failed += TEST_FMTREG("ymm0", FD_RT_VEC, FD_REG_R0, 5);
failed += TEST_FMTREG("zmm0", FD_RT_VEC, FD_REG_R0, 6);
static const struct TestCase {
uint8_t buf[21];
uint8_t buf_len;
uint8_t mode;
uint8_t addr;
const char* exp;
} cases[] = {
#define TEST1(mode, buf, exp) {buf, sizeof(buf) - 1, mode, 0, exp},
#define TEST32(buf, exp) TEST1(32, buf, exp)
#define TEST64(buf, exp) TEST1(64, buf, exp)
#define TEST3264(buf, exp32, exp64) TEST32(buf, exp32) TEST64(buf, exp64)
#define TEST(buf, exp) TEST32(buf, exp) TEST64(buf, exp)
#include "decode-test.inc"
// Test legacy absolute address mode.
{"\x70\x00", 2, 64, /*addr=*/128, "jo 0x82"},
// Test invalid mode.
{"", 0, 16, 0, ""},
};
const struct TestCase* end = cases + sizeof(cases) / sizeof(cases[0]);
for (const struct TestCase* tc = cases; tc != end; tc++) {
FdInstr instr;
char fmt[128] = {0};
int retval = fd_decode(tc->buf, tc->buf_len, tc->mode, tc->addr, &instr);
if (retval == FD_ERR_INTERNAL)
continue; // not compiled with this arch-mode (32/64 bit)
else if (retval == FD_ERR_PARTIAL)
strcpy(fmt, "PARTIAL");
else if (retval == FD_ERR_UD)
strcpy(fmt, "UD");
else
fd_format(&instr, fmt, sizeof(fmt));
if ((retval < 0 || (unsigned)retval == tc->buf_len)) {
if (!strcmp(fmt, tc->exp))
continue;
// Consider 32/64 bit differences, e.g. for addressing mode.
for (const char* it = tc->exp; (it = (const char*)strchr(it, '@')); it++)
if (fmt[it - tc->exp] == (tc->mode != 64 ? 'e' : 'r'))
fmt[it - tc->exp] = '@';
if (!strcmp(fmt, tc->exp))
continue;
}
failed += 1;
printf("Failed case (%u-bit): ", tc->mode);
for (size_t i = 0; i < tc->buf_len; i++)
printf("%02x", tc->buf[i]);
printf("\n Exp (%2u): %s", tc->buf_len, tc->exp);
printf("\n Got (%2d): %s\n", retval, fmt);
}
puts(failed ? "Some tests FAILED" : "All tests PASSED");
return failed ? EXIT_FAILURE : EXIT_SUCCESS;
}