dolphin/Source/UnitTests/DSPJitTester.cpp

165 lines
3.7 KiB
C++
Raw Normal View History

#include "DSPJitTester.h"
DSPJitTester::DSPJitTester(u16 opcode, u16 opcode_ext, bool verbose, bool only_failed)
: be_verbose(verbose), failed_only(only_failed), run_count(0), fail_count(0)
{
instruction = opcode | opcode_ext;
opcode_template = GetOpTemplate(instruction);
sprintf(instruction_name, "%s", opcode_template->name);
if (opcode_template->extended)
sprintf(&instruction_name[strlen(instruction_name)], "'%s",
extOpTable[instruction & (((instruction >> 12) == 0x3) ? 0x7F : 0xFF)]->name);
}
bool DSPJitTester::Test(SDSP dsp_settings)
{
if (be_verbose && !failed_only)
{
printf("Running %s: ", instruction_name);
DumpRegs(dsp_settings);
}
last_input_dsp = dsp_settings;
last_int_dsp = RunInterpreter(dsp_settings);
last_jit_dsp = RunJit(dsp_settings);
run_count++;
bool success = AreEqual(last_int_dsp, last_jit_dsp);
if (!success)
fail_count++;
return success;
}
SDSP DSPJitTester::RunInterpreter(SDSP dsp_settings)
{
ResetInterpreter();
memcpy(&g_dsp, &dsp_settings, sizeof(SDSP));
ExecuteInstruction(instruction);
return g_dsp;
}
SDSP DSPJitTester::RunJit(SDSP dsp_settings)
{
ResetJit();
memcpy(&g_dsp, &dsp_settings, sizeof(SDSP));
const u8* code = jit.GetCodePtr();
jit.WriteCallInterpreter(instruction);
jit.RET();
((void(*)())code)();
return g_dsp;
}
void DSPJitTester::ResetInterpreter()
{
for (int i=0; i < WRITEBACKLOGSIZE; i++)
writeBackLogIdx[i] = -1;
}
void DSPJitTester::ResetJit()
{
jit.ClearCodeSpace();
}
bool DSPJitTester::AreEqual(SDSP& int_dsp, SDSP& jit_dsp)
{
bool equal = true;
for (int i = 0; i < DSP_REG_NUM; i++)
{
if (int_dsp.r[i] != jit_dsp.r[i])
{
if (equal)
{
if (failed_only)
{
printf("%s ", instruction_name);
DumpRegs(last_input_dsp);
}
if (be_verbose || failed_only)
printf("failed\n");
}
equal = false;
if (be_verbose || failed_only)
printf("\t%s: int = 0x%04x, jit = 0x%04x\n", regnames[i].name, int_dsp.r[i], jit_dsp.r[i]);
}
}
if (equal && be_verbose && !failed_only)
printf("passed\n");
return equal;
}
void DSPJitTester::Report()
{
printf("%s (0x%04x): Ran %d times, Failed %d times.\n", instruction_name, instruction, run_count, fail_count);
}
void DSPJitTester::DumpJittedCode()
{
ResetJit();
const u8* code = jit.GetCodePtr();
jit.WriteCallInterpreter(instruction);
int code_size = jit.GetCodePtr() - code;
printf("%s emitted: ", instruction_name);
for (int i = 0; i < code_size; i++)
printf("%02x ", code[i]);
printf("\n");
}
void DSPJitTester::DumpRegs(SDSP& dsp)
{
for (int i = 0; i < DSP_REG_NUM; i++)
if (dsp.r[i])
printf("%s=0x%04x ", regnames[i].name, dsp.r[i]);
}
void DSPJitTester::Initialize()
{
//init int
InitInstructionTable();
}
int DSPJitTester::TestOne(TestDataIterator it, SDSP& dsp)
{
int failed = 0;
if (it != test_values.end())
{
u8 reg = it->first;
TestData& data = it->second;
it++;
for (TestData::size_type i = 0; i < data.size(); i++)
{
dsp.r[reg] = data.at(i);
failed += TestOne(it, dsp);
}
}
else
{
if (!Test(dsp))
failed++;
}
return failed;
}
int DSPJitTester::TestAll(bool verbose_fail)
{
int failed = 0;
SDSP dsp;
memset(&dsp, 0, sizeof(SDSP));
bool verbose = failed_only;
failed_only = verbose_fail;
failed += TestOne(test_values.begin(), dsp);
failed_only = verbose;
return failed;
}
void DSPJitTester::AddTestData(u8 reg)
{
AddTestData(reg, 0);
AddTestData(reg, 1);
AddTestData(reg, 0x1fff);
AddTestData(reg, 0x2000);
AddTestData(reg, 0x2001);
AddTestData(reg, 0x7fff);
AddTestData(reg, 0x8000);
AddTestData(reg, 0x8001);
AddTestData(reg, 0xfffe);
AddTestData(reg, 0xffff);
}
void DSPJitTester::AddTestData(u8 reg, u16 value)
{
if (reg < DSP_REG_NUM)
test_values[reg].push_back(value);
}