aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/TranslatedSub.cs
diff options
context:
space:
mode:
authorAlex Barney <thealexbarney@gmail.com>2018-10-30 19:43:02 -0600
committergdkchan <gab.dark.100@gmail.com>2018-10-30 22:43:02 -0300
commit9cb57fb4bb3bbae0ae052a5af4a96a49fc5d864d (patch)
tree0c97425aeb311c142bc92a6fcc503cb2c07d4376 /ChocolArm64/TranslatedSub.cs
parent5a87e58183578f5b84ca8d01cbb76aed11820f78 (diff)
Adjust naming conventions for Ryujinx and ChocolArm64 projects (#484)
* Change naming convention for Ryujinx project * Change naming convention for ChocolArm64 project * Fix NaN * Remove unneeded this. from Ryujinx project * Adjust naming from new PRs * Name changes based on feedback * How did this get removed? * Rebasing fix * Change FP enum case * Remove prefix from ChocolArm64 classes - Part 1 * Remove prefix from ChocolArm64 classes - Part 2 * Fix alignment from last commit's renaming * Rename namespaces * Rename stragglers * Fix alignment * Rename OpCode class * Missed a few * Adjust alignment
Diffstat (limited to 'ChocolArm64/TranslatedSub.cs')
-rw-r--r--ChocolArm64/TranslatedSub.cs150
1 files changed, 150 insertions, 0 deletions
diff --git a/ChocolArm64/TranslatedSub.cs b/ChocolArm64/TranslatedSub.cs
new file mode 100644
index 00000000..8b3ec3f0
--- /dev/null
+++ b/ChocolArm64/TranslatedSub.cs
@@ -0,0 +1,150 @@
+using ChocolArm64.Memory;
+using ChocolArm64.State;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace ChocolArm64
+{
+ class TranslatedSub
+ {
+ private delegate long Aa64Subroutine(CpuThreadState register, MemoryManager memory);
+
+ private const int MinCallCountForReJit = 250;
+
+ private Aa64Subroutine _execDelegate;
+
+ public static int StateArgIdx { get; private set; }
+ public static int MemoryArgIdx { get; private set; }
+
+ public static Type[] FixedArgTypes { get; private set; }
+
+ public DynamicMethod Method { get; private set; }
+
+ public ReadOnlyCollection<Register> Params { get; private set; }
+
+ private HashSet<long> _callers;
+
+ private TranslatedSubType _type;
+
+ private int _callCount;
+
+ private bool _needsReJit;
+
+ public TranslatedSub(DynamicMethod method, List<Register> Params)
+ {
+ if (method == null)
+ {
+ throw new ArgumentNullException(nameof(method));
+ }
+
+ if (Params == null)
+ {
+ throw new ArgumentNullException(nameof(Params));
+ }
+
+ Method = method;
+ this.Params = Params.AsReadOnly();
+
+ _callers = new HashSet<long>();
+
+ PrepareDelegate();
+ }
+
+ static TranslatedSub()
+ {
+ MethodInfo mthdInfo = typeof(Aa64Subroutine).GetMethod("Invoke");
+
+ ParameterInfo[] Params = mthdInfo.GetParameters();
+
+ FixedArgTypes = new Type[Params.Length];
+
+ for (int index = 0; index < Params.Length; index++)
+ {
+ Type paramType = Params[index].ParameterType;
+
+ FixedArgTypes[index] = paramType;
+
+ if (paramType == typeof(CpuThreadState))
+ {
+ StateArgIdx = index;
+ }
+ else if (paramType == typeof(MemoryManager))
+ {
+ MemoryArgIdx = index;
+ }
+ }
+ }
+
+ private void PrepareDelegate()
+ {
+ string name = $"{Method.Name}_Dispatch";
+
+ DynamicMethod mthd = new DynamicMethod(name, typeof(long), FixedArgTypes);
+
+ ILGenerator generator = mthd.GetILGenerator();
+
+ generator.EmitLdargSeq(FixedArgTypes.Length);
+
+ foreach (Register reg in Params)
+ {
+ generator.EmitLdarg(StateArgIdx);
+
+ generator.Emit(OpCodes.Ldfld, reg.GetField());
+ }
+
+ generator.Emit(OpCodes.Call, Method);
+ generator.Emit(OpCodes.Ret);
+
+ _execDelegate = (Aa64Subroutine)mthd.CreateDelegate(typeof(Aa64Subroutine));
+ }
+
+ public bool ShouldReJit()
+ {
+ if (_needsReJit && _callCount < MinCallCountForReJit)
+ {
+ _callCount++;
+
+ return false;
+ }
+
+ return _needsReJit;
+ }
+
+ public long Execute(CpuThreadState threadState, MemoryManager memory)
+ {
+ return _execDelegate(threadState, memory);
+ }
+
+ public void AddCaller(long position)
+ {
+ lock (_callers)
+ {
+ _callers.Add(position);
+ }
+ }
+
+ public long[] GetCallerPositions()
+ {
+ lock (_callers)
+ {
+ return _callers.ToArray();
+ }
+ }
+
+ public void SetType(TranslatedSubType type)
+ {
+ _type = type;
+
+ if (type == TranslatedSubType.SubTier0)
+ {
+ _needsReJit = true;
+ }
+ }
+
+ public void MarkForReJit() => _needsReJit = true;
+ }
+} \ No newline at end of file