mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2025-03-10 19:29:31 +00:00
Z80 .net 9 analysis changes
This commit is contained in:
parent
3b80ee7b37
commit
f6829f2ec0
@ -2,9 +2,11 @@
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
|
||||
namespace Z80
|
||||
{
|
||||
using System;
|
||||
using EightBit;
|
||||
using System.Globalization;
|
||||
|
||||
public class Disassembler(Bus bus)
|
||||
{
|
||||
@ -71,8 +73,8 @@ namespace EightBit
|
||||
public string Disassemble(Z80 cpu)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(cpu);
|
||||
_prefixCB = _prefixDD = _prefixED = _prefixFD = false;
|
||||
return Disassemble(cpu, cpu.PC.Word);
|
||||
this._prefixCB = this._prefixDD = this._prefixED = this._prefixFD = false;
|
||||
return this.Disassemble(cpu, cpu.PC.Word);
|
||||
}
|
||||
|
||||
private static string CC(int flag) => flag switch
|
||||
@ -103,7 +105,7 @@ namespace EightBit
|
||||
|
||||
private string Disassemble(Z80 cpu, ushort pc)
|
||||
{
|
||||
var opCode = Bus.Peek(pc);
|
||||
var opCode = this.Bus.Peek(pc);
|
||||
|
||||
var decoded = cpu.GetDecodedOpCode(opCode);
|
||||
|
||||
@ -114,37 +116,37 @@ namespace EightBit
|
||||
var p = decoded.P;
|
||||
var q = decoded.Q;
|
||||
|
||||
var immediate = Bus.Peek((ushort)(pc + 1));
|
||||
var immediate = this.Bus.Peek((ushort)(pc + 1));
|
||||
var absolute = cpu.PeekWord((ushort)(pc + 1)).Word;
|
||||
var displacement = (sbyte)immediate;
|
||||
var relative = pc + displacement + 2;
|
||||
var indexedImmediate = Bus.Peek((ushort)(pc + 1));
|
||||
var indexedImmediate = this.Bus.Peek((ushort)(pc + 1));
|
||||
|
||||
var dumpCount = 0;
|
||||
|
||||
var output = $"{opCode:x2}";
|
||||
|
||||
var specification = string.Empty;
|
||||
if (_prefixCB)
|
||||
if (this._prefixCB)
|
||||
{
|
||||
output += DisassembleCB(ref specification, x, y, z);
|
||||
output += this.DisassembleCB(ref specification, x, y, z);
|
||||
}
|
||||
else if (_prefixED)
|
||||
else if (this._prefixED)
|
||||
{
|
||||
output += DisassembleED(ref specification, ref dumpCount, x, y, z, p, q);
|
||||
output += this.DisassembleED(ref specification, ref dumpCount, x, y, z, p, q);
|
||||
}
|
||||
else
|
||||
{
|
||||
output += DisassembleOther(cpu, pc, ref specification, ref dumpCount, x, y, z, p, q);
|
||||
output += this.DisassembleOther(cpu, pc, ref specification, ref dumpCount, x, y, z, p, q);
|
||||
}
|
||||
|
||||
for (var i = 0; i < dumpCount; ++i)
|
||||
{
|
||||
output += $"{Bus.Peek((ushort)(pc + i + 1)):x2}";
|
||||
output += $"{this.Bus.Peek((ushort)(pc + i + 1)):x2}";
|
||||
}
|
||||
|
||||
var outputFormatSpecification = !_prefixDD;
|
||||
if (_prefixDD)
|
||||
var outputFormatSpecification = !this._prefixDD;
|
||||
if (this._prefixDD)
|
||||
{
|
||||
if (opCode != 0xdd)
|
||||
{
|
||||
@ -170,40 +172,44 @@ namespace EightBit
|
||||
switch (y)
|
||||
{
|
||||
case 0:
|
||||
specification = $"RLC {R(z)}";
|
||||
specification = $"RLC {this.R(z)}";
|
||||
break;
|
||||
case 1:
|
||||
specification = $"RRC {R(z)}";
|
||||
specification = $"RRC {this.R(z)}";
|
||||
break;
|
||||
case 2:
|
||||
specification = $"RL {R(z)}";
|
||||
specification = $"RL {this.R(z)}";
|
||||
break;
|
||||
case 3:
|
||||
specification = $"RR {R(z)}";
|
||||
specification = $"RR {this.R(z)}";
|
||||
break;
|
||||
case 4:
|
||||
specification = $"SLA {R(z)}";
|
||||
specification = $"SLA {this.R(z)}";
|
||||
break;
|
||||
case 5:
|
||||
specification = $"SRA {R(z)}";
|
||||
specification = $"SRA {this.R(z)}";
|
||||
break;
|
||||
case 6:
|
||||
specification = $"SWAP {R(z)}";
|
||||
specification = $"SWAP {this.R(z)}";
|
||||
break;
|
||||
case 7:
|
||||
specification = $"SRL {R(z)}";
|
||||
specification = $"SRL {this.R(z)}";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 1: // BIT y, r[z]
|
||||
specification = $"BIT {y},{R(z)}";
|
||||
specification = $"BIT {y},{this.R(z)}";
|
||||
break;
|
||||
case 2: // RES y, r[z]
|
||||
specification = $"RES {y},{R(z)}";
|
||||
specification = $"RES {y},{this.R(z)}";
|
||||
break;
|
||||
case 3: // SET y, r[z]
|
||||
specification = $"SET {y},{R(z)}";
|
||||
specification = $"SET {y},{this.R(z)}";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -223,21 +229,23 @@ namespace EightBit
|
||||
switch (z)
|
||||
{
|
||||
case 0:
|
||||
specification = $"IN {R(y)}, (C)";
|
||||
specification = $"IN {this.R(y)}, (C)";
|
||||
break;
|
||||
|
||||
case 1:
|
||||
specification = $"OUT (C), {R(y)}";
|
||||
specification = $"OUT (C), {this.R(y)}";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
switch (q)
|
||||
{
|
||||
case 0: // SBC HL,rp
|
||||
specification = $"SBC HL,{RP(p)}";
|
||||
specification = $"SBC HL,{this.RP(p)}";
|
||||
break;
|
||||
case 1: // ADC HL,rp
|
||||
specification = $"ADC HL,{RP(p)}";
|
||||
specification = $"ADC HL,{this.RP(p)}";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -246,10 +254,12 @@ namespace EightBit
|
||||
switch (q)
|
||||
{
|
||||
case 0: // LD (nn),rp
|
||||
specification = "LD ({1:X4}H)," + RP(p);
|
||||
specification = "LD ({1:X4}H)," + this.RP(p);
|
||||
break;
|
||||
case 1: // LD rp,(nn)
|
||||
specification = "LD " + RP(p) + ",(%2$04XH)";
|
||||
specification = "LD " + this.RP(p) + ",(%2$04XH)";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -282,6 +292,8 @@ namespace EightBit
|
||||
case 7:
|
||||
specification = "IM 2";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -310,8 +322,12 @@ namespace EightBit
|
||||
case 7:
|
||||
specification = "NOP";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -334,6 +350,8 @@ namespace EightBit
|
||||
case 7: // LDDR
|
||||
specification = "LDDR";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -352,6 +370,8 @@ namespace EightBit
|
||||
case 7: // CPDR
|
||||
specification = "CPDR";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -370,6 +390,8 @@ namespace EightBit
|
||||
case 7: // INDR
|
||||
specification = "INDR";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -388,11 +410,17 @@ namespace EightBit
|
||||
case 7: // OTDR
|
||||
specification = "OTDR";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -435,11 +463,13 @@ namespace EightBit
|
||||
switch (q)
|
||||
{
|
||||
case 0: // LD rp,nn
|
||||
specification = "LD " + RP(p) + ",{1:X4}H";
|
||||
specification = "LD " + this.RP(p) + ",{1:X4}H";
|
||||
dumpCount += 2;
|
||||
break;
|
||||
case 1: // ADD HL,rp
|
||||
specification = $"ADD HL,{RP(p)}";
|
||||
specification = $"ADD HL,{this.RP(p)}";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -464,6 +494,8 @@ namespace EightBit
|
||||
specification = "LD ({1:X4}H),A";
|
||||
dumpCount += 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -484,8 +516,12 @@ namespace EightBit
|
||||
specification = "LD A,({1:X4}H)";
|
||||
dumpCount += 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -494,23 +530,25 @@ namespace EightBit
|
||||
switch (q)
|
||||
{
|
||||
case 0: // INC rp
|
||||
specification = $"INC {RP(p)}";
|
||||
specification = $"INC {this.RP(p)}";
|
||||
break;
|
||||
case 1: // DEC rp
|
||||
specification = $"DEC {RP(p)}";
|
||||
specification = $"DEC {this.RP(p)}";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 4: // 8-bit INC
|
||||
specification = $"INC {R(y)}";
|
||||
specification = $"INC {this.R(y)}";
|
||||
break;
|
||||
case 5: // 8-bit DEC
|
||||
specification = $"DEC {R(y)}";
|
||||
specification = $"DEC {this.R(y)}";
|
||||
break;
|
||||
case 6: // 8-bit load immediate
|
||||
specification = $"LD {R(y)}";
|
||||
if (y == 6 && (_prefixDD || _prefixFD))
|
||||
specification = $"LD {this.R(y)}";
|
||||
if (y == 6 && (this._prefixDD || this._prefixFD))
|
||||
{
|
||||
specification += ",{4:X2}H";
|
||||
dumpCount++;
|
||||
@ -549,17 +587,21 @@ namespace EightBit
|
||||
case 7:
|
||||
specification = "CCF";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 1: // 8-bit loading
|
||||
specification = z == 6 && y == 6 ? "HALT" : $"LD {R(y)},{R(z)}";
|
||||
specification = z == 6 && y == 6 ? "HALT" : $"LD {this.R(y)},{this.R(z)}";
|
||||
break;
|
||||
case 2: // Operate on accumulator and register/memory location
|
||||
specification = $"{ALU(y)} A,{R(z)}";
|
||||
specification = $"{ALU(y)} A,{this.R(z)}";
|
||||
break;
|
||||
case 3:
|
||||
switch (z)
|
||||
@ -571,7 +613,7 @@ namespace EightBit
|
||||
switch (q)
|
||||
{
|
||||
case 0: // POP rp2[p]
|
||||
specification = $"POP {RP2(p)}";
|
||||
specification = $"POP {this.RP2(p)}";
|
||||
break;
|
||||
case 1:
|
||||
switch (p)
|
||||
@ -588,8 +630,12 @@ namespace EightBit
|
||||
case 3: // LD SP,HL
|
||||
specification = "LD SP,HL";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -606,8 +652,8 @@ namespace EightBit
|
||||
dumpCount += 2;
|
||||
break;
|
||||
case 1: // CB prefix
|
||||
_prefixCB = true;
|
||||
output += Disassemble(cpu, ++pc);
|
||||
this._prefixCB = true;
|
||||
output += this.Disassemble(cpu, ++pc);
|
||||
break;
|
||||
case 2: // OUT (n),A
|
||||
specification = "OUT ({0:X2}H),A";
|
||||
@ -629,6 +675,8 @@ namespace EightBit
|
||||
case 7: // EI
|
||||
specification = "EI";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -640,7 +688,7 @@ namespace EightBit
|
||||
switch (q)
|
||||
{
|
||||
case 0: // PUSH rp2[p]
|
||||
specification = $"PUSH {RP2(p)}";
|
||||
specification = $"PUSH {this.RP2(p)}";
|
||||
break;
|
||||
case 1:
|
||||
switch (p)
|
||||
@ -650,19 +698,23 @@ namespace EightBit
|
||||
dumpCount += 2;
|
||||
break;
|
||||
case 1: // DD prefix
|
||||
_prefixDD = true;
|
||||
output += Disassemble(cpu, ++pc);
|
||||
this._prefixDD = true;
|
||||
output += this.Disassemble(cpu, ++pc);
|
||||
break;
|
||||
case 2: // ED prefix
|
||||
_prefixED = true;
|
||||
output += Disassemble(cpu, ++pc);
|
||||
this._prefixED = true;
|
||||
output += this.Disassemble(cpu, ++pc);
|
||||
break;
|
||||
case 3: // FD prefix
|
||||
_prefixFD = true;
|
||||
output += Disassemble(cpu, ++pc);
|
||||
this._prefixFD = true;
|
||||
output += this.Disassemble(cpu, ++pc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -674,8 +726,12 @@ namespace EightBit
|
||||
case 7: // Restart: RST y * 8
|
||||
specification = $"RST {y * 8:X2}";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -691,12 +747,12 @@ namespace EightBit
|
||||
case 1:
|
||||
return "DE";
|
||||
case 2:
|
||||
if (_prefixDD)
|
||||
if (this._prefixDD)
|
||||
{
|
||||
return "IX";
|
||||
}
|
||||
|
||||
if (_prefixFD)
|
||||
if (this._prefixFD)
|
||||
{
|
||||
return "IY";
|
||||
}
|
||||
@ -704,6 +760,8 @@ namespace EightBit
|
||||
return "HL";
|
||||
case 3:
|
||||
return "SP";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(rp));
|
||||
@ -718,12 +776,12 @@ namespace EightBit
|
||||
case 1:
|
||||
return "DE";
|
||||
case 2:
|
||||
if (_prefixDD)
|
||||
if (this._prefixDD)
|
||||
{
|
||||
return "IX";
|
||||
}
|
||||
|
||||
if (_prefixFD)
|
||||
if (this._prefixFD)
|
||||
{
|
||||
return "IY";
|
||||
}
|
||||
@ -731,6 +789,8 @@ namespace EightBit
|
||||
return "HL";
|
||||
case 3:
|
||||
return "AF";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(rp));
|
||||
@ -749,38 +809,38 @@ namespace EightBit
|
||||
case 3:
|
||||
return "E";
|
||||
case 4:
|
||||
if (_prefixDD)
|
||||
if (this._prefixDD)
|
||||
{
|
||||
return "IXH";
|
||||
}
|
||||
|
||||
if (_prefixFD)
|
||||
if (this._prefixFD)
|
||||
{
|
||||
return "IYH";
|
||||
}
|
||||
|
||||
return "H";
|
||||
case 5:
|
||||
if (_prefixDD)
|
||||
if (this._prefixDD)
|
||||
{
|
||||
return "IXL";
|
||||
}
|
||||
|
||||
if (_prefixFD)
|
||||
if (this._prefixFD)
|
||||
{
|
||||
return "IYL";
|
||||
}
|
||||
|
||||
return "L";
|
||||
case 6:
|
||||
if (_prefixDD || _prefixFD)
|
||||
if (this._prefixDD || this._prefixFD)
|
||||
{
|
||||
if (_prefixDD)
|
||||
if (this._prefixDD)
|
||||
{
|
||||
return "IX+{4}";
|
||||
}
|
||||
|
||||
if (_prefixFD)
|
||||
if (this._prefixFD)
|
||||
{
|
||||
return "IY+{4}";
|
||||
}
|
||||
@ -793,6 +853,8 @@ namespace EightBit
|
||||
break;
|
||||
case 7:
|
||||
return "A";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(r));
|
||||
|
@ -2,8 +2,10 @@
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
namespace Z80
|
||||
{
|
||||
using EightBit;
|
||||
|
||||
public struct RefreshRegister(byte value) : IEquatable<RefreshRegister>
|
||||
{
|
||||
private readonly byte high = (byte)(value & (byte)Bits.Bit7);
|
||||
@ -31,15 +33,8 @@ namespace EightBit
|
||||
|
||||
public readonly byte ToByte() => ToByte(this);
|
||||
|
||||
public override readonly bool Equals(object? obj)
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public override readonly bool Equals(object? obj) => obj is not null && this.Equals((RefreshRegister)obj);
|
||||
|
||||
return this.Equals((RefreshRegister)obj);
|
||||
}
|
||||
public readonly bool Equals(RefreshRegister other) => other.high == this.high && other.variable == this.variable;
|
||||
|
||||
public override readonly int GetHashCode() => this.high + this.variable;
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
namespace Z80
|
||||
{
|
||||
public enum RegisterIndex
|
||||
{
|
||||
|
@ -2,9 +2,9 @@
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
namespace Z80
|
||||
{
|
||||
using System;
|
||||
using EightBit;
|
||||
|
||||
[Flags]
|
||||
public enum StatusBits
|
||||
|
@ -2,16 +2,9 @@
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
using Z80.FuseTest;
|
||||
|
||||
var suite = new TestSuite("fuse-tests\\tests");
|
||||
suite.Read();
|
||||
suite.Parse();
|
||||
suite.Run();
|
||||
|
@ -1,25 +1,27 @@
|
||||
// <copyright file="RegisterState.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace Fuse
|
||||
|
||||
namespace Z80.FuseTest
|
||||
{
|
||||
using System;
|
||||
using Fuse;
|
||||
using System.Globalization;
|
||||
|
||||
public class RegisterState : AbstractRegisterState, IRegisterState
|
||||
internal 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 IFF1 { get; private set; }
|
||||
|
||||
public bool IFF2 { get; private set; } = false;
|
||||
public bool IFF2 { get; private set; }
|
||||
|
||||
public int IM { get; private set; } = -1;
|
||||
|
||||
protected override void ParseInternalState(string[] tokens)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(tokens);
|
||||
this.I = Convert.ToInt32(tokens[0], 16);
|
||||
this.R = Convert.ToInt32(tokens[1], 16);
|
||||
this.IFF1 = Convert.ToInt32(tokens[2], CultureInfo.InvariantCulture) == 1;
|
||||
|
@ -2,12 +2,13 @@
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace Fuse
|
||||
namespace Z80.FuseTest
|
||||
{
|
||||
using System;
|
||||
using Fuse;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
public enum Register
|
||||
internal enum Register
|
||||
{
|
||||
AF,
|
||||
BC,
|
||||
@ -24,18 +25,18 @@ namespace Fuse
|
||||
MEMPTR,
|
||||
}
|
||||
|
||||
public class TestRunner : EightBit.Bus
|
||||
internal class TestRunner : EightBit.Bus
|
||||
{
|
||||
private readonly Test<RegisterState> test;
|
||||
private readonly Result<RegisterState> result;
|
||||
private readonly TestEvents expectedEvents = new TestEvents();
|
||||
private readonly TestEvents actualEvents = new TestEvents();
|
||||
private readonly EightBit.Ram ram = new EightBit.Ram(0x10000);
|
||||
private readonly EightBit.InputOutput ports = new EightBit.InputOutput();
|
||||
private readonly EightBit.Z80 cpu;
|
||||
private readonly EightBit.Disassembler disassembler;
|
||||
private readonly TestEvents expectedEvents = new();
|
||||
private readonly TestEvents actualEvents = new();
|
||||
private readonly EightBit.Ram ram = new(0x10000);
|
||||
private readonly EightBit.InputOutput ports = new();
|
||||
private readonly Z80.Z80 cpu;
|
||||
private readonly Disassembler disassembler;
|
||||
|
||||
private int totalCycles = 0;
|
||||
private int totalCycles;
|
||||
|
||||
public TestRunner(Test<RegisterState> test, Result<RegisterState> result)
|
||||
{
|
||||
@ -47,18 +48,19 @@ namespace Fuse
|
||||
foreach (var e in result.Events.Container)
|
||||
{
|
||||
// Ignore contention events
|
||||
if (!e.Specifier.EndsWith("C", System.StringComparison.Ordinal))
|
||||
Debug.Assert(e.Specifier is not null);
|
||||
if (!e.Specifier.EndsWith('C'))
|
||||
{
|
||||
this.expectedEvents.Add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Failed { get; private set; } = false;
|
||||
public bool Failed { get; private set; }
|
||||
|
||||
public bool Unimplemented { get; private set; } = false;
|
||||
public bool Unimplemented { get; private set; }
|
||||
|
||||
public override EightBit.MemoryMapping Mapping(ushort address) => new EightBit.MemoryMapping(this.ram, 0, EightBit.Mask.Sixteen, EightBit.AccessLevel.ReadWrite);
|
||||
public override EightBit.MemoryMapping Mapping(ushort address) => new(this.ram, 0, EightBit.Mask.Sixteen, EightBit.AccessLevel.ReadWrite);
|
||||
|
||||
public void Run()
|
||||
{
|
||||
@ -67,13 +69,13 @@ namespace Fuse
|
||||
var allowedCycles = this.test.RegisterState.TStates;
|
||||
try
|
||||
{
|
||||
this.cpu.Run(allowedCycles);
|
||||
_ = this.cpu.Run(allowedCycles);
|
||||
this.Check();
|
||||
}
|
||||
catch (System.InvalidOperationException error)
|
||||
catch (InvalidOperationException error)
|
||||
{
|
||||
this.Unimplemented = true;
|
||||
System.Console.Error.WriteLine($"**** Error: {error.Message}");
|
||||
Console.Error.WriteLine($"**** Error: {error.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,14 +118,14 @@ namespace Fuse
|
||||
private static void DumpDifference(string description, byte expected, byte actual)
|
||||
{
|
||||
var output = $"**** {description}, Expected: {expected:x2}, Got {actual:x2}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
private void Ports_WrittenPort(object sender, EightBit.PortEventArgs e) => this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "PW", this.Address.Word, this.Data));
|
||||
private void Ports_WrittenPort(object? sender, EightBit.PortEventArgs e) => this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "PW", this.Address.Word, this.Data));
|
||||
|
||||
private void Ports_ReadPort(object sender, EightBit.PortEventArgs e) => this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "PR", this.Address.Word, this.Data));
|
||||
private void Ports_ReadPort(object? sender, EightBit.PortEventArgs e) => this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "PR", this.Address.Word, this.Data));
|
||||
|
||||
private void Cpu_ExecutedInstruction(object sender, System.EventArgs e) => this.totalCycles += this.cpu.Cycles;
|
||||
private void Cpu_ExecutedInstruction(object? sender, EventArgs e) => this.totalCycles += this.cpu.Cycles;
|
||||
|
||||
private static void DumpDifference(string highDescription, string lowDescription, EightBit.Register16 expected, EightBit.Register16 actual)
|
||||
{
|
||||
@ -243,7 +245,7 @@ namespace Fuse
|
||||
if (!success)
|
||||
{
|
||||
this.Failed = true;
|
||||
System.Console.Error.WriteLine($"**** Failed test (Register): {this.test.Description}");
|
||||
Console.Error.WriteLine($"**** Failed test (Register): {this.test.Description}");
|
||||
|
||||
if (!af)
|
||||
{
|
||||
@ -258,8 +260,8 @@ namespace Fuse
|
||||
var gotF = this.cpu.F;
|
||||
if (expectedF != gotF)
|
||||
{
|
||||
var output = $"**** F, Expected: {EightBit.Disassembler.AsFlags(expectedF)}, Got: {EightBit.Disassembler.AsFlags(gotF)}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
var output = $"**** F, Expected: {Disassembler.AsFlags(expectedF)}, Got: {Disassembler.AsFlags(gotF)}";
|
||||
Console.Error.WriteLine(output);
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,8 +337,8 @@ namespace Fuse
|
||||
var gotF = this.cpu.F;
|
||||
if (expectedF != gotF)
|
||||
{
|
||||
var output = $"**** F', Expected: {EightBit.Disassembler.AsFlags(expectedF)}, Got: {EightBit.Disassembler.AsFlags(gotF)}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
var output = $"**** F', Expected: {Disassembler.AsFlags(expectedF)}, Got: {Disassembler.AsFlags(gotF)}";
|
||||
Console.Error.WriteLine(output);
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,36 +366,36 @@ namespace Fuse
|
||||
if (!iv)
|
||||
{
|
||||
var output = $"**** IV, Expected: {expectedState.I:X2}, Got: {this.cpu.IV:X2}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
if (!refresh)
|
||||
{
|
||||
var output = $"**** R, Expected: {expectedState.R:X2}, Got: {this.cpu.REFRESH.ToByte():X2}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
if (!iff1)
|
||||
{
|
||||
var output = $"**** IFF1, Expected: {expectedState.IFF1}, Got: {this.cpu.IFF1}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
if (!iff2)
|
||||
{
|
||||
var output = $"**** IFF2, Expected: {expectedState.IFF2}, Got: {this.cpu.IFF2}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
if (!im)
|
||||
{
|
||||
var output = $"**** IM, Expected: {expectedState.IM}, Got: {this.cpu.IM}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
this.cpu.PC.Word = this.test.RegisterState.Registers[(int)Register.PC].Word;
|
||||
var disassembled = this.disassembler.Disassemble(this.cpu);
|
||||
System.Console.Error.WriteLine(disassembled);
|
||||
Console.Error.WriteLine(disassembled);
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,7 +405,7 @@ namespace Fuse
|
||||
var actuals = this.actualEvents.Container;
|
||||
|
||||
var eventFailure = expectations.Count != actuals.Count;
|
||||
for (var i = 0; !eventFailure && (i < expectations.Count); ++i)
|
||||
for (var i = 0; !eventFailure && i < expectations.Count; ++i)
|
||||
{
|
||||
var expectation = expectations[i];
|
||||
var actual = actuals[i];
|
||||
@ -431,13 +433,13 @@ namespace Fuse
|
||||
|
||||
private void DumpExpectedEvents()
|
||||
{
|
||||
System.Console.Error.WriteLine("++++ Dumping expected events:");
|
||||
Console.Error.WriteLine("++++ Dumping expected events:");
|
||||
DumpEvents(this.expectedEvents.Container);
|
||||
}
|
||||
|
||||
private void DumpActualEvents()
|
||||
{
|
||||
System.Console.Error.WriteLine("++++ Dumping actual events:");
|
||||
Console.Error.WriteLine("++++ Dumping actual events:");
|
||||
DumpEvents(this.actualEvents.Container);
|
||||
}
|
||||
|
||||
@ -452,7 +454,7 @@ namespace Fuse
|
||||
private static void DumpEvent(TestEvent e)
|
||||
{
|
||||
var output = $" Event issue {e}";
|
||||
System.Console.Error.WriteLine(output);
|
||||
Console.Error.WriteLine(output);
|
||||
}
|
||||
|
||||
private void CheckMemory()
|
||||
@ -471,10 +473,10 @@ namespace Fuse
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
System.Console.Error.WriteLine($"**** Failed test (Memory): {this.test.Description}");
|
||||
Console.Error.WriteLine($"**** Failed test (Memory): {this.test.Description}");
|
||||
}
|
||||
|
||||
System.Console.Error.WriteLine($"**** Difference: Address: {address:x4} Expected: {expected:x2} Actual: {actual:x2}");
|
||||
Console.Error.WriteLine($"**** Difference: Address: {address:x4} Expected: {expected:x2} Actual: {actual:x2}");
|
||||
}
|
||||
|
||||
++address;
|
||||
|
@ -1,18 +1,15 @@
|
||||
// <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");
|
||||
}
|
||||
namespace Z80.FuseTest
|
||||
{
|
||||
using Fuse;
|
||||
|
||||
internal class TestSuite(string path)
|
||||
{
|
||||
private readonly Tests<RegisterState> tests = new(path + ".in");
|
||||
private readonly Results<RegisterState> results = new(path + ".expected");
|
||||
|
||||
public void Read()
|
||||
{
|
||||
@ -33,7 +30,7 @@ namespace Fuse
|
||||
foreach (var test in this.tests.Container)
|
||||
{
|
||||
var key = test.Key;
|
||||
System.Console.Out.WriteLine($"** Checking: {key}");
|
||||
Console.Out.WriteLine($"** Checking: {key}");
|
||||
|
||||
var input = test.Value;
|
||||
var result = this.results.Container[key];
|
||||
@ -51,8 +48,8 @@ namespace Fuse
|
||||
}
|
||||
}
|
||||
|
||||
System.Console.Out.WriteLine($"+++ Failed test count: {failedCount}");
|
||||
System.Console.Out.WriteLine($"+++ Unimplemented test count: {unimplementedCount}");
|
||||
Console.Out.WriteLine($"+++ Failed test count: {failedCount}");
|
||||
Console.Out.WriteLine($"+++ Unimplemented test count: {unimplementedCount}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ namespace Z80.Test
|
||||
{
|
||||
var programPath = this.configuration.RomDirectory + "/" + this.configuration.Program;
|
||||
var loadAddress = this.configuration.LoadAddress;
|
||||
this.ram.Load(programPath, loadAddress.Word);
|
||||
_ = this.ram.Load(programPath, loadAddress.Word);
|
||||
|
||||
this.CPU.LoweredHALT += this.CPU_LoweredHALT;
|
||||
this.CPU.ExecutingInstruction += this.CPU_ExecutingInstruction_CPM;
|
||||
@ -78,6 +78,8 @@ namespace Z80.Test
|
||||
System.Console.Out.Write((char)this.Peek(i));
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -108,6 +110,6 @@ namespace Z80.Test
|
||||
|
||||
private void CPU_LoweredHALT(object? sender, System.EventArgs e) => this.LowerPOWER();
|
||||
|
||||
private void CPU_ExecutingInstruction_Debug(object? sender, System.EventArgs e) => System.Console.Error.WriteLine($"{EightBit.Disassembler.State(this.CPU)}\t{this.disassembler.Disassemble(this.CPU)}");
|
||||
private void CPU_ExecutingInstruction_Debug(object? sender, System.EventArgs e) => System.Console.Error.WriteLine($"{Z80.Disassembler.State(this.CPU)}\t{this.disassembler.Disassemble(this.CPU)}");
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ namespace Z80.Test
|
||||
{
|
||||
using EightBit;
|
||||
|
||||
public static class Program
|
||||
internal static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
|
1227
Z80/Z80.cs
1227
Z80/Z80.cs
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user