Skip to content

Commit

Permalink
Slightly faster and prettier call/address recording for debugging.
Browse files Browse the repository at this point in the history
  • Loading branch information
JorisVanEijden committed Jun 29, 2024
1 parent c88027c commit f08f473
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 9 deletions.
6 changes: 3 additions & 3 deletions src/Spice86.Core/Emulator/CPU/CPU.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public class Cpu : IDebuggableComponent {
/// CPU uses this internally and adjusts IP after instruction execution is done.
/// </remarks>
private ushort _internalIp;
private readonly CircularBuffer<string> _lastAddresses = new(20);
private readonly CircularBuffer<SegmentedAddress> _lastAddresses = new(20);

private readonly IOPortDispatcher _ioPortDispatcher;

Expand Down Expand Up @@ -115,7 +115,7 @@ public void ExecuteNextInstruction() {

ExecutionFlowRecorder.RegisterExecutedInstruction(State.CS, _internalIp);
#if DEBUG
_lastAddresses.Add($"{State.CS:X4}:{_internalIp:X4}");
_lastAddresses.Add(new SegmentedAddress(State.CS, _internalIp));
#endif
byte opcode = ProcessPrefixes();
if (State.ContinueZeroFlagValue != null && IsStringOpcode(opcode)) {
Expand All @@ -127,7 +127,7 @@ public void ExecuteNextInstruction() {
} catch (CpuException e) {
HandleCpuException(e);
} catch (Exception e) {
_loggerService.Fatal(e, "Cpu Failure {LastAdresses}", _lastAddresses.ToString());
_loggerService.Fatal(e, "Cpu Failure {LastAddresses}", _lastAddresses.ToString());
throw;
}
}
Expand Down
18 changes: 12 additions & 6 deletions src/Spice86.Core/Emulator/Function/ExecutionFlowRecorder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ public class ExecutionFlowRecorder {
private readonly HashSet<uint> _instructionsEncountered = new(200000);
private readonly HashSet<uint> _executableCodeAreasEncountered = new(200000);

private readonly CircularBuffer<string> _callStack = new(20);
private readonly CircularBuffer<CallRecord> _functionCalls = new(20);
private ushort _callDepth;

/// <summary>
/// Gets or sets whether we register self modifying machine code.
Expand Down Expand Up @@ -83,7 +84,7 @@ public ExecutionFlowRecorder() {
public void RegisterCall(ushort fromCS, ushort fromIP, ushort toCS, ushort toIP) {
RegisterAddressJump(CallsFromTo, _callsEncountered, fromCS, fromIP, toCS, toIP);
#if DEBUG
_callStack.Add($"{fromCS:X4}:{fromIP:X4} -> {toCS:X4}:{toIP:X4}");
_functionCalls.Add(new CallRecord(_callDepth++, fromCS, fromIP, toCS, toIP));
#endif
}

Expand All @@ -107,6 +108,7 @@ public void RegisterJump(ushort fromCS, ushort fromIP, ushort toCS, ushort toIP)
/// <param name="toIP">The offset of the address being called.</param>
public void RegisterReturn(ushort fromCS, ushort fromIP, ushort toCS, ushort toIP) {
RegisterAddressJump(RetsFromTo, _retsEncountered, fromCS, fromIP, toCS, toIP);
_callDepth--;
}

/// <summary>
Expand Down Expand Up @@ -236,10 +238,14 @@ private void RegisterAddressJump(IDictionary<uint, HashSet<SegmentedAddress>> Fr
}

/// <summary>
/// Lists the current call stack.
/// Create an overview of the function call flow of the last X function calls.
/// </summary>
/// <returns></returns>
public string DumpCallStack() {
return _callStack.ToString();
public string DumpFunctionCalls() {
return $"Address -> called function\n{_functionCalls}";
}
}

private readonly record struct CallRecord(ushort Depth, ushort FromCs, ushort FromIp, ushort ToCs, ushort ToIp) {
public override string ToString() => $"{new string('.', Depth)}{FromCs:X4}:{FromIp:X4} -> {ToCs:X4}:{ToIp:X4}";
}
}

0 comments on commit f08f473

Please sign in to comment.