aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Decoders
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/Decoders
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/Decoders')
-rw-r--r--ChocolArm64/Decoders/Block.cs35
-rw-r--r--ChocolArm64/Decoders/Cond.cs22
-rw-r--r--ChocolArm64/Decoders/DataOp.cs10
-rw-r--r--ChocolArm64/Decoders/Decoder.cs239
-rw-r--r--ChocolArm64/Decoders/DecoderHelper.cs107
-rw-r--r--ChocolArm64/Decoders/IOpCode64.cs13
-rw-r--r--ChocolArm64/Decoders/IOpCodeAlu64.cs10
-rw-r--r--ChocolArm64/Decoders/IOpCodeAluImm64.cs7
-rw-r--r--ChocolArm64/Decoders/IOpCodeAluRs64.cs10
-rw-r--r--ChocolArm64/Decoders/IOpCodeAluRx64.cs10
-rw-r--r--ChocolArm64/Decoders/IOpCodeCond64.cs7
-rw-r--r--ChocolArm64/Decoders/IOpCodeLit64.cs11
-rw-r--r--ChocolArm64/Decoders/IOpCodeSimd64.cs7
-rw-r--r--ChocolArm64/Decoders/IntType.cs14
-rw-r--r--ChocolArm64/Decoders/OpCode64.cs40
-rw-r--r--ChocolArm64/Decoders/OpCodeAdr64.cs18
-rw-r--r--ChocolArm64/Decoders/OpCodeAlu64.cs24
-rw-r--r--ChocolArm64/Decoders/OpCodeAluImm64.cs39
-rw-r--r--ChocolArm64/Decoders/OpCodeAluRs64.cs29
-rw-r--r--ChocolArm64/Decoders/OpCodeAluRx64.cs19
-rw-r--r--ChocolArm64/Decoders/OpCodeBImm64.cs11
-rw-r--r--ChocolArm64/Decoders/OpCodeBImmAl64.cs12
-rw-r--r--ChocolArm64/Decoders/OpCodeBImmCmp64.cs21
-rw-r--r--ChocolArm64/Decoders/OpCodeBImmCond64.cs25
-rw-r--r--ChocolArm64/Decoders/OpCodeBImmTest64.cs20
-rw-r--r--ChocolArm64/Decoders/OpCodeBReg64.cs24
-rw-r--r--ChocolArm64/Decoders/OpCodeBfm64.cs29
-rw-r--r--ChocolArm64/Decoders/OpCodeCcmp64.cs31
-rw-r--r--ChocolArm64/Decoders/OpCodeCcmpImm64.cs11
-rw-r--r--ChocolArm64/Decoders/OpCodeCcmpReg64.cs15
-rw-r--r--ChocolArm64/Decoders/OpCodeCsel64.cs17
-rw-r--r--ChocolArm64/Decoders/OpCodeException64.cs14
-rw-r--r--ChocolArm64/Decoders/OpCodeMem64.cs19
-rw-r--r--ChocolArm64/Decoders/OpCodeMemEx64.cs16
-rw-r--r--ChocolArm64/Decoders/OpCodeMemImm64.cs53
-rw-r--r--ChocolArm64/Decoders/OpCodeMemLit64.cs28
-rw-r--r--ChocolArm64/Decoders/OpCodeMemPair64.cs25
-rw-r--r--ChocolArm64/Decoders/OpCodeMemReg64.cs20
-rw-r--r--ChocolArm64/Decoders/OpCodeMov64.cs36
-rw-r--r--ChocolArm64/Decoders/OpCodeMul64.cs16
-rw-r--r--ChocolArm64/Decoders/OpCodeSimd64.cs25
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdCvt64.cs31
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdExt64.cs14
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdFcond64.cs17
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdFmov64.cs33
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdImm64.cs101
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdIns64.cs36
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemImm64.cs19
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemLit64.cs31
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemMs64.cs49
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemPair64.cs16
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemReg64.cs14
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdMemSs64.cs98
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdReg64.cs18
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdRegElem64.cs31
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs33
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdShImm64.cs16
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdTbl64.cs12
-rw-r--r--ChocolArm64/Decoders/OpCodeSystem64.cs24
-rw-r--r--ChocolArm64/Decoders/ShiftType.cs10
60 files changed, 1742 insertions, 0 deletions
diff --git a/ChocolArm64/Decoders/Block.cs b/ChocolArm64/Decoders/Block.cs
new file mode 100644
index 00000000..c89ea7c6
--- /dev/null
+++ b/ChocolArm64/Decoders/Block.cs
@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+
+namespace ChocolArm64.Decoders
+{
+ class Block
+ {
+ public long Position { get; set; }
+ public long EndPosition { get; set; }
+
+ public Block Next { get; set; }
+ public Block Branch { get; set; }
+
+ public List<OpCode64> OpCodes { get; private set; }
+
+ public Block()
+ {
+ OpCodes = new List<OpCode64>();
+ }
+
+ public Block(long position) : this()
+ {
+ Position = position;
+ }
+
+ public OpCode64 GetLastOp()
+ {
+ if (OpCodes.Count > 0)
+ {
+ return OpCodes[OpCodes.Count - 1];
+ }
+
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/Cond.cs b/ChocolArm64/Decoders/Cond.cs
new file mode 100644
index 00000000..57e12cd6
--- /dev/null
+++ b/ChocolArm64/Decoders/Cond.cs
@@ -0,0 +1,22 @@
+namespace ChocolArm64.Decoders
+{
+ enum Cond
+ {
+ Eq = 0,
+ Ne = 1,
+ GeUn = 2,
+ LtUn = 3,
+ Mi = 4,
+ Pl = 5,
+ Vs = 6,
+ Vc = 7,
+ GtUn = 8,
+ LeUn = 9,
+ Ge = 10,
+ Lt = 11,
+ Gt = 12,
+ Le = 13,
+ Al = 14,
+ Nv = 15
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/DataOp.cs b/ChocolArm64/Decoders/DataOp.cs
new file mode 100644
index 00000000..b7768bb4
--- /dev/null
+++ b/ChocolArm64/Decoders/DataOp.cs
@@ -0,0 +1,10 @@
+namespace ChocolArm64.Decoders
+{
+ enum DataOp
+ {
+ Adr = 0,
+ Arithmetic = 1,
+ Logical = 2,
+ BitField = 3
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/Decoder.cs b/ChocolArm64/Decoders/Decoder.cs
new file mode 100644
index 00000000..db43ac4f
--- /dev/null
+++ b/ChocolArm64/Decoders/Decoder.cs
@@ -0,0 +1,239 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.Memory;
+using ChocolArm64.State;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Decoders
+{
+ static class Decoder
+ {
+ private delegate object OpActivator(Inst inst, long position, int opCode);
+
+ private static ConcurrentDictionary<Type, OpActivator> _opActivators;
+
+ static Decoder()
+ {
+ _opActivators = new ConcurrentDictionary<Type, OpActivator>();
+ }
+
+ public static Block DecodeBasicBlock(CpuThreadState state, MemoryManager memory, long start)
+ {
+ Block block = new Block(start);
+
+ FillBlock(state, memory, block);
+
+ return block;
+ }
+
+ public static (Block[] Graph, Block Root) DecodeSubroutine(
+ TranslatorCache cache,
+ CpuThreadState state,
+ MemoryManager memory,
+ long start)
+ {
+ Dictionary<long, Block> visited = new Dictionary<long, Block>();
+ Dictionary<long, Block> visitedEnd = new Dictionary<long, Block>();
+
+ Queue<Block> blocks = new Queue<Block>();
+
+ Block Enqueue(long position)
+ {
+ if (!visited.TryGetValue(position, out Block output))
+ {
+ output = new Block(position);
+
+ blocks.Enqueue(output);
+
+ visited.Add(position, output);
+ }
+
+ return output;
+ }
+
+ Block root = Enqueue(start);
+
+ while (blocks.Count > 0)
+ {
+ Block current = blocks.Dequeue();
+
+ FillBlock(state, memory, current);
+
+ //Set child blocks. "Branch" is the block the branch instruction
+ //points to (when taken), "Next" is the block at the next address,
+ //executed when the branch is not taken. For Unconditional Branches
+ //(except BL/BLR that are sub calls) or end of executable, Next is null.
+ if (current.OpCodes.Count > 0)
+ {
+ bool hasCachedSub = false;
+
+ OpCode64 lastOp = current.GetLastOp();
+
+ if (lastOp is OpCodeBImm64 op)
+ {
+ if (op.Emitter == InstEmit.Bl)
+ {
+ hasCachedSub = cache.HasSubroutine(op.Imm);
+ }
+ else
+ {
+ current.Branch = Enqueue(op.Imm);
+ }
+ }
+
+ if (!((lastOp is OpCodeBImmAl64) ||
+ (lastOp is OpCodeBReg64)) || hasCachedSub)
+ {
+ current.Next = Enqueue(current.EndPosition);
+ }
+ }
+
+ //If we have on the graph two blocks with the same end position,
+ //then we need to split the bigger block and have two small blocks,
+ //the end position of the bigger "Current" block should then be == to
+ //the position of the "Smaller" block.
+ while (visitedEnd.TryGetValue(current.EndPosition, out Block smaller))
+ {
+ if (current.Position > smaller.Position)
+ {
+ Block temp = smaller;
+
+ smaller = current;
+ current = temp;
+ }
+
+ current.EndPosition = smaller.Position;
+ current.Next = smaller;
+ current.Branch = null;
+
+ current.OpCodes.RemoveRange(
+ current.OpCodes.Count - smaller.OpCodes.Count,
+ smaller.OpCodes.Count);
+
+ visitedEnd[smaller.EndPosition] = smaller;
+ }
+
+ visitedEnd.Add(current.EndPosition, current);
+ }
+
+ //Make and sort Graph blocks array by position.
+ Block[] graph = new Block[visited.Count];
+
+ while (visited.Count > 0)
+ {
+ ulong firstPos = ulong.MaxValue;
+
+ foreach (Block block in visited.Values)
+ {
+ if (firstPos > (ulong)block.Position)
+ firstPos = (ulong)block.Position;
+ }
+
+ Block current = visited[(long)firstPos];
+
+ do
+ {
+ graph[graph.Length - visited.Count] = current;
+
+ visited.Remove(current.Position);
+
+ current = current.Next;
+ }
+ while (current != null);
+ }
+
+ return (graph, root);
+ }
+
+ private static void FillBlock(CpuThreadState state, MemoryManager memory, Block block)
+ {
+ long position = block.Position;
+
+ OpCode64 opCode;
+
+ do
+ {
+ //TODO: This needs to be changed to support both AArch32 and AArch64,
+ //once JIT support is introduced on AArch32 aswell.
+ opCode = DecodeOpCode(state, memory, position);
+
+ block.OpCodes.Add(opCode);
+
+ position += 4;
+ }
+ while (!(IsBranch(opCode) || IsException(opCode)));
+
+ block.EndPosition = position;
+ }
+
+ private static bool IsBranch(OpCode64 opCode)
+ {
+ return opCode is OpCodeBImm64 ||
+ opCode is OpCodeBReg64;
+ }
+
+ private static bool IsException(OpCode64 opCode)
+ {
+ return opCode.Emitter == InstEmit.Brk ||
+ opCode.Emitter == InstEmit.Svc ||
+ opCode.Emitter == InstEmit.Und;
+ }
+
+ public static OpCode64 DecodeOpCode(CpuThreadState state, MemoryManager memory, long position)
+ {
+ int opCode = memory.ReadInt32(position);
+
+ Inst inst;
+
+ if (state.ExecutionMode == ExecutionMode.AArch64)
+ {
+ inst = OpCodeTable.GetInstA64(opCode);
+ }
+ else
+ {
+ //TODO: Thumb support.
+ inst = OpCodeTable.GetInstA32(opCode);
+ }
+
+ OpCode64 decodedOpCode = new OpCode64(Inst.Undefined, position, opCode);
+
+ if (inst.Type != null)
+ {
+ decodedOpCode = MakeOpCode(inst.Type, inst, position, opCode);
+ }
+
+ return decodedOpCode;
+ }
+
+ private static OpCode64 MakeOpCode(Type type, Inst inst, long position, int opCode)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ OpActivator createInstance = _opActivators.GetOrAdd(type, CacheOpActivator);
+
+ return (OpCode64)createInstance(inst, position, opCode);
+ }
+
+ private static OpActivator CacheOpActivator(Type type)
+ {
+ Type[] argTypes = new Type[] { typeof(Inst), typeof(long), 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 (OpActivator)mthd.CreateDelegate(typeof(OpActivator));
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/DecoderHelper.cs b/ChocolArm64/Decoders/DecoderHelper.cs
new file mode 100644
index 00000000..6ee279d7
--- /dev/null
+++ b/ChocolArm64/Decoders/DecoderHelper.cs
@@ -0,0 +1,107 @@
+using System;
+
+namespace ChocolArm64.Decoders
+{
+ static class DecoderHelper
+ {
+ public struct BitMask
+ {
+ public long WMask;
+ public long TMask;
+ public int Pos;
+ public int Shift;
+ public bool IsUndefined;
+
+ public static BitMask Invalid => new BitMask { IsUndefined = true };
+ }
+
+ public static BitMask DecodeBitMask(int opCode, bool immediate)
+ {
+ int immS = (opCode >> 10) & 0x3f;
+ int immR = (opCode >> 16) & 0x3f;
+
+ int n = (opCode >> 22) & 1;
+ int sf = (opCode >> 31) & 1;
+
+ int length = BitUtils.HighestBitSet32((~immS & 0x3f) | (n << 6));
+
+ if (length < 1 || (sf == 0 && n != 0))
+ {
+ return BitMask.Invalid;
+ }
+
+ int size = 1 << length;
+
+ int levels = size - 1;
+
+ int s = immS & levels;
+ int r = immR & levels;
+
+ if (immediate && s == levels)
+ {
+ return BitMask.Invalid;
+ }
+
+ long wMask = BitUtils.FillWithOnes(s + 1);
+ long tMask = BitUtils.FillWithOnes(((s - r) & levels) + 1);
+
+ if (r > 0)
+ {
+ wMask = BitUtils.RotateRight(wMask, r, size);
+ wMask &= BitUtils.FillWithOnes(size);
+ }
+
+ return new BitMask()
+ {
+ WMask = BitUtils.Replicate(wMask, size),
+ TMask = BitUtils.Replicate(tMask, size),
+
+ Pos = immS,
+ Shift = immR
+ };
+ }
+
+ public static long DecodeImm8Float(long imm, int size)
+ {
+ int e = 0, f = 0;
+
+ switch (size)
+ {
+ case 0: e = 8; f = 23; break;
+ case 1: e = 11; f = 52; break;
+
+ default: throw new ArgumentOutOfRangeException(nameof(size));
+ }
+
+ long value = (imm & 0x3f) << f - 4;
+
+ long eBit = (imm >> 6) & 1;
+ long sBit = (imm >> 7) & 1;
+
+ if (eBit != 0)
+ {
+ value |= (1L << e - 3) - 1 << f + 2;
+ }
+
+ value |= (eBit ^ 1) << f + e - 1;
+ value |= sBit << f + e;
+
+ return value;
+ }
+
+ public static long DecodeImm26_2(int opCode)
+ {
+ return ((long)opCode << 38) >> 36;
+ }
+
+ public static long DecodeImmS19_2(int opCode)
+ {
+ return (((long)opCode << 40) >> 43) & ~3;
+ }
+
+ public static long DecodeImmS14_2(int opCode)
+ {
+ return (((long)opCode << 45) >> 48) & ~3;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/IOpCode64.cs b/ChocolArm64/Decoders/IOpCode64.cs
new file mode 100644
index 00000000..e9407123
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCode64.cs
@@ -0,0 +1,13 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ interface IOpCode64
+ {
+ long Position { get; }
+
+ InstEmitter Emitter { get; }
+ RegisterSize RegisterSize { get; }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/IOpCodeAlu64.cs b/ChocolArm64/Decoders/IOpCodeAlu64.cs
new file mode 100644
index 00000000..b9a5fe9e
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeAlu64.cs
@@ -0,0 +1,10 @@
+namespace ChocolArm64.Decoders
+{
+ interface IOpCodeAlu64 : IOpCode64
+ {
+ int Rd { get; }
+ int Rn { get; }
+
+ DataOp DataOp { get; }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/IOpCodeAluImm64.cs b/ChocolArm64/Decoders/IOpCodeAluImm64.cs
new file mode 100644
index 00000000..4b305e27
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeAluImm64.cs
@@ -0,0 +1,7 @@
+namespace ChocolArm64.Decoders
+{
+ interface IOpCodeAluImm64 : IOpCodeAlu64
+ {
+ long Imm { get; }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/IOpCodeAluRs64.cs b/ChocolArm64/Decoders/IOpCodeAluRs64.cs
new file mode 100644
index 00000000..df503ae9
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeAluRs64.cs
@@ -0,0 +1,10 @@
+namespace ChocolArm64.Decoders
+{
+ interface IOpCodeAluRs64 : IOpCodeAlu64
+ {
+ int Shift { get; }
+ int Rm { get; }
+
+ ShiftType ShiftType { get; }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/IOpCodeAluRx64.cs b/ChocolArm64/Decoders/IOpCodeAluRx64.cs
new file mode 100644
index 00000000..f41fc4d2
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeAluRx64.cs
@@ -0,0 +1,10 @@
+namespace ChocolArm64.Decoders
+{
+ interface IOpCodeAluRx64 : IOpCodeAlu64
+ {
+ int Shift { get; }
+ int Rm { get; }
+
+ IntType IntType { get; }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/IOpCodeCond64.cs b/ChocolArm64/Decoders/IOpCodeCond64.cs
new file mode 100644
index 00000000..9c39d633
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeCond64.cs
@@ -0,0 +1,7 @@
+namespace ChocolArm64.Decoders
+{
+ interface IOpCodeCond64 : IOpCode64
+ {
+ Cond Cond { get; }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/IOpCodeLit64.cs b/ChocolArm64/Decoders/IOpCodeLit64.cs
new file mode 100644
index 00000000..c6dc2c7f
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeLit64.cs
@@ -0,0 +1,11 @@
+namespace ChocolArm64.Decoders
+{
+ interface IOpCodeLit64 : IOpCode64
+ {
+ int Rt { get; }
+ long Imm { get; }
+ int Size { get; }
+ bool Signed { get; }
+ bool Prefetch { get; }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/IOpCodeSimd64.cs b/ChocolArm64/Decoders/IOpCodeSimd64.cs
new file mode 100644
index 00000000..fc8f54d6
--- /dev/null
+++ b/ChocolArm64/Decoders/IOpCodeSimd64.cs
@@ -0,0 +1,7 @@
+namespace ChocolArm64.Decoders
+{
+ interface IOpCodeSimd64 : IOpCode64
+ {
+ int Size { get; }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/IntType.cs b/ChocolArm64/Decoders/IntType.cs
new file mode 100644
index 00000000..70f833ec
--- /dev/null
+++ b/ChocolArm64/Decoders/IntType.cs
@@ -0,0 +1,14 @@
+namespace ChocolArm64.Decoders
+{
+ enum IntType
+ {
+ UInt8 = 0,
+ UInt16 = 1,
+ UInt32 = 2,
+ UInt64 = 3,
+ Int8 = 4,
+ Int16 = 5,
+ Int32 = 6,
+ Int64 = 7
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCode64.cs b/ChocolArm64/Decoders/OpCode64.cs
new file mode 100644
index 00000000..b2dc363b
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCode64.cs
@@ -0,0 +1,40 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+using System;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCode64 : IOpCode64
+ {
+ public long Position { get; private set; }
+ public int RawOpCode { get; private set; }
+
+ public InstEmitter Emitter { get; protected set; }
+ public InstInterpreter Interpreter { get; protected set; }
+ public RegisterSize RegisterSize { get; protected set; }
+
+ public OpCode64(Inst inst, long position, int opCode)
+ {
+ Position = position;
+ RawOpCode = opCode;
+
+ RegisterSize = RegisterSize.Int64;
+
+ Emitter = inst.Emitter;
+ Interpreter = inst.Interpreter;
+ }
+
+ public int GetBitsCount()
+ {
+ switch (RegisterSize)
+ {
+ case RegisterSize.Int32: return 32;
+ case RegisterSize.Int64: return 64;
+ case RegisterSize.Simd64: return 64;
+ case RegisterSize.Simd128: return 128;
+ }
+
+ throw new InvalidOperationException();
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeAdr64.cs b/ChocolArm64/Decoders/OpCodeAdr64.cs
new file mode 100644
index 00000000..98b2f07b
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeAdr64.cs
@@ -0,0 +1,18 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeAdr64 : OpCode64
+ {
+ public int Rd { get; private set; }
+ public long Imm { get; private set; }
+
+ public OpCodeAdr64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rd = opCode & 0x1f;
+
+ Imm = DecoderHelper.DecodeImmS19_2(opCode);
+ Imm |= ((long)opCode >> 29) & 3;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeAlu64.cs b/ChocolArm64/Decoders/OpCodeAlu64.cs
new file mode 100644
index 00000000..5f094572
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeAlu64.cs
@@ -0,0 +1,24 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeAlu64 : OpCode64, IOpCodeAlu64
+ {
+ public int Rd { get; protected set; }
+ public int Rn { get; private set; }
+
+ public DataOp DataOp { get; private set; }
+
+ public OpCodeAlu64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rd = (opCode >> 0) & 0x1f;
+ Rn = (opCode >> 5) & 0x1f;
+ DataOp = (DataOp)((opCode >> 24) & 0x3);
+
+ RegisterSize = (opCode >> 31) != 0
+ ? State.RegisterSize.Int64
+ : State.RegisterSize.Int32;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeAluImm64.cs b/ChocolArm64/Decoders/OpCodeAluImm64.cs
new file mode 100644
index 00000000..64ac08a7
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeAluImm64.cs
@@ -0,0 +1,39 @@
+using ChocolArm64.Instructions;
+using System;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeAluImm64 : OpCodeAlu64, IOpCodeAluImm64
+ {
+ public long Imm { get; private set; }
+
+ public OpCodeAluImm64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ if (DataOp == DataOp.Arithmetic)
+ {
+ Imm = (opCode >> 10) & 0xfff;
+
+ int shift = (opCode >> 22) & 3;
+
+ Imm <<= shift * 12;
+ }
+ else if (DataOp == DataOp.Logical)
+ {
+ var bm = DecoderHelper.DecodeBitMask(opCode, true);
+
+ if (bm.IsUndefined)
+ {
+ Emitter = InstEmit.Und;
+
+ return;
+ }
+
+ Imm = bm.WMask;
+ }
+ else
+ {
+ throw new ArgumentException(nameof(opCode));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeAluRs64.cs b/ChocolArm64/Decoders/OpCodeAluRs64.cs
new file mode 100644
index 00000000..f24c7f37
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeAluRs64.cs
@@ -0,0 +1,29 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeAluRs64 : OpCodeAlu64, IOpCodeAluRs64
+ {
+ public int Shift { get; private set; }
+ public int Rm { get; private set; }
+
+ public ShiftType ShiftType { get; private set; }
+
+ public OpCodeAluRs64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ int shift = (opCode >> 10) & 0x3f;
+
+ if (shift >= GetBitsCount())
+ {
+ Emitter = InstEmit.Und;
+
+ return;
+ }
+
+ Shift = shift;
+
+ Rm = (opCode >> 16) & 0x1f;
+ ShiftType = (ShiftType)((opCode >> 22) & 0x3);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeAluRx64.cs b/ChocolArm64/Decoders/OpCodeAluRx64.cs
new file mode 100644
index 00000000..a36f94ca
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeAluRx64.cs
@@ -0,0 +1,19 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeAluRx64 : OpCodeAlu64, IOpCodeAluRx64
+ {
+ public int Shift { get; private set; }
+ public int Rm { get; private set; }
+
+ public IntType IntType { get; private set; }
+
+ public OpCodeAluRx64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Shift = (opCode >> 10) & 0x7;
+ IntType = (IntType)((opCode >> 13) & 0x7);
+ Rm = (opCode >> 16) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeBImm64.cs b/ChocolArm64/Decoders/OpCodeBImm64.cs
new file mode 100644
index 00000000..71c61bab
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBImm64.cs
@@ -0,0 +1,11 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeBImm64 : OpCode64
+ {
+ public long Imm { get; protected set; }
+
+ public OpCodeBImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) { }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeBImmAl64.cs b/ChocolArm64/Decoders/OpCodeBImmAl64.cs
new file mode 100644
index 00000000..f419ffa0
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBImmAl64.cs
@@ -0,0 +1,12 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeBImmAl64 : OpCodeBImm64
+ {
+ public OpCodeBImmAl64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Imm = position + DecoderHelper.DecodeImm26_2(opCode);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeBImmCmp64.cs b/ChocolArm64/Decoders/OpCodeBImmCmp64.cs
new file mode 100644
index 00000000..6f433199
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBImmCmp64.cs
@@ -0,0 +1,21 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeBImmCmp64 : OpCodeBImm64
+ {
+ public int Rt { get; private set; }
+
+ public OpCodeBImmCmp64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rt = opCode & 0x1f;
+
+ Imm = position + DecoderHelper.DecodeImmS19_2(opCode);
+
+ RegisterSize = (opCode >> 31) != 0
+ ? State.RegisterSize.Int64
+ : State.RegisterSize.Int32;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeBImmCond64.cs b/ChocolArm64/Decoders/OpCodeBImmCond64.cs
new file mode 100644
index 00000000..22702309
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBImmCond64.cs
@@ -0,0 +1,25 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeBImmCond64 : OpCodeBImm64, IOpCodeCond64
+ {
+ public Cond Cond { get; private set; }
+
+ public OpCodeBImmCond64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ int o0 = (opCode >> 4) & 1;
+
+ if (o0 != 0)
+ {
+ Emitter = InstEmit.Und;
+
+ return;
+ }
+
+ Cond = (Cond)(opCode & 0xf);
+
+ Imm = position + DecoderHelper.DecodeImmS19_2(opCode);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeBImmTest64.cs b/ChocolArm64/Decoders/OpCodeBImmTest64.cs
new file mode 100644
index 00000000..a2e8baea
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBImmTest64.cs
@@ -0,0 +1,20 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeBImmTest64 : OpCodeBImm64
+ {
+ public int Rt { get; private set; }
+ public int Pos { get; private set; }
+
+ public OpCodeBImmTest64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rt = opCode & 0x1f;
+
+ Imm = position + DecoderHelper.DecodeImmS14_2(opCode);
+
+ Pos = (opCode >> 19) & 0x1f;
+ Pos |= (opCode >> 26) & 0x20;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeBReg64.cs b/ChocolArm64/Decoders/OpCodeBReg64.cs
new file mode 100644
index 00000000..74dbff58
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBReg64.cs
@@ -0,0 +1,24 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeBReg64 : OpCode64
+ {
+ public int Rn { get; private set; }
+
+ public OpCodeBReg64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ int op4 = (opCode >> 0) & 0x1f;
+ int op2 = (opCode >> 16) & 0x1f;
+
+ if (op2 != 0b11111 || op4 != 0b00000)
+ {
+ Emitter = InstEmit.Und;
+
+ return;
+ }
+
+ Rn = (opCode >> 5) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeBfm64.cs b/ChocolArm64/Decoders/OpCodeBfm64.cs
new file mode 100644
index 00000000..6891a8f4
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeBfm64.cs
@@ -0,0 +1,29 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeBfm64 : OpCodeAlu64
+ {
+ public long WMask { get; private set; }
+ public long TMask { get; private set; }
+ public int Pos { get; private set; }
+ public int Shift { get; private set; }
+
+ public OpCodeBfm64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ var bm = DecoderHelper.DecodeBitMask(opCode, false);
+
+ if (bm.IsUndefined)
+ {
+ Emitter = InstEmit.Und;
+
+ return;
+ }
+
+ WMask = bm.WMask;
+ TMask = bm.TMask;
+ Pos = bm.Pos;
+ Shift = bm.Shift;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeCcmp64.cs b/ChocolArm64/Decoders/OpCodeCcmp64.cs
new file mode 100644
index 00000000..e2aae96d
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeCcmp64.cs
@@ -0,0 +1,31 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeCcmp64 : OpCodeAlu64, IOpCodeCond64
+ {
+ public int Nzcv { get; private set; }
+ protected int RmImm;
+
+ public Cond Cond { get; private set; }
+
+ public OpCodeCcmp64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ int o3 = (opCode >> 4) & 1;
+
+ if (o3 != 0)
+ {
+ Emitter = InstEmit.Und;
+
+ return;
+ }
+
+ Nzcv = (opCode >> 0) & 0xf;
+ Cond = (Cond)((opCode >> 12) & 0xf);
+ RmImm = (opCode >> 16) & 0x1f;
+
+ Rd = CpuThreadState.ZrIndex;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeCcmpImm64.cs b/ChocolArm64/Decoders/OpCodeCcmpImm64.cs
new file mode 100644
index 00000000..78d5de55
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeCcmpImm64.cs
@@ -0,0 +1,11 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeCcmpImm64 : OpCodeCcmp64, IOpCodeAluImm64
+ {
+ public long Imm => RmImm;
+
+ public OpCodeCcmpImm64(Inst inst, long position, int opCode) : base(inst, position, opCode) { }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeCcmpReg64.cs b/ChocolArm64/Decoders/OpCodeCcmpReg64.cs
new file mode 100644
index 00000000..a0544d98
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeCcmpReg64.cs
@@ -0,0 +1,15 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeCcmpReg64 : OpCodeCcmp64, IOpCodeAluRs64
+ {
+ public int Rm => RmImm;
+
+ public int Shift => 0;
+
+ public ShiftType ShiftType => ShiftType.Lsl;
+
+ public OpCodeCcmpReg64(Inst inst, long position, int opCode) : base(inst, position, opCode) { }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeCsel64.cs b/ChocolArm64/Decoders/OpCodeCsel64.cs
new file mode 100644
index 00000000..d085a823
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeCsel64.cs
@@ -0,0 +1,17 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeCsel64 : OpCodeAlu64, IOpCodeCond64
+ {
+ public int Rm { get; private set; }
+
+ public Cond Cond { get; private set; }
+
+ public OpCodeCsel64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rm = (opCode >> 16) & 0x1f;
+ Cond = (Cond)((opCode >> 12) & 0xf);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeException64.cs b/ChocolArm64/Decoders/OpCodeException64.cs
new file mode 100644
index 00000000..2554124c
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeException64.cs
@@ -0,0 +1,14 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeException64 : OpCode64
+ {
+ public int Id { get; private set; }
+
+ public OpCodeException64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Id = (opCode >> 5) & 0xffff;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeMem64.cs b/ChocolArm64/Decoders/OpCodeMem64.cs
new file mode 100644
index 00000000..36e67583
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMem64.cs
@@ -0,0 +1,19 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeMem64 : OpCode64
+ {
+ public int Rt { get; protected set; }
+ public int Rn { get; protected set; }
+ public int Size { get; protected set; }
+ public bool Extend64 { get; protected set; }
+
+ public OpCodeMem64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rt = (opCode >> 0) & 0x1f;
+ Rn = (opCode >> 5) & 0x1f;
+ Size = (opCode >> 30) & 0x3;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeMemEx64.cs b/ChocolArm64/Decoders/OpCodeMemEx64.cs
new file mode 100644
index 00000000..39935eb3
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMemEx64.cs
@@ -0,0 +1,16 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeMemEx64 : OpCodeMem64
+ {
+ public int Rt2 { get; private set; }
+ public int Rs { get; private set; }
+
+ public OpCodeMemEx64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rt2 = (opCode >> 10) & 0x1f;
+ Rs = (opCode >> 16) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeMemImm64.cs b/ChocolArm64/Decoders/OpCodeMemImm64.cs
new file mode 100644
index 00000000..edaa4970
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMemImm64.cs
@@ -0,0 +1,53 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeMemImm64 : OpCodeMem64
+ {
+ public long Imm { get; protected set; }
+ public bool WBack { get; protected set; }
+ public bool PostIdx { get; protected set; }
+ protected bool Unscaled { get; private set; }
+
+ private enum MemOp
+ {
+ Unscaled = 0,
+ PostIndexed = 1,
+ Unprivileged = 2,
+ PreIndexed = 3,
+ Unsigned
+ }
+
+ public OpCodeMemImm64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Extend64 = ((opCode >> 22) & 3) == 2;
+ WBack = ((opCode >> 24) & 1) == 0;
+
+ //The type is not valid for the Unsigned Immediate 12-bits encoding,
+ //because the bits 11:10 are used for the larger Immediate offset.
+ MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned;
+
+ PostIdx = type == MemOp.PostIndexed;
+ Unscaled = type == MemOp.Unscaled ||
+ type == MemOp.Unprivileged;
+
+ //Unscaled and Unprivileged doesn't write back,
+ //but they do use the 9-bits Signed Immediate.
+ if (Unscaled)
+ {
+ WBack = false;
+ }
+
+ if (WBack || Unscaled)
+ {
+ //9-bits Signed Immediate.
+ Imm = (opCode << 43) >> 55;
+ }
+ else
+ {
+ //12-bits Unsigned Immediate.
+ Imm = ((opCode >> 10) & 0xfff) << Size;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeMemLit64.cs b/ChocolArm64/Decoders/OpCodeMemLit64.cs
new file mode 100644
index 00000000..29bfeee3
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMemLit64.cs
@@ -0,0 +1,28 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeMemLit64 : OpCode64, IOpCodeLit64
+ {
+ public int Rt { get; private set; }
+ public long Imm { get; private set; }
+ public int Size { get; private set; }
+ public bool Signed { get; private set; }
+ public bool Prefetch { get; private set; }
+
+ public OpCodeMemLit64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rt = opCode & 0x1f;
+
+ Imm = position + DecoderHelper.DecodeImmS19_2(opCode);
+
+ switch ((opCode >> 30) & 3)
+ {
+ case 0: Size = 2; Signed = false; Prefetch = false; break;
+ case 1: Size = 3; Signed = false; Prefetch = false; break;
+ case 2: Size = 2; Signed = true; Prefetch = false; break;
+ case 3: Size = 0; Signed = false; Prefetch = true; break;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeMemPair64.cs b/ChocolArm64/Decoders/OpCodeMemPair64.cs
new file mode 100644
index 00000000..5b81c755
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMemPair64.cs
@@ -0,0 +1,25 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeMemPair64 : OpCodeMemImm64
+ {
+ public int Rt2 { get; private set; }
+
+ public OpCodeMemPair64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rt2 = (opCode >> 10) & 0x1f;
+ WBack = ((opCode >> 23) & 0x1) != 0;
+ PostIdx = ((opCode >> 23) & 0x3) == 1;
+ Extend64 = ((opCode >> 30) & 0x3) == 1;
+ Size = ((opCode >> 31) & 0x1) | 2;
+
+ DecodeImm(opCode);
+ }
+
+ protected void DecodeImm(int opCode)
+ {
+ Imm = ((long)(opCode >> 15) << 57) >> (57 - Size);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeMemReg64.cs b/ChocolArm64/Decoders/OpCodeMemReg64.cs
new file mode 100644
index 00000000..3dd210fb
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMemReg64.cs
@@ -0,0 +1,20 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeMemReg64 : OpCodeMem64
+ {
+ public bool Shift { get; private set; }
+ public int Rm { get; private set; }
+
+ public IntType IntType { get; private set; }
+
+ public OpCodeMemReg64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Shift = ((opCode >> 12) & 0x1) != 0;
+ IntType = (IntType)((opCode >> 13) & 0x7);
+ Rm = (opCode >> 16) & 0x1f;
+ Extend64 = ((opCode >> 22) & 0x3) == 2;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeMov64.cs b/ChocolArm64/Decoders/OpCodeMov64.cs
new file mode 100644
index 00000000..f9697854
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMov64.cs
@@ -0,0 +1,36 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeMov64 : OpCode64
+ {
+ public int Rd { get; private set; }
+ public long Imm { get; private set; }
+ public int Pos { get; private set; }
+
+ public OpCodeMov64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ int p1 = (opCode >> 22) & 1;
+ int sf = (opCode >> 31) & 1;
+
+ if (sf == 0 && p1 != 0)
+ {
+ Emitter = InstEmit.Und;
+
+ return;
+ }
+
+ Rd = (opCode >> 0) & 0x1f;
+ Imm = (opCode >> 5) & 0xffff;
+ Pos = (opCode >> 21) & 0x3;
+
+ Pos <<= 4;
+ Imm <<= Pos;
+
+ RegisterSize = (opCode >> 31) != 0
+ ? State.RegisterSize.Int64
+ : State.RegisterSize.Int32;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeMul64.cs b/ChocolArm64/Decoders/OpCodeMul64.cs
new file mode 100644
index 00000000..176b7b93
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeMul64.cs
@@ -0,0 +1,16 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeMul64 : OpCodeAlu64
+ {
+ public int Rm { get; private set; }
+ public int Ra { get; private set; }
+
+ public OpCodeMul64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Ra = (opCode >> 10) & 0x1f;
+ Rm = (opCode >> 16) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimd64.cs b/ChocolArm64/Decoders/OpCodeSimd64.cs
new file mode 100644
index 00000000..a705e489
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimd64.cs
@@ -0,0 +1,25 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimd64 : OpCode64, IOpCodeSimd64
+ {
+ public int Rd { get; private set; }
+ public int Rn { get; private set; }
+ public int Opc { get; private set; }
+ public int Size { get; protected set; }
+
+ public OpCodeSimd64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rd = (opCode >> 0) & 0x1f;
+ Rn = (opCode >> 5) & 0x1f;
+ Opc = (opCode >> 15) & 0x3;
+ Size = (opCode >> 22) & 0x3;
+
+ RegisterSize = ((opCode >> 30) & 1) != 0
+ ? RegisterSize.Simd128
+ : RegisterSize.Simd64;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdCvt64.cs b/ChocolArm64/Decoders/OpCodeSimdCvt64.cs
new file mode 100644
index 00000000..6c68a3af
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdCvt64.cs
@@ -0,0 +1,31 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdCvt64 : OpCodeSimd64
+ {
+ public int FBits { get; private set; }
+
+ public OpCodeSimdCvt64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ //TODO:
+ //Und of Fixed Point variants.
+ int scale = (opCode >> 10) & 0x3f;
+ int sf = (opCode >> 31) & 0x1;
+
+ /*if (Type != SF && !(Type == 2 && SF == 1))
+ {
+ Emitter = AInstEmit.Und;
+
+ return;
+ }*/
+
+ FBits = 64 - scale;
+
+ RegisterSize = sf != 0
+ ? State.RegisterSize.Int64
+ : State.RegisterSize.Int32;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdExt64.cs b/ChocolArm64/Decoders/OpCodeSimdExt64.cs
new file mode 100644
index 00000000..1c57f19c
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdExt64.cs
@@ -0,0 +1,14 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdExt64 : OpCodeSimdReg64
+ {
+ public int Imm4 { get; private set; }
+
+ public OpCodeSimdExt64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Imm4 = (opCode >> 11) & 0xf;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdFcond64.cs b/ChocolArm64/Decoders/OpCodeSimdFcond64.cs
new file mode 100644
index 00000000..b0f1c0eb
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdFcond64.cs
@@ -0,0 +1,17 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdFcond64 : OpCodeSimdReg64, IOpCodeCond64
+ {
+ public int Nzcv { get; private set; }
+
+ public Cond Cond { get; private set; }
+
+ public OpCodeSimdFcond64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Nzcv = (opCode >> 0) & 0xf;
+ Cond = (Cond)((opCode >> 12) & 0xf);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdFmov64.cs b/ChocolArm64/Decoders/OpCodeSimdFmov64.cs
new file mode 100644
index 00000000..6752e185
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdFmov64.cs
@@ -0,0 +1,33 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdFmov64 : OpCode64, IOpCodeSimd64
+ {
+ public int Rd { get; private set; }
+ public long Imm { get; private set; }
+ public int Size { get; private set; }
+
+ public OpCodeSimdFmov64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ int imm5 = (opCode >> 5) & 0x1f;
+ int type = (opCode >> 22) & 0x3;
+
+ if (imm5 != 0b00000 || type > 1)
+ {
+ Emitter = InstEmit.Und;
+
+ return;
+ }
+
+ Size = type;
+
+ long imm;
+
+ Rd = (opCode >> 0) & 0x1f;
+ imm = (opCode >> 13) & 0xff;
+
+ Imm = DecoderHelper.DecodeImm8Float(imm, type);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdImm64.cs b/ChocolArm64/Decoders/OpCodeSimdImm64.cs
new file mode 100644
index 00000000..3ef6a8c6
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdImm64.cs
@@ -0,0 +1,101 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdImm64 : OpCode64, IOpCodeSimd64
+ {
+ public int Rd { get; private set; }
+ public long Imm { get; private set; }
+ public int Size { get; private set; }
+
+ public OpCodeSimdImm64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rd = opCode & 0x1f;
+
+ int cMode = (opCode >> 12) & 0xf;
+ int op = (opCode >> 29) & 0x1;
+
+ int modeLow = cMode & 1;
+ int modeHigh = cMode >> 1;
+
+ long imm;
+
+ imm = ((uint)opCode >> 5) & 0x1f;
+ imm |= ((uint)opCode >> 11) & 0xe0;
+
+ if (modeHigh == 0b111)
+ {
+ Size = modeLow != 0 ? op : 3;
+
+ switch (op | (modeLow << 1))
+ {
+ case 0:
+ //64-bits Immediate.
+ //Transform abcd efgh into abcd efgh abcd efgh ...
+ imm = (long)((ulong)imm * 0x0101010101010101);
+ break;
+
+ case 1:
+ //64-bits Immediate.
+ //Transform abcd efgh into aaaa aaaa bbbb bbbb ...
+ imm = (imm & 0xf0) >> 4 | (imm & 0x0f) << 4;
+ imm = (imm & 0xcc) >> 2 | (imm & 0x33) << 2;
+ imm = (imm & 0xaa) >> 1 | (imm & 0x55) << 1;
+
+ imm = (long)((ulong)imm * 0x8040201008040201);
+ imm = (long)((ulong)imm & 0x8080808080808080);
+
+ imm |= imm >> 4;
+ imm |= imm >> 2;
+ imm |= imm >> 1;
+ break;
+
+ case 2:
+ case 3:
+ //Floating point Immediate.
+ imm = DecoderHelper.DecodeImm8Float(imm, Size);
+ break;
+ }
+ }
+ else if ((modeHigh & 0b110) == 0b100)
+ {
+ //16-bits shifted Immediate.
+ Size = 1; imm <<= (modeHigh & 1) << 3;
+ }
+ else if ((modeHigh & 0b100) == 0b000)
+ {
+ //32-bits shifted Immediate.
+ Size = 2; imm <<= modeHigh << 3;
+ }
+ else if ((modeHigh & 0b111) == 0b110)
+ {
+ //32-bits shifted Immediate (fill with ones).
+ Size = 2; imm = ShlOnes(imm, 8 << modeLow);
+ }
+ else
+ {
+ //8 bits without shift.
+ Size = 0;
+ }
+
+ Imm = imm;
+
+ RegisterSize = ((opCode >> 30) & 1) != 0
+ ? State.RegisterSize.Simd128
+ : State.RegisterSize.Simd64;
+ }
+
+ private static long ShlOnes(long value, int shift)
+ {
+ if (shift != 0)
+ {
+ return value << shift | (long)(ulong.MaxValue >> (64 - shift));
+ }
+ else
+ {
+ return value;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdIns64.cs b/ChocolArm64/Decoders/OpCodeSimdIns64.cs
new file mode 100644
index 00000000..3b25faeb
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdIns64.cs
@@ -0,0 +1,36 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdIns64 : OpCodeSimd64
+ {
+ public int SrcIndex { get; private set; }
+ public int DstIndex { get; private set; }
+
+ public OpCodeSimdIns64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ int imm4 = (opCode >> 11) & 0xf;
+ int imm5 = (opCode >> 16) & 0x1f;
+
+ if (imm5 == 0b10000)
+ {
+ Emitter = InstEmit.Und;
+
+ return;
+ }
+
+ Size = imm5 & -imm5;
+
+ switch (Size)
+ {
+ case 1: Size = 0; break;
+ case 2: Size = 1; break;
+ case 4: Size = 2; break;
+ case 8: Size = 3; break;
+ }
+
+ SrcIndex = imm4 >> Size;
+ DstIndex = imm5 >> (Size + 1);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdMemImm64.cs b/ChocolArm64/Decoders/OpCodeSimdMemImm64.cs
new file mode 100644
index 00000000..9fbab567
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemImm64.cs
@@ -0,0 +1,19 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdMemImm64 : OpCodeMemImm64, IOpCodeSimd64
+ {
+ public OpCodeSimdMemImm64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Size |= (opCode >> 21) & 4;
+
+ if (!WBack && !Unscaled && Size >= 4)
+ {
+ Imm <<= 4;
+ }
+
+ Extend64 = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdMemLit64.cs b/ChocolArm64/Decoders/OpCodeSimdMemLit64.cs
new file mode 100644
index 00000000..c98ffd03
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemLit64.cs
@@ -0,0 +1,31 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdMemLit64 : OpCode64, IOpCodeSimd64, IOpCodeLit64
+ {
+ public int Rt { get; private set; }
+ public long Imm { get; private set; }
+ public int Size { get; private set; }
+ public bool Signed => false;
+ public bool Prefetch => false;
+
+ public OpCodeSimdMemLit64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ int opc = (opCode >> 30) & 3;
+
+ if (opc == 3)
+ {
+ Emitter = InstEmit.Und;
+
+ return;
+ }
+
+ Rt = opCode & 0x1f;
+
+ Imm = position + DecoderHelper.DecodeImmS19_2(opCode);
+
+ Size = opc + 2;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdMemMs64.cs b/ChocolArm64/Decoders/OpCodeSimdMemMs64.cs
new file mode 100644
index 00000000..0748ef43
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemMs64.cs
@@ -0,0 +1,49 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdMemMs64 : OpCodeMemReg64, IOpCodeSimd64
+ {
+ public int Reps { get; private set; }
+ public int SElems { get; private set; }
+ public int Elems { get; private set; }
+ public bool WBack { get; private set; }
+
+ public OpCodeSimdMemMs64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ switch ((opCode >> 12) & 0xf)
+ {
+ case 0b0000: Reps = 1; SElems = 4; break;
+ case 0b0010: Reps = 4; SElems = 1; break;
+ case 0b0100: Reps = 1; SElems = 3; break;
+ case 0b0110: Reps = 3; SElems = 1; break;
+ case 0b0111: Reps = 1; SElems = 1; break;
+ case 0b1000: Reps = 1; SElems = 2; break;
+ case 0b1010: Reps = 2; SElems = 1; break;
+
+ default: inst = Inst.Undefined; return;
+ }
+
+ Size = (opCode >> 10) & 3;
+ WBack = ((opCode >> 23) & 1) != 0;
+
+ bool q = ((opCode >> 30) & 1) != 0;
+
+ if (!q && Size == 3 && SElems != 1)
+ {
+ inst = Inst.Undefined;
+
+ return;
+ }
+
+ Extend64 = false;
+
+ RegisterSize = q
+ ? State.RegisterSize.Simd128
+ : State.RegisterSize.Simd64;
+
+ Elems = (GetBitsCount() >> 3) >> Size;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdMemPair64.cs b/ChocolArm64/Decoders/OpCodeSimdMemPair64.cs
new file mode 100644
index 00000000..1b796742
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemPair64.cs
@@ -0,0 +1,16 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdMemPair64 : OpCodeMemPair64, IOpCodeSimd64
+ {
+ public OpCodeSimdMemPair64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Size = ((opCode >> 30) & 3) + 2;
+
+ Extend64 = false;
+
+ DecodeImm(opCode);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdMemReg64.cs b/ChocolArm64/Decoders/OpCodeSimdMemReg64.cs
new file mode 100644
index 00000000..4ccbbed2
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemReg64.cs
@@ -0,0 +1,14 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdMemReg64 : OpCodeMemReg64, IOpCodeSimd64
+ {
+ public OpCodeSimdMemReg64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Size |= (opCode >> 21) & 4;
+
+ Extend64 = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdMemSs64.cs b/ChocolArm64/Decoders/OpCodeSimdMemSs64.cs
new file mode 100644
index 00000000..07ec8ab7
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdMemSs64.cs
@@ -0,0 +1,98 @@
+using ChocolArm64.Instructions;
+using ChocolArm64.State;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdMemSs64 : OpCodeMemReg64, IOpCodeSimd64
+ {
+ public int SElems { get; private set; }
+ public int Index { get; private set; }
+ public bool Replicate { get; private set; }
+ public bool WBack { get; private set; }
+
+ public OpCodeSimdMemSs64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ int size = (opCode >> 10) & 3;
+ int s = (opCode >> 12) & 1;
+ int sElems = (opCode >> 12) & 2;
+ int scale = (opCode >> 14) & 3;
+ int l = (opCode >> 22) & 1;
+ int q = (opCode >> 30) & 1;
+
+ sElems |= (opCode >> 21) & 1;
+
+ sElems++;
+
+ int index = (q << 3) | (s << 2) | size;
+
+ switch (scale)
+ {
+ case 1:
+ {
+ if ((size & 1) != 0)
+ {
+ inst = Inst.Undefined;
+
+ return;
+ }
+
+ index >>= 1;
+
+ break;
+ }
+
+ case 2:
+ {
+ if ((size & 2) != 0 ||
+ ((size & 1) != 0 && s != 0))
+ {
+ inst = Inst.Undefined;
+
+ return;
+ }
+
+ if ((size & 1) != 0)
+ {
+ index >>= 3;
+
+ scale = 3;
+ }
+ else
+ {
+ index >>= 2;
+ }
+
+ break;
+ }
+
+ case 3:
+ {
+ if (l == 0 || s != 0)
+ {
+ inst = Inst.Undefined;
+
+ return;
+ }
+
+ scale = size;
+
+ Replicate = true;
+
+ break;
+ }
+ }
+
+ Index = index;
+ SElems = sElems;
+ Size = scale;
+
+ Extend64 = false;
+
+ WBack = ((opCode >> 23) & 1) != 0;
+
+ RegisterSize = q != 0
+ ? State.RegisterSize.Simd128
+ : State.RegisterSize.Simd64;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdReg64.cs b/ChocolArm64/Decoders/OpCodeSimdReg64.cs
new file mode 100644
index 00000000..4bf462de
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdReg64.cs
@@ -0,0 +1,18 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdReg64 : OpCodeSimd64
+ {
+ public bool Bit3 { get; private set; }
+ public int Ra { get; private set; }
+ public int Rm { get; protected set; }
+
+ public OpCodeSimdReg64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Bit3 = ((opCode >> 3) & 0x1) != 0;
+ Ra = (opCode >> 10) & 0x1f;
+ Rm = (opCode >> 16) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdRegElem64.cs b/ChocolArm64/Decoders/OpCodeSimdRegElem64.cs
new file mode 100644
index 00000000..04e95861
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdRegElem64.cs
@@ -0,0 +1,31 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdRegElem64 : OpCodeSimdReg64
+ {
+ public int Index { get; private set; }
+
+ public OpCodeSimdRegElem64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ switch (Size)
+ {
+ case 1:
+ Index = (opCode >> 20) & 3 |
+ (opCode >> 9) & 4;
+
+ Rm &= 0xf;
+
+ break;
+
+ case 2:
+ Index = (opCode >> 21) & 1 |
+ (opCode >> 10) & 2;
+
+ break;
+
+ default: Emitter = InstEmit.Und; return;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs b/ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs
new file mode 100644
index 00000000..b5db7345
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdRegElemF64.cs
@@ -0,0 +1,33 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdRegElemF64 : OpCodeSimdReg64
+ {
+ public int Index { get; private set; }
+
+ public OpCodeSimdRegElemF64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ switch ((opCode >> 21) & 3) // sz:L
+ {
+ case 0: // H:0
+ Index = (opCode >> 10) & 2; // 0, 2
+
+ break;
+
+ case 1: // H:1
+ Index = (opCode >> 10) & 2;
+ Index++; // 1, 3
+
+ break;
+
+ case 2: // H
+ Index = (opCode >> 11) & 1; // 0, 1
+
+ break;
+
+ default: Emitter = InstEmit.Und; return;
+ }
+ }
+ }
+}
diff --git a/ChocolArm64/Decoders/OpCodeSimdShImm64.cs b/ChocolArm64/Decoders/OpCodeSimdShImm64.cs
new file mode 100644
index 00000000..d4cd88d1
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdShImm64.cs
@@ -0,0 +1,16 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdShImm64 : OpCodeSimd64
+ {
+ public int Imm { get; private set; }
+
+ public OpCodeSimdShImm64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Imm = (opCode >> 16) & 0x7f;
+
+ Size = BitUtils.HighestBitSetNibble(Imm >> 3);
+ }
+ }
+}
diff --git a/ChocolArm64/Decoders/OpCodeSimdTbl64.cs b/ChocolArm64/Decoders/OpCodeSimdTbl64.cs
new file mode 100644
index 00000000..13cc9090
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSimdTbl64.cs
@@ -0,0 +1,12 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSimdTbl64 : OpCodeSimdReg64
+ {
+ public OpCodeSimdTbl64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Size = ((opCode >> 13) & 3) + 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/OpCodeSystem64.cs b/ChocolArm64/Decoders/OpCodeSystem64.cs
new file mode 100644
index 00000000..41c51565
--- /dev/null
+++ b/ChocolArm64/Decoders/OpCodeSystem64.cs
@@ -0,0 +1,24 @@
+using ChocolArm64.Instructions;
+
+namespace ChocolArm64.Decoders
+{
+ class OpCodeSystem64 : OpCode64
+ {
+ public int Rt { get; private set; }
+ public int Op2 { get; private set; }
+ public int CRm { get; private set; }
+ public int CRn { get; private set; }
+ public int Op1 { get; private set; }
+ public int Op0 { get; private set; }
+
+ public OpCodeSystem64(Inst inst, long position, int opCode) : base(inst, position, opCode)
+ {
+ Rt = (opCode >> 0) & 0x1f;
+ Op2 = (opCode >> 5) & 0x7;
+ CRm = (opCode >> 8) & 0xf;
+ CRn = (opCode >> 12) & 0xf;
+ Op1 = (opCode >> 16) & 0x7;
+ Op0 = ((opCode >> 19) & 0x1) | 2;
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Decoders/ShiftType.cs b/ChocolArm64/Decoders/ShiftType.cs
new file mode 100644
index 00000000..5f6a7a4c
--- /dev/null
+++ b/ChocolArm64/Decoders/ShiftType.cs
@@ -0,0 +1,10 @@
+namespace ChocolArm64.Decoders
+{
+ enum ShiftType
+ {
+ Lsl,
+ Lsr,
+ Asr,
+ Ror
+ }
+} \ No newline at end of file