AOpCodeTable: Speed up instruction decoding (#284)

This commit is contained in:
Merry 2018-07-19 06:32:37 +01:00 committed by gdkchan
parent 60f2198a1e
commit bdb6cbb435

View file

@ -4,6 +4,7 @@ using ChocolArm64.Instruction;
using ChocolArm64.Instruction32; using ChocolArm64.Instruction32;
using ChocolArm64.State; using ChocolArm64.State;
using System; using System;
using System.Collections.Generic;
namespace ChocolArm64 namespace ChocolArm64
{ {
@ -438,18 +439,43 @@ namespace ChocolArm64
SetA64("0>001110<<0xxxxx001110xxxxxxxxxx", AInstEmit.Zip1_V, typeof(AOpCodeSimdReg)); SetA64("0>001110<<0xxxxx001110xxxxxxxxxx", AInstEmit.Zip1_V, typeof(AOpCodeSimdReg));
SetA64("0>001110<<0xxxxx011110xxxxxxxxxx", AInstEmit.Zip2_V, typeof(AOpCodeSimdReg)); SetA64("0>001110<<0xxxxx011110xxxxxxxxxx", AInstEmit.Zip2_V, typeof(AOpCodeSimdReg));
#endregion #endregion
#region "Generate InstA64FastLookup Table (AArch64)"
var Tmp = new List<InstInfo>[FastLookupSize];
for (int i = 0; i < FastLookupSize; i++)
{
Tmp[i] = new List<InstInfo>();
}
foreach (var Inst in AllInstA64)
{
int Mask = ToFastLookupIndex(Inst.Mask);
int Value = ToFastLookupIndex(Inst.Value);
for (int i = 0; i < FastLookupSize; i++)
{
if ((i & Mask) == Value)
{
Tmp[i].Add(Inst);
}
}
}
for (int i = 0; i < FastLookupSize; i++)
{
InstA64FastLookup[i] = Tmp[i].ToArray();
}
#endregion
} }
private class TreeNode private class InstInfo
{ {
public int Mask; public int Mask;
public int Value; public int Value;
public TreeNode Next;
public AInst Inst; public AInst Inst;
public TreeNode(int Mask, int Value, AInst Inst) public InstInfo(int Mask, int Value, AInst Inst)
{ {
this.Mask = Mask; this.Mask = Mask;
this.Value = Value; this.Value = Value;
@ -457,8 +483,11 @@ namespace ChocolArm64
} }
} }
private static TreeNode InstHeadA32; private static List<InstInfo> AllInstA32 = new List<InstInfo>();
private static TreeNode InstHeadA64; private static List<InstInfo> AllInstA64 = new List<InstInfo>();
private static int FastLookupSize = 0x1000;
private static InstInfo[][] InstA64FastLookup = new InstInfo[FastLookupSize][];
private static void SetA32(string Encoding, AInstInterpreter Interpreter, Type Type) private static void SetA32(string Encoding, AInstInterpreter Interpreter, Type Type)
{ {
@ -519,7 +548,7 @@ namespace ChocolArm64
if (XBits == 0) if (XBits == 0)
{ {
InsertTop(XMask, Value, Inst, Mode); InsertInst(XMask, Value, Inst, Mode);
return; return;
} }
@ -535,55 +564,53 @@ namespace ChocolArm64
if (Mask != Blacklisted) if (Mask != Blacklisted)
{ {
InsertTop(XMask, Value | Mask, Inst, Mode); InsertInst(XMask, Value | Mask, Inst, Mode);
} }
} }
} }
private static void InsertTop( private static void InsertInst(
int XMask, int XMask,
int Value, int Value,
AInst Inst, AInst Inst,
AExecutionMode Mode) AExecutionMode Mode)
{ {
TreeNode Node = new TreeNode(XMask, Value, Inst); InstInfo Info = new InstInfo(XMask, Value, Inst);
if (Mode == AExecutionMode.AArch64) if (Mode == AExecutionMode.AArch64)
{ {
Node.Next = InstHeadA64; AllInstA64.Add(Info);
InstHeadA64 = Node;
} }
else else
{ {
Node.Next = InstHeadA32; AllInstA32.Add(Info);
InstHeadA32 = Node;
} }
} }
public static AInst GetInstA32(int OpCode) public static AInst GetInstA32(int OpCode)
{ {
return GetInst(InstHeadA32, OpCode); return GetInstFromList(AllInstA32, OpCode);
} }
public static AInst GetInstA64(int OpCode) public static AInst GetInstA64(int OpCode)
{ {
return GetInst(InstHeadA64, OpCode); return GetInstFromList(InstA64FastLookup[ToFastLookupIndex(OpCode)], OpCode);
} }
private static AInst GetInst(TreeNode Head, int OpCode) private static int ToFastLookupIndex(int Value)
{ {
TreeNode Node = Head; return ((Value >> 10) & 0x00F) | ((Value >> 18) & 0xFF0);
}
do private static AInst GetInstFromList(IEnumerable<InstInfo> InstList, int OpCode)
{
foreach (var Node in InstList)
{ {
if ((OpCode & Node.Mask) == Node.Value) if ((OpCode & Node.Mask) == Node.Value)
{ {
return Node.Inst; return Node.Inst;
} }
} }
while ((Node = Node.Next) != null);
return AInst.Undefined; return AInst.Undefined;
} }