diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-04-22 01:21:49 -0300 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-04-22 01:22:46 -0300 |
| commit | bd9b1e2c6b912c7cdab55ec6acc063c88a59cff1 (patch) | |
| tree | 077ab8da47828f9fd23893eeefa54c7d8fb2a314 /ChocolArm64 | |
| parent | 4906acdde96c09b4e12a3801a4bacd5233a2f8e6 (diff) | |
Stub a few services, add support for generating call stacks on the CPU
Diffstat (limited to 'ChocolArm64')
| -rw-r--r-- | ChocolArm64/AOptimizations.cs | 2 | ||||
| -rw-r--r-- | ChocolArm64/Instruction/AInstEmitException.cs | 12 | ||||
| -rw-r--r-- | ChocolArm64/Instruction/AInstEmitFlow.cs | 31 | ||||
| -rw-r--r-- | ChocolArm64/State/AThreadState.cs | 30 | ||||
| -rw-r--r-- | ChocolArm64/Translation/AILEmitterCtx.cs | 15 |
5 files changed, 80 insertions, 10 deletions
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<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; @@ -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) |
