diff options
Diffstat (limited to 'src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs')
-rw-r--r-- | src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs b/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs new file mode 100644 index 00000000..facb9142 --- /dev/null +++ b/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs @@ -0,0 +1,153 @@ +using ARMeilleure.Memory; +using ARMeilleure.State; +using System; + +namespace Ryujinx.Cpu.LightningJit.State +{ + public class ExecutionContext : IExecutionContext + { + private const int MinCountForCheck = 4000; + + private readonly NativeContext _nativeContext; + + internal IntPtr NativeContextPtr => _nativeContext.BasePtr; + + private bool _interrupted; + private readonly ICounter _counter; + + public ulong Pc => _nativeContext.GetPc(); + + public ulong CntfrqEl0 => _counter.Frequency; + public ulong CntpctEl0 => _counter.Counter; + + public long TpidrEl0 + { + get => _nativeContext.GetTpidrEl0(); + set => _nativeContext.SetTpidrEl0(value); + } + + public long TpidrroEl0 + { + get => _nativeContext.GetTpidrroEl0(); + set => _nativeContext.SetTpidrroEl0(value); + } + + public uint Pstate + { + get => _nativeContext.GetPstate(); + set => _nativeContext.SetPstate(value); + } + + public uint Fpsr + { + get => _nativeContext.GetFPState((uint)FPSR.Mask); + set => _nativeContext.SetFPState(value, (uint)FPSR.Mask); + } + + public uint Fpcr + { + get => _nativeContext.GetFPState((uint)FPCR.Mask); + set => _nativeContext.SetFPState(value, (uint)FPCR.Mask); + } + + public bool IsAarch32 { get; set; } + + internal ExecutionMode ExecutionMode + { + get + { + if (IsAarch32) + { + return (Pstate & (1u << 5)) != 0 + ? ExecutionMode.Aarch32Thumb + : ExecutionMode.Aarch32Arm; + } + else + { + return ExecutionMode.Aarch64; + } + } + } + + public bool Running + { + get => _nativeContext.GetRunning(); + private set => _nativeContext.SetRunning(value); + } + + private readonly ExceptionCallbackNoArgs _interruptCallback; + private readonly ExceptionCallback _breakCallback; + private readonly ExceptionCallback _supervisorCallback; + private readonly ExceptionCallback _undefinedCallback; + + public ExecutionContext(IJitMemoryAllocator allocator, ICounter counter, ExceptionCallbacks exceptionCallbacks) + { + _nativeContext = new NativeContext(allocator); + _counter = counter; + _interruptCallback = exceptionCallbacks.InterruptCallback; + _breakCallback = exceptionCallbacks.BreakCallback; + _supervisorCallback = exceptionCallbacks.SupervisorCallback; + _undefinedCallback = exceptionCallbacks.UndefinedCallback; + + Running = true; + + _nativeContext.SetCounter(MinCountForCheck); + } + + public ulong GetX(int index) => _nativeContext.GetX(index); + public void SetX(int index, ulong value) => _nativeContext.SetX(index, value); + + public V128 GetV(int index) => _nativeContext.GetV(index); + public void SetV(int index, V128 value) => _nativeContext.SetV(index, value); + + internal void CheckInterrupt() + { + if (_interrupted) + { + _interrupted = false; + + _interruptCallback?.Invoke(this); + } + + _nativeContext.SetCounter(MinCountForCheck); + } + + public void RequestInterrupt() + { + _interrupted = true; + } + + internal void OnBreak(ulong address, int imm) + { + _breakCallback?.Invoke(this, address, imm); + } + + internal void OnSupervisorCall(ulong address, int imm) + { + _supervisorCallback?.Invoke(this, address, imm); + } + + internal void OnUndefined(ulong address, int opCode) + { + _undefinedCallback?.Invoke(this, address, opCode); + } + + public void StopRunning() + { + Running = false; + + _nativeContext.SetCounter(0); + } + + protected virtual void Dispose(bool disposing) + { + _nativeContext.Dispose(); + } + + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} |