This commit is contained in:
Adrian Conlon 2019-11-18 00:17:11 +00:00
commit 15a8f312ff
14 changed files with 860 additions and 360 deletions

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.329
# Visual Studio Version 16
VisualStudioVersion = 16.0.29418.71
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EightBit", "EightBit\EightBit.csproj", "{6EBF8857-62A3-4EF4-AF21-C1844031D7E4}"
EndProject
@ -35,6 +35,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Fuse", "Fuse\Fuse.csproj",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LR35902.BlarggTest", "LR35902\LR35902.BlarggTest\LR35902.BlarggTest.csproj", "{DDFC8E91-B9EE-41DC-8FBD-09198AB01C6C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Z80.FuseTest", "Z80\Z80.FuseTest\Z80.FuseTest.csproj", "{0233FF6C-DB1A-4353-8E42-D22717770226}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -237,6 +239,18 @@ Global
{DDFC8E91-B9EE-41DC-8FBD-09198AB01C6C}.Release|x64.Build.0 = Release|Any CPU
{DDFC8E91-B9EE-41DC-8FBD-09198AB01C6C}.Release|x86.ActiveCfg = Release|Any CPU
{DDFC8E91-B9EE-41DC-8FBD-09198AB01C6C}.Release|x86.Build.0 = Release|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Debug|x64.ActiveCfg = Debug|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Debug|x64.Build.0 = Debug|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Debug|x86.ActiveCfg = Debug|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Debug|x86.Build.0 = Debug|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Release|Any CPU.Build.0 = Release|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Release|x64.ActiveCfg = Release|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Release|x64.Build.0 = Release|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Release|x86.ActiveCfg = Release|Any CPU
{0233FF6C-DB1A-4353-8E42-D22717770226}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -28,16 +28,22 @@ namespace EightBit
public virtual void RaisePOWER()
{
this.OnRaisingPOWER();
this.POWER.Raise();
this.OnRaisedPOWER();
if (this.POWER.Lowered())
{
this.OnRaisingPOWER();
this.POWER.Raise();
this.OnRaisedPOWER();
}
}
public virtual void LowerPOWER()
{
this.OnLoweringPOWER();
this.POWER.Lower();
this.OnLoweredPOWER();
if (this.POWER.Raised())
{
this.OnLoweringPOWER();
this.POWER.Lower();
this.OnLoweredPOWER();
}
}
protected virtual void OnRaisingPOWER() => this.RaisingPOWER?.Invoke(this, EventArgs.Empty);

View File

@ -25,7 +25,7 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
@ -35,6 +35,7 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisIgnoreGeneratedCode>true</CodeAnalysisIgnoreGeneratedCode>
<RunCodeAnalysis>false</RunCodeAnalysis>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>

View File

@ -62,29 +62,26 @@ namespace EightBit
public ref PinLevel HALT => ref this.haltLine;
protected bool Halted => this.HALT.Lowered();
public IntelOpCodeDecoded GetDecodedOpCode(byte opCode) => this.decodedOpCodes[opCode];
public override void RaisePOWER()
{
base.RaisePOWER();
this.RaiseHALT();
this.SP.Word = this.AF.Word = this.BC.Word = this.DE.Word = this.HL.Word = (ushort)Mask.Mask16;
}
public virtual void RaiseHALT()
{
this.OnRaisingHALT();
this.HALT.Raise();
this.OnRaisedHALT();
if (this.HALT.Lowered())
{
this.OnRaisingHALT();
this.HALT.Raise();
this.OnRaisedHALT();
}
}
public virtual void LowerHALT()
{
this.OnLoweringHALT();
this.HALT.Lower();
this.OnLoweredHALT();
if (this.HALT.Raised())
{
this.OnLoweringHALT();
this.HALT.Lower();
this.OnLoweredHALT();
}
}
protected static int BuildHalfCarryIndex(byte before, byte value, int calculation) => ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
@ -101,13 +98,28 @@ namespace EightBit
return HalfCarryTableSub[index & (int)Mask.Mask3];
}
protected override void OnRaisedPOWER()
{
this.PC.Word = this.SP.Word = this.AF.Word = this.BC.Word = this.DE.Word = this.HL.Word = (ushort)Mask.Mask16;
this.RaiseHALT();
base.OnRaisedPOWER();
}
protected virtual void OnRaisingHALT() => this.RaisingHALT?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedHALT() => this.RaisedHALT?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedHALT()
{
++this.PC.Word; // Release the PC from HALT instruction
this.RaisedHALT?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnLoweringHALT() => this.LoweringHALT?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredHALT() => this.LoweredHALT?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredHALT()
{
--this.PC.Word; // Keep the PC on the HALT instruction (i.e. executing NOP)
this.LoweredHALT?.Invoke(this, EventArgs.Empty);
}
protected override void HandleRESET()
{
@ -196,17 +208,5 @@ namespace EightBit
base.Return();
this.MEMPTR.Word = this.PC.Word;
}
protected void Halt()
{
--this.PC.Word;
this.LowerHALT();
}
protected void Proceed()
{
++this.PC.Word;
this.RaiseHALT();
}
}
}

