mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2025-02-03 18:32:11 +00:00
Add a .net Fuse test suite for the Z80 core (one "unexpected" result).
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
parent
63ef445a78
commit
9550ed57be
@ -30,7 +30,7 @@ namespace Fuse
|
||||
|
||||
protected virtual void ParseInternalState(string line)
|
||||
{
|
||||
var tokens = line.Split(new char[] { ' ', '\t' });
|
||||
var tokens = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
this.ParseInternalState(tokens);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace Fuse
|
||||
|
||||
private bool TryParseLine(string line)
|
||||
{
|
||||
var split = line.Split(new char[] { ' ', '\t' });
|
||||
var split = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
return this.TryParseLine(split);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace Fuse
|
||||
|
||||
public void Parse(Lines lines)
|
||||
{
|
||||
var success = false;
|
||||
bool success;
|
||||
do
|
||||
{
|
||||
var e = new TestEvent();
|
||||
|
6
Z80/Z80.FuseTest/App.config
Normal file
6
Z80/Z80.FuseTest/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
|
||||
</startup>
|
||||
</configuration>
|
17
Z80/Z80.FuseTest/Program.cs
Normal file
17
Z80/Z80.FuseTest/Program.cs
Normal file
@ -0,0 +1,17 @@
|
||||
// <copyright file="Program.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace Fuse
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var suite = new TestSuite("fuse-tests\\tests");
|
||||
suite.Read();
|
||||
suite.Parse();
|
||||
suite.Run();
|
||||
}
|
||||
}
|
||||
}
|
36
Z80/Z80.FuseTest/Properties/AssemblyInfo.cs
Normal file
36
Z80/Z80.FuseTest/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Z80.FuseTest")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Z80.FuseTest")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("0233ff6c-db1a-4353-8e42-d22717770226")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
32
Z80/Z80.FuseTest/RegisterState.cs
Normal file
32
Z80/Z80.FuseTest/RegisterState.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// <copyright file="RegisterState.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace Fuse
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
public class RegisterState : AbstractRegisterState, IRegisterState
|
||||
{
|
||||
public int I { get; private set; } = -1;
|
||||
|
||||
public int R { get; private set; } = -1;
|
||||
|
||||
public bool IFF1 { get; private set; } = false;
|
||||
|
||||
public bool IFF2 { get; private set; } = false;
|
||||
|
||||
public int IM { get; private set; } = -1;
|
||||
|
||||
protected override void ParseInternalState(string[] tokens)
|
||||
{
|
||||
this.I = Convert.ToInt32(tokens[0], 16);
|
||||
this.R = Convert.ToInt32(tokens[1], 16);
|
||||
this.IFF1 = Convert.ToInt32(tokens[2], CultureInfo.InvariantCulture) == 1;
|
||||
this.IFF2 = Convert.ToInt32(tokens[3], CultureInfo.InvariantCulture) == 1;
|
||||
this.IM = Convert.ToInt32(tokens[4], CultureInfo.InvariantCulture);
|
||||
this.Halted = Convert.ToInt32(tokens[5], CultureInfo.InvariantCulture) == 1;
|
||||
this.TStates = Convert.ToInt32(tokens[6], CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
361
Z80/Z80.FuseTest/TestRunner.cs
Normal file
361
Z80/Z80.FuseTest/TestRunner.cs
Normal file
@ -0,0 +1,361 @@
|
||||
// <copyright file="TestRunner.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace Fuse
|
||||
{
|
||||
public enum Register
|
||||
{
|
||||
AF,
|
||||
BC,
|
||||
DE,
|
||||
HL,
|
||||
AF_,
|
||||
BC_,
|
||||
DE_,
|
||||
HL_,
|
||||
IX,
|
||||
IY,
|
||||
SP,
|
||||
PC,
|
||||
MEMPTR,
|
||||
}
|
||||
|
||||
public class TestRunner : EightBit.Bus
|
||||
{
|
||||
private readonly Test<RegisterState> test;
|
||||
private readonly Result<RegisterState> result;
|
||||
private readonly EightBit.Ram ram = new EightBit.Ram(0x10000);
|
||||
private readonly EightBit.InputOutput ports = new EightBit.InputOutput();
|
||||
private readonly EightBit.Z80 cpu;
|
||||
|
||||
public TestRunner(Test<RegisterState> test, Result<RegisterState> result)
|
||||
{
|
||||
this.cpu = new EightBit.Z80(this, this.ports);
|
||||
this.test = test;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public bool Failed { get; private set; } = false;
|
||||
|
||||
public bool Unimplemented { get; private set; } = false;
|
||||
|
||||
public override EightBit.MemoryMapping Mapping(ushort address) => new EightBit.MemoryMapping(this.ram, 0, EightBit.Mask.Mask16, EightBit.AccessLevel.ReadWrite);
|
||||
|
||||
public void Run()
|
||||
{
|
||||
this.RaisePOWER();
|
||||
this.Initialize();
|
||||
var allowedCycles = this.test.RegisterState.TStates;
|
||||
try
|
||||
{
|
||||
this.cpu.Run(allowedCycles);
|
||||
this.Check();
|
||||
}
|
||||
catch (System.InvalidOperationException error)
|
||||
{
|
||||
this.Unimplemented = true;
|
||||
System.Console.Error.WriteLine($"**** Error: {error.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void RaisePOWER()
|
||||
{
|
||||
base.RaisePOWER();
|
||||
this.cpu.RaisePOWER();
|
||||
this.cpu.RaiseRESET();
|
||||
this.cpu.RaiseINT();
|
||||
this.cpu.RaiseNMI();
|
||||
this.InitialiseRegisters();
|
||||
this.InitialiseMemory();
|
||||
}
|
||||
|
||||
public override void LowerPOWER()
|
||||
{
|
||||
this.cpu.LowerPOWER();
|
||||
base.LowerPOWER();
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
private static void DumpDifference(string description, byte expected, byte actual)
|
||||
{
|
||||
var output = $"**** {description}, Expected: {expected:x2}, Got {actual:x2}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
private static void DumpDifference(string highDescription, string lowDescription, EightBit.Register16 expected, EightBit.Register16 actual)
|
||||
{
|
||||
var expectedHigh = expected.High;
|
||||
var expectedLow = expected.Low;
|
||||
|
||||
var actualHigh = actual.High;
|
||||
var actualLow = actual.Low;
|
||||
|
||||
if (expectedHigh != actualHigh)
|
||||
{
|
||||
DumpDifference(highDescription, actualHigh, expectedHigh);
|
||||
}
|
||||
|
||||
if (expectedLow != actualLow)
|
||||
{
|
||||
DumpDifference(lowDescription, actualLow, expectedLow);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitialiseRegisters()
|
||||
{
|
||||
var testState = this.test.RegisterState;
|
||||
var inputRegisters = testState.Registers;
|
||||
|
||||
this.cpu.AF.Word = inputRegisters[(int)Register.AF_].Word;
|
||||
this.cpu.BC.Word = inputRegisters[(int)Register.BC_].Word;
|
||||
this.cpu.DE.Word = inputRegisters[(int)Register.DE_].Word;
|
||||
this.cpu.HL.Word = inputRegisters[(int)Register.HL_].Word;
|
||||
this.cpu.Exx();
|
||||
this.cpu.ExxAF();
|
||||
this.cpu.AF.Word = inputRegisters[(int)Register.AF].Word;
|
||||
this.cpu.BC.Word = inputRegisters[(int)Register.BC].Word;
|
||||
this.cpu.DE.Word = inputRegisters[(int)Register.DE].Word;
|
||||
this.cpu.HL.Word = inputRegisters[(int)Register.HL].Word;
|
||||
|
||||
this.cpu.IX.Word = inputRegisters[(int)Register.IX].Word;
|
||||
this.cpu.IY.Word = inputRegisters[(int)Register.IY].Word;
|
||||
|
||||
this.cpu.SP.Word = inputRegisters[(int)Register.SP].Word;
|
||||
this.cpu.PC.Word = inputRegisters[(int)Register.PC].Word;
|
||||
|
||||
this.cpu.MEMPTR.Word = inputRegisters[(int)Register.MEMPTR].Word;
|
||||
|
||||
this.cpu.IV = (byte)testState.I;
|
||||
this.cpu.REFRESH = (byte)testState.R;
|
||||
this.cpu.IFF1 = testState.IFF1;
|
||||
this.cpu.IFF2 = testState.IFF2;
|
||||
this.cpu.IM = testState.IM;
|
||||
}
|
||||
|
||||
private void InitialiseMemory()
|
||||
{
|
||||
foreach (var memoryDatum in this.test.MemoryData)
|
||||
{
|
||||
var address = memoryDatum.Address;
|
||||
foreach (var seed in memoryDatum.Bytes)
|
||||
{
|
||||
this.Poke(address++, seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Check()
|
||||
{
|
||||
this.Checkregisters();
|
||||
this.CheckMemory();
|
||||
}
|
||||
|
||||
private void Checkregisters()
|
||||
{
|
||||
var expectedState = this.result.RegisterState;
|
||||
var expectedRegisters = expectedState.Registers;
|
||||
|
||||
var af = this.cpu.AF.Word == expectedRegisters[(int)Register.AF].Word;
|
||||
var bc = this.cpu.BC.Word == expectedRegisters[(int)Register.BC].Word;
|
||||
var de = this.cpu.DE.Word == expectedRegisters[(int)Register.DE].Word;
|
||||
var hl = this.cpu.HL.Word == expectedRegisters[(int)Register.HL].Word;
|
||||
|
||||
this.cpu.Exx();
|
||||
this.cpu.ExxAF();
|
||||
|
||||
var af_ = this.cpu.AF.Word == expectedRegisters[(int)Register.AF_].Word;
|
||||
var bc_ = this.cpu.BC.Word == expectedRegisters[(int)Register.BC_].Word;
|
||||
var de_ = this.cpu.DE.Word == expectedRegisters[(int)Register.DE_].Word;
|
||||
var hl_ = this.cpu.HL.Word == expectedRegisters[(int)Register.HL_].Word;
|
||||
|
||||
var ix = this.cpu.IX.Word == expectedRegisters[(int)Register.IX].Word;
|
||||
var iy = this.cpu.IY.Word == expectedRegisters[(int)Register.IY].Word;
|
||||
|
||||
var sp = this.cpu.SP.Word == expectedRegisters[(int)Register.SP].Word;
|
||||
var pc = this.cpu.PC.Word == expectedRegisters[(int)Register.PC].Word;
|
||||
|
||||
var memptr = this.cpu.MEMPTR.Word == expectedRegisters[(int)Register.MEMPTR].Word;
|
||||
|
||||
var iv = this.cpu.IV == expectedState.I;
|
||||
var refresh = this.cpu.REFRESH == expectedState.R;
|
||||
var iff1 = this.cpu.IFF1 == expectedState.IFF1;
|
||||
var iff2 = this.cpu.IFF2 == expectedState.IFF2;
|
||||
var im = this.cpu.IM == expectedState.IM;
|
||||
|
||||
// And back again, so the following works as expected...
|
||||
this.cpu.Exx();
|
||||
this.cpu.ExxAF();
|
||||
|
||||
var success =
|
||||
af && bc && de && hl
|
||||
&& af_ && bc_ && de_ && hl_
|
||||
&& ix && iy
|
||||
&& sp && pc
|
||||
&& iv && refresh
|
||||
&& iff1 && iff2
|
||||
&& im
|
||||
&& memptr;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
this.Failed = true;
|
||||
System.Console.Error.WriteLine($"**** Failed test (Register): {this.test.Description}");
|
||||
|
||||
if (!af)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.AF];
|
||||
var actualWord = this.cpu.AF;
|
||||
DumpDifference("A", "F", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!bc)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.BC];
|
||||
var actualWord = this.cpu.BC;
|
||||
DumpDifference("B", "C", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!de)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.DE];
|
||||
var actualWord = this.cpu.DE;
|
||||
DumpDifference("D", "E", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!hl)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.HL];
|
||||
var actualWord = this.cpu.HL;
|
||||
DumpDifference("H", "L", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!ix)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.IX];
|
||||
var actualWord = this.cpu.IX;
|
||||
DumpDifference("IXH", "IXL", actualWord, expectedWord);
|
||||
}
|
||||
|
||||
if (!iy)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.IY];
|
||||
var actualWord = this.cpu.IY;
|
||||
DumpDifference("IYH", "IYL", actualWord, expectedWord);
|
||||
}
|
||||
|
||||
if (!sp)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.SP];
|
||||
var actualWord = this.cpu.SP;
|
||||
DumpDifference("SPH", "SPL", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!pc)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.PC];
|
||||
var actualWord = this.cpu.PC;
|
||||
DumpDifference("PCH", "PCL", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!memptr)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.MEMPTR];
|
||||
var actualWord = this.cpu.MEMPTR;
|
||||
DumpDifference("MEMPTRH", "MEMPTRL", actualWord, expectedWord);
|
||||
}
|
||||
|
||||
this.cpu.ExxAF();
|
||||
this.cpu.Exx();
|
||||
|
||||
if (!af_)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.AF];
|
||||
var actualWord = this.cpu.AF;
|
||||
DumpDifference("A'", "F'", expectedWord, actualWord);
|
||||
}
|
||||
|
||||
if (!bc_)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.BC_];
|
||||
var actualWord = this.cpu.BC;
|
||||
DumpDifference("B'", "C'", actualWord, expectedWord);
|
||||
}
|
||||
|
||||
if (!de_)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.DE_];
|
||||
var actualWord = this.cpu.DE;
|
||||
DumpDifference("D'", "E'", actualWord, expectedWord);
|
||||
}
|
||||
|
||||
if (!hl_)
|
||||
{
|
||||
var expectedWord = expectedRegisters[(int)Register.HL_];
|
||||
var actualWord = this.cpu.HL;
|
||||
DumpDifference("H'", "L'", actualWord, expectedWord);
|
||||
}
|
||||
|
||||
if (!iv)
|
||||
{
|
||||
var output = $"**** IV, Expected: {expectedState.I:X2}, Got: {this.cpu.IV:X2}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
if (!refresh)
|
||||
{
|
||||
var output = $"**** R, Expected: {expectedState.R:X2}, Got: {this.cpu.REFRESH:X2}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
if (!iff1)
|
||||
{
|
||||
var output = $"**** IFF1, Expected: {expectedState.IFF1}, Got: {this.cpu.IFF1}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
if (!iff2)
|
||||
{
|
||||
var output = $"**** IFF2, Expected: {expectedState.IFF2}, Got: {this.cpu.IFF2}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
if (!im)
|
||||
{
|
||||
var output = $"**** IM, Expected: {expectedState.IM}, Got: {this.cpu.IM}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckMemory()
|
||||
{
|
||||
var first = true;
|
||||
|
||||
foreach (var memoryDatum in this.result.MemoryData)
|
||||
{
|
||||
var address = memoryDatum.Address;
|
||||
foreach (var expected in memoryDatum.Bytes)
|
||||
{
|
||||
var actual = this.Peek(address);
|
||||
if (expected != actual)
|
||||
{
|
||||
this.Failed = true;
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
System.Console.Error.WriteLine($"**** Failed test (Memory): {this.test.Description}");
|
||||
}
|
||||
|
||||
System.Console.Error.WriteLine($"**** Difference: Address: {address:x4} Expected: {expected:x2} Actual: {actual:x2}");
|
||||
}
|
||||
|
||||
++address;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
Z80/Z80.FuseTest/TestSuite.cs
Normal file
58
Z80/Z80.FuseTest/TestSuite.cs
Normal file
@ -0,0 +1,58 @@
|
||||
// <copyright file="TestSuite.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace Fuse
|
||||
{
|
||||
public class TestSuite
|
||||
{
|
||||
private readonly Tests<RegisterState> tests;
|
||||
private readonly Results<RegisterState> results;
|
||||
|
||||
public TestSuite(string path)
|
||||
{
|
||||
this.tests = new Tests<RegisterState>(path + ".in");
|
||||
this.results = new Results<RegisterState>(path + ".expected");
|
||||
}
|
||||
|
||||
public void Read()
|
||||
{
|
||||
this.tests.Read();
|
||||
this.results.Read();
|
||||
}
|
||||
|
||||
public void Parse()
|
||||
{
|
||||
this.tests.Parse();
|
||||
this.results.Parse();
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
var failedCount = 0;
|
||||
var unimplementedCount = 0;
|
||||
foreach (var test in this.tests.Container)
|
||||
{
|
||||
var key = test.Key;
|
||||
System.Console.Out.WriteLine($"** Checking: {key}");
|
||||
|
||||
var input = test.Value;
|
||||
var result = this.results.Container[key];
|
||||
var runner = new TestRunner(input, result);
|
||||
|
||||
runner.Run();
|
||||
if (runner.Failed)
|
||||
{
|
||||
++failedCount;
|
||||
}
|
||||
|
||||
if (runner.Unimplemented)
|
||||
{
|
||||
++unimplementedCount;
|
||||
}
|
||||
}
|
||||
|
||||
System.Console.Out.WriteLine($"+++ Failed test count: {failedCount}");
|
||||
System.Console.Out.WriteLine($"+++ Unimplemented test count: {unimplementedCount}");
|
||||
}
|
||||
}
|
||||
}
|
70
Z80/Z80.FuseTest/Z80.FuseTest.csproj
Normal file
70
Z80/Z80.FuseTest/Z80.FuseTest.csproj
Normal file
@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{0233FF6C-DB1A-4353-8E42-D22717770226}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Z80.FuseTest</RootNamespace>
|
||||
<AssemblyName>Z80.FuseTest</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RegisterState.cs" />
|
||||
<Compile Include="TestRunner.cs" />
|
||||
<Compile Include="TestSuite.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\EightBit\EightBit.csproj">
|
||||
<Project>{6ebf8857-62a3-4ef4-af21-c1844031d7e4}</Project>
|
||||
<Name>EightBit</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Fuse\Fuse.csproj">
|
||||
<Project>{28e65032-5dff-406f-9385-0ee1422a7f4a}</Project>
|
||||
<Name>Fuse</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Z80.csproj">
|
||||
<Project>{c00648c1-bac1-4efb-816f-e87c091619d7}</Project>
|
||||
<Name>Z80</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
79
Z80/Z80.FuseTest/fuse-tests/README
Normal file
79
Z80/Z80.FuseTest/fuse-tests/README
Normal 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).
|
||||
|
18913
Z80/Z80.FuseTest/fuse-tests/tests.expected
Normal file
18913
Z80/Z80.FuseTest/fuse-tests/tests.expected
Normal file
File diff suppressed because it is too large
Load Diff
9153
Z80/Z80.FuseTest/fuse-tests/tests.in
Normal file
9153
Z80/Z80.FuseTest/fuse-tests/tests.in
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user