From bd9b1e2c6b912c7cdab55ec6acc063c88a59cff1 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 22 Apr 2018 01:21:49 -0300 Subject: Stub a few services, add support for generating call stacks on the CPU --- ChocolArm64/AOptimizations.cs | 2 ++ ChocolArm64/Instruction/AInstEmitException.cs | 12 ++--------- ChocolArm64/Instruction/AInstEmitFlow.cs | 31 +++++++++++++++++++++++++++ ChocolArm64/State/AThreadState.cs | 30 ++++++++++++++++++++++++++ ChocolArm64/Translation/AILEmitterCtx.cs | 15 +++++++++++++ 5 files changed, 80 insertions(+), 10 deletions(-) (limited to 'ChocolArm64') diff --git a/ChocolArm64/AOptimizations.cs b/ChocolArm64/AOptimizations.cs index a3c82dcc..2627c236 100644 --- a/ChocolArm64/AOptimizations.cs +++ b/ChocolArm64/AOptimizations.cs @@ -1,4 +1,6 @@ public static class AOptimizations { public static bool DisableMemoryChecks = false; + + public static bool GenerateCallStack = true; } \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitException.cs b/ChocolArm64/Instruction/AInstEmitException.cs index 3964c949..041e2890 100644 --- a/ChocolArm64/Instruction/AInstEmitException.cs +++ b/ChocolArm64/Instruction/AInstEmitException.cs @@ -8,8 +8,6 @@ namespace ChocolArm64.Instruction { static partial class AInstEmit { - private const BindingFlags Binding = BindingFlags.NonPublic | BindingFlags.Instance; - public static void Brk(AILEmitterCtx Context) { EmitExceptionCall(Context, nameof(AThreadState.OnBreak)); @@ -30,9 +28,7 @@ namespace ChocolArm64.Instruction Context.EmitLdc_I4(Op.Id); - MethodInfo MthdInfo = typeof(AThreadState).GetMethod(MthdName, Binding); - - Context.EmitCall(MthdInfo); + Context.EmitPrivateCall(typeof(AThreadState), MthdName); //Check if the thread should still be running, if it isn't then we return 0 //to force a return to the dispatcher and then exit the thread. @@ -73,11 +69,7 @@ namespace ChocolArm64.Instruction Context.EmitLdc_I8(Op.Position); Context.EmitLdc_I4(Op.RawOpCode); - string MthdName = nameof(AThreadState.OnUndefined); - - MethodInfo MthdInfo = typeof(AThreadState).GetMethod(MthdName, Binding); - - Context.EmitCall(MthdInfo); + Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.OnUndefined)); if (Context.CurrBlock.Next != null) { diff --git a/ChocolArm64/Instruction/AInstEmitFlow.cs b/ChocolArm64/Instruction/AInstEmitFlow.cs index 91262834..89979d05 100644 --- a/ChocolArm64/Instruction/AInstEmitFlow.cs +++ b/ChocolArm64/Instruction/AInstEmitFlow.cs @@ -35,6 +35,14 @@ namespace ChocolArm64.Instruction { AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp; + if (AOptimizations.GenerateCallStack) + { + Context.EmitLdarg(ATranslatedSub.StateArgIdx); + Context.EmitLdc_I8(Op.Imm); + + Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.EnterMethod)); + } + Context.EmitLdc_I(Op.Position + 4); Context.EmitStint(AThreadState.LRIndex); Context.EmitStoreState(); @@ -72,6 +80,14 @@ namespace ChocolArm64.Instruction { AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp; + if (AOptimizations.GenerateCallStack) + { + Context.EmitLdarg(ATranslatedSub.StateArgIdx); + Context.EmitLdintzr(Op.Rn); + + Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.EnterMethod)); + } + Context.EmitLdc_I(Op.Position + 4); Context.EmitStint(AThreadState.LRIndex); Context.EmitStoreState(); @@ -84,6 +100,14 @@ namespace ChocolArm64.Instruction { AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp; + if (AOptimizations.GenerateCallStack) + { + Context.EmitLdarg(ATranslatedSub.StateArgIdx); + Context.EmitLdintzr(Op.Rn); + + Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.JumpMethod)); + } + Context.EmitStoreState(); Context.EmitLdintzr(Op.Rn); @@ -105,6 +129,13 @@ namespace ChocolArm64.Instruction public static void Ret(AILEmitterCtx Context) { + if (AOptimizations.GenerateCallStack) + { + Context.EmitLdarg(ATranslatedSub.StateArgIdx); + + Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.ExitMethod)); + } + Context.EmitStoreState(); Context.EmitLdint(AThreadState.LRIndex); diff --git a/ChocolArm64/State/AThreadState.cs b/ChocolArm64/State/AThreadState.cs index 6f3f62f6..ce127886 100644 --- a/ChocolArm64/State/AThreadState.cs +++ b/ChocolArm64/State/AThreadState.cs @@ -1,5 +1,6 @@ using ChocolArm64.Events; using System; +using System.Collections.Generic; using System.Diagnostics; namespace ChocolArm64.State @@ -56,10 +57,17 @@ namespace ChocolArm64.State public event EventHandler SvcCall; public event EventHandler Undefined; + private Stack CallStack; + private static Stopwatch TickCounter; private static double HostTickFreq; + public AThreadState() + { + CallStack = new Stack(); + } + static AThreadState() { HostTickFreq = 1.0 / Stopwatch.Frequency; @@ -83,5 +91,27 @@ namespace ChocolArm64.State { 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(); + } } } \ No newline at end of file diff --git a/ChocolArm64/Translation/AILEmitterCtx.cs b/ChocolArm64/Translation/AILEmitterCtx.cs index 2f4a67e1..a004a966 100644 --- a/ChocolArm64/Translation/AILEmitterCtx.cs +++ b/ChocolArm64/Translation/AILEmitterCtx.cs @@ -461,6 +461,21 @@ namespace ChocolArm64.Translation EmitCall(ObjType.GetMethod(MthdName)); } + public void EmitPrivateCall(Type ObjType, string MthdName) + { + if (ObjType == null) + { + throw new ArgumentNullException(nameof(ObjType)); + } + + if (MthdName == null) + { + throw new ArgumentNullException(nameof(MthdName)); + } + + EmitCall(ObjType.GetMethod(MthdName, BindingFlags.Instance | BindingFlags.NonPublic)); + } + public void EmitCall(MethodInfo MthdInfo) { if (MthdInfo == null) -- cgit v1.2.3