forked from Mirror/Ryujinx
Implement SvcGetThreadContext3
This commit is contained in:
parent
c818093528
commit
65105c2a3b
10 changed files with 163 additions and 12 deletions
|
@ -4,11 +4,13 @@ namespace ChocolArm64.Events
|
|||
{
|
||||
public class AInstExceptionEventArgs : EventArgs
|
||||
{
|
||||
public int Id { get; private set; }
|
||||
public long Position { get; private set; }
|
||||
public int Id { get; private set; }
|
||||
|
||||
public AInstExceptionEventArgs(int Id)
|
||||
public AInstExceptionEventArgs(long Position, int Id)
|
||||
{
|
||||
this.Id = Id;
|
||||
this.Position = Position;
|
||||
this.Id = Id;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ namespace ChocolArm64.Instruction
|
|||
|
||||
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||
|
||||
Context.EmitLdc_I8(Op.Position);
|
||||
Context.EmitLdc_I4(Op.Id);
|
||||
|
||||
Context.EmitPrivateCall(typeof(AThreadState), MthdName);
|
||||
|
|
|
@ -51,6 +51,17 @@ namespace ChocolArm64.State
|
|||
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;
|
||||
|
||||
|
@ -89,14 +100,14 @@ namespace ChocolArm64.State
|
|||
TickCounter.Start();
|
||||
}
|
||||
|
||||
internal void OnBreak(int Imm)
|
||||
internal void OnBreak(long Position, int Imm)
|
||||
{
|
||||
Break?.Invoke(this, new AInstExceptionEventArgs(Imm));
|
||||
Break?.Invoke(this, new AInstExceptionEventArgs(Position, Imm));
|
||||
}
|
||||
|
||||
internal void OnSvcCall(int Imm)
|
||||
internal void OnSvcCall(long Position, int Imm)
|
||||
{
|
||||
SvcCall?.Invoke(this, new AInstExceptionEventArgs(Imm));
|
||||
SvcCall?.Invoke(this, new AInstExceptionEventArgs(Position, Imm));
|
||||
}
|
||||
|
||||
internal void OnUndefined(long Position, int RawOpCode)
|
||||
|
|
|
@ -47,6 +47,8 @@ namespace Ryujinx.HLE.OsHle.Handles
|
|||
|
||||
if (TryAddToCore(Thread))
|
||||
{
|
||||
SchedThread.IsRunning = true;
|
||||
|
||||
Thread.Thread.Execute();
|
||||
|
||||
PrintDbgThreadInfo(Thread, "running.");
|
||||
|
@ -94,10 +96,7 @@ namespace Ryujinx.HLE.OsHle.Handles
|
|||
|
||||
public void SetThreadActivity(KThread Thread, bool Active)
|
||||
{
|
||||
if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
SchedulerThread SchedThread = AllThreads[Thread];
|
||||
|
||||
SchedThread.IsActive = Active;
|
||||
|
||||
|
@ -111,6 +110,16 @@ namespace Ryujinx.HLE.OsHle.Handles
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsThreadRunning(KThread Thread)
|
||||
{
|
||||
if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return SchedThread.IsRunning;
|
||||
}
|
||||
|
||||
public void EnterWait(KThread Thread, int TimeoutMs = Timeout.Infinite)
|
||||
{
|
||||
SchedulerThread SchedThread = AllThreads[Thread];
|
||||
|
@ -161,6 +170,8 @@ namespace Ryujinx.HLE.OsHle.Handles
|
|||
{
|
||||
lock (SchedLock)
|
||||
{
|
||||
AllThreads[Thread].IsRunning = false;
|
||||
|
||||
PrintDbgThreadInfo(Thread, "suspended.");
|
||||
|
||||
int ActualCore = Thread.ActualCore;
|
||||
|
@ -252,6 +263,8 @@ namespace Ryujinx.HLE.OsHle.Handles
|
|||
|
||||
private void TryResumingExecution(SchedulerThread SchedThread)
|
||||
{
|
||||
SchedThread.IsRunning = false;
|
||||
|
||||
KThread Thread = SchedThread.Thread;
|
||||
|
||||
PrintDbgThreadInfo(Thread, "trying to resume...");
|
||||
|
@ -262,6 +275,8 @@ namespace Ryujinx.HLE.OsHle.Handles
|
|||
{
|
||||
if (TryAddToCore(Thread))
|
||||
{
|
||||
SchedThread.IsRunning = true;
|
||||
|
||||
PrintDbgThreadInfo(Thread, "resuming execution...");
|
||||
|
||||
return;
|
||||
|
@ -291,6 +306,8 @@ namespace Ryujinx.HLE.OsHle.Handles
|
|||
{
|
||||
PrintDbgThreadInfo(SchedThread.Thread, "running.");
|
||||
}
|
||||
|
||||
SchedThread.IsRunning = true;
|
||||
}
|
||||
|
||||
public void Resort(KThread Thread)
|
||||
|
|
|
@ -29,6 +29,8 @@ namespace Ryujinx.HLE.OsHle.Handles
|
|||
|
||||
public int WaitHandle { get; set; }
|
||||
|
||||
public long LastPc { get; set; }
|
||||
|
||||
public int ThreadId => Thread.ThreadId;
|
||||
|
||||
public KThread(
|
||||
|
|
|
@ -11,6 +11,8 @@ namespace Ryujinx.HLE.OsHle.Handles
|
|||
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
public bool IsRunning { get; set; }
|
||||
|
||||
public AutoResetEvent WaitSync { get; private set; }
|
||||
public ManualResetEvent WaitActivity { get; private set; }
|
||||
public AutoResetEvent WaitSched { get; private set; }
|
||||
|
|
|
@ -13,5 +13,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
public const int Canceled = 118;
|
||||
public const int CountOutOfRange = 119;
|
||||
public const int InvalidInfo = 120;
|
||||
public const int InvalidThread = 122;
|
||||
public const int InvalidState = 125;
|
||||
}
|
||||
}
|
|
@ -72,7 +72,8 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
{ 0x29, SvcGetInfo },
|
||||
{ 0x2c, SvcMapPhysicalMemory },
|
||||
{ 0x2d, SvcUnmapPhysicalMemory },
|
||||
{ 0x32, SvcSetThreadActivity }
|
||||
{ 0x32, SvcSetThreadActivity },
|
||||
{ 0x33, SvcGetThreadContext3 }
|
||||
};
|
||||
|
||||
this.Ns = Ns;
|
||||
|
|
|
@ -280,5 +280,116 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
||||
}
|
||||
}
|
||||
|
||||
private void SvcGetThreadContext3(AThreadState ThreadState)
|
||||
{
|
||||
long Position = (long)ThreadState.X0;
|
||||
int Handle = (int)ThreadState.X1;
|
||||
|
||||
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
||||
|
||||
if (Thread == null)
|
||||
{
|
||||
Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
|
||||
|
||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Process.GetThread(ThreadState.Tpidr) == Thread)
|
||||
{
|
||||
Ns.Log.PrintWarning(LogClass.KernelSvc, $"Thread handle 0x{Handle:x8} is current thread!");
|
||||
|
||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidThread);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Process.Scheduler.IsThreadRunning(Thread))
|
||||
{
|
||||
Ns.Log.PrintWarning(LogClass.KernelSvc, $"Thread handle 0x{Handle:x8} is running!");
|
||||
|
||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Memory.WriteUInt64(Position + 0x0, ThreadState.X0);
|
||||
Memory.WriteUInt64(Position + 0x8, ThreadState.X1);
|
||||
Memory.WriteUInt64(Position + 0x10, ThreadState.X2);
|
||||
Memory.WriteUInt64(Position + 0x18, ThreadState.X3);
|
||||
Memory.WriteUInt64(Position + 0x20, ThreadState.X4);
|
||||
Memory.WriteUInt64(Position + 0x28, ThreadState.X5);
|
||||
Memory.WriteUInt64(Position + 0x30, ThreadState.X6);
|
||||
Memory.WriteUInt64(Position + 0x38, ThreadState.X7);
|
||||
Memory.WriteUInt64(Position + 0x40, ThreadState.X8);
|
||||
Memory.WriteUInt64(Position + 0x48, ThreadState.X9);
|
||||
Memory.WriteUInt64(Position + 0x50, ThreadState.X10);
|
||||
Memory.WriteUInt64(Position + 0x58, ThreadState.X11);
|
||||
Memory.WriteUInt64(Position + 0x60, ThreadState.X12);
|
||||
Memory.WriteUInt64(Position + 0x68, ThreadState.X13);
|
||||
Memory.WriteUInt64(Position + 0x70, ThreadState.X14);
|
||||
Memory.WriteUInt64(Position + 0x78, ThreadState.X15);
|
||||
Memory.WriteUInt64(Position + 0x80, ThreadState.X16);
|
||||
Memory.WriteUInt64(Position + 0x88, ThreadState.X17);
|
||||
Memory.WriteUInt64(Position + 0x90, ThreadState.X18);
|
||||
Memory.WriteUInt64(Position + 0x98, ThreadState.X19);
|
||||
Memory.WriteUInt64(Position + 0xa0, ThreadState.X20);
|
||||
Memory.WriteUInt64(Position + 0xa8, ThreadState.X21);
|
||||
Memory.WriteUInt64(Position + 0xb0, ThreadState.X22);
|
||||
Memory.WriteUInt64(Position + 0xb8, ThreadState.X23);
|
||||
Memory.WriteUInt64(Position + 0xc0, ThreadState.X24);
|
||||
Memory.WriteUInt64(Position + 0xc8, ThreadState.X25);
|
||||
Memory.WriteUInt64(Position + 0xd0, ThreadState.X26);
|
||||
Memory.WriteUInt64(Position + 0xd8, ThreadState.X27);
|
||||
Memory.WriteUInt64(Position + 0xe0, ThreadState.X28);
|
||||
Memory.WriteUInt64(Position + 0xe8, ThreadState.X29);
|
||||
Memory.WriteUInt64(Position + 0xf0, ThreadState.X30);
|
||||
Memory.WriteUInt64(Position + 0xf8, ThreadState.X31);
|
||||
|
||||
Memory.WriteInt64(Position + 0x100, Thread.LastPc);
|
||||
|
||||
Memory.WriteUInt64(Position + 0x108, (ulong)ThreadState.Psr);
|
||||
|
||||
Memory.WriteVector128(Position + 0x110, ThreadState.V0);
|
||||
Memory.WriteVector128(Position + 0x120, ThreadState.V1);
|
||||
Memory.WriteVector128(Position + 0x130, ThreadState.V2);
|
||||
Memory.WriteVector128(Position + 0x140, ThreadState.V3);
|
||||
Memory.WriteVector128(Position + 0x150, ThreadState.V4);
|
||||
Memory.WriteVector128(Position + 0x160, ThreadState.V5);
|
||||
Memory.WriteVector128(Position + 0x170, ThreadState.V6);
|
||||
Memory.WriteVector128(Position + 0x180, ThreadState.V7);
|
||||
Memory.WriteVector128(Position + 0x190, ThreadState.V8);
|
||||
Memory.WriteVector128(Position + 0x1a0, ThreadState.V9);
|
||||
Memory.WriteVector128(Position + 0x1b0, ThreadState.V10);
|
||||
Memory.WriteVector128(Position + 0x1c0, ThreadState.V11);
|
||||
Memory.WriteVector128(Position + 0x1d0, ThreadState.V12);
|
||||
Memory.WriteVector128(Position + 0x1e0, ThreadState.V13);
|
||||
Memory.WriteVector128(Position + 0x1f0, ThreadState.V14);
|
||||
Memory.WriteVector128(Position + 0x200, ThreadState.V15);
|
||||
Memory.WriteVector128(Position + 0x210, ThreadState.V16);
|
||||
Memory.WriteVector128(Position + 0x220, ThreadState.V17);
|
||||
Memory.WriteVector128(Position + 0x230, ThreadState.V18);
|
||||
Memory.WriteVector128(Position + 0x240, ThreadState.V19);
|
||||
Memory.WriteVector128(Position + 0x250, ThreadState.V20);
|
||||
Memory.WriteVector128(Position + 0x260, ThreadState.V21);
|
||||
Memory.WriteVector128(Position + 0x270, ThreadState.V22);
|
||||
Memory.WriteVector128(Position + 0x280, ThreadState.V23);
|
||||
Memory.WriteVector128(Position + 0x290, ThreadState.V24);
|
||||
Memory.WriteVector128(Position + 0x2a0, ThreadState.V25);
|
||||
Memory.WriteVector128(Position + 0x2b0, ThreadState.V26);
|
||||
Memory.WriteVector128(Position + 0x2c0, ThreadState.V27);
|
||||
Memory.WriteVector128(Position + 0x2d0, ThreadState.V28);
|
||||
Memory.WriteVector128(Position + 0x2e0, ThreadState.V29);
|
||||
Memory.WriteVector128(Position + 0x2f0, ThreadState.V30);
|
||||
Memory.WriteVector128(Position + 0x300, ThreadState.V31);
|
||||
|
||||
Memory.WriteInt32(Position + 0x310, ThreadState.Fpcr);
|
||||
Memory.WriteInt32(Position + 0x314, ThreadState.Fpsr);
|
||||
Memory.WriteInt64(Position + 0x318, ThreadState.Tpidr);
|
||||
|
||||
ThreadState.X0 = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -205,6 +205,8 @@ namespace Ryujinx.HLE.OsHle
|
|||
|
||||
KThread Thread = new KThread(CpuThread, this, ProcessorId, Priority);
|
||||
|
||||
Thread.LastPc = EntryPoint;
|
||||
|
||||
int Handle = HandleTable.OpenHandle(Thread);
|
||||
|
||||
int ThreadId = GetFreeTlsSlot(CpuThread);
|
||||
|
|
Loading…
Reference in a new issue