Starting to port Fuse test runner for LR35902 emulator. Not running yet.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon
2019-07-19 23:59:32 +01:00
parent b6ced1ddd5
commit ed92ce33f6
18 changed files with 9479 additions and 0 deletions

View File

@@ -27,6 +27,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MC6850", "MC6850\MC6850.csp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MC6809.Test", "MC6809\MC6809.Test\MC6809.Test.csproj", "{5ADB4727-2F5F-4A41-979B-6734501E34BC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LR35902", "LR35902\LR35902.csproj", "{01F61A1D-CB4A-4EA3-96EF-222F831DF483}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LR35902.FuseTest", "LR35902\LR35902.FuseTest\LR35902.FuseTest.csproj", "{CC24B08D-1C51-43FD-961D-7C9A49253D69}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -181,6 +185,30 @@ Global
{5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|x64.Build.0 = Release|Any CPU
{5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|x86.ActiveCfg = Release|Any CPU
{5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|x86.Build.0 = Release|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|Any CPU.Build.0 = Debug|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|x64.ActiveCfg = Debug|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|x64.Build.0 = Debug|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|x86.ActiveCfg = Debug|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Debug|x86.Build.0 = Debug|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|Any CPU.ActiveCfg = Release|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|Any CPU.Build.0 = Release|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|x64.ActiveCfg = Release|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|x64.Build.0 = Release|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|x86.ActiveCfg = Release|Any CPU
{01F61A1D-CB4A-4EA3-96EF-222F831DF483}.Release|x86.Build.0 = Release|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|x64.ActiveCfg = Debug|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|x64.Build.0 = Debug|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|x86.ActiveCfg = Debug|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Debug|x86.Build.0 = Debug|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|Any CPU.Build.0 = Release|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|x64.ActiveCfg = Release|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|x64.Build.0 = Release|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|x86.ActiveCfg = Release|Any CPU
{CC24B08D-1C51-43FD-961D-7C9A49253D69}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>

View File

@@ -0,0 +1,58 @@
namespace Fuse
{
using System;
using System.Collections.Generic;
using System.IO;
public class ExpectedTestResult
{
private readonly TestEvents events = new TestEvents();
public bool Finish { get; private set; } = false;
public string Description { get; private set; }
public RegisterState RegisterState { get; } = new RegisterState();
public List<MemoryDatum> MemoryData { get; } = new List<MemoryDatum>();
public void Read(StreamReader file)
{
this.Finish = false;
do
{
this.Description = file.ReadLine();
this.Finish = file.EndOfStream;
}
while (string.IsNullOrEmpty(this.Description) && !this.Finish);
if (this.Finish)
{
return;
}
this.events.Read(file);
this.RegisterState.Read(file);
var line = file.ReadLine();
if (line.Length > 0)
{
throw new InvalidOperationException("EOL swallow failure!!");
}
var finished = false;
do
{
line = file.ReadLine();
finished = string.IsNullOrEmpty(line);
if (!finished)
{
var datum = new MemoryDatum();
datum.Parse(line);
this.MemoryData.Add(datum);
}
}
while (!finished);
}
}
}

View File

@@ -0,0 +1,33 @@
namespace Fuse
{
using System.Collections.Generic;
using System.IO;
public class ExpectedTestResults
{
public Dictionary<string, ExpectedTestResult> Results { get; } = new Dictionary<string, ExpectedTestResult>();
public void Read(string path)
{
using (var file = new StreamReader(path))
{
this.Read(file);
}
}
private void Read(StreamReader file)
{
var finished = false;
while (!file.EndOfStream)
{
var result = new ExpectedTestResult();
result.Read(file);
finished = result.Finish;
if (!finished)
{
this.Results[result.Description] = result;
}
}
}
}
}

View File

@@ -0,0 +1,73 @@
<?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>{CC24B08D-1C51-43FD-961D-7C9A49253D69}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>Fuse</RootNamespace>
<AssemblyName>LR35902.FuseTest</AssemblyName>
<TargetFrameworkVersion>v4.7.2</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="ExpectedTestResult.cs" />
<Compile Include="ExpectedTestResults.cs" />
<Compile Include="MemoryDatum.cs" />
<Compile Include="RegisterState.cs" />
<Compile Include="Test.cs" />
<Compile Include="TestEvent.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestEvents.cs" />
<Compile Include="TestRunner.cs" />
<Compile Include="Tests.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="..\LR35902.csproj">
<Project>{01f61a1d-cb4a-4ea3-96ef-222f831df483}</Project>
<Name>LR35902</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,34 @@
namespace Fuse
{
using System;
using System.Collections.Generic;
public class MemoryDatum
{
public ushort Address { get; private set; } = (ushort)EightBit.Mask.Mask16;
public List<byte> Bytes { get; } = new List<byte>();
public void Parse(string line)
{
var tokens = line.Split(new char[] { ' ', '\t' });
this.Parse(tokens);
}
public void Parse(string[] tokens)
{
this.Address = Convert.ToUInt16(tokens[0], 16);
var finished = false;
for (var i = 1; !finished && (i < tokens.Length); ++i)
{
var token = tokens[i];
finished = token == "-1";
if (!finished)
{
this.Bytes.Add(Convert.ToByte(token, 16));
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
namespace Fuse
{
public static class Program
{
public static void Main(string[] args)
{
TestSuite testSuite = new TestSuite("fuse-tests\\tests");
testSuite.Run();
}
}
}

View 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("LR35902.FuseTest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LR35902.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("cc24b08d-1c51-43fd-961d-7c9a49253d69")]
// 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")]

View File

@@ -0,0 +1,44 @@
namespace Fuse
{
using System;
using System.Collections.Generic;
using System.IO;
using EightBit;
public class RegisterState
{
public enum Register
{
AF, BC, DE, HL, SP, PC
};
public List<Register16> Registers { get; } = new List<Register16>();
public bool Halted { get; private set; } = false;
public int TStates { get; private set; } = -1;
public void Read(StreamReader file)
{
this.ReadExternalState(file);
this.ReadInternalState(file);
}
private void ReadInternalState(StreamReader file)
{
var line = file.ReadLine();
var tokens = line.Split(new char[] { ' ', '\t' });
this.Halted = Convert.ToInt32(tokens[0]) == 1;
this.TStates = Convert.ToInt32(tokens[1]);
}
private void ReadExternalState(StreamReader file)
{
var line = file.ReadLine();
foreach (var token in line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries))
{
this.Registers.Add(new Register16(Convert.ToUInt16(token, 16)));
}
}
}
}

View File

@@ -0,0 +1,45 @@
namespace Fuse
{
using System.Collections.Generic;
using System.IO;
public class Test
{
public bool Valid => !string.IsNullOrEmpty(this.Description);
public string Description { get; private set; }
public RegisterState RegisterState { get; } = new RegisterState();
public List<MemoryDatum> MemoryData { get; } = new List<MemoryDatum>();
public void Read(StreamReader file)
{
while ((string.IsNullOrWhiteSpace(this.Description) || this.Description.StartsWith(";")) && !file.EndOfStream)
{
this.Description = file.ReadLine();
}
if (!this.Valid)
{
return;
}
this.RegisterState.Read(file);
var finished = false;
do
{
var line = file.ReadLine();
finished = line == "-1";
if (!finished)
{
var datum = new MemoryDatum();
datum.Parse(line);
this.MemoryData.Add(datum);
}
}
while (!finished);
}
}
}

View File

@@ -0,0 +1,65 @@
namespace Fuse
{
using System;
using System.IO;
public class TestEvent
{
public bool Valid { get; private set; } = false;
public int Cycles { get; private set; } = -1;
public string Specifier { get; private set; }
public ushort Address { get; private set; } = (ushort)EightBit.Mask.Mask16;
public ushort Value { get; private set; } = (byte)EightBit.Mask.Mask8;
public void Read(StreamReader file)
{
var prior = file.BaseStream.Position;
this.ParseLine(file.ReadLine());
if (!this.Valid)
{
file.BaseStream.Seek(prior, SeekOrigin.Begin);
}
}
private void ParseLine(string line)
{
var split = line.Split(new char[] { ' ', '\t' });
this.ParseLine(split);
}
private void ParseLine(string[] tokens)
{
this.Cycles = int.Parse(tokens[0]);
this.Specifier = tokens[1];
this.Valid = true;
switch (this.Specifier)
{
case "MR":
case "MW":
this.Address = Convert.ToUInt16(tokens[2], 16);
this.Value = Convert.ToByte(tokens[3], 16);
break;
case "MC":
case "PC":
this.Address = Convert.ToUInt16(tokens[2], 16);
break;
case "PR":
case "PW":
this.Address = Convert.ToUInt16(tokens[2], 16);
this.Value = Convert.ToByte(tokens[3], 16);
break;
default:
this.Valid = false;
break;
}
}
}
}

View File

@@ -0,0 +1,26 @@
namespace Fuse
{
using System.Collections.Generic;
using System.IO;
public class TestEvents
{
public List<TestEvent> Events { get; } = new List<TestEvent>();
public void Read(StreamReader file)
{
var complete = false;
do
{
var e = new TestEvent();
e.Read(file);
complete = !e.Valid;
if (!complete)
{
this.Events.Add(e);
}
}
while (!complete);
}
}
}

View File

@@ -0,0 +1,204 @@
namespace Fuse
{
public class TestRunner : EightBit.GameBoy.Bus
{
private readonly Test test;
private readonly ExpectedTestResult expected;
private readonly EightBit.Ram ram = new EightBit.Ram(0x10000);
public TestRunner(Test test, ExpectedTestResult expected)
{
this.test = test;
this.expected = expected;
}
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.Mask8, 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.InitialiseRegisters();
this.InitialiseMemory();
}
public override void LowerPOWER()
{
this.CPU.LowerPOWER();
base.LowerPOWER();
}
public override void Initialize() => this.DisableGameRom();
private void InitialiseRegisters()
{
var testState = this.test.RegisterState;
var inputRegisters = testState.Registers;
this.CPU.AF.Word = inputRegisters[(int)RegisterState.Register.AF].Word;
this.CPU.BC.Word = inputRegisters[(int)RegisterState.Register.BC].Word;
this.CPU.DE.Word = inputRegisters[(int)RegisterState.Register.DE].Word;
this.CPU.HL.Word = inputRegisters[(int)RegisterState.Register.HL].Word;
this.CPU.SP.Word = inputRegisters[(int)RegisterState.Register.SP].Word;
this.CPU.PC.Word = inputRegisters[(int)RegisterState.Register.PC].Word;
}
private void InitialiseMemory()
{
foreach (var memoryDatum in this.test.MemoryData)
{
var address = memoryDatum.Address;
var bytes = memoryDatum.Bytes;
for (var i = 0; i < bytes.Count; ++i)
{
this.Poke((ushort)(address + i), bytes[i]);
}
}
}
private void Check()
{
this.Checkregisters();
this.CheckMemory();
}
private void Checkregisters()
{
var expectedState = this.expected.RegisterState;
var expectedRegisters = expectedState.Registers;
var af = this.CPU.AF.Word == expectedRegisters[(int)RegisterState.Register.AF].Word;
var bc = this.CPU.BC.Word == expectedRegisters[(int)RegisterState.Register.BC].Word;
var de = this.CPU.DE.Word == expectedRegisters[(int)RegisterState.Register.DE].Word;
var hl = this.CPU.HL.Word == expectedRegisters[(int)RegisterState.Register.HL].Word;
var sp = this.CPU.SP.Word == expectedRegisters[(int)RegisterState.Register.SP].Word;
var pc = this.CPU.PC.Word == expectedRegisters[(int)RegisterState.Register.PC].Word;
var success = af && bc && de && hl && sp && pc;
if (!success)
{
this.Failed = true;
System.Console.Error.WriteLine($"**** Failed test (Register): {this.test.Description}");
if (!af)
{
var expectedWord = expectedRegisters[(int)RegisterState.Register.AF];
var actualWord = this.CPU.AF;
DumpDifference("A", "F", expectedWord, actualWord);
}
if (!bc)
{
var expectedWord = expectedRegisters[(int)RegisterState.Register.BC];
var actualWord = this.CPU.BC;
DumpDifference("B", "C", expectedWord, actualWord);
}
if (!de)
{
var expectedWord = expectedRegisters[(int)RegisterState.Register.DE];
var actualWord = this.CPU.DE;
DumpDifference("D", "E", expectedWord, actualWord);
}
if (!hl)
{
var expectedWord = expectedRegisters[(int)RegisterState.Register.HL];
var actualWord = this.CPU.HL;
DumpDifference("H", "L", expectedWord, actualWord);
}
if (!sp)
{
var expectedWord = expectedRegisters[(int)RegisterState.Register.SP];
var actualWord = this.CPU.SP;
DumpDifference("SPH", "SPL", expectedWord, actualWord);
}
if (!pc)
{
var expectedWord = expectedRegisters[(int)RegisterState.Register.PC];
var actualWord = this.CPU.PC;
DumpDifference("PCH", "PCL", expectedWord, actualWord);
}
}
}
private void CheckMemory()
{
var first = true;
foreach (var memoryDatum in this.expected.MemoryData)
{
var bytes = memoryDatum.Bytes;
for (var i = 0; i < bytes.Count; ++i)
{
var expected = bytes[i];
var address = (ushort)(memoryDatum.Address + i);
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}");
}
}
}
}
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);
}
}
}
}

View File

@@ -0,0 +1,42 @@
namespace Fuse
{
public class TestSuite
{
private readonly Tests tests = new Tests();
private readonly ExpectedTestResults results = new ExpectedTestResults();
public TestSuite(string path)
{
this.tests.Read(path + ".in");
this.results.Read(path + ".expected");
}
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.Results[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}");
}
}
}

View File

@@ -0,0 +1,31 @@
namespace Fuse
{
using System.Collections.Generic;
using System.IO;
public class Tests
{
public void Read(string path)
{
using (var file = new StreamReader(path))
{
this.Read(file);
}
}
public Dictionary<string, Test> Container { get; } = new Dictionary<string, Test>();
public void Read(StreamReader file)
{
while (!file.EndOfStream)
{
var test = new Test();
test.Read(file);
if (test.Valid)
{
this.Container.Add(test.Description, test);
}
}
}
}
}

View File

@@ -0,0 +1,79 @@
File formats
============
tests.in
--------
Each test has the format:
<arbitrary test description>
AF BC DE HL SP PC
<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