feat(analysis): add basic block model and SMC event type

This commit is contained in:
dualfroz committed 2026-08-25 14:39:22 +02:00
1 parent 1f3ed9595e
commit a6c2b4f7d4
2 files changed
+120

No files matched your search

+90
View File
@@ -0,0 +1,90 @@
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace Chip8.Analysis;
public sealed class BasicBlock
{
readonly List<InstructionInfo> instructionList = new();
readonly List<ControlFlowEdge> successorList = new();
readonly List<ushort> predecessorList = new();
public BasicBlock(ushort startAddress)
{
this.startAddress = startAddress;
}
public ushort startAddress { get; }
public IReadOnlyList<InstructionInfo> instructions => instructionList;
public IReadOnlyList<ControlFlowEdge> successors => successorList;
public IReadOnlyList<ushort> predecessors => predecessorList;
public InstructionInfo terminator => instructionList[instructionList.Count - 1];
public InstructionInfo first => instructionList[0];
public ushort endAddress => terminator.address;
public ushort nextAddress => terminator.nextAddress;
public int byteLength
{
get
{
int total = 0;
foreach (var instruction in instructionList)
{
total += instruction.byteLength;
}
return total;
}
}
public int instructionCount => instructionList.Count;
public bool isReturn => terminator.flow == FlowEffect.Return;
public bool isCall => terminator.flow == FlowEffect.Call;
public bool isBranch => terminator.flow == FlowEffect.Branch;
public bool isUnconditionalJump => terminator.flow == FlowEffect.Jump;
public bool hasIndirectExit => terminator.flow == FlowEffect.IndirectJump;
public bool isTerminal => successorList.Count == 0;
internal void add(InstructionInfo instruction) => instructionList.Add(instruction);
internal void addSuccessor(ControlFlowEdge edge) => successorList.Add(edge);
internal void addPredecessor(ushort predecessor)
{
if (!predecessorList.Contains(predecessor))
{
predecessorList.Add(predecessor);
}
}
public string render()
{
var builder = new StringBuilder();
builder.Append("block 0x").Append(startAddress.ToString("X4", CultureInfo.InvariantCulture));
builder.Append(" (").Append(instructionCount).Append(" instr, ").Append(byteLength).Append(" bytes)\n");
foreach (var instruction in instructionList)
{
builder.Append(" ").Append(instruction).Append('\n');
}
foreach (var edge in successorList)
{
builder.Append(" => ").Append(edge).Append('\n');
}
return builder.ToString();
}
public override string ToString() =>
"block@0x" + startAddress.ToString("X4", CultureInfo.InvariantCulture)
+ " [" + instructionCount + " instr]";
}
+30
View File
@@ -0,0 +1,30 @@
using System.Globalization;
namespace Chip8.Analysis;
public sealed class SmcEvent
{
public SmcEvent(int step, ushort writerAddress, ushort targetAddress, byte oldValue, byte newValue)
{
this.step = step;
this.writerAddress = writerAddress;
this.targetAddress = targetAddress;
this.oldValue = oldValue;
this.newValue = newValue;
}
public int step { get; }
public ushort writerAddress { get; }
public ushort targetAddress { get; }
public byte oldValue { get; }
public byte newValue { get; }
public override string ToString()
{
return "step " + step.ToString(CultureInfo.InvariantCulture)
+ ": writer 0x" + writerAddress.ToString("X4", CultureInfo.InvariantCulture)
+ " changed 0x" + targetAddress.ToString("X4", CultureInfo.InvariantCulture)
+ " from 0x" + oldValue.ToString("X2", CultureInfo.InvariantCulture)
+ " to 0x" + newValue.ToString("X2", CultureInfo.InvariantCulture);
}
}