forked from Mirror/Ryujinx
Move the MakeOp to OpCodeTable class, for reduce the use of ConcurrentDictionary (#996)
This commit is contained in:
parent
8e64984158
commit
31b94f4641
2 changed files with 35 additions and 47 deletions
|
@ -3,9 +3,7 @@ using ARMeilleure.Instructions;
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection.Emit;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Decoders
|
namespace ARMeilleure.Decoders
|
||||||
{
|
{
|
||||||
|
@ -19,15 +17,6 @@ namespace ARMeilleure.Decoders
|
||||||
// For lower code quality translation, we set a lower limit since we're blocking execution.
|
// For lower code quality translation, we set a lower limit since we're blocking execution.
|
||||||
private const int MaxInstsPerFunctionLowCq = 500;
|
private const int MaxInstsPerFunctionLowCq = 500;
|
||||||
|
|
||||||
private delegate object MakeOp(InstDescriptor inst, ulong address, int opCode);
|
|
||||||
|
|
||||||
private static ConcurrentDictionary<Type, MakeOp> _opActivators;
|
|
||||||
|
|
||||||
static Decoder()
|
|
||||||
{
|
|
||||||
_opActivators = new ConcurrentDictionary<Type, MakeOp>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Block[] DecodeBasicBlock(MemoryManager memory, ulong address, ExecutionMode mode)
|
public static Block[] DecodeBasicBlock(MemoryManager memory, ulong address, ExecutionMode mode)
|
||||||
{
|
{
|
||||||
Block block = new Block(address);
|
Block block = new Block(address);
|
||||||
|
@ -319,56 +308,32 @@ namespace ARMeilleure.Decoders
|
||||||
|
|
||||||
InstDescriptor inst;
|
InstDescriptor inst;
|
||||||
|
|
||||||
Type type;
|
OpCodeTable.MakeOp makeOp;
|
||||||
|
|
||||||
if (mode == ExecutionMode.Aarch64)
|
if (mode == ExecutionMode.Aarch64)
|
||||||
{
|
{
|
||||||
(inst, type) = OpCodeTable.GetInstA64(opCode);
|
(inst, makeOp) = OpCodeTable.GetInstA64(opCode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mode == ExecutionMode.Aarch32Arm)
|
if (mode == ExecutionMode.Aarch32Arm)
|
||||||
{
|
{
|
||||||
(inst, type) = OpCodeTable.GetInstA32(opCode);
|
(inst, makeOp) = OpCodeTable.GetInstA32(opCode);
|
||||||
}
|
}
|
||||||
else /* if (mode == ExecutionMode.Aarch32Thumb) */
|
else /* if (mode == ExecutionMode.Aarch32Thumb) */
|
||||||
{
|
{
|
||||||
(inst, type) = OpCodeTable.GetInstT32(opCode);
|
(inst, makeOp) = OpCodeTable.GetInstT32(opCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != null)
|
if (makeOp != null)
|
||||||
{
|
{
|
||||||
return MakeOpCode(inst, type, address, opCode);
|
return (OpCode)makeOp(inst, address, opCode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new OpCode(inst, address, opCode);
|
return new OpCode(inst, address, opCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OpCode MakeOpCode(InstDescriptor inst, Type type, ulong address, int opCode)
|
|
||||||
{
|
|
||||||
MakeOp createInstance = _opActivators.GetOrAdd(type, CacheOpActivator);
|
|
||||||
|
|
||||||
return (OpCode)createInstance(inst, address, opCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MakeOp CacheOpActivator(Type type)
|
|
||||||
{
|
|
||||||
Type[] argTypes = new Type[] { typeof(InstDescriptor), typeof(ulong), typeof(int) };
|
|
||||||
|
|
||||||
DynamicMethod mthd = new DynamicMethod($"Make{type.Name}", type, argTypes);
|
|
||||||
|
|
||||||
ILGenerator generator = mthd.GetILGenerator();
|
|
||||||
|
|
||||||
generator.Emit(OpCodes.Ldarg_0);
|
|
||||||
generator.Emit(OpCodes.Ldarg_1);
|
|
||||||
generator.Emit(OpCodes.Ldarg_2);
|
|
||||||
generator.Emit(OpCodes.Newobj, type.GetConstructor(argTypes));
|
|
||||||
generator.Emit(OpCodes.Ret);
|
|
||||||
|
|
||||||
return (MakeOp)mthd.CreateDelegate(typeof(MakeOp));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,11 +2,14 @@ using ARMeilleure.Instructions;
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
|
||||||
namespace ARMeilleure.Decoders
|
namespace ARMeilleure.Decoders
|
||||||
{
|
{
|
||||||
static class OpCodeTable
|
static class OpCodeTable
|
||||||
{
|
{
|
||||||
|
public delegate object MakeOp(InstDescriptor inst, ulong address, int opCode);
|
||||||
|
|
||||||
private const int FastLookupSize = 0x1000;
|
private const int FastLookupSize = 0x1000;
|
||||||
|
|
||||||
private struct InstInfo
|
private struct InstInfo
|
||||||
|
@ -18,12 +21,32 @@ namespace ARMeilleure.Decoders
|
||||||
|
|
||||||
public Type Type { get; }
|
public Type Type { get; }
|
||||||
|
|
||||||
|
public MakeOp MakeOp { get; }
|
||||||
|
|
||||||
public InstInfo(int mask, int value, InstDescriptor inst, Type type)
|
public InstInfo(int mask, int value, InstDescriptor inst, Type type)
|
||||||
{
|
{
|
||||||
Mask = mask;
|
Mask = mask;
|
||||||
Value = value;
|
Value = value;
|
||||||
Inst = inst;
|
Inst = inst;
|
||||||
Type = type;
|
Type = type;
|
||||||
|
MakeOp = CacheOpActivator(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MakeOp CacheOpActivator(Type type)
|
||||||
|
{
|
||||||
|
Type[] argTypes = new Type[] { typeof(InstDescriptor), typeof(ulong), typeof(int) };
|
||||||
|
|
||||||
|
DynamicMethod mthd = new DynamicMethod($"Make{type.Name}", type, argTypes);
|
||||||
|
|
||||||
|
ILGenerator generator = mthd.GetILGenerator();
|
||||||
|
|
||||||
|
generator.Emit(OpCodes.Ldarg_0);
|
||||||
|
generator.Emit(OpCodes.Ldarg_1);
|
||||||
|
generator.Emit(OpCodes.Ldarg_2);
|
||||||
|
generator.Emit(OpCodes.Newobj, type.GetConstructor(argTypes));
|
||||||
|
generator.Emit(OpCodes.Ret);
|
||||||
|
|
||||||
|
return (MakeOp)mthd.CreateDelegate(typeof(MakeOp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,32 +1057,32 @@ namespace ARMeilleure.Decoders
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (InstDescriptor inst, Type type) GetInstA32(int opCode)
|
public static (InstDescriptor inst, MakeOp makeOp) GetInstA32(int opCode)
|
||||||
{
|
{
|
||||||
return GetInstFromList(_instA32FastLookup[ToFastLookupIndex(opCode)], opCode);
|
return GetInstFromList(_instA32FastLookup[ToFastLookupIndex(opCode)], opCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (InstDescriptor inst, Type type) GetInstT32(int opCode)
|
public static (InstDescriptor inst, MakeOp makeOp) GetInstT32(int opCode)
|
||||||
{
|
{
|
||||||
return GetInstFromList(_instT32FastLookup[ToFastLookupIndex(opCode)], opCode);
|
return GetInstFromList(_instT32FastLookup[ToFastLookupIndex(opCode)], opCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (InstDescriptor inst, Type type) GetInstA64(int opCode)
|
public static (InstDescriptor inst, MakeOp makeOp) GetInstA64(int opCode)
|
||||||
{
|
{
|
||||||
return GetInstFromList(_instA64FastLookup[ToFastLookupIndex(opCode)], opCode);
|
return GetInstFromList(_instA64FastLookup[ToFastLookupIndex(opCode)], opCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (InstDescriptor inst, Type type) GetInstFromList(InstInfo[] insts, int opCode)
|
private static (InstDescriptor inst, MakeOp makeOp) GetInstFromList(InstInfo[] insts, int opCode)
|
||||||
{
|
{
|
||||||
foreach (InstInfo info in insts)
|
foreach (InstInfo info in insts)
|
||||||
{
|
{
|
||||||
if ((opCode & info.Mask) == info.Value)
|
if ((opCode & info.Mask) == info.Value)
|
||||||
{
|
{
|
||||||
return (info.Inst, info.Type);
|
return (info.Inst, info.MakeOp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (new InstDescriptor(InstName.Und, InstEmit.Und), typeof(OpCode));
|
return (new InstDescriptor(InstName.Und, InstEmit.Und), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int ToFastLookupIndex(int value)
|
private static int ToFastLookupIndex(int value)
|
||||||
|
|
Loading…
Reference in a new issue