/ src / ARMeilleure / State / ExecutionContext.cs
ExecutionContext.cs
  1  using ARMeilleure.Memory;
  2  using System;
  3  
  4  namespace ARMeilleure.State
  5  {
  6      public class ExecutionContext
  7      {
  8          private const int MinCountForCheck = 4000;
  9  
 10          private readonly NativeContext _nativeContext;
 11  
 12          internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
 13  
 14          private bool _interrupted;
 15  
 16          private readonly ICounter _counter;
 17  
 18          public ulong Pc => _nativeContext.GetPc();
 19  
 20  #pragma warning disable CA1822 // Mark member as static
 21          public uint CtrEl0 => 0x8444c004;
 22          public uint DczidEl0 => 0x00000004;
 23  #pragma warning restore CA1822
 24  
 25          public ulong CntfrqEl0 => _counter.Frequency;
 26          public ulong CntpctEl0 => _counter.Counter;
 27  
 28          // CNTVCT_EL0 = CNTPCT_EL0 - CNTVOFF_EL2
 29          // Since EL2 isn't implemented, CNTVOFF_EL2 = 0
 30          public ulong CntvctEl0 => CntpctEl0;
 31  
 32          public long TpidrEl0
 33          {
 34              get => _nativeContext.GetTpidrEl0();
 35              set => _nativeContext.SetTpidrEl0(value);
 36          }
 37  
 38          public long TpidrroEl0
 39          {
 40              get => _nativeContext.GetTpidrroEl0();
 41              set => _nativeContext.SetTpidrroEl0(value);
 42          }
 43  
 44          public uint Pstate
 45          {
 46              get => _nativeContext.GetPstate();
 47              set => _nativeContext.SetPstate(value);
 48          }
 49  
 50          public FPSR Fpsr
 51          {
 52              get => (FPSR)_nativeContext.GetFPState((uint)FPSR.Mask);
 53              set => _nativeContext.SetFPState((uint)value, (uint)FPSR.Mask);
 54          }
 55  
 56          public FPCR Fpcr
 57          {
 58              get => (FPCR)_nativeContext.GetFPState((uint)FPCR.Mask);
 59              set => _nativeContext.SetFPState((uint)value, (uint)FPCR.Mask);
 60          }
 61          public FPCR StandardFpcrValue => (Fpcr & (FPCR.Ahp)) | FPCR.Dn | FPCR.Fz;
 62  
 63          public FPSCR Fpscr
 64          {
 65              get => (FPSCR)_nativeContext.GetFPState((uint)FPSCR.Mask);
 66              set => _nativeContext.SetFPState((uint)value, (uint)FPSCR.Mask);
 67          }
 68  
 69          public bool IsAarch32 { get; set; }
 70  
 71          internal ExecutionMode ExecutionMode
 72          {
 73              get
 74              {
 75                  if (IsAarch32)
 76                  {
 77                      return GetPstateFlag(PState.TFlag)
 78                          ? ExecutionMode.Aarch32Thumb
 79                          : ExecutionMode.Aarch32Arm;
 80                  }
 81                  else
 82                  {
 83                      return ExecutionMode.Aarch64;
 84                  }
 85              }
 86          }
 87  
 88          public bool Running
 89          {
 90              get => _nativeContext.GetRunning();
 91              private set => _nativeContext.SetRunning(value);
 92          }
 93  
 94          private readonly ExceptionCallbackNoArgs _interruptCallback;
 95          private readonly ExceptionCallback _breakCallback;
 96          private readonly ExceptionCallback _supervisorCallback;
 97          private readonly ExceptionCallback _undefinedCallback;
 98  
 99          public ExecutionContext(
100              IJitMemoryAllocator allocator,
101              ICounter counter,
102              ExceptionCallbackNoArgs interruptCallback = null,
103              ExceptionCallback breakCallback = null,
104              ExceptionCallback supervisorCallback = null,
105              ExceptionCallback undefinedCallback = null)
106          {
107              _nativeContext = new NativeContext(allocator);
108              _counter = counter;
109              _interruptCallback = interruptCallback;
110              _breakCallback = breakCallback;
111              _supervisorCallback = supervisorCallback;
112              _undefinedCallback = undefinedCallback;
113  
114              Running = true;
115  
116              _nativeContext.SetCounter(MinCountForCheck);
117          }
118  
119          public ulong GetX(int index) => _nativeContext.GetX(index);
120          public void SetX(int index, ulong value) => _nativeContext.SetX(index, value);
121  
122          public V128 GetV(int index) => _nativeContext.GetV(index);
123          public void SetV(int index, V128 value) => _nativeContext.SetV(index, value);
124  
125          public bool GetPstateFlag(PState flag) => _nativeContext.GetPstateFlag(flag);
126          public void SetPstateFlag(PState flag, bool value) => _nativeContext.SetPstateFlag(flag, value);
127  
128          public bool GetFPstateFlag(FPState flag) => _nativeContext.GetFPStateFlag(flag);
129          public void SetFPstateFlag(FPState flag, bool value) => _nativeContext.SetFPStateFlag(flag, value);
130  
131          internal void CheckInterrupt()
132          {
133              if (_interrupted)
134              {
135                  _interrupted = false;
136  
137                  _interruptCallback?.Invoke(this);
138              }
139  
140              _nativeContext.SetCounter(MinCountForCheck);
141          }
142  
143          public void RequestInterrupt()
144          {
145              _interrupted = true;
146          }
147  
148          internal void OnBreak(ulong address, int imm)
149          {
150              _breakCallback?.Invoke(this, address, imm);
151          }
152  
153          internal void OnSupervisorCall(ulong address, int imm)
154          {
155              _supervisorCallback?.Invoke(this, address, imm);
156          }
157  
158          internal void OnUndefined(ulong address, int opCode)
159          {
160              _undefinedCallback?.Invoke(this, address, opCode);
161          }
162  
163          public void StopRunning()
164          {
165              Running = false;
166  
167              _nativeContext.SetCounter(0);
168          }
169  
170          public void Dispose()
171          {
172              _nativeContext.Dispose();
173          }
174      }
175  }