View File

@ -78,30 +78,42 @@ namespace EightBit
public virtual void RaiseRESET()
{
this.OnRaisingRESET();
this.RESET.Raise();
this.OnRaisedRESET();
if (this.RESET.Lowered())
{
this.OnRaisingRESET();
this.RESET.Raise();
this.OnRaisedRESET();
}
}
public virtual void LowerRESET()
{
this.OnLoweringRESET();
this.RESET.Lower();
this.OnLoweredRESET();
if (this.RESET.Raised())
{
this.OnLoweringRESET();
this.RESET.Lower();
this.OnLoweredRESET();
}
}
public virtual void RaiseINT()
{
this.OnRaisingINT();
this.INT.Raise();
this.OnRaisedINT();
if (this.INT.Lowered())
{
this.OnRaisingINT();
this.INT.Raise();
this.OnRaisedINT();
}
}
public virtual void LowerINT()
{
this.OnLoweringINT();
this.INT.Lower();
this.OnLoweredINT();
if (this.INT.Raised())
{
this.OnLoweringINT();
this.INT.Lower();
this.OnLoweredINT();
}
}
protected virtual void OnRaisingRESET() => this.RaisingRESET?.Invoke(this, EventArgs.Empty);

View File

@ -66,7 +66,7 @@ namespace EightBit
{
this.HandleINT();
}
else if (this.Halted)
else if (this.HALT.Lowered())
{
this.Execute(0); // NOP
}
@ -401,7 +401,7 @@ namespace EightBit
case 1: // 8-bit loading
if (z == 6 && y == 6)
{
this.Halt(); // Exception (replaces LD (HL), (HL))
this.LowerHALT(); // Exception (replaces LD (HL), (HL))
}
else
{

View File

@ -86,10 +86,7 @@ namespace EightBit.GameBoy
}
else
{
if (this.Halted)
{
this.Proceed();
}
this.RaiseHALT();
}
}
@ -101,7 +98,7 @@ namespace EightBit.GameBoy
{
this.HandleINT();
}
else if (this.Halted)
else if (this.HALT.Lowered())
{
this.Execute(0); // NOP
}
@ -557,7 +554,7 @@ namespace EightBit.GameBoy
case 1: // 8-bit loading
if (z == 6 && y == 6)
{
this.Halt(); // Exception (replaces LD (HL), (HL))
this.LowerHALT(); // Exception (replaces LD (HL), (HL))
}
else
{

View File

@ -23,6 +23,7 @@ namespace EightBit
private PinLevel soLine = PinLevel.Low;
private PinLevel syncLine = PinLevel.Low;
private PinLevel rdyLine = PinLevel.Low;
private PinLevel rwLine = PinLevel.Low;
public M6502(Bus bus)
: base(bus)
@ -65,6 +66,14 @@ namespace EightBit
public event EventHandler<EventArgs> LoweredRDY;
public event EventHandler<EventArgs> RaisingRW;
public event EventHandler<EventArgs> RaisedRW;
public event EventHandler<EventArgs> LoweringRW;
public event EventHandler<EventArgs> LoweredRW;
public ref PinLevel NMI => ref this.nmiLine;
public ref PinLevel SO => ref this.soLine;
@ -73,6 +82,8 @@ namespace EightBit
public ref PinLevel RDY => ref this.rdyLine;
public ref PinLevel RW => ref this.rwLine;
public byte X { get; set; } = 0;
public byte Y { get; set; } = 0;
@ -95,57 +106,84 @@ namespace EightBit
private int Carry => this.P & (byte)StatusBits.CF;
public override void RaisePOWER()
{
base.RaisePOWER();
this.X = (byte)Bits.Bit7;
this.Y = 0;
this.A = 0;
this.P = (byte)StatusBits.RF;
this.S = (byte)Mask.Mask8;
this.LowerSYNC();
}
public virtual void RaiseNMI()
{
this.OnRaisingNMI();
this.NMI.Raise();
this.OnRaisedNMI();
if (this.NMI.Lowered())
{
this.OnRaisingNMI();
this.NMI.Raise();
this.OnRaisedNMI();
}
}
public virtual void LowerNMI()
{
this.OnLoweringNMI();
this.NMI.Lower();
this.OnLoweredNMI();
if (this.NMI.Raised())
{
this.OnLoweringNMI();
this.NMI.Lower();
this.OnLoweredNMI();
}
}
public virtual void RaiseSO()
{
this.OnRaisingSO();
this.SO.Raise();
this.OnRaisedSO();
if (this.SO.Lowered())
{
this.OnRaisingSO();
this.SO.Raise();
this.OnRaisedSO();
}
}
public virtual void LowerSO()
{
this.OnLoweringSO();
this.SO.Lower();
this.OnLoweredSO();
if (this.SO.Raised())
{
this.OnLoweringSO();
this.SO.Lower();
this.OnLoweredSO();
}
}
public virtual void RaiseRDY()
{
this.OnRaisingRDY();
this.RDY.Raise();
this.OnRaisedRDY();
if (this.RDY.Lowered())
{
this.OnRaisingRDY();
this.RDY.Raise();
this.OnRaisedRDY();
}
}
public virtual void LowerRDY()
{
this.OnLoweringRDY();
this.RDY.Lower();
this.OnLoweredRDY();
if (this.RDY.Raised())
{
this.OnLoweringRDY();
this.RDY.Lower();
this.OnLoweredRDY();
}
}
public virtual void RaiseRW()
{
if (this.RW.Lowered())
{
this.OnRaisingRW();
this.RW.Raise();
this.OnRaisedRW();
}
}
public virtual void LowerRW()
{
if (this.RW.Raised())
{
this.OnLoweringRW();
this.RW.Lower();
this.OnLoweredRW();
}
}
public override int Execute()
@ -444,6 +482,7 @@ namespace EightBit
if (this.RDY.Raised())
{
this.LowerSYNC(); // Instruction fetch beginning
this.RaiseRW();
this.OpCode = this.Bus.Read(this.PC.Word++); // can't use fetchByte
if (this.RESET.Lowered())
{
@ -502,6 +541,26 @@ namespace EightBit
protected virtual void OnLoweredRDY() => this.LoweredRDY?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisingRW() => this.RaisingRW?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedRW() => this.RaisedRW?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweringRW() => this.LoweringRW?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredRW() => this.LoweredRW?.Invoke(this, EventArgs.Empty);
protected override void OnRaisedPOWER()
{
this.X = (byte)Bits.Bit7;
this.Y = 0;
this.A = 0;
this.P = (byte)StatusBits.RF;
this.S = (byte)Mask.Mask8;
this.LowerSYNC();
this.LowerRW();
base.OnRaisedPOWER();
}
protected override byte Pop() => this.BusRead(++this.S, 1);
protected override void Push(byte value) => this.BusWrite(this.S--, 1, value);
@ -537,12 +596,14 @@ namespace EightBit
protected override sealed void BusWrite()
{
this.Tick();
this.LowerRW();
base.BusWrite();
}
protected override sealed byte BusRead()
{
this.Tick();
this.RaiseRW();
return base.BusRead();
}

View File

@ -36,6 +36,7 @@
private PinLevel haltLine = PinLevel.Low;
private PinLevel baLine = PinLevel.Low;
private PinLevel bsLine = PinLevel.Low;
private PinLevel rwLine = PinLevel.Low;
private bool prefix10 = false;
private bool prefix11 = false;
@ -89,6 +90,14 @@
public event EventHandler<EventArgs> LoweredBS;
public event EventHandler<EventArgs> RaisingRW;
public event EventHandler<EventArgs> RaisedRW;
public event EventHandler<EventArgs> LoweringRW;
public event EventHandler<EventArgs> LoweredRW;
public Register16 D { get; } = new Register16();
public ref byte A => ref this.D.High;
@ -147,6 +156,8 @@
public ref PinLevel BS => ref this.bsLine;
public ref PinLevel RW => ref this.rwLine;
public void Halt()
{
--this.PC.Word;
@ -221,81 +232,132 @@
return this.Cycles;
}
public override void RaisePOWER()
{
base.RaisePOWER();
this.LowerBA();
this.LowerBS();
}
public void RaiseNMI()
{
this.OnRaisingNMI();
this.NMI.Raise();
this.OnRaisedNMI();
if (this.NMI.Lowered())
{
this.OnRaisingNMI();
this.NMI.Raise();
this.OnRaisedNMI();
}
}
public void LowerNMI()
{
this.OnLoweringNMI();
this.NMI.Lower();
this.OnLoweredNMI();
if (this.NMI.Raised())
{
this.OnLoweringNMI();
this.NMI.Lower();
this.OnLoweredNMI();
}
}
public void RaiseFIRQ()
{
this.OnRaisingFIRQ();
this.FIRQ.Raise();
this.OnRaisedFIRQ();
if (this.FIRQ.Lowered())
{
this.OnRaisingFIRQ();
this.FIRQ.Raise();
this.OnRaisedFIRQ();
}
}
public void LowerFIRQ()
{
this.OnLoweringFIRQ();
this.FIRQ.Lower();
this.OnLoweredFIRQ();
if (this.FIRQ.Raised())
{
this.OnLoweringFIRQ();
this.FIRQ.Lower();
this.OnLoweredFIRQ();
}
}
public void RaiseHALT()
{
this.OnRaisingHALT();
this.HALT.Raise();
this.OnRaisedHALT();
if (this.HALT.Lowered())
{
this.OnRaisingHALT();
this.HALT.Raise();
this.OnRaisedHALT();
}
}
public void LowerHALT()
{
this.OnLoweringHALT();
this.HALT.Lower();
this.OnLoweredHALT();
if (this.HALT.Raised())
{
this.OnLoweringHALT();
this.HALT.Lower();
this.OnLoweredHALT();
}
}
public void RaiseBA()
{
this.OnRaisingBA();
this.BA.Raise();
this.OnRaisedBA();
if (this.BA.Lowered())
{
this.OnRaisingBA();
this.BA.Raise();
this.OnRaisedBA();
}
}
public void LowerBA()
{
this.OnLoweringBA();
this.BA.Lower();
this.OnLoweredBA();
if (this.BA.Raised())
{
this.OnLoweringBA();
this.BA.Lower();
this.OnLoweredBA();
}
}
public void RaiseBS()
{
this.OnRaisingBS();
this.BS.Raise();
this.OnRaisedBS();
if (this.BS.Lowered())
{
this.OnRaisingBS();
this.BS.Raise();
this.OnRaisedBS();
}
}
public void LowerBS()
{
this.OnLoweringBS();
this.BS.Lower();
this.OnLoweredBS();
if (this.BS.Raised())
{
this.OnLoweringBS();
this.BS.Lower();
this.OnLoweredBS();
}
}
public void RaiseRW()
{
if (this.RW.Lowered())
{
this.OnRaisingRW();
this.RW.Raise();
this.OnRaisedRW();
}
}
public void LowerRW()
{
if (this.RW.Raised())
{
this.OnLoweringRW();
this.RW.Lower();
this.OnLoweredRW();
}
}
protected override void OnRaisedPOWER()
{
this.LowerBA();
this.LowerBS();
this.LowerRW();
base.OnRaisedPOWER();
}
protected override void HandleRESET()
@ -326,6 +388,18 @@
protected override void Push(byte value) => this.PushS(value);
protected override void BusWrite()
{
this.LowerRW();
base.BusWrite();
}
protected override byte BusRead()
{
this.RaiseRW();
return base.BusRead();
}
private void HandleHALT()
{
this.RaiseBA();
@ -396,6 +470,14 @@
private void OnLoweredBS() => this.LoweredBS?.Invoke(this, EventArgs.Empty);
private void OnRaisingRW() => this.RaisingRW?.Invoke(this, EventArgs.Empty);
private void OnRaisedRW() => this.RaisedRW?.Invoke(this, EventArgs.Empty);
private void OnLoweringRW() => this.LoweringRW?.Invoke(this, EventArgs.Empty);
private void OnLoweredRW() => this.LoweredRW?.Invoke(this, EventArgs.Empty);
private void OnExecutingInstruction() => this.ExecutingInstruction?.Invoke(this, EventArgs.Empty);
private void OnExecutedInstruction() => this.ExecutedInstruction?.Invoke(this, EventArgs.Empty);

View File

@ -337,12 +337,6 @@ namespace EightBit
}
}
public override void RaisePOWER()
{
base.RaisePOWER();
this.startup = StartupCondition.ColdStart;
}
public void MarkTransmitComplete()
{
this.statusTDRE = this.CTS.Lowered();
@ -383,6 +377,12 @@ namespace EightBit
return returned;
}
protected override void OnRaisedPOWER()
{
this.startup = StartupCondition.ColdStart;
base.OnRaisedPOWER();
}
protected override void OnTicked()
{
base.OnTicked();

View File

@ -55,8 +55,15 @@ namespace EightBit
+ $"B={b:x2} C={c:x2} "
+ $"D={d:x2} E={e:x2} "
+ $"H={h:x2} L={l:x2} "
+ $"IX={cpu.IX.Word:x4} "
+ $"IY={cpu.IY.Word:x4} "
+ $"I={i:x2} R={(byte)r:x2} "
+ $"IM={im}";
+ $"IM={im} "
+ $"IFF1={(cpu.IFF1 ? 1 : 0)} "
+ $"{(cpu.RESET.Lowered() ? "R" : "-")}"
+ $"{(cpu.INT.Lowered() ? "I" : "-")}"
+ $"{(cpu.HALT.Lowered() ? "H" : "-")}"
+ $"{(cpu.NMI.Lowered() ? "N" : "-")}";
}
public string Disassemble(Z80 cpu)
@ -261,6 +268,39 @@ namespace EightBit
dumpCount += 2;
break;
case 4: // Negate accumulator
specification = "NEG";
break;
case 5: // Return from interrupt
switch (y)
{
case 1:
specification = "RETI";
break;
default:
specification = "RETN";
break;
}
break;
case 6: // Set interrupt mode
switch (y)
{
case 0:
case 1:
case 4:
case 5:
specification = "IM 0";
break;
case 2:
case 6:
specification = "IM 1";
break;
case 3:
case 7:
specification = "IM 2";
break;
}
break;
case 7:
switch (y)
{

View File

@ -41,9 +41,10 @@ namespace Fuse
foreach (var e in result.Events.Container)
{
// Ignore contention events
if (!e.Specifier.EndsWith("C"))
{
this.expectedEvents.Add(new TestEvent(0, e.Specifier, e.Address, e.Value));
this.expectedEvents.Add(e);
}
}
}
@ -96,13 +97,13 @@ namespace Fuse
protected override void OnReadByte()
{
this.actualEvents.Add(new TestEvent(0, "MR", this.Address.Word, this.Data));
this.actualEvents.Add(new TestEvent(this.cpu.Cycles, "MR", this.Address.Word, this.Data));
base.OnReadByte();
}
protected override void OnWrittenByte()
{
this.actualEvents.Add(new TestEvent(0, "MW", this.Address.Word, this.Data));
this.actualEvents.Add(new TestEvent(this.cpu.Cycles, "MW", this.Address.Word, this.Data));
base.OnWrittenByte();
}
@ -400,7 +401,7 @@ namespace Fuse
var equalAddress = expectation.Address == actual.Address;
var equalValue = expectation.Value == actual.Value;
var equal = equalCycles && equalSpecifier && equalAddress && equalValue;
var equal = /* equalCycles && */equalSpecifier && equalAddress && equalValue;
eventFailure = !equal;
}

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
@ -33,6 +33,7 @@
<LangVersion>latest</LangVersion>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />