First stab at adding Fuse Test runner.

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian.Conlon 2017-06-05 23:24:08 +01:00
parent 211c75d84d
commit 982bccf0c9
30 changed files with 29313 additions and 0 deletions

View File

@ -13,6 +13,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Z80", "Z80\src\Z80.vcxproj"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_Z80", "Z80\test\test_Z80.vcxproj", "{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fusetest_Z80", "Z80\fusetest_Z80\fusetest_Z80.vcxproj", "{618F7A88-A262-4071-A6F1-FEB3A181B541}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -61,6 +63,14 @@ Global
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Release|x64.Build.0 = Release|x64
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Release|x86.ActiveCfg = Release|Win32
{F8EE7116-0D75-4C82-BA9E-409F69F5D47C}.Release|x86.Build.0 = Release|Win32
{618F7A88-A262-4071-A6F1-FEB3A181B541}.Debug|x64.ActiveCfg = Debug|x64
{618F7A88-A262-4071-A6F1-FEB3A181B541}.Debug|x64.Build.0 = Debug|x64
{618F7A88-A262-4071-A6F1-FEB3A181B541}.Debug|x86.ActiveCfg = Debug|Win32
{618F7A88-A262-4071-A6F1-FEB3A181B541}.Debug|x86.Build.0 = Debug|Win32
{618F7A88-A262-4071-A6F1-FEB3A181B541}.Release|x64.ActiveCfg = Release|x64
{618F7A88-A262-4071-A6F1-FEB3A181B541}.Release|x64.Build.0 = Release|x64
{618F7A88-A262-4071-A6F1-FEB3A181B541}.Release|x86.ActiveCfg = Release|Win32
{618F7A88-A262-4071-A6F1-FEB3A181B541}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,48 @@
#include "stdafx.h"
#include "FuseExpectedTestResult.h"
#include <sstream>
/*
75
0 MC 0000
4 MR 0000 75
4 MC a169
7 MW a169 69
0200 cf98 90d8 a169 0000 0000 0000 0000 0000 0000 0000 0001 0000
00 01 0 0 0 0 7
a169 69 -1
*/
void Fuse::ExpectedTestResult::read(std::ifstream& file) {
finish = false;
do {
std::getline(file, description);
finish = file.eof();
} while (description.empty() && !finish);
if (finish)
return;
events.read(file);
registerState.read(file);
std::string line;
std::getline(file, line);
if (!line.empty())
throw std::logic_error("EOL swallow failure!!");
do {
auto before = file.tellg();
std::getline(file, line);
if (!line.empty()) {
file.seekg(before);
MemoryDatum datum;
datum.read(file);
memoryData.push_back(datum);
}
} while (!line.empty());
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <fstream>
#include <string>
#include <vector>
#include "FuseTestEvents.h"
#include "FuseRegisterState.h"
#include "FuseMemoryDatum.h"
namespace Fuse {
class ExpectedTestResult
{
public:
std::string description;
TestEvents events;
RegisterState registerState;
std::vector<MemoryDatum> memoryData;
bool finish;
ExpectedTestResult()
: finish(false) {}
void read(std::ifstream& file);
};
}

View File

@ -0,0 +1,20 @@
#include "stdafx.h"
#include "FuseExpectedTestResults.h"
void Fuse::ExpectedTestResults::read(std::ifstream& file) {
bool finished = false;
while (!file.eof()) {
ExpectedTestResult result;
result.read(file);
finished = result.finish;
if (!finished)
results[result.description] = result;
}
}
void Fuse::ExpectedTestResults::read(std::string path) {
std::ifstream file;
file >> std::hex;
file.open(path);
read(file);
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <map>
#include <string>
#include <fstream>
#include "FuseExpectedTestResult.h"
namespace Fuse {
class ExpectedTestResults {
private:
std::map<std::string, ExpectedTestResult> results;
void read(std::ifstream& file);
public:
void read(std::string path);
const std::map<std::string, ExpectedTestResult>& container() const {
return results;
}
};
}

View File

@ -0,0 +1,20 @@
#include "stdafx.h"
#include "FuseMemoryDatum.h"
void Fuse::MemoryDatum::read(std::ifstream& file) {
int begin;
file >> begin;
finish = (begin == -1);
if (finish)
return;
address = begin;
int byte;
bool completed = false;
do {
file >> byte;
completed = (byte == -1);
if (!completed)
bytes.push_back(byte);
} while (!completed);
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <cinttypes>
#include <vector>
#include <fstream>
namespace Fuse {
class MemoryDatum {
private:
bool finish;
public:
int address;
std::vector<uint8_t> bytes;
MemoryDatum()
: address(-1),
finish(false) {}
bool finished() const { return finish; }
void read(std::ifstream& file);
};
}

View File

@ -0,0 +1,32 @@
#include "stdafx.h"
#include "FuseRegisterState.h"
Fuse::RegisterState::RegisterState()
: registers(NUMBER_OF_REGISTERS) {
}
void Fuse::RegisterState::read(std::ifstream& file) {
readExternal(file);
readInternal(file);
}
void Fuse::RegisterState::readExternal(std::ifstream& file) {
for (int idx = 0; idx < registers.size(); ++idx) {
int input;
file >> input;
registers[idx].word = input;
}
}
void Fuse::RegisterState::readInternal(std::ifstream& file) {
file >> i;
file >> r;
file >> iff1;
file >> iff2;
file >> im;
file >> halted;
file >> std::dec;
file >> tstates;
file >> std::hex;
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <vector>
#include <string>
#include <fstream>
#include "Memory.h"
namespace Fuse {
class RegisterState {
public:
enum {
AF, BC, DE, HL, AF_, BC_, DE_, HL_, IX, IY, SP, PC, MEMPTR, NUMBER_OF_REGISTERS
};
std::vector<EightBit::register16_t> registers;
int i, r;
bool iff1, iff2;
int im;
bool halted;
int tstates;
public:
RegisterState();
void read(std::ifstream& file);
void readInternal(std::ifstream& file);
void readExternal(std::ifstream& file);
};
}

View File

@ -0,0 +1,25 @@
#include "stdafx.h"
#include "FuseTest.h"
void Fuse::Test::read(std::ifstream& file) {
finish = false;
do {
std::getline(file, description);
finish = file.eof();
} while (description.empty() && !finish);
if (finish)
return;
registerState.read(file);
bool complete = false;
do {
MemoryDatum memoryDatum;
memoryDatum.read(file);
complete = memoryDatum.finished();
if (!complete)
memoryData.push_back(memoryDatum);
} while (!complete);
}

View File

@ -0,0 +1,20 @@
#pragma once
#include <string>
#include <vector>
#include <fstream>
#include "FuseMemoryDatum.h"
#include "FuseRegisterState.h"
namespace Fuse {
class Test {
public:
std::string description;
RegisterState registerState;
std::vector<MemoryDatum> memoryData;
bool finish = false;
void read(std::ifstream& file);
};
}

View File

@ -0,0 +1,34 @@
#include "stdafx.h"
#include "FuseTestEvent.h"
void Fuse::TestEvent::read(std::ifstream& file) {
auto prior = file.tellg();
std::string line;
std::getline(file, line);
std::stringstream in(line);
in >> cycles;
in >> specifier;
in >> std::hex;
valid = true;
if (specifier == "MR" || specifier == "MW") {
in >> address;
in >> value;
} else if (specifier == "MC" || specifier == "PC") {
in >> address;
value = -1;
} else if (specifier == "PR" || specifier == "PW") {
in >> address;
in >> value;
} else {
valid = false;
}
if (!valid) {
file.seekg(prior);
}
}

View File

@ -0,0 +1,20 @@
#pragma once
#include <string>
namespace Fuse {
class TestEvent
{
public:
bool valid;
std::string specifier;
int cycles, address, value;
TestEvent()
: valid(false),
cycles(-1), address(-1), value(-1) {
}
void read(std::ifstream& file);
};
}

View File

@ -0,0 +1,13 @@
#include "stdafx.h"
#include "FuseTestEvents.h"
void Fuse::TestEvents::read(std::ifstream& file) {
bool complete = false;
do {
TestEvent event;
event.read(file);
complete = !event.valid;
if (!complete)
events.push_back(event);
} while (!complete);
}

View File

@ -0,0 +1,13 @@
#pragma once
#include <vector>
#include "FuseTestEvent.h"
namespace Fuse {
class TestEvents {
public:
std::vector<TestEvent> events;
void read(std::ifstream& file);
};
}

View File

@ -0,0 +1,340 @@
#include "stdafx.h"
#include "FuseTestRunner.h"
#include "Disassembler.h"
Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& expected)
: m_test(test),
m_expected(expected),
m_memory(0xffff),
m_cpu(m_memory, m_ports),
m_failed(false),
m_unimplemented(false) {
m_memory.clear();
m_cpu.initialise();
}
//
void Fuse::TestRunner::initialise() {
initialiseRegisters();
initialiseMemory();
}
void Fuse::TestRunner::initialiseRegisters() {
const auto& testState = m_test.registerState;
const auto& inputRegisters = testState.registers;
m_cpu.AF() = inputRegisters[Fuse::RegisterState::AF_];
m_cpu.BC() = inputRegisters[Fuse::RegisterState::BC_];
m_cpu.DE() = inputRegisters[Fuse::RegisterState::DE_];
m_cpu.HL() = inputRegisters[Fuse::RegisterState::HL_];
m_cpu.exx();
m_cpu.exxAF();
m_cpu.AF() = inputRegisters[Fuse::RegisterState::AF];
m_cpu.BC() = inputRegisters[Fuse::RegisterState::BC];
m_cpu.DE() = inputRegisters[Fuse::RegisterState::DE];
m_cpu.HL() = inputRegisters[Fuse::RegisterState::HL];
m_cpu.IX() = inputRegisters[Fuse::RegisterState::IX];
m_cpu.IY() = inputRegisters[Fuse::RegisterState::IY];
m_cpu.setStackPointer(inputRegisters[Fuse::RegisterState::SP]);
m_cpu.setProgramCounter(inputRegisters[Fuse::RegisterState::PC]);
m_cpu.MEMPTR() = inputRegisters[Fuse::RegisterState::MEMPTR];
m_cpu.IV() = testState.i;
m_cpu.REFRESH() = testState.r;
m_cpu.IFF1() = testState.iff1;
m_cpu.IFF2() = testState.iff2;
m_cpu.IM() = testState.im;
}
void Fuse::TestRunner::initialiseMemory() {
for (auto memoryDatum : m_test.memoryData) {
auto address = memoryDatum.address;
auto bytes = memoryDatum.bytes;
for (int i = 0; i < bytes.size(); ++i) {
m_memory.ADDRESS().word = address + i;
m_memory.reference() = bytes[i];
}
}
}
//
void Fuse::TestRunner::check() {
checkregisters();
checkMemory();
}
void Fuse::TestRunner::dumpDifference(const std::string& description, uint8_t actual, uint8_t expected) const {
std::cerr
<< "**** " << description << ", Expected: "
<< EightBit::Disassembler::hex(expected)
<< ", Got: "
<< EightBit::Disassembler::hex(actual)
<< std::endl;
}
void Fuse::TestRunner::dumpDifference(
const std::string& highDescription,
const std::string& lowDescription,
EightBit::register16_t actual, EightBit::register16_t expected) const {
auto expectedHigh = expected.high;
auto expectedLow = expected.low;
auto actualHigh = actual.high;
auto actualLow = actual.low;
if (expectedHigh != actualHigh)
dumpDifference(highDescription, actualHigh, expectedHigh);
if (expectedLow != actualLow)
dumpDifference(lowDescription, actualLow, expectedLow);
}
void Fuse::TestRunner::checkregisters() {
const auto& expectedState = m_expected.registerState;
const auto& expectedRegisters = expectedState.registers;
auto af = m_cpu.AF().word == expectedRegisters[Fuse::RegisterState::AF].word;
auto bc = m_cpu.BC().word == expectedRegisters[Fuse::RegisterState::BC].word;
auto de = m_cpu.DE().word == expectedRegisters[Fuse::RegisterState::DE].word;
auto hl = m_cpu.HL().word == expectedRegisters[Fuse::RegisterState::HL].word;
m_cpu.exx();
m_cpu.exxAF();
auto af_ = m_cpu.AF().word == expectedRegisters[Fuse::RegisterState::AF_].word;
auto bc_ = m_cpu.BC().word == expectedRegisters[Fuse::RegisterState::BC_].word;
auto de_ = m_cpu.DE().word == expectedRegisters[Fuse::RegisterState::DE_].word;
auto hl_ = m_cpu.HL().word == expectedRegisters[Fuse::RegisterState::HL_].word;
auto ix = m_cpu.IX().word == expectedRegisters[Fuse::RegisterState::IX].word;
auto iy = m_cpu.IY().word == expectedRegisters[Fuse::RegisterState::IY].word;
auto sp = m_cpu.getStackPointer().word == expectedRegisters[Fuse::RegisterState::SP].word;
auto pc = m_cpu.getProgramCounter().word == expectedRegisters[Fuse::RegisterState::PC].word;
auto memptr = m_cpu.MEMPTR().word == expectedRegisters[Fuse::RegisterState::MEMPTR].word;
auto iv = m_cpu.IV() == expectedState.i;
auto refresh = m_cpu.REFRESH() == expectedState.r;
auto iff1 = m_cpu.IFF1() == expectedState.iff1;
auto iff2 = m_cpu.IFF2() == expectedState.iff2;
auto im = m_cpu.IM() == expectedState.im;
// And back again, so the following works as expected...
m_cpu.exx();
m_cpu.exxAF();
auto success =
af && bc && de && hl
&& af_ && bc_ && de_ && hl_
&& ix && iy
&& sp && pc
&& iv && refresh
&& iff1 && iff2
&& im
&& memptr;
if (!success) {
m_failed = true;
std::cerr << "**** Failed test (Register): " << m_test.description << std::endl;
if (!af) {
auto expectedA = expectedRegisters[Fuse::RegisterState::AF].high;
auto gotA = m_cpu.A();
if (expectedA != gotA)
dumpDifference("A", gotA, expectedA);
auto expectedF = expectedRegisters[Fuse::RegisterState::AF].low;
auto gotF = m_cpu.F();
if (expectedF != gotF) {
std::cerr
<< "**** F, Expected: "
<< EightBit::Disassembler::flags(expectedF)
<< ", Got: "
<< EightBit::Disassembler::flags(gotF)
<< std::endl;
}
}
if (!bc) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::BC];
auto actualWord = m_cpu.BC();
dumpDifference("B", "C", actualWord, expectedWord);
}
if (!de) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::DE];
auto actualWord = m_cpu.DE();
dumpDifference("D", "E", actualWord, expectedWord);
}
if (!hl) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::HL];
auto actualWord = m_cpu.HL();
dumpDifference("H", "L", actualWord, expectedWord);
}
if (!ix) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::IX];
auto actualWord = m_cpu.IX();
dumpDifference("IXH", "IXL", actualWord, expectedWord);
}
if (!iy) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::IY];
auto actualWord = m_cpu.IY();
dumpDifference("IYH", "IYL", actualWord, expectedWord);
}
if (!sp) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::SP];
auto actualWord = m_cpu.getStackPointer();
dumpDifference("SPH", "SPL", actualWord, expectedWord);
}
if (!pc) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::PC];
auto actualWord = m_cpu.getProgramCounter();
dumpDifference("PCH", "PCL", actualWord, expectedWord);
}
if (!memptr) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::MEMPTR];
auto actualWord = m_cpu.MEMPTR();
dumpDifference("MEMPTRH", "MEMPTRL", actualWord, expectedWord);
}
m_cpu.exxAF();
m_cpu.exx();
if (!af_) {
auto expectedA_ = expectedRegisters[Fuse::RegisterState::AF_].high;
auto gotA_ = m_cpu.A();
if (expectedA_ != gotA_)
dumpDifference("A'", gotA_, expectedA_);
auto expectedF_ = expectedRegisters[Fuse::RegisterState::AF_].low;
auto gotF_ = m_cpu.F();
if (expectedF_ != gotF_) {
std::cerr
<< "**** F', Expected: "
<< EightBit::Disassembler::flags(expectedF_)
<< ", Got: "
<< EightBit::Disassembler::flags(gotF_)
<< std::endl;
}
}
if (!bc_) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::BC_];
auto actualWord = m_cpu.BC();
dumpDifference("B'", "C'", actualWord, expectedWord);
}
if (!de_) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::DE_];
auto actualWord = m_cpu.DE();
dumpDifference("D'", "E'", actualWord, expectedWord);
}
if (!hl_) {
auto expectedWord = expectedRegisters[Fuse::RegisterState::HL_];
auto actualWord = m_cpu.HL();
dumpDifference("H'", "L'", actualWord, expectedWord);
}
if (!iv) {
std::cerr
<< "**** IV, Expected: "
<< EightBit::Disassembler::hex((uint8_t)expectedState.i)
<< ", Got: "
<< EightBit::Disassembler::hex(m_cpu.IV())
<< std::endl;
}
if (!refresh) {
std::cerr
<< "**** R, Expected: "
<< EightBit::Disassembler::hex((uint8_t)expectedState.r)
<< ", Got: "
<< EightBit::Disassembler::hex(m_cpu.REFRESH())
<< std::endl;
}
if (!iff1) {
std::cerr
<< "**** IFF1, Expected: "
<< (bool)expectedState.iff1
<< ", Got: "
<< m_cpu.IFF1()
<< std::endl;
}
if (!iff2) {
std::cerr
<< "**** IFF2, Expected: "
<< (bool)expectedState.iff2
<< ", Got: "
<< m_cpu.IFF2()
<< std::endl;
}
if (!im) {
std::cerr
<< "**** IM, Expected: "
<< expectedState.im
<< ", Got: "
<< m_cpu.IM()
<< std::endl;
}
}
}
void Fuse::TestRunner::checkMemory() {
bool first = true;
for (auto memoryDatum : m_expected.memoryData) {
auto bytes = memoryDatum.bytes;
for (int i = 0; i < bytes.size(); ++i) {
auto expected = bytes[i];
uint16_t address = memoryDatum.address + i;
auto actual = m_cpu.getMemory().peek(address);
if (expected != actual) {
m_failed = true;
if (first) {
first = false;
std::cerr << "**** Failed test (Memory): " << m_test.description << std::endl;
}
std::cerr
<< "**** Difference: "
<< "Address: " << EightBit::Disassembler::hex(address)
<< " Expected: " << EightBit::Disassembler::hex(expected)
<< " Actual: " << EightBit::Disassembler::hex(actual)
<< std::endl;
}
}
}
}
void Fuse::TestRunner::run() {
initialise();
auto allowedCycles = m_test.registerState.tstates;
try {
auto cycles = 0;
do {
cycles += m_cpu.step();
} while (allowedCycles > cycles);
check();
} catch (std::logic_error& error) {
m_unimplemented = true;
std::cerr << "**** Error: " << error.what() << std::endl;
}
}

