mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2024-06-02 16:41:33 +00:00
Add MC6809 profiler (mainly so I can pin down problem printing numbers)
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
parent
d21afdc1c7
commit
c4d52512b2
|
@ -52,25 +52,20 @@
|
|||
|
||||
////private static string Dump_RelativeValue(Register16 value) => Dump_RelativeValue(value);
|
||||
|
||||
private string Disassemble(ushort current)
|
||||
public string Disassemble(ushort current)
|
||||
{
|
||||
if (this.CPU.Powered)
|
||||
this.address = current;
|
||||
if (this.prefix10)
|
||||
{
|
||||
this.address = current;
|
||||
if (this.prefix10)
|
||||
{
|
||||
return this.Disassemble10();
|
||||
}
|
||||
|
||||
if (this.prefix11)
|
||||
{
|
||||
return this.Disassemble11();
|
||||
}
|
||||
|
||||
return this.DisassembleUnprefixed();
|
||||
return this.Disassemble10();
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
if (this.prefix11)
|
||||
{
|
||||
return this.Disassemble11();
|
||||
}
|
||||
|
||||
return this.DisassembleUnprefixed();
|
||||
}
|
||||
|
||||
private string Disassemble(int current) => this.Disassemble((ushort)current);
|
||||
|
@ -764,8 +759,8 @@
|
|||
|
||||
var type8 = (reg1 & (byte)Bits.Bit3) != 0; // 8 bit?
|
||||
return type8
|
||||
? $"{ReferenceTransfer8(reg1)},{ReferenceTransfer8(reg2)}"
|
||||
: $"{ReferenceTransfer16(reg1)},{ReferenceTransfer16(reg2)}";
|
||||
? $"{output}{ReferenceTransfer8(reg1)},{ReferenceTransfer8(reg2)}"
|
||||
: $"{output}{ReferenceTransfer16(reg1)},{ReferenceTransfer16(reg2)}";
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -781,7 +776,7 @@
|
|||
private string PulX(string mnemomic, string upon)
|
||||
{
|
||||
var data = this.GetByte(++this.address);
|
||||
var output = $"data:x2\t{mnemomic}\t";
|
||||
var output = $"{data:x2}\t{mnemomic}\t";
|
||||
var registers = new List<string>();
|
||||
|
||||
if ((data & (byte)Bits.Bit0) != 0)
|
||||
|
@ -830,7 +825,7 @@
|
|||
private string PshX(string mnemomic, string upon)
|
||||
{
|
||||
var data = this.GetByte(++this.address);
|
||||
var output = $"data:x2\t{mnemomic}\t";
|
||||
var output = $"{data:x2}\t{mnemomic}\t";
|
||||
var registers = new List<string>();
|
||||
|
||||
if ((data & (byte)Bits.Bit7) != 0)
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace EightBit
|
|||
private readonly Rom rom = new Rom(0x4000); // C000 - FFFF, 16K ROM
|
||||
|
||||
private readonly Disassembler disassembler;
|
||||
private readonly Profiler profiler;
|
||||
|
||||
private ulong totalCycleCount = 0UL;
|
||||
private long frameCycleCount = 0L;
|
||||
|
@ -28,6 +29,7 @@ namespace EightBit
|
|||
this.configuration = configuration;
|
||||
this.CPU = new MC6809(this);
|
||||
this.disassembler = new Disassembler(this, this.CPU);
|
||||
this.profiler = new Profiler(this, this.CPU, this.disassembler);
|
||||
}
|
||||
|
||||
public MC6809 CPU { get; }
|
||||
|
@ -78,6 +80,8 @@ namespace EightBit
|
|||
|
||||
public override void LowerPOWER()
|
||||
{
|
||||
////this.profiler.Generate();
|
||||
|
||||
this.ACIA.LowerPOWER();
|
||||
this.CPU.LowerPOWER();
|
||||
base.LowerPOWER();
|
||||
|
@ -109,6 +113,9 @@ namespace EightBit
|
|||
// Early termination condition for CPU timing code
|
||||
this.CPU.ExecutedInstruction += this.CPU_ExecutedInstruction_Termination;
|
||||
}
|
||||
|
||||
////this.profiler.Enable();
|
||||
////this.profiler.EmitLine += this.Profiler_EmitLine;
|
||||
}
|
||||
|
||||
// Marshal data from ACIA -> memory
|
||||
|
@ -137,6 +144,13 @@ namespace EightBit
|
|||
}
|
||||
}
|
||||
|
||||
private void Profiler_EmitLine(object sender, ProfileLineEventArgs e)
|
||||
{
|
||||
var cycles = e.Cycles;
|
||||
var disassembled = e.Source;
|
||||
System.Console.Error.WriteLine(disassembled);
|
||||
}
|
||||
|
||||
private void CPU_ExecutedInstruction_Termination(object sender, EventArgs e)
|
||||
{
|
||||
this.totalCycleCount += (ulong)this.CPU.Cycles;
|
||||
|
@ -151,14 +165,14 @@ namespace EightBit
|
|||
if (!this.ignoreDisassembly)
|
||||
{
|
||||
var disassembled = $"{this.disassembler.Trace(this.disassembleAt)}\t{this.ACIA.DumpStatus()}";
|
||||
System.Console.Out.WriteLine(disassembled);
|
||||
System.Console.Error.WriteLine(disassembled);
|
||||
}
|
||||
}
|
||||
|
||||
private void CPU_ExecutingInstruction(object sender, EventArgs e)
|
||||
{
|
||||
this.disassembleAt = this.CPU.PC.Word;
|
||||
this.ignoreDisassembly = this.disassembler.Ignore;
|
||||
this.ignoreDisassembly = this.disassembler.Ignore || this.disassembler.Pause;
|
||||
}
|
||||
|
||||
private void CPU_ExecutedInstruction(object sender, EventArgs e)
|
||||
|
@ -169,6 +183,11 @@ namespace EightBit
|
|||
if (System.Console.KeyAvailable)
|
||||
{
|
||||
var key = System.Console.ReadKey(true);
|
||||
if (key.Key == ConsoleKey.F12)
|
||||
{
|
||||
this.LowerPOWER();
|
||||
}
|
||||
|
||||
this.ACIA.RDR = System.Convert.ToByte(key.KeyChar);
|
||||
this.ACIA.MarkReceiveStarting();
|
||||
}
|
||||
|
|
|
@ -42,6 +42,10 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="Disassembler.cs" />
|
||||
<Compile Include="MC6809.cs" />
|
||||
<Compile Include="ProfileEventArgs.cs" />
|
||||
<Compile Include="ProfileLineEventArgs.cs" />
|
||||
<Compile Include="Profiler.cs" />
|
||||
<Compile Include="ProfileScopeEventArgs.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StatusBits.cs" />
|
||||
</ItemGroup>
|
||||
|
|
11
MC6809/ProfileEventArgs.cs
Normal file
11
MC6809/ProfileEventArgs.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
public class ProfileEventArgs : EventArgs
|
||||
{
|
||||
public ProfileEventArgs(string output) => this.Output = output;
|
||||
|
||||
public string Output { get; }
|
||||
}
|
||||
}
|
17
MC6809/ProfileLineEventArgs.cs
Normal file
17
MC6809/ProfileLineEventArgs.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
public class ProfileLineEventArgs : EventArgs
|
||||
{
|
||||
public ProfileLineEventArgs(string source, ulong cycles)
|
||||
{
|
||||
this.Source = source;
|
||||
this.Cycles = cycles;
|
||||
}
|
||||
|
||||
public string Source { get; }
|
||||
|
||||
public ulong Cycles { get; }
|
||||
}
|
||||
}
|
20
MC6809/ProfileScopeEventArgs.cs
Normal file
20
MC6809/ProfileScopeEventArgs.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
public class ProfileScopeEventArgs : EventArgs
|
||||
{
|
||||
public ProfileScopeEventArgs(string scope, ulong cycles, ulong count)
|
||||
{
|
||||
this.Scope = scope;
|
||||
this.Cycles = cycles;
|
||||
this.Count = count;
|
||||
}
|
||||
|
||||
public string Scope { get; }
|
||||
|
||||
public ulong Cycles { get; }
|
||||
|
||||
public ulong Count { get; }
|
||||
}
|
||||
}
|
111
MC6809/Profiler.cs
Normal file
111
MC6809/Profiler.cs
Normal file
|
@ -0,0 +1,111 @@
|
|||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
public sealed class Profiler
|
||||
{
|
||||
private readonly ulong[] instructionCounts;
|
||||
private readonly ulong[] addressProfiles;
|
||||
private readonly ulong[] addressCounts;
|
||||
|
||||
private ushort address;
|
||||
|
||||
private readonly Bus board;
|
||||
private readonly MC6809 processor;
|
||||
private readonly Disassembler disassembler;
|
||||
|
||||
public Profiler(Bus board, MC6809 processor, Disassembler disassembler)
|
||||
{
|
||||
this.board = board;
|
||||
this.processor = processor;
|
||||
this.disassembler = disassembler;
|
||||
|
||||
this.instructionCounts = new ulong[0x10000];
|
||||
this.addressProfiles = new ulong[0x10000];
|
||||
this.addressCounts = new ulong[0x10000];
|
||||
}
|
||||
|
||||
public event EventHandler<EventArgs> StartingOutput;
|
||||
|
||||
public event EventHandler<EventArgs> FinishedOutput;
|
||||
|
||||
public event EventHandler<EventArgs> StartingLineOutput;
|
||||
|
||||
public event EventHandler<EventArgs> FinishedLineOutput;
|
||||
|
||||
public event EventHandler<ProfileLineEventArgs> EmitLine;
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
this.processor.ExecutingInstruction += this.Processor_ExecutingInstruction;
|
||||
this.processor.ExecutedInstruction += this.Processor_ExecutedInstruction;
|
||||
}
|
||||
|
||||
public void Generate()
|
||||
{
|
||||
this.OnStartingOutput();
|
||||
try
|
||||
{
|
||||
this.EmitProfileInformation();
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.OnFinishedOutput();
|
||||
}
|
||||
}
|
||||
|
||||
private void EmitProfileInformation()
|
||||
{
|
||||
this.OnStartingLineOutput();
|
||||
try
|
||||
{
|
||||
// For each memory address
|
||||
for (var i = 0; i < 0x10000; ++i)
|
||||
{
|
||||
// If there are any cycles associated
|
||||
var cycles = this.addressProfiles[i];
|
||||
if (cycles > 0)
|
||||
{
|
||||
var address = (ushort)i;
|
||||
|
||||
// Dump a profile/disassembly line
|
||||
var disassembled = this.disassembler.Disassemble(address);
|
||||
var output = $"{address:x4}|{disassembled}";
|
||||
this.OnEmitLine(output, cycles);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.OnFinishedLineOutput();
|
||||
}
|
||||
}
|
||||
|
||||
private void Processor_ExecutingInstruction(object sender, EventArgs e) => this.address = this.processor.PC.Word;
|
||||
|
||||
private void Processor_ExecutedInstruction(object sender, EventArgs e)
|
||||
{
|
||||
ushort opcode = this.board.Peek(this.address);
|
||||
if (opcode == 0x10 || opcode == 0x11)
|
||||
{
|
||||
opcode *= 0x100;
|
||||
opcode += this.board.Peek((ushort)(this.address + 1));
|
||||
}
|
||||
|
||||
this.addressCounts[this.address]++;
|
||||
this.instructionCounts[opcode]++;
|
||||
|
||||
this.addressProfiles[this.address] += (ulong)this.processor.Cycles;
|
||||
}
|
||||
|
||||
private void OnStartingOutput() => this.StartingOutput?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
private void OnFinishedOutput() => this.FinishedOutput?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
private void OnStartingLineOutput() => this.StartingLineOutput?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
private void OnFinishedLineOutput() => this.FinishedLineOutput?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
private void OnEmitLine(string source, ulong cycles) => this.EmitLine?.Invoke(this, new ProfileLineEventArgs(source, cycles));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user