mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 07:09:48 -06:00
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:
@ -2,69 +2,78 @@
|
|||||||
|
|
||||||
void nx_dr()
|
void nx_dr()
|
||||||
{
|
{
|
||||||
SDSP test_dsp;
|
DSPJitTester tester(0x8000, 0x0004);
|
||||||
DSPJitTester tester(0x40, 0x04);
|
tester.AddTestData(DSP_REG_ACC0);
|
||||||
|
tester.AddTestData(DSP_REG_WR0);
|
||||||
for (u16 input_reg = 0; input_reg < 50; input_reg++)
|
tester.TestAll();
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tester.Report();
|
tester.Report();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx_ir()
|
void nx_ir()
|
||||||
{
|
{
|
||||||
SDSP test_dsp;
|
DSPJitTester tester(0x8000, 0x0008);
|
||||||
DSPJitTester tester(0x40, 0x08);
|
tester.AddTestData(DSP_REG_ACC0);
|
||||||
|
tester.AddTestData(DSP_REG_WR0);
|
||||||
for (u16 input_reg = 0; input_reg < 50; input_reg++)
|
tester.TestAll();
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tester.Report();
|
tester.Report();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx_nr()
|
void nx_nr()
|
||||||
{
|
{
|
||||||
SDSP test_dsp;
|
DSPJitTester tester(0x8000, 0x000c);
|
||||||
DSPJitTester tester(0x40, 0x0c);
|
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++)
|
void dar()
|
||||||
for (u16 input_wr0 = 0; input_wr0 < 10; input_wr0++)
|
{
|
||||||
for (u16 input_ix0 = 0; input_ix0 < 10; input_ix0++)
|
DSPJitTester tester(0x0004);
|
||||||
{
|
tester.AddTestData(DSP_REG_ACC0);
|
||||||
memset(&test_dsp, 0, sizeof(SDSP));
|
tester.AddTestData(DSP_REG_WR0);
|
||||||
test_dsp.r[DSP_REG_IX0] = input_ix0;
|
tester.TestAll();
|
||||||
test_dsp.r[DSP_REG_WR0] = input_wr0;
|
tester.Report();
|
||||||
test_dsp.r[0] = input_reg;
|
}
|
||||||
if (!tester.Test(test_dsp))
|
void iar()
|
||||||
{
|
{
|
||||||
printf("%s Test failed: in = 0x%04x, wr0 = 0x%04x, ix0 = 0x%04x > int = 0x%04x, jit = 0x%04x\n",
|
DSPJitTester tester(0x0008);
|
||||||
tester.GetInstructionName(),
|
tester.AddTestData(DSP_REG_ACC0);
|
||||||
input_reg, input_wr0, input_ix0,
|
tester.AddTestData(DSP_REG_WR0);
|
||||||
tester.GetLastInterpreterDSP().r[0], tester.GetLastJitDSP().r[0]);
|
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();
|
tester.Report();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +81,13 @@ void AudioJitTests()
|
|||||||
{
|
{
|
||||||
DSPJitTester::Initialize();
|
DSPJitTester::Initialize();
|
||||||
|
|
||||||
|
dar();
|
||||||
|
iar();
|
||||||
|
subarn();
|
||||||
|
addarn();
|
||||||
|
sbclr();
|
||||||
|
sbset();
|
||||||
|
|
||||||
nx_ir();
|
nx_ir();
|
||||||
nx_dr();
|
nx_dr();
|
||||||
nx_nr();
|
nx_nr();
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include "DSPJitTester.h"
|
#include "DSPJitTester.h"
|
||||||
|
|
||||||
DSPJitTester::DSPJitTester(u16 opcode, u16 opcode_ext, bool verbose)
|
DSPJitTester::DSPJitTester(u16 opcode, u16 opcode_ext, bool verbose, bool only_failed)
|
||||||
: be_verbose(verbose), run_count(0), fail_count(0)
|
: 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);
|
opcode_template = GetOpTemplate(instruction);
|
||||||
sprintf(instruction_name, "%s", opcode_template->name);
|
sprintf(instruction_name, "%s", opcode_template->name);
|
||||||
if (opcode_template->extended)
|
if (opcode_template->extended)
|
||||||
@ -12,9 +12,13 @@ DSPJitTester::DSPJitTester(u16 opcode, u16 opcode_ext, bool verbose)
|
|||||||
}
|
}
|
||||||
bool DSPJitTester::Test(SDSP dsp_settings)
|
bool DSPJitTester::Test(SDSP dsp_settings)
|
||||||
{
|
{
|
||||||
if (be_verbose)
|
if (be_verbose && !failed_only)
|
||||||
|
{
|
||||||
printf("Running %s: ", instruction_name);
|
printf("Running %s: ", instruction_name);
|
||||||
|
DumpRegs(dsp_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
last_input_dsp = dsp_settings;
|
||||||
last_int_dsp = RunInterpreter(dsp_settings);
|
last_int_dsp = RunInterpreter(dsp_settings);
|
||||||
last_jit_dsp = RunJit(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 DSPJitTester::AreEqual(SDSP& int_dsp, SDSP& jit_dsp)
|
||||||
{
|
{
|
||||||
bool equal = true;
|
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 (int_dsp.r[i] != jit_dsp.r[i])
|
||||||
{
|
{
|
||||||
if (equal && be_verbose)
|
if (equal)
|
||||||
printf("failed\n");
|
{
|
||||||
|
if (failed_only)
|
||||||
|
{
|
||||||
|
printf("%s ", instruction_name);
|
||||||
|
DumpRegs(last_input_dsp);
|
||||||
|
}
|
||||||
|
if (be_verbose || failed_only)
|
||||||
|
printf("failed\n");
|
||||||
|
}
|
||||||
equal = false;
|
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]);
|
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");
|
printf("passed\n");
|
||||||
return equal;
|
return equal;
|
||||||
}
|
}
|
||||||
@ -86,8 +98,68 @@ void DSPJitTester::DumpJittedCode()
|
|||||||
printf("%02x ", code[i]);
|
printf("%02x ", code[i]);
|
||||||
printf("\n");
|
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()
|
void DSPJitTester::Initialize()
|
||||||
{
|
{
|
||||||
//init int
|
//init int
|
||||||
InitInstructionTable();
|
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_
|
#ifndef __DSP_JIT_TESTER_
|
||||||
#define __DSP_JIT_TESTER_
|
#define __DSP_JIT_TESTER_
|
||||||
|
|
||||||
#include "DSPCore.h"
|
#include "DSPCore.h"
|
||||||
#include "DSPInterpreter.h"
|
#include "DSPInterpreter.h"
|
||||||
//#include "DSPIntExtOps.h"
|
#include <map>
|
||||||
//
|
#include <vector>
|
||||||
//#include "x64Emitter.h"
|
|
||||||
|
typedef std::vector<u16> TestData;
|
||||||
|
typedef std::map<u8, TestData> TestDataList;
|
||||||
|
typedef TestDataList::iterator TestDataIterator;
|
||||||
|
#define DSP_REG_NUM 32
|
||||||
|
|
||||||
class DSPJitTester
|
class DSPJitTester
|
||||||
{
|
{
|
||||||
@ -14,15 +79,24 @@ class DSPJitTester
|
|||||||
DSPEmitter jit;
|
DSPEmitter jit;
|
||||||
SDSP last_int_dsp;
|
SDSP last_int_dsp;
|
||||||
SDSP last_jit_dsp;
|
SDSP last_jit_dsp;
|
||||||
|
SDSP last_input_dsp;
|
||||||
bool be_verbose;
|
bool be_verbose;
|
||||||
|
bool failed_only;
|
||||||
int run_count;
|
int run_count;
|
||||||
int fail_count;
|
int fail_count;
|
||||||
char instruction_name[16];
|
char instruction_name[16];
|
||||||
|
TestDataList test_values;
|
||||||
|
|
||||||
bool AreEqual(SDSP&, SDSP&);
|
bool AreEqual(SDSP&, SDSP&);
|
||||||
|
int TestOne(TestDataIterator, SDSP&);
|
||||||
|
void DumpRegs(SDSP&);
|
||||||
public:
|
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);
|
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 RunInterpreter(SDSP);
|
||||||
SDSP RunJit(SDSP);
|
SDSP RunJit(SDSP);
|
||||||
void ResetInterpreter();
|
void ResetInterpreter();
|
||||||
|
Reference in New Issue
Block a user