View File

@ -0,0 +1,44 @@
#pragma once
#include "FuseTest.h"
#include "FuseExpectedTestResult.h"
#include "Memory.h"
#include "InputOutput.h"
#include "Z80.h"
namespace Fuse {
class TestRunner {
private:
const Test& m_test;
const ExpectedTestResult& m_expected;
bool m_failed;
bool m_unimplemented;
EightBit::Memory m_memory;
EightBit::InputOutput m_ports;
EightBit::Z80 m_cpu;
void initialise();
void initialiseRegisters();
void initialiseMemory();
void check();
void checkregisters();
void checkMemory();
void dumpDifference(const std::string& description, uint8_t high, uint8_t low) const;
void dumpDifference(
const std::string& highDescription,
const std::string& lowDescription,
EightBit::register16_t actual, EightBit::register16_t expected) const;
public:
TestRunner(const Test& test, const ExpectedTestResult& expected);
void run();
bool failed() const { return m_failed; }
bool unimplemented() const { return m_unimplemented; }
};
}

View File

@ -0,0 +1,31 @@
#include "stdafx.h"
#include "FuseTestSuite.h"
#include "FuseTestRunner.h"
Fuse::TestSuite::TestSuite(std::string path) {
m_tests.read(path + ".in");
m_results.read(path + ".expected");
}
void Fuse::TestSuite::run() {
auto failedCount = 0;
auto unimplementedCount = 0;
for (auto test : m_tests.container()) {
auto key = test.first;
std::cout << "** Checking: " << key << std::endl;
auto input = test.second;
auto result = m_results.container().find(key)->second;
Fuse::TestRunner runner(input, result);
runner.run();
if (runner.failed())
++failedCount;
if (runner.unimplemented())
++unimplementedCount;
}
std::cout << "+++ Failed test count: " << failedCount << std::endl;
std::cout << "+++ Unimplemented test count: " << unimplementedCount << std::endl;
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <string>
#include "FuseTests.h"
#include "FuseExpectedTestResults.h"
namespace Fuse {
class TestSuite {
private:
Tests m_tests;
ExpectedTestResults m_results;
public:
TestSuite(std::string path);
void run();
};
}

View File

@ -0,0 +1,20 @@
#include "stdafx.h"
#include "FuseTests.h"
void Fuse::Tests::read(std::ifstream& file) {
bool finished = false;
while (!file.eof()) {
Test test;
test.read(file);
finished = test.finish;
if (!finished)
tests[test.description] = test;
}
}
void Fuse::Tests::read(std::string path) {
std::ifstream file;
file >> std::hex;
file.open(path);
read(file);
}

View File

@ -0,0 +1,20 @@
#pragma once
#include <map>
#include <string>
#include <fstream>
#include "FuseTest.h"
namespace Fuse {
class Tests {
private:
std::map<std::string, Test> tests;
void read(std::ifstream& file);
public:
void read(std::string path);
const std::map<std::string, Test>& container() const { return tests; }
};
}

View File

@ -0,0 +1,79 @@
File formats
============
tests.in
--------
Each test has the format:
<arbitrary test description>
AF BC DE HL AF' BC' DE' HL' IX IY SP PC MEMPTR
I R IFF1 IFF2 IM <halted> <tstates>
<halted> specifies whether the Z80 is halted.
<tstates> specifies the number of tstates to run the test for, in
decimal; the number actually executed may be higher, as the final
instruction is allowed to complete.
Then followed by lines specifying the initial memory setup. Each has
the format:
<start address> <byte1> <byte2> ... -1
eg
1234 56 78 9a -1
says to put 0x56 at 0x1234, 0x78 at 0x1235 and 0x9a at 0x1236.
Finally, -1 to end the test. Blank lines may follow before the next test.
tests.expected
--------------
Each test output starts with the test description, followed by a list
of 'events': each has the format
<time> <type> <address> <data>
<time> is simply the time at which the event occurs.
<type> is one of MR (memory read), MW (memory write), MC (memory
contend), PR (port read), PW (port write) or PC (port contend).
<address> is the address (or IO port) affected.
<data> is the byte written or read. Missing for contentions.
After that, lines specifying AF, BC etc as for .in files. <tstates>
now specifies the final time.
After that, lines specifying which bits of memory have changed since
the initial setup. Same format as for .in files.
Why some specific tests are here
================================
{02,0a,32}_1,edb[012389ab]_[12],d3_4:
check MEMPTR is set correctly after various instructions.
37_{1,2,3}: check the behaviour of SCF with respect to bits 3 and 5
(bug fixed on 20040225).
cb46_{1,2,3,4,5}: check the correct bits of MEMPTR are copied to bits 3
and 5 of the flags register after a BIT n,(HL) instruction.
cb{4,5,6,7}{7,f}_1: designed to check that bits 3 and 5 are copied to
F only for BIT 3,<arg> and BIT 5,<arg> respectively
(bug fixed on 20040225).
However, later research has revealed the bits 3
and 5 are copied on all BIT instructions, so these
tests are now essentially redundant.
d{3,b}_{1,2,3}: check for correct port contention on IO in the four
relevant states (port high byte in 0x40 to 0x7f or not,
port low bit set or reset).
dd00.in, ddfd00.in: test timings of "extended NOP" opcodes DD 00 and
DD FD 00; the extra 00 at the end is to check the
next opcode executes at the right time (bug fixed
on 20060722).

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,194 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{618F7A88-A262-4071-A6F1-FEB3A181B541}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>fuse_test_Z80</RootNamespace>
<ProjectName>fusetest_Z80</ProjectName>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\inc;..\..\inc;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="FuseExpectedTestResults.h" />
<ClInclude Include="FuseMemoryDatum.h" />
<ClInclude Include="FuseRegisterState.h" />
<ClInclude Include="FuseTest.h" />
<ClInclude Include="FuseTestEvent.h" />
<ClInclude Include="FuseTestEvents.h" />
<ClInclude Include="FuseTestRunner.h" />
<ClInclude Include="FuseTests.h" />
<ClInclude Include="FuseTestSuite.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="FuseExpectedTestResult.cpp" />
<ClCompile Include="FuseExpectedTestResults.cpp" />
<ClCompile Include="FuseMemoryDatum.cpp" />
<ClCompile Include="FuseRegisterState.cpp" />
<ClCompile Include="FuseTest.cpp" />
<ClCompile Include="FuseTestEvent.cpp" />
<ClCompile Include="FuseTestEvents.cpp" />
<ClCompile Include="FuseTestRunner.cpp" />
<ClCompile Include="FuseTests.cpp" />
<ClCompile Include="FuseTestSuite.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="tests.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\EightBit.vcxproj">
<Project>{a9c24bd9-0cb4-4c84-b09b-46b815f9da47}</Project>
</ProjectReference>
<ProjectReference Include="..\src\Z80.vcxproj">
<Project>{01974f81-2750-45af-b845-2c903a54a334}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\packages\boost.1.64.0.0\build\native\boost.targets" Condition="Exists('..\..\packages\boost.1.64.0.0\build\native\boost.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\boost.1.64.0.0\build\native\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\boost.1.64.0.0\build\native\boost.targets'))" />
</Target>
</Project>

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FuseExpectedTestResults.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FuseMemoryDatum.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FuseRegisterState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FuseTest.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FuseTestEvent.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FuseTestEvents.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FuseTestRunner.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FuseTests.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FuseTestSuite.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FuseExpectedTestResult.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FuseExpectedTestResults.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FuseMemoryDatum.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FuseRegisterState.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FuseTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FuseTestEvent.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FuseTestEvents.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FuseTestRunner.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FuseTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FuseTestSuite.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="boost" version="1.64.0.0" targetFramework="native" />
</packages>

