mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2025-07-25 13:24:08 +00:00
Turns out using lambdas to control pins is lovely and correct, but terribly slow. Back to a more traditional method.
This commit is contained in:
@@ -14,7 +14,6 @@ namespace EightBit
|
||||
|
||||
public override void PokeWord(ushort address, Register16 value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
this.Bus.Poke(address, value.High);
|
||||
this.Bus.Poke(++address, value.Low);
|
||||
}
|
||||
@@ -51,14 +50,12 @@ namespace EightBit
|
||||
|
||||
protected override void PushWord(Register16 value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
this.Push(value.Low);
|
||||
this.Push(value.High);
|
||||
}
|
||||
|
||||
protected override void SetWord(Register16 value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
this.MemoryWrite(value.High);
|
||||
++this.Bus.Address.Word;
|
||||
this.MemoryWrite(value.Low);
|
||||
@@ -66,7 +63,6 @@ namespace EightBit
|
||||
|
||||
protected override void SetWordPaged(Register16 value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
this.MemoryWrite(value.High);
|
||||
++this.Bus.Address.Low;
|
||||
this.MemoryWrite(value.Low);
|
||||
|
@@ -28,7 +28,6 @@ namespace EightBit
|
||||
|
||||
public byte Peek(Register16 absolute)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(absolute);
|
||||
return this.Peek(absolute.Word);
|
||||
}
|
||||
|
||||
@@ -38,7 +37,6 @@ namespace EightBit
|
||||
|
||||
public void Poke(Register16 absolute, byte value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(absolute);
|
||||
this.Poke(absolute.Word, value);
|
||||
}
|
||||
|
||||
@@ -58,7 +56,6 @@ namespace EightBit
|
||||
|
||||
public byte Read(Register16 absolute)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(absolute);
|
||||
return this.Read(absolute.Low, absolute.High);
|
||||
}
|
||||
|
||||
@@ -89,7 +86,6 @@ namespace EightBit
|
||||
|
||||
public void Write(Register16 absolute, byte value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(absolute);
|
||||
this.Write(absolute.Low, absolute.High, value);
|
||||
}
|
||||
|
||||
@@ -133,7 +129,6 @@ namespace EightBit
|
||||
|
||||
protected ref byte Reference(Register16 absolute)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(absolute);
|
||||
return ref this.Reference(absolute.Word);
|
||||
}
|
||||
|
||||
|
@@ -25,9 +25,9 @@ namespace EightBit
|
||||
{
|
||||
if (this.POWER.Lowered())
|
||||
{
|
||||
this.OnRaisingPOWER();
|
||||
RaisingPOWER?.Invoke(this, EventArgs.Empty);
|
||||
this.POWER.Raise();
|
||||
this.OnRaisedPOWER();
|
||||
RaisedPOWER?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,18 +35,10 @@ namespace EightBit
|
||||
{
|
||||
if (this.POWER.Raised())
|
||||
{
|
||||
this.OnLoweringPOWER();
|
||||
LoweringPOWER?.Invoke(this, EventArgs.Empty);
|
||||
this.POWER.Lower();
|
||||
this.OnLoweredPOWER();
|
||||
LoweredPOWER?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnRaisingPOWER() => RaisingPOWER?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisedPOWER() => RaisedPOWER?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweringPOWER() => LoweringPOWER?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredPOWER() => LoweredPOWER?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<GenerateDocumentationFile>False</GenerateDocumentationFile>
|
||||
<SignAssembly>False</SignAssembly>
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
<AnalysisLevel>latest-all</AnalysisLevel>
|
||||
<AnalysisLevel>latest-recommended</AnalysisLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
|
@@ -20,6 +20,7 @@ namespace EightBit
|
||||
{
|
||||
this._decodedOpCodes[i] = new((byte)i);
|
||||
}
|
||||
this.RaisedPOWER += this.IntelProcessor_RaisedPOWER;
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs>? RaisingHALT;
|
||||
@@ -67,9 +68,10 @@ namespace EightBit
|
||||
{
|
||||
if (this.HALT.Lowered())
|
||||
{
|
||||
this.OnRaisingHALT();
|
||||
RaisingHALT?.Invoke(this, EventArgs.Empty);
|
||||
this.HALT.Raise();
|
||||
this.OnRaisedHALT();
|
||||
++this.PC.Word; // Release the PC from HALT instruction
|
||||
RaisedHALT?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,9 +79,10 @@ namespace EightBit
|
||||
{
|
||||
if (this.HALT.Raised())
|
||||
{
|
||||
this.OnLoweringHALT();
|
||||
LoweringHALT?.Invoke(this, EventArgs.Empty);
|
||||
this.HALT.Lower();
|
||||
this.OnLoweredHALT();
|
||||
--this.PC.Word; // Keep the PC on the HALT instruction (i.e. executing NOP)
|
||||
LoweredHALT?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,27 +105,10 @@ namespace EightBit
|
||||
return HalfCarryTableSub[index & (int)Mask.Three];
|
||||
}
|
||||
|
||||
protected override void OnRaisedPOWER()
|
||||
private void IntelProcessor_RaisedPOWER(object? sender, EventArgs e)
|
||||
{
|
||||
this.PC.Word = this.SP.Word = this.AF.Word = this.BC.Word = this.DE.Word = this.HL.Word = (ushort)Mask.Sixteen;
|
||||
this.RaiseHALT();
|
||||
base.OnRaisedPOWER();
|
||||
}
|
||||
|
||||
protected virtual void OnRaisingHALT() => RaisingHALT?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisedHALT()
|
||||
{
|
||||
++this.PC.Word; // Release the PC from HALT instruction
|
||||
RaisedHALT?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
protected virtual void OnLoweringHALT() => LoweringHALT?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredHALT()
|
||||
{
|
||||
--this.PC.Word; // Keep the PC on the HALT instruction (i.e. executing NOP)
|
||||
LoweredHALT?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
protected override void HandleRESET()
|
||||
|
@@ -15,7 +15,6 @@ namespace EightBit
|
||||
|
||||
public override void PokeWord(ushort address, Register16 value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
this.Bus.Poke(address, value.Low);
|
||||
this.Bus.Poke(++address, value.High);
|
||||
}
|
||||
@@ -52,14 +51,12 @@ namespace EightBit
|
||||
|
||||
protected override void PushWord(Register16 value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
this.Push(value.High);
|
||||
this.Push(value.Low);
|
||||
}
|
||||
|
||||
protected override void SetWord(Register16 value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
this.MemoryWrite(value.Low);
|
||||
++this.Bus.Address.Word;
|
||||
this.MemoryWrite(value.High);
|
||||
@@ -67,7 +64,6 @@ namespace EightBit
|
||||
|
||||
protected override void SetWordPaged(Register16 value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
this.MemoryWrite(value.Low);
|
||||
++this.Bus.Address.Low;
|
||||
this.MemoryWrite(value.High);
|
||||
|
@@ -10,57 +10,9 @@ namespace EightBit
|
||||
|
||||
public event EventHandler<EventArgs>? ExecutingInstruction;
|
||||
public event EventHandler<EventArgs>? ExecutedInstruction;
|
||||
protected virtual void OnExecutedInstruction() => ExecutedInstruction?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnExecutingInstruction() => ExecutingInstruction?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Bus events
|
||||
|
||||
#region Memory events
|
||||
|
||||
#region Memory read events
|
||||
|
||||
public event EventHandler<EventArgs>? ReadingMemory;
|
||||
public event EventHandler<EventArgs>? ReadMemory;
|
||||
protected virtual void OnReadingMemory() => ReadingMemory?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnReadMemory() => ReadMemory?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Memory write events
|
||||
|
||||
public event EventHandler<EventArgs>? WritingMemory;
|
||||
public event EventHandler<EventArgs>? WrittenMemory;
|
||||
protected virtual void OnWritingMemory() => WritingMemory?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnWrittenMemory() => WrittenMemory?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region IO events
|
||||
|
||||
#region IO read events
|
||||
|
||||
public event EventHandler<EventArgs>? ReadingIO;
|
||||
public event EventHandler<EventArgs>? ReadIO;
|
||||
protected virtual void OnReadingIO() => ReadingIO?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnReadIO() => ReadIO?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#endregion
|
||||
|
||||
#region IO write events
|
||||
|
||||
public event EventHandler<EventArgs>? WritingIO;
|
||||
public event EventHandler<EventArgs>? WrittenIO;
|
||||
protected virtual void OnWritingIO() => WritingIO?.Invoke(this, EventArgs.Empty);
|
||||
protected virtual void OnWrittenIO() => WrittenIO?.Invoke(this, EventArgs.Empty);
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
private PinLevel _resetLine;
|
||||
private PinLevel _intLine;
|
||||
@@ -108,12 +60,12 @@ namespace EightBit
|
||||
public virtual int Step()
|
||||
{
|
||||
this.ResetCycles();
|
||||
this.OnExecutingInstruction();
|
||||
ExecutingInstruction?.Invoke(this, EventArgs.Empty);
|
||||
if (this.Powered)
|
||||
{
|
||||
this.PoweredStep();
|
||||
}
|
||||
this.OnExecutedInstruction();
|
||||
ExecutedInstruction?.Invoke(this, EventArgs.Empty);
|
||||
return this.Cycles;
|
||||
}
|
||||
|
||||
@@ -149,9 +101,9 @@ namespace EightBit
|
||||
{
|
||||
if (this.RESET.Lowered())
|
||||
{
|
||||
this.OnRaisingRESET();
|
||||
RaisingRESET?.Invoke(this, EventArgs.Empty);
|
||||
this.RESET.Raise();
|
||||
this.OnRaisedRESET();
|
||||
RaisedRESET?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,9 +111,9 @@ namespace EightBit
|
||||
{
|
||||
if (this.RESET.Raised())
|
||||
{
|
||||
this.OnLoweringRESET();
|
||||
LoweringRESET?.Invoke(this, EventArgs.Empty);
|
||||
this.RESET.Lower();
|
||||
this.OnLoweredRESET();
|
||||
LoweredRESET?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,9 +122,9 @@ namespace EightBit
|
||||
{
|
||||
if (this.INT.Lowered())
|
||||
{
|
||||
this.OnRaisingINT();
|
||||
RaisingINT?.Invoke(this, EventArgs.Empty);
|
||||
this.INT.Raise();
|
||||
this.OnRaisedINT();
|
||||
RaisedINT?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,9 +132,9 @@ namespace EightBit
|
||||
{
|
||||
if (this.INT.Raised())
|
||||
{
|
||||
this.OnLoweringINT();
|
||||
LoweringINT?.Invoke(this, EventArgs.Empty);
|
||||
this.INT.Lower();
|
||||
this.OnLoweredINT();
|
||||
LoweredINT?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,13 +178,11 @@ namespace EightBit
|
||||
|
||||
protected void MemoryWrite(Register16 address, byte data)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(address);
|
||||
this.MemoryWrite(address.Low, address.High, data);
|
||||
}
|
||||
|
||||
protected void MemoryWrite(Register16 address)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(address);
|
||||
this.MemoryWrite(address.Low, address.High);
|
||||
}
|
||||
|
||||
@@ -260,7 +210,6 @@ namespace EightBit
|
||||
|
||||
protected byte MemoryRead(Register16 address)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(address);
|
||||
return this.MemoryRead(address.Low, address.High);
|
||||
}
|
||||
|
||||
@@ -286,7 +235,6 @@ namespace EightBit
|
||||
|
||||
protected Register16 GetWordPaged(Register16 address)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(address);
|
||||
return this.GetWordPaged(address.High, address.Low);
|
||||
}
|
||||
|
||||
@@ -300,7 +248,6 @@ namespace EightBit
|
||||
|
||||
protected void SetWordPaged(Register16 address, Register16 value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(address);
|
||||
this.SetWordPaged(address.High, address.Low, value);
|
||||
}
|
||||
|
||||
@@ -354,7 +301,6 @@ namespace EightBit
|
||||
|
||||
protected void Jump(Register16 destination)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(destination);
|
||||
this.PC.Assign(destination);
|
||||
}
|
||||
|
||||
|
@@ -46,7 +46,6 @@ namespace EightBit
|
||||
|
||||
public Register16(Register16 rhs)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(rhs);
|
||||
this.Low = rhs.Low;
|
||||
this.High = rhs.High;
|
||||
}
|
||||
@@ -68,7 +67,6 @@ namespace EightBit
|
||||
|
||||
public static bool operator ==(Register16 left, Register16 right)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(left);
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
@@ -88,7 +86,6 @@ namespace EightBit
|
||||
|
||||
public void Assign(Register16 from)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(from);
|
||||
this.Assign(from._low, from._high);
|
||||
}
|
||||
}
|
||||
|
@@ -8,8 +8,14 @@ namespace M6502
|
||||
{
|
||||
using EightBit;
|
||||
|
||||
public abstract class Core(Bus bus) : LittleEndianProcessor(bus)
|
||||
public abstract class Core : LittleEndianProcessor
|
||||
{
|
||||
protected Core(Bus bus)
|
||||
: base(bus)
|
||||
{
|
||||
this.RaisedPOWER += this.Core_RaisedPOWER;
|
||||
}
|
||||
|
||||
#region Pin controls
|
||||
|
||||
#region NMI pin
|
||||
@@ -104,16 +110,22 @@ namespace M6502
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||
protected virtual void RaiseSYNC()
|
||||
{
|
||||
this.OnRaisingSYNC();
|
||||
if (this.SYNC.Lowered())
|
||||
{
|
||||
RaisingSYNC?.Invoke(this, EventArgs.Empty);
|
||||
this.SYNC.Raise();
|
||||
this.OnRaisedSYNC();
|
||||
RaisedSYNC?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void LowerSYNC()
|
||||
{
|
||||
this.OnLoweringSYNC();
|
||||
if (this.SYNC.Raised())
|
||||
{
|
||||
LoweringSYNC?.Invoke(this, EventArgs.Empty);
|
||||
this.SYNC.Lower();
|
||||
this.OnLoweredSYNC();
|
||||
LoweredSYNC?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -190,7 +202,7 @@ namespace M6502
|
||||
|
||||
#endregion
|
||||
|
||||
protected override void OnRaisedPOWER()
|
||||
private void Core_RaisedPOWER(object? sender, EventArgs e)
|
||||
{
|
||||
this.X = (byte)Bits.Bit7;
|
||||
this.Y = 0;
|
||||
@@ -199,7 +211,6 @@ namespace M6502
|
||||
this.S = (byte)Mask.Eight;
|
||||
this.LowerSYNC();
|
||||
this.LowerRW();
|
||||
base.OnRaisedPOWER();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -551,9 +562,7 @@ namespace M6502
|
||||
|
||||
private void FetchInstruction()
|
||||
{
|
||||
// Instruction fetch beginning
|
||||
this.LowerSYNC();
|
||||
|
||||
System.Diagnostics.Debug.Assert(this.Cycles == 1, "An extra cycle has occurred");
|
||||
|
||||
// Can't use fetchByte, since that would add an extra tick.
|
||||
@@ -561,8 +570,6 @@ namespace M6502
|
||||
this.OpCode = this.ReadFromBus();
|
||||
|
||||
System.Diagnostics.Debug.Assert(this.Cycles == 1, "BUS read has introduced stray cycles");
|
||||
|
||||
// Instruction fetch has now completed
|
||||
this.RaiseSYNC();
|
||||
}
|
||||
|
||||
|
@@ -282,13 +282,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
private void Runner_ReadByte(object? sender, EventArgs e) => this.AddActualReadCycle(this.Runner.Address, this.Runner.Data);
|
||||
private void Runner_ReadByte(object? sender, EventArgs e) => this.AddActualCycle(this.Runner.Address, this.Runner.Data, "read");
|
||||
|
||||
private void Runner_WrittenByte(object? sender, EventArgs e) => this.AddActualWriteCycle(this.Runner.Address, this.Runner.Data);
|
||||
|
||||
private void AddActualReadCycle(EightBit.Register16 address, byte value) => this.AddActualCycle(address, value, "read");
|
||||
|
||||
private void AddActualWriteCycle(EightBit.Register16 address, byte value) => this.AddActualCycle(address, value, "write");
|
||||
private void Runner_WrittenByte(object? sender, EventArgs e) => this.AddActualCycle(this.Runner.Address, this.Runner.Data, "write");
|
||||
|
||||
private void AddActualCycle(EightBit.Register16 address, byte value, string action) => this.AddActualCycle(address.Word, value, action);
|
||||
|
||||
|
@@ -98,21 +98,30 @@ namespace Z80.FuseTest
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
this.ReadByte += this.Event_ReadByte;
|
||||
this.WrittenByte += this.Event_WrittenByte;
|
||||
this.ports.ReadPort += this.Ports_ReadPort;
|
||||
this.ports.WrittenPort += this.Ports_WrittenPort;
|
||||
this.cpu.ExecutedInstruction += this.Cpu_ExecutedInstruction;
|
||||
}
|
||||
|
||||
protected override void OnReadByte()
|
||||
{
|
||||
this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "MR", this.Address.Word, this.Data));
|
||||
base.OnReadByte();
|
||||
}
|
||||
private void Ports_ReadPort(object? sender, EventArgs e) => this.AddActualEvent("PR");
|
||||
private void Ports_WrittenPort(object? sender, EventArgs e) => this.AddActualEvent("PW");
|
||||
private void Event_ReadByte(object? sender, EventArgs e) => this.AddActualEvent("MR");
|
||||
private void Event_WrittenByte(object? sender, EventArgs e) => this.AddActualEvent("MW");
|
||||
|
||||
protected override void OnWrittenByte()
|
||||
private void AddActualEvent(string specifier)
|
||||
{
|
||||
this.actualEvents.Add(new TestEvent(this.totalCycles + this.cpu.Cycles, "MW", this.Address.Word, this.Data));
|
||||
base.OnWrittenByte();
|
||||
var address = this.Address.Word;
|
||||
var cycles = this.totalCycles + this.cpu.Cycles;
|
||||
if (specifier.EndsWith('C'))
|
||||
{
|
||||
this.actualEvents.Add(new TestEvent(cycles, specifier, address));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.actualEvents.Add(new TestEvent(cycles, specifier, address, this.Data));
|
||||
}
|
||||
}
|
||||
|
||||
private static void DumpDifference(string description, byte expected, byte actual)
|
||||
@@ -121,11 +130,12 @@ namespace Z80.FuseTest
|
||||
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_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, EventArgs e) => this.totalCycles += this.cpu.Cycles;
|
||||
private void Cpu_ExecutedInstruction(object? sender, EventArgs e)
|
||||
{
|
||||
var output = $"**** Cycle count: {this.cpu.Cycles}";
|
||||
Console.Out.WriteLine(output);
|
||||
this.totalCycles += this.cpu.Cycles;
|
||||
}
|
||||
|
||||
private static void DumpDifference(string highDescription, string lowDescription, EightBit.Register16 expected, EightBit.Register16 actual)
|
||||
{
|
||||
|
279
Z80/Z80.cs
279
Z80/Z80.cs
@@ -5,12 +5,17 @@
|
||||
namespace Z80
|
||||
{
|
||||
using EightBit;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
public class Z80(Bus bus, InputOutput ports) : IntelProcessor(bus)
|
||||
public class Z80 : IntelProcessor
|
||||
{
|
||||
private readonly InputOutput _ports = ports;
|
||||
public Z80(Bus bus, InputOutput ports)
|
||||
: base(bus)
|
||||
{
|
||||
this._ports = ports;
|
||||
this.RaisedPOWER += this.Z80_RaisedPOWER;
|
||||
}
|
||||
|
||||
private readonly InputOutput _ports;
|
||||
|
||||
private readonly Register16[] _accumulatorFlags = [new Register16(), new Register16()];
|
||||
private readonly Register16[][] _registers =
|
||||
@@ -161,7 +166,7 @@ namespace Z80
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRaisedPOWER()
|
||||
private void Z80_RaisedPOWER(object? sender, EventArgs e)
|
||||
{
|
||||
this.RaiseM1();
|
||||
this.RaiseRFSH();
|
||||
@@ -183,8 +188,6 @@ namespace Z80
|
||||
base.ResetWorkingRegisters();
|
||||
|
||||
this.ResetPrefixes();
|
||||
|
||||
base.OnRaisedPOWER();
|
||||
}
|
||||
|
||||
private void ResetPrefixes()
|
||||
@@ -192,34 +195,7 @@ namespace Z80
|
||||
this._prefixCB = this._prefixDD = this._prefixED = this._prefixFD = false;
|
||||
}
|
||||
|
||||
private static void WithPinChange(Func<bool> check, Action enter, Action leave, Action task)
|
||||
{
|
||||
if (check())
|
||||
{
|
||||
enter();
|
||||
try
|
||||
{
|
||||
task();
|
||||
}
|
||||
finally
|
||||
{
|
||||
leave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static byte WithPin(Action enter, Action leave, Func<byte> task)
|
||||
{
|
||||
enter();
|
||||
try
|
||||
{
|
||||
return task();
|
||||
}
|
||||
finally
|
||||
{
|
||||
leave();
|
||||
}
|
||||
}
|
||||
#region Z80 specific pins
|
||||
|
||||
#region NMI pin
|
||||
|
||||
@@ -235,22 +211,14 @@ namespace Z80
|
||||
|
||||
public ref PinLevel NMI => ref this._nmiLine;
|
||||
|
||||
protected virtual void OnRaisingNMI() => RaisingNMI?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisedNMI() => RaisedNMI?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweringNMI() => LoweringNMI?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredNMI() => LoweredNMI?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||
public virtual void RaiseNMI()
|
||||
{
|
||||
if (this.NMI.Lowered())
|
||||
{
|
||||
this.OnRaisingNMI();
|
||||
RaisingNMI?.Invoke(this, EventArgs.Empty);
|
||||
this.NMI.Raise();
|
||||
this.OnRaisedNMI();
|
||||
RaisedNMI?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,9 +226,9 @@ namespace Z80
|
||||
{
|
||||
if (this.NMI.Raised())
|
||||
{
|
||||
this.OnLoweringNMI();
|
||||
LoweringNMI?.Invoke(this, EventArgs.Empty);
|
||||
this.NMI.Lower();
|
||||
this.OnLoweredNMI();
|
||||
LoweredNMI?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,14 +248,6 @@ namespace Z80
|
||||
|
||||
public ref PinLevel M1 => ref this._m1Line;
|
||||
|
||||
protected virtual void OnRaisingM1() => RaisingM1?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisedM1()
|
||||
{
|
||||
++this.REFRESH;
|
||||
RaisedM1?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
protected virtual void OnLoweringM1() => LoweringM1?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredM1() => LoweredM1?.Invoke(this, EventArgs.Empty);
|
||||
@@ -295,17 +255,23 @@ namespace Z80
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||
public virtual void RaiseM1()
|
||||
{
|
||||
WithPinChange(() => this.M1.Lowered(), this.OnRaisingM1, this.OnRaisedM1, () => this.M1.Raise());
|
||||
if (this.M1.Lowered())
|
||||
{
|
||||
RaisingM1?.Invoke(this, EventArgs.Empty);
|
||||
this.M1.Raise();
|
||||
++this.REFRESH;
|
||||
RaisedM1?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void LowerM1()
|
||||
{
|
||||
WithPinChange(() => this.M1.Raised(), this.OnLoweringM1, this.OnLoweredM1, () => this.M1.Lower());
|
||||
}
|
||||
|
||||
private byte WithM1(Func<byte> function)
|
||||
if (this.M1.Raised())
|
||||
{
|
||||
return WithPin(this.LowerM1, this.RaiseM1, function);
|
||||
LoweringM1?.Invoke(this, EventArgs.Empty);
|
||||
this.M1.Lower();
|
||||
LoweredM1?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -329,28 +295,25 @@ namespace Z80
|
||||
|
||||
public ref PinLevel RFSH => ref this._rfshLine;
|
||||
|
||||
protected virtual void OnRaisingRFSH() => RaisingRFSH?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisedRFSH() => RaisedRFSH?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweringRFSH() => LoweringRFSH?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredRFSH() => LoweredRFSH?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||
public virtual void RaiseRFSH()
|
||||
{
|
||||
WithPinChange(() => this.RFSH.Lowered(), this.OnRaisingRFSH, this.OnRaisedRFSH, () => this.RFSH.Raise());
|
||||
if (this.RFSH.Lowered())
|
||||
{
|
||||
RaisingRFSH?.Invoke(this, EventArgs.Empty);
|
||||
this.RFSH.Raise();
|
||||
RaisedRFSH?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void LowerRFSH()
|
||||
{
|
||||
WithPinChange(() => this.RFSH.Raised(), this.OnLoweringRFSH, this.OnLoweredRFSH, () => this.RFSH.Lower());
|
||||
}
|
||||
|
||||
private byte WithRFSH(Func<byte> function)
|
||||
if (this.RFSH.Raised())
|
||||
{
|
||||
return WithPin(this.LowerRFSH, this.RaiseRFSH, function);
|
||||
LoweringRFSH?.Invoke(this, EventArgs.Empty);
|
||||
this.RFSH.Lower();
|
||||
LoweredRFSH?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -369,28 +332,25 @@ namespace Z80
|
||||
|
||||
public ref PinLevel MREQ => ref this._mreqLine;
|
||||
|
||||
protected virtual void OnLoweringMREQ() => LoweringMREQ?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredMREQ() => LoweredMREQ?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisingMREQ() => RaisingMREQ?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisedMREQ() => RaisedMREQ?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||
public virtual void RaiseMREQ()
|
||||
{
|
||||
WithPinChange(() => this.MREQ.Lowered(), this.OnRaisingMREQ, this.OnRaisedMREQ, () => this.MREQ.Raise());
|
||||
if (this.MREQ.Lowered())
|
||||
{
|
||||
RaisingMREQ?.Invoke(this, EventArgs.Empty);
|
||||
this.MREQ.Raise();
|
||||
RaisedMREQ?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void LowerMREQ()
|
||||
{
|
||||
WithPinChange(() => this.MREQ.Raised(), this.OnLoweringMREQ, this.OnLoweredMREQ, () => this.MREQ.Lower());
|
||||
}
|
||||
|
||||
private byte WithMREQ(Func<byte> function)
|
||||
if (this.MREQ.Raised())
|
||||
{
|
||||
return WithPin(this.LowerMREQ, this.RaiseMREQ, function);
|
||||
LoweringMREQ?.Invoke(this, EventArgs.Empty);
|
||||
this.MREQ.Lower();
|
||||
LoweredMREQ?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -409,29 +369,25 @@ namespace Z80
|
||||
|
||||
public ref PinLevel IORQ => ref this._iorqLine;
|
||||
|
||||
protected virtual void OnLoweringIORQ() => LoweringIORQ?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredIORQ() => LoweredIORQ?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisingIORQ() => RaisingIORQ?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisedIORQ() => RaisedIORQ?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||
public virtual void RaiseIORQ()
|
||||
{
|
||||
WithPinChange(() => this.IORQ.Lowered(), this.OnRaisingIORQ, this.OnRaisedIORQ, () => this.IORQ.Raise());
|
||||
if (this.IORQ.Lowered())
|
||||
{
|
||||
RaisingIORQ?.Invoke(this, EventArgs.Empty);
|
||||
this.IORQ.Raise();
|
||||
RaisedIORQ?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void LowerIORQ()
|
||||
{
|
||||
WithPinChange(() => this.IORQ.Raised(), this.OnLoweringIORQ, this.OnLoweredIORQ, () => this.IORQ.Lower());
|
||||
}
|
||||
|
||||
private byte WithIORQ(Func<byte> function)
|
||||
if (this.IORQ.Raised())
|
||||
{
|
||||
return WithPin(this.LowerIORQ, this.RaiseIORQ, function);
|
||||
LoweringIORQ?.Invoke(this, EventArgs.Empty);
|
||||
this.IORQ.Lower();
|
||||
LoweredIORQ?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -450,28 +406,25 @@ namespace Z80
|
||||
|
||||
public ref PinLevel RD => ref this._rdLine;
|
||||
|
||||
protected virtual void OnLoweringRD() => LoweringRD?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredRD() => LoweredRD?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisingRD() => RaisingRD?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisedRD() => RaisedRD?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||
public virtual void RaiseRD()
|
||||
{
|
||||
WithPinChange(() => this.RD.Lowered(), this.OnRaisingRD, this.OnRaisedRD, () => this.RD.Raise());
|
||||
if (this.RD.Lowered())
|
||||
{
|
||||
RaisingRD?.Invoke(this, EventArgs.Empty);
|
||||
this.RD.Raise();
|
||||
RaisedRD?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void LowerRD()
|
||||
{
|
||||
WithPinChange(() => this.RD.Raised(), this.OnLoweringRD, this.OnLoweredRD, () => this.RD.Lower());
|
||||
}
|
||||
|
||||
private byte WithRD(Func<byte> function)
|
||||
if (this.RD.Raised())
|
||||
{
|
||||
return WithPin(this.LowerRD, this.RaiseRD, function);
|
||||
LoweringRD?.Invoke(this, EventArgs.Empty);
|
||||
this.RD.Lower();
|
||||
LoweredRD?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -490,63 +443,50 @@ namespace Z80
|
||||
|
||||
public ref PinLevel WR => ref this._wrLine;
|
||||
|
||||
protected virtual void OnLoweringWR() => LoweringWR?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnLoweredWR() => LoweredWR?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisingWR() => RaisingWR?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
protected virtual void OnRaisedWR() => RaisedWR?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
|
||||
public virtual void RaiseWR()
|
||||
{
|
||||
WithPinChange(() => this.WR.Lowered(), this.OnRaisingWR, this.OnRaisedWR, () => this.WR.Raise());
|
||||
if (this.WR.Lowered())
|
||||
{
|
||||
RaisingWR?.Invoke(this, EventArgs.Empty);
|
||||
this.WR.Raise();
|
||||
RaisedWR?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void LowerWR()
|
||||
{
|
||||
WithPinChange(() => this.WR.Raised(), this.OnLoweringWR, this.OnLoweredWR, () => this.WR.Lower());
|
||||
}
|
||||
|
||||
private byte WithWR(Func<byte> function)
|
||||
if (this.WR.Raised())
|
||||
{
|
||||
this.LowerWR();
|
||||
try
|
||||
{
|
||||
return function();
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.RaiseWR();
|
||||
LoweringWR?.Invoke(this, EventArgs.Empty);
|
||||
this.WR.Lower();
|
||||
LoweredWR?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
protected override void MemoryWrite()
|
||||
{
|
||||
_ = this.WithMREQ(() =>
|
||||
{
|
||||
return this.WithWR(() =>
|
||||
{
|
||||
this.LowerMREQ();
|
||||
this.LowerWR();
|
||||
this.Tick(3);
|
||||
base.MemoryWrite();
|
||||
return 0;
|
||||
});
|
||||
});
|
||||
this.RaiseWR();
|
||||
this.RaiseMREQ();
|
||||
}
|
||||
|
||||
protected override byte MemoryRead()
|
||||
{
|
||||
return this.WithMREQ(() =>
|
||||
{
|
||||
return this.WithRD(() =>
|
||||
{
|
||||
this.LowerMREQ();
|
||||
this.LowerRD();
|
||||
this.Tick(3);
|
||||
return base.MemoryRead();
|
||||
});
|
||||
});
|
||||
var returned = base.MemoryRead();
|
||||
this.RaiseRD();
|
||||
this.RaiseMREQ();
|
||||
return returned;
|
||||
}
|
||||
|
||||
protected override void HandleRESET()
|
||||
@@ -562,13 +502,11 @@ namespace Z80
|
||||
{
|
||||
base.HandleINT();
|
||||
|
||||
var data = this.WithM1(() =>
|
||||
{
|
||||
return this.WithIORQ(() =>
|
||||
{
|
||||
return this.Bus.Data;
|
||||
});
|
||||
});
|
||||
this.LowerM1();
|
||||
this.LowerIORQ();
|
||||
var data = this.Bus.Data;
|
||||
this.RaiseIORQ();
|
||||
this.RaiseM1();
|
||||
|
||||
this.DisableInterrupts();
|
||||
this.Tick(5);
|
||||
@@ -1723,18 +1661,17 @@ namespace Z80
|
||||
private byte ReadInitialOpCode()
|
||||
{
|
||||
this.Tick();
|
||||
var returned = this.WithM1(() =>
|
||||
{
|
||||
return this.MemoryRead(this.PC);
|
||||
});
|
||||
|
||||
this.LowerM1();
|
||||
var returned = this.MemoryRead(this.PC);
|
||||
this.RaiseM1();
|
||||
|
||||
this.Bus.Address.Assign(this.REFRESH, this.IV);
|
||||
_ = this.WithRFSH(() =>
|
||||
{
|
||||
return this.WithMREQ(() =>
|
||||
{
|
||||
return 0;
|
||||
});
|
||||
});
|
||||
this.LowerRFSH();
|
||||
this.LowerMREQ();
|
||||
this.RaiseMREQ();
|
||||
this.RaiseRFSH();
|
||||
|
||||
return returned;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user