moar testing! changed some things to make it easier to use, added some bits of documentation for other devs eager to use it :)
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5358 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
122d5e7b4e
commit
578828a142
|
@ -2,69 +2,78 @@
|
|||
|
||||
void nx_dr()
|
||||
{
|
||||
SDSP test_dsp;
|
||||
DSPJitTester tester(0x40, 0x04);
|
||||
|
||||
for (u16 input_reg = 0; input_reg < 50; input_reg++)
|
||||
for (u16 input_wr0 = 0; input_wr0 < 10; input_wr0++)
|
||||
{
|
||||
memset(&test_dsp, 0, sizeof(SDSP));
|
||||
test_dsp.r[DSP_REG_WR0] = input_wr0;
|
||||
test_dsp.r[0] = input_reg;
|
||||
if (!tester.Test(test_dsp))
|
||||
{
|
||||
printf("%s Test failed: in = 0x%04x, wr0 = 0x%04x > int = 0x%04x, jit = 0x%04x\n",
|
||||
tester.GetInstructionName(),
|
||||
input_reg, input_wr0,
|
||||
tester.GetLastInterpreterDSP().r[0], tester.GetLastJitDSP().r[0]);
|
||||
}
|
||||
}
|
||||
DSPJitTester tester(0x8000, 0x0004);
|
||||
tester.AddTestData(DSP_REG_ACC0);
|
||||
tester.AddTestData(DSP_REG_WR0);
|
||||
tester.TestAll();
|
||||
tester.Report();
|
||||
}
|
||||
|
||||
void nx_ir()
|
||||
{
|
||||
SDSP test_dsp;
|
||||
DSPJitTester tester(0x40, 0x08);
|
||||
|
||||
for (u16 input_reg = 0; input_reg < 50; input_reg++)
|
||||
for (u16 input_wr0 = 0; input_wr0 < 10; input_wr0++)
|
||||
{
|
||||
memset(&test_dsp, 0, sizeof(SDSP));
|
||||
test_dsp.r[DSP_REG_WR0] = input_wr0;
|
||||
test_dsp.r[0] = input_reg;
|
||||
if (!tester.Test(test_dsp))
|
||||
{
|
||||
printf("%s Test failed: in = 0x%04x, wr0 = 0x%04x > int = 0x%04x, jit = 0x%04x\n",
|
||||
tester.GetInstructionName(),
|
||||
input_reg, input_wr0,
|
||||
tester.GetLastInterpreterDSP().r[0], tester.GetLastJitDSP().r[0]);
|
||||
}
|
||||
}
|
||||
DSPJitTester tester(0x8000, 0x0008);
|
||||
tester.AddTestData(DSP_REG_ACC0);
|
||||
tester.AddTestData(DSP_REG_WR0);
|
||||
tester.TestAll();
|
||||
tester.Report();
|
||||
}
|
||||
|
||||
void nx_nr()
|
||||
{
|
||||
SDSP test_dsp;
|
||||
DSPJitTester tester(0x40, 0x0c);
|
||||
DSPJitTester tester(0x8000, 0x000c);
|
||||
tester.AddTestData(DSP_REG_ACC0);
|
||||
tester.AddTestData(DSP_REG_WR0);
|
||||
tester.AddTestData(DSP_REG_IX0);
|
||||
tester.TestAll(true);
|
||||
tester.Report();
|
||||
}
|
||||
|
||||
for (u16 input_reg = 0; input_reg < 10; input_reg++)
|
||||
for (u16 input_wr0 = 0; input_wr0 < 10; input_wr0++)
|
||||
for (u16 input_ix0 = 0; input_ix0 < 10; input_ix0++)
|
||||
{
|
||||
memset(&test_dsp, 0, sizeof(SDSP));
|
||||
test_dsp.r[DSP_REG_IX0] = input_ix0;
|
||||
test_dsp.r[DSP_REG_WR0] = input_wr0;
|
||||
test_dsp.r[0] = input_reg;
|
||||
if (!tester.Test(test_dsp))
|
||||
{
|
||||
printf("%s Test failed: in = 0x%04x, wr0 = 0x%04x, ix0 = 0x%04x > int = 0x%04x, jit = 0x%04x\n",
|
||||
tester.GetInstructionName(),
|
||||
input_reg, input_wr0, input_ix0,
|
||||
tester.GetLastInterpreterDSP().r[0], tester.GetLastJitDSP().r[0]);
|
||||
}
|
||||
}
|
||||
void dar()
|
||||
{
|
||||
DSPJitTester tester(0x0004);
|
||||
tester.AddTestData(DSP_REG_ACC0);
|
||||
tester.AddTestData(DSP_REG_WR0);
|
||||
tester.TestAll();
|
||||
tester.Report();
|
||||
}
|
||||
void iar()
|
||||
{
|
||||
DSPJitTester tester(0x0008);
|
||||
tester.AddTestData(DSP_REG_ACC0);
|
||||
tester.AddTestData(DSP_REG_WR0);
|
||||
tester.TestAll();
|
||||
tester.Report();
|
||||
}
|
||||
void subarn()
|
||||
{
|
||||
DSPJitTester tester(0x000c);
|
||||
tester.AddTestData(DSP_REG_ACC0);
|
||||
tester.AddTestData(DSP_REG_WR0);
|
||||
tester.AddTestData(DSP_REG_IX0);
|
||||
tester.TestAll();
|
||||
tester.Report();
|
||||
}
|
||||
void addarn()
|
||||
{
|
||||
DSPJitTester tester(0x0010);
|
||||
tester.AddTestData(DSP_REG_ACC0);
|
||||
tester.AddTestData(DSP_REG_WR0);
|
||||
tester.AddTestData(DSP_REG_IX0);
|
||||
tester.TestAll();
|
||||
tester.Report();
|
||||
}
|
||||
void sbclr()
|
||||
{
|
||||
DSPJitTester tester(0x1200);
|
||||
tester.AddTestData(DSP_REG_SR);
|
||||
tester.TestAll();
|
||||
tester.Report();
|
||||
}
|
||||
void sbset()
|
||||
{
|
||||
DSPJitTester tester(0x1300);
|
||||
tester.AddTestData(DSP_REG_SR);
|
||||
tester.TestAll();
|
||||
tester.Report();
|
||||
}
|
||||
|
||||
|
@ -72,6 +81,13 @@ void AudioJitTests()
|
|||
{
|
||||
DSPJitTester::Initialize();
|
||||
|
||||
dar();
|
||||
iar();
|
||||
subarn();
|
||||
addarn();
|
||||
sbclr();
|
||||
sbset();
|
||||
|
||||
nx_ir();
|
||||
nx_dr();
|
||||
nx_nr();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "DSPJitTester.h"
|
||||
|
||||
DSPJitTester::DSPJitTester(u16 opcode, u16 opcode_ext, bool verbose)
|
||||
: be_verbose(verbose), run_count(0), fail_count(0)
|
||||
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 << 9 | opcode_ext;
|
||||
instruction = opcode | opcode_ext;
|
||||
opcode_template = GetOpTemplate(instruction);
|
||||
sprintf(instruction_name, "%s", opcode_template->name);
|
||||
if (opcode_template->extended)
|
||||
|
@ -12,9 +12,13 @@ DSPJitTester::DSPJitTester(u16 opcode, u16 opcode_ext, bool verbose)
|
|||
}
|
||||
bool DSPJitTester::Test(SDSP dsp_settings)
|
||||
{
|
||||
if (be_verbose)
|
||||
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);
|
||||
|
||||
|
@ -55,18 +59,26 @@ void DSPJitTester::ResetJit()
|
|||
bool DSPJitTester::AreEqual(SDSP& int_dsp, SDSP& jit_dsp)
|
||||
{
|
||||
bool equal = true;
|
||||
for (int i = 0; i < 32; i++)
|
||||
for (int i = 0; i < DSP_REG_NUM; i++)
|
||||
{
|
||||
if (int_dsp.r[i] != jit_dsp.r[i])
|
||||
{
|
||||
if (equal && be_verbose)
|
||||
printf("failed\n");
|
||||
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)
|
||||
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)
|
||||
if (equal && be_verbose && !failed_only)
|
||||
printf("passed\n");
|
||||
return equal;
|
||||
}
|
||||
|
@ -86,8 +98,68 @@ void DSPJitTester::DumpJittedCode()
|
|||
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);
|
||||
}
|
|
@ -1,11 +1,76 @@
|
|||
// How to use the DSPJitTester:
|
||||
//
|
||||
// == Before running ==
|
||||
// Make sure to call Initialize to set initial stuff required by int and jit:
|
||||
// DSPJitTester::Initialize();
|
||||
//
|
||||
// == Creation of a testcase ==
|
||||
// Create a testcase for a normal operation:
|
||||
// DSPJitTester tester(0x0004); //taken from DSPTables.cpp, opcodes[]
|
||||
//
|
||||
// Create a testcase for an extended operation:
|
||||
// DSPJitTester tester(0x8000, 0x0004); //NX from opcodes, DR from opcodes_ext
|
||||
//
|
||||
// By default, no messages are written.
|
||||
// To log all operations, set verbose to true:
|
||||
// DSPJitTester tester(0x8000, 0x0004, true);
|
||||
//
|
||||
// You can also choose to only print failing tests:
|
||||
// DSPJitTester tester(0x8000, 0x0004, verbosity_setting, true);
|
||||
// verbose = true will give the same output as verbose,
|
||||
// while verbose = false will only (really!) print failing tests.
|
||||
//
|
||||
// == Setting up values ==
|
||||
// You can set the tester up with values for each DSP register:
|
||||
// tester.AddTestData(DSP_REG_ACC0, 1);
|
||||
// tester.AddTestData(DSP_REG_ACC0, 2);
|
||||
// tester.AddTestData(DSP_REG_ACC0, 3);
|
||||
//
|
||||
// You can also choose to have a few predefined values added for a register:
|
||||
// tester.AddTestData(DSP_REG_ACC0); //see the method body for the values added
|
||||
//
|
||||
// == Running the tests ==
|
||||
// After setup, you can either run JIT against the interpreter
|
||||
// using all predefined register values, pass your own set of
|
||||
// registers or run either of the two independently from each other.
|
||||
//
|
||||
// int failed_tests = tester.TestAll(); //run jit against int, using values from AddTestData
|
||||
// int failed_tests = tester.TestAll(true); //override the value for only_failed to show failure
|
||||
//
|
||||
// SDSP dsp = GetCustomSetOfRegisters();
|
||||
// bool success = tester.Test(dsp); //run jit against int, using a custom set of register values
|
||||
//
|
||||
// SDSP result = tester.RunInterpreter(dsp); //run int alone
|
||||
// SDSP result = tester.RunJit(dsp); //run jit alone
|
||||
//
|
||||
// == Examining results ==
|
||||
// When either verbose or only_failed is set to true, the tester will automatically report
|
||||
// failure to stdout, along with input registers and the differences in output registers.
|
||||
//
|
||||
// tester.Report(); //display a small report afterwards
|
||||
//
|
||||
// SDSP int = tester.GetLastInterpreterDSP(); //examine the DSP set left after running int
|
||||
// SDSP jit = tester.GetLastJitDSP(); //same for jit
|
||||
//
|
||||
// int tests_run = tester.GetRunCount();
|
||||
// int tests_failed = tester.GetFailCount();
|
||||
// const char* tested_instruction = tester.GetInstructionName();
|
||||
// printf("%s ran %d tests and failed %d times\n", tested_instruction, tests_run, tests_failed);
|
||||
//
|
||||
// tester.DumpJittedCode(); //prints the code bytes produced by jit (examine with udcli/udis86 or similar)
|
||||
|
||||
#ifndef __DSP_JIT_TESTER_
|
||||
#define __DSP_JIT_TESTER_
|
||||
|
||||
#include "DSPCore.h"
|
||||
#include "DSPInterpreter.h"
|
||||
//#include "DSPIntExtOps.h"
|
||||
//
|
||||
//#include "x64Emitter.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<u16> TestData;
|
||||
typedef std::map<u8, TestData> TestDataList;
|
||||
typedef TestDataList::iterator TestDataIterator;
|
||||
#define DSP_REG_NUM 32
|
||||
|
||||
class DSPJitTester
|
||||
{
|
||||
|
@ -14,15 +79,24 @@ class DSPJitTester
|
|||
DSPEmitter jit;
|
||||
SDSP last_int_dsp;
|
||||
SDSP last_jit_dsp;
|
||||
SDSP last_input_dsp;
|
||||
bool be_verbose;
|
||||
bool failed_only;
|
||||
int run_count;
|
||||
int fail_count;
|
||||
char instruction_name[16];
|
||||
TestDataList test_values;
|
||||
|
||||
bool AreEqual(SDSP&, SDSP&);
|
||||
int TestOne(TestDataIterator, SDSP&);
|
||||
void DumpRegs(SDSP&);
|
||||
public:
|
||||
DSPJitTester(u16 opcode, u16 opcode_ext, bool verbose = false);
|
||||
DSPJitTester(u16 opcode, u16 opcode_ext = 0, bool verbose = false, bool only_failed = false);
|
||||
bool Test(SDSP);
|
||||
int TestAll() { return TestAll(failed_only); }
|
||||
int TestAll(bool verbose_fail);
|
||||
void AddTestData(u8 reg);
|
||||
void AddTestData(u8 reg, u16 value);
|
||||
SDSP RunInterpreter(SDSP);
|
||||
SDSP RunJit(SDSP);
|
||||
void ResetInterpreter();
|
||||
|
|
Loading…
Reference in New Issue