View File

@ -0,0 +1 @@
#include "stdafx.h"

42
Z80/fusetest_Z80/stdafx.h Normal file
View File

@ -0,0 +1,42 @@
#ifdef _MSC_VER
#pragma once
#endif
#include <string>
#include <cstdint>
#include <stdexcept>
#include <functional>
#include <algorithm>
#include <memory>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <array>
#include <vector>
#include <bitset>
//#include <boost/format.hpp>
//
//#include <SDL.h>
//#include <SDL_mixer.h>
//#if SDL_BYTEORDER == SDL_LIL_ENDIAN
//#define HOST_LITTLE_ENDIAN
//#endif
//
//#if SDL_BYTEORDER == SDL_BIG_ENDIAN
//#define HOST_BIG_ENDIAN
//#endif
//
//#define RUN_TESTS
////#define RUN_CPM
////#define RUN_INVADERS
//
//#ifdef _MSC_VER
//#pragma comment(lib, "SDL2.lib")
//#pragma comment(lib, "SDL2main.lib")
//#pragma comment(lib, "SDL2_mixer.lib")
//#endif

View File

@ -0,0 +1,11 @@
#include "stdafx.h"
#include "FuseTestSuite.h"
int main(int, char*[]) {
Fuse::TestSuite testSuite("C:\\github\\cpp\\invaders\\fuse-tests\\tests");
testSuite.run();
return 0;
}