Ryujinx/ChocolArm64/State/AThreadState.cs
gdkchan b8133c1997
Thread scheduler rewrite (#393)
* Started to rewrite the thread scheduler

* Add a single core-like scheduling mode, enabled by default

* Clear exclusive monitor on context switch

* Add SetThreadActivity, misc fixes

* Implement WaitForAddress and SignalToAddress svcs, misc fixes

* Misc fixes (on SetActivity and Arbiter), other tweaks

* Rebased

* Add missing null check

* Rename multicore key on config, fix UpdatePriorityInheritance

* Make scheduling data MLQs private

* nit: Ordering
2018-09-18 20:36:43 -03:00

163 lines
4.2 KiB
C#

using ChocolArm64.Events;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Intrinsics;
namespace ChocolArm64.State
{
public class AThreadState
{
internal const int LRIndex = 30;
internal const int ZRIndex = 31;
internal const int ErgSizeLog2 = 4;
internal const int DczSizeLog2 = 4;
internal AExecutionMode ExecutionMode;
//AArch32 state.
public uint R0, R1, R2, R3,
R4, R5, R6, R7,
R8, R9, R10, R11,
R12, R13, R14, R15;
public bool Thumb;
//AArch64 state.
public ulong X0, X1, X2, X3, X4, X5, X6, X7,
X8, X9, X10, X11, X12, X13, X14, X15,
X16, X17, X18, X19, X20, X21, X22, X23,
X24, X25, X26, X27, X28, X29, X30, X31;
public Vector128<float> V0, V1, V2, V3, V4, V5, V6, V7,
V8, V9, V10, V11, V12, V13, V14, V15,
V16, V17, V18, V19, V20, V21, V22, V23,
V24, V25, V26, V27, V28, V29, V30, V31;
public bool Overflow;
public bool Carry;
public bool Zero;
public bool Negative;
public bool Running { get; set; }
public int Core { get; set; }
private bool Interrupted;
public long TpidrEl0 { get; set; }
public long Tpidr { get; set; }
public int Fpcr { get; set; }
public int Fpsr { get; set; }
public int Psr
{
get
{
return (Negative ? (int)APState.N : 0) |
(Zero ? (int)APState.Z : 0) |
(Carry ? (int)APState.C : 0) |
(Overflow ? (int)APState.V : 0);
}
}
public uint CtrEl0 => 0x8444c004;
public uint DczidEl0 => 0x00000004;
public ulong CntfrqEl0 { get; set; }
public ulong CntpctEl0
{
get
{
double Ticks = TickCounter.ElapsedTicks * HostTickFreq;
return (ulong)(Ticks * CntfrqEl0);
}
}
public event EventHandler<EventArgs> Interrupt;
public event EventHandler<AInstExceptionEventArgs> Break;
public event EventHandler<AInstExceptionEventArgs> SvcCall;
public event EventHandler<AInstUndefinedEventArgs> Undefined;
private Stack<long> CallStack;
private static Stopwatch TickCounter;
private static double HostTickFreq;
public AThreadState()
{
CallStack = new Stack<long>();
}
static AThreadState()
{
HostTickFreq = 1.0 / Stopwatch.Frequency;
TickCounter = new Stopwatch();
TickCounter.Start();
}
internal bool Synchronize()
{
if (Interrupted)
{
Interrupted = false;
OnInterrupt();
}
return Running;
}
internal void RequestInterrupt()
{
Interrupted = true;
}
private void OnInterrupt()
{
Interrupt?.Invoke(this, EventArgs.Empty);
}
internal void OnBreak(long Position, int Imm)
{
Break?.Invoke(this, new AInstExceptionEventArgs(Position, Imm));
}
internal void OnSvcCall(long Position, int Imm)
{
SvcCall?.Invoke(this, new AInstExceptionEventArgs(Position, Imm));
}
internal void OnUndefined(long Position, int RawOpCode)
{
Undefined?.Invoke(this, new AInstUndefinedEventArgs(Position, RawOpCode));
}
internal void EnterMethod(long Position)
{
CallStack.Push(Position);
}
internal void ExitMethod()
{
CallStack.TryPop(out _);
}
internal void JumpMethod(long Position)
{
CallStack.TryPop(out _);
CallStack.Push(Position);
}
public long[] GetCallStack()
{
return CallStack.ToArray();
}
}
}