170 lines
4.2 KiB
C#
170 lines
4.2 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace BizHawk.Emulation.Common
|
|
{
|
|
/// <summary>
|
|
/// This service manages debugging capabilities from the core to the client. Tools such as the debugger make use of this, as well as LUA scripting
|
|
/// This service specifically manages getting/setting CPU registers, managing breakpoints, and stepping through CPU instructions
|
|
/// Providing a disassembly is managed by another service, these are aspects outside of the disassembler that are essential to debugging tools
|
|
/// Tools like the debugger will gracefully degrade based on the availability of each component of this service,
|
|
/// it is expected that any of these features will throw a NotImplementedException if not implemented, and the client will manage accordingly
|
|
/// </summary>
|
|
public interface IDebuggable : IEmulatorService
|
|
{
|
|
/// <summary>
|
|
/// Returns a list of CPU registers and their current state
|
|
/// </summary>
|
|
IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters();
|
|
|
|
/// <summary>
|
|
/// Sets a given CPU register to the given value
|
|
/// </summary>
|
|
void SetCpuRegister(string register, int value);
|
|
|
|
/// <summary>
|
|
/// Gets a memory callback implementation that manages memory callback functionality
|
|
/// </summary>
|
|
IMemoryCallbackSystem MemoryCallbacks { get; }
|
|
|
|
/// <summary>
|
|
/// Informs the calling code whether or not the given step type is implemented,
|
|
/// if false, a NotImplementedException will be thrown if Step is called with the given value
|
|
/// </summary>
|
|
bool CanStep(StepType type);
|
|
|
|
/// <summary>
|
|
/// Advances the core based on the given Step type
|
|
/// </summary>
|
|
void Step(StepType type);
|
|
|
|
/// <summary>
|
|
/// Gets the total number of CPU cycles since the beginning of the core's lifecycle
|
|
/// Note that the CPU in this case is the "main" CPU, for some cores that may be somewhat subjective
|
|
/// </summary>
|
|
int TotalExecutedCycles { get; } // TODO: this should probably be a long, but most cores were using int, oh well
|
|
}
|
|
|
|
public class RegisterValue
|
|
{
|
|
public ulong Value { get; private set; }
|
|
public byte BitSize { get; private set; }
|
|
|
|
public RegisterValue(ulong val, byte bitSize)
|
|
{
|
|
if (bitSize == 64)
|
|
{
|
|
Value = val;
|
|
}
|
|
else if (bitSize > 64 || bitSize == 0)
|
|
{
|
|
throw new System.ArgumentOutOfRangeException(nameof(bitSize), "BitSize must be in 1..64");
|
|
}
|
|
else
|
|
{
|
|
Value = val & (1UL << bitSize) - 1;
|
|
}
|
|
|
|
BitSize = bitSize;
|
|
}
|
|
|
|
public RegisterValue(bool val)
|
|
{
|
|
Value = val ? 1UL : 0UL;
|
|
BitSize = 1;
|
|
}
|
|
|
|
public RegisterValue(byte val)
|
|
{
|
|
Value = val;
|
|
BitSize = 8;
|
|
}
|
|
|
|
public RegisterValue(sbyte val)
|
|
{
|
|
Value = (byte)val;
|
|
BitSize = 8;
|
|
}
|
|
|
|
public RegisterValue(ushort val)
|
|
{
|
|
Value = val;
|
|
BitSize = 16;
|
|
}
|
|
|
|
public RegisterValue(short val)
|
|
{
|
|
Value = (ushort)val;
|
|
BitSize = 16;
|
|
}
|
|
|
|
public RegisterValue(uint val)
|
|
{
|
|
Value = val;
|
|
BitSize = 32;
|
|
}
|
|
|
|
public RegisterValue(int val)
|
|
{
|
|
Value = (uint)val;
|
|
BitSize = 32;
|
|
}
|
|
|
|
public RegisterValue(ulong val)
|
|
{
|
|
Value = val;
|
|
BitSize = 64;
|
|
}
|
|
|
|
public RegisterValue(long val)
|
|
{
|
|
Value = (ulong)val;
|
|
BitSize = 64;
|
|
}
|
|
|
|
public static implicit operator RegisterValue(bool val)
|
|
{
|
|
return new RegisterValue(val);
|
|
}
|
|
|
|
public static implicit operator RegisterValue(byte val)
|
|
{
|
|
return new RegisterValue(val);
|
|
}
|
|
|
|
public static implicit operator RegisterValue(sbyte val)
|
|
{
|
|
return new RegisterValue(val);
|
|
}
|
|
|
|
public static implicit operator RegisterValue(ushort val)
|
|
{
|
|
return new RegisterValue(val);
|
|
}
|
|
|
|
public static implicit operator RegisterValue(short val)
|
|
{
|
|
return new RegisterValue(val);
|
|
}
|
|
|
|
public static implicit operator RegisterValue(uint val)
|
|
{
|
|
return new RegisterValue(val);
|
|
}
|
|
|
|
public static implicit operator RegisterValue(int val)
|
|
{
|
|
return new RegisterValue(val);
|
|
}
|
|
|
|
public static implicit operator RegisterValue(ulong val)
|
|
{
|
|
return new RegisterValue(val);
|
|
}
|
|
|
|
public static implicit operator RegisterValue(long val)
|
|
{
|
|
return new RegisterValue(val);
|
|
}
|
|
}
|
|
}
|