mirror of
https://github.com/edmccard/twoapple-reboot.git
synced 2024-12-21 20:29:18 +00:00
105 lines
2.6 KiB
D
105 lines
2.6 KiB
D
|
module test.test_func;
|
||
|
|
||
|
|
||
|
import std.string;
|
||
|
|
||
|
import test.base, test.cpu, test.opcodes;
|
||
|
|
||
|
|
||
|
alias void delegate(ubyte, ref Expected, CpuInfo, const ref TestMemory, string)
|
||
|
testreport;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Runs one opcode. Calls expect for the expected values of the cpu
|
||
|
* registers and memory. Calls report with the expected and actual
|
||
|
* values.
|
||
|
*/
|
||
|
auto run_opcode_test(T)(testexpect expect, testreport report)
|
||
|
{
|
||
|
auto setup(ubyte opcode, CpuInfo cpu, Block[] data, OpInfo info,
|
||
|
string msg, TestSetup* next)
|
||
|
{
|
||
|
mixin testCallNext;
|
||
|
auto testcpu = makeCpu!T(cpu);
|
||
|
auto mem = TestMemory(data);
|
||
|
auto expected = Expected(cpu, mem);
|
||
|
expect(expected, info);
|
||
|
connectMem(testcpu, mem);
|
||
|
runOneOpcode(testcpu);
|
||
|
auto cpuResult = CpuInfo.fromCpu(testcpu);
|
||
|
report(opcode, expected, cpuResult, mem, T.stringof ~ " | " ~ msg);
|
||
|
callNext();
|
||
|
}
|
||
|
return TestSetup(&setup);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Dummy function. Reports nothing.
|
||
|
auto report_none()
|
||
|
{
|
||
|
void report(ubyte opcode, ref Expected expected, CpuInfo cpu,
|
||
|
const ref TestMemory mem, string msg)
|
||
|
{
|
||
|
}
|
||
|
return &report;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Prints the differences between expected and actual cpu/memory.
|
||
|
auto report_debug()
|
||
|
{
|
||
|
void report(ubyte opcode, ref Expected expected, CpuInfo cpu,
|
||
|
const ref TestMemory mem, string msg)
|
||
|
{
|
||
|
import std.stdio;
|
||
|
bool badCpu = (expected.cpu != cpu);
|
||
|
bool badMem = (expected.mem != mem);
|
||
|
if (badCpu || badMem)
|
||
|
writeln(format("[%0.2X] %s", opcode, msg));
|
||
|
if (badCpu)
|
||
|
{
|
||
|
writeln(" expect ", expected.cpu);
|
||
|
writeln(" actual ", cpu);
|
||
|
}
|
||
|
if (badMem)
|
||
|
{
|
||
|
foreach (h; MemDiff(expected.mem, mem))
|
||
|
{
|
||
|
writeln(format(" %0.4X | %s", h.base, formatMemory(h.a, 8)));
|
||
|
writeln(format(" | %s", formatMemory(h.b, 8)));
|
||
|
}
|
||
|
}
|
||
|
if (badCpu || badMem) throw new Exception("BAD");
|
||
|
}
|
||
|
return &report;
|
||
|
}
|
||
|
|
||
|
|
||
|
void test_one_opcode(T)(ubyte opcode, testreport report)
|
||
|
{
|
||
|
TestSetup setup_addr;
|
||
|
TestSetup setup_test;
|
||
|
testexpect expect;
|
||
|
|
||
|
mixin(getMemSetup!T());
|
||
|
|
||
|
auto setup = connect(setup_mask_flags(), setup_addr, setup_test);
|
||
|
auto run = connect(setup, run_opcode_test!T(expect, report));
|
||
|
run.run(opcode);
|
||
|
}
|
||
|
|
||
|
|
||
|
unittest
|
||
|
{
|
||
|
auto report = report_debug();
|
||
|
|
||
|
alias CPU!("65C02", false, false) T1;
|
||
|
foreach (opcode; 0..255)
|
||
|
test_one_opcode!T1(cast(ubyte)opcode, report);
|
||
|
|
||
|
alias CPU!("6502", false, false) T2;
|
||
|
foreach (opcode; 0..255)
|
||
|
test_one_opcode!T2(cast(ubyte)opcode, report);
|
||
|
}
|