aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Decoders
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/Decoders')
-rw-r--r--ARMeilleure/Decoders/Block.cs99
-rw-r--r--ARMeilleure/Decoders/Condition.cs32
-rw-r--r--ARMeilleure/Decoders/DataOp.cs10
-rw-r--r--ARMeilleure/Decoders/Decoder.cs351
-rw-r--r--ARMeilleure/Decoders/DecoderHelper.cs113
-rw-r--r--ARMeilleure/Decoders/IOpCode.cs17
-rw-r--r--ARMeilleure/Decoders/IOpCode32.cs9
-rw-r--r--ARMeilleure/Decoders/IOpCode32Alu.cs10
-rw-r--r--ARMeilleure/Decoders/IOpCode32BImm.cs4
-rw-r--r--ARMeilleure/Decoders/IOpCode32BReg.cs7
-rw-r--r--ARMeilleure/Decoders/IOpCode32Mem.cs12
-rw-r--r--ARMeilleure/Decoders/IOpCode32MemMult.cs13
-rw-r--r--ARMeilleure/Decoders/IOpCodeAlu.cs10
-rw-r--r--ARMeilleure/Decoders/IOpCodeAluImm.cs7
-rw-r--r--ARMeilleure/Decoders/IOpCodeAluRs.cs10
-rw-r--r--ARMeilleure/Decoders/IOpCodeAluRx.cs10
-rw-r--r--ARMeilleure/Decoders/IOpCodeBImm.cs7
-rw-r--r--ARMeilleure/Decoders/IOpCodeCond.cs7
-rw-r--r--ARMeilleure/Decoders/IOpCodeLit.cs11
-rw-r--r--ARMeilleure/Decoders/IOpCodeSimd.cs7
-rw-r--r--ARMeilleure/Decoders/InstDescriptor.cs18
-rw-r--r--ARMeilleure/Decoders/InstEmitter.cs6
-rw-r--r--ARMeilleure/Decoders/IntType.cs14
-rw-r--r--ARMeilleure/Decoders/OpCode.cs48
-rw-r--r--ARMeilleure/Decoders/OpCode32.cs21
-rw-r--r--ARMeilleure/Decoders/OpCode32Alu.cs18
-rw-r--r--ARMeilleure/Decoders/OpCode32AluImm.cs21
-rw-r--r--ARMeilleure/Decoders/OpCode32AluRsImm.cs18
-rw-r--r--ARMeilleure/Decoders/OpCode32BImm.cs27
-rw-r--r--ARMeilleure/Decoders/OpCode32BReg.cs12
-rw-r--r--ARMeilleure/Decoders/OpCode32Mem.cs37
-rw-r--r--ARMeilleure/Decoders/OpCode32MemImm.cs10
-rw-r--r--ARMeilleure/Decoders/OpCode32MemImm8.cs13
-rw-r--r--ARMeilleure/Decoders/OpCode32MemMult.cs55
-rw-r--r--ARMeilleure/Decoders/OpCodeAdr.cs17
-rw-r--r--ARMeilleure/Decoders/OpCodeAlu.cs21
-rw-r--r--ARMeilleure/Decoders/OpCodeAluBinary.cs12
-rw-r--r--ARMeilleure/Decoders/OpCodeAluImm.cs38
-rw-r--r--ARMeilleure/Decoders/OpCodeAluRs.cs27
-rw-r--r--ARMeilleure/Decoders/OpCodeAluRx.cs17
-rw-r--r--ARMeilleure/Decoders/OpCodeBImm.cs9
-rw-r--r--ARMeilleure/Decoders/OpCodeBImmAl.cs10
-rw-r--r--ARMeilleure/Decoders/OpCodeBImmCmp.cs18
-rw-r--r--ARMeilleure/Decoders/OpCodeBImmCond.cs23
-rw-r--r--ARMeilleure/Decoders/OpCodeBImmTest.cs18
-rw-r--r--ARMeilleure/Decoders/OpCodeBReg.cs22
-rw-r--r--ARMeilleure/Decoders/OpCodeBfm.cs27
-rw-r--r--ARMeilleure/Decoders/OpCodeCcmp.cs30
-rw-r--r--ARMeilleure/Decoders/OpCodeCcmpImm.cs9
-rw-r--r--ARMeilleure/Decoders/OpCodeCcmpReg.cs13
-rw-r--r--ARMeilleure/Decoders/OpCodeCsel.cs15
-rw-r--r--ARMeilleure/Decoders/OpCodeException.cs12
-rw-r--r--ARMeilleure/Decoders/OpCodeMem.cs17
-rw-r--r--ARMeilleure/Decoders/OpCodeMemEx.cs14
-rw-r--r--ARMeilleure/Decoders/OpCodeMemImm.cs51
-rw-r--r--ARMeilleure/Decoders/OpCodeMemLit.cs26
-rw-r--r--ARMeilleure/Decoders/OpCodeMemPair.cs23
-rw-r--r--ARMeilleure/Decoders/OpCodeMemReg.cs18
-rw-r--r--ARMeilleure/Decoders/OpCodeMov.cs36
-rw-r--r--ARMeilleure/Decoders/OpCodeMul.cs14
-rw-r--r--ARMeilleure/Decoders/OpCodeSimd.cs22
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdCvt.cs19
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdExt.cs12
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdFcond.cs15
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdFmov.cs31
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdImm.cs98
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdIns.cs34
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdMemImm.cs17
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdMemLit.cs29
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdMemMs.cs46
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdMemPair.cs14
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdMemReg.cs12
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdMemSs.cs95
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdReg.cs16
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdRegElem.cs29
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdRegElemF.cs31
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdShImm.cs16
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdTbl.cs10
-rw-r--r--ARMeilleure/Decoders/OpCodeSystem.cs22
-rw-r--r--ARMeilleure/Decoders/OpCodeT16.cs12
-rw-r--r--ARMeilleure/Decoders/OpCodeT16AluImm8.cs20
-rw-r--r--ARMeilleure/Decoders/OpCodeT16BReg.cs12
-rw-r--r--ARMeilleure/Decoders/OpCodeTable.cs787
-rw-r--r--ARMeilleure/Decoders/RegisterSize.cs10
-rw-r--r--ARMeilleure/Decoders/ShiftType.cs10
85 files changed, 3020 insertions, 0 deletions
diff --git a/ARMeilleure/Decoders/Block.cs b/ARMeilleure/Decoders/Block.cs
new file mode 100644
index 00000000..3d13c2d5
--- /dev/null
+++ b/ARMeilleure/Decoders/Block.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+
+namespace ARMeilleure.Decoders
+{
+ class Block
+ {
+ public ulong Address { get; set; }
+ public ulong EndAddress { get; set; }
+
+ public Block Next { get; set; }
+ public Block Branch { get; set; }
+
+ public List<OpCode> OpCodes { get; private set; }
+
+ public Block()
+ {
+ OpCodes = new List<OpCode>();
+ }
+
+ public Block(ulong address) : this()
+ {
+ Address = address;
+ }
+
+ public void Split(Block rightBlock)
+ {
+ int splitIndex = BinarySearch(OpCodes, rightBlock.Address);
+
+ if ((ulong)OpCodes[splitIndex].Address < rightBlock.Address)
+ {
+ splitIndex++;
+ }
+
+ int splitCount = OpCodes.Count - splitIndex;
+
+ if (splitCount <= 0)
+ {
+ throw new ArgumentException("Can't split at right block address.");
+ }
+
+ rightBlock.EndAddress = EndAddress;
+
+ rightBlock.Next = Next;
+ rightBlock.Branch = Branch;
+
+ rightBlock.OpCodes.AddRange(OpCodes.GetRange(splitIndex, splitCount));
+
+ EndAddress = rightBlock.Address;
+
+ Next = rightBlock;
+ Branch = null;
+
+ OpCodes.RemoveRange(splitIndex, splitCount);
+ }
+
+ private static int BinarySearch(List<OpCode> opCodes, ulong address)
+ {
+ int left = 0;
+ int middle = 0;
+ int right = opCodes.Count - 1;
+
+ while (left <= right)
+ {
+ int size = right - left;
+
+ middle = left + (size >> 1);
+
+ OpCode opCode = opCodes[middle];
+
+ if (address == (ulong)opCode.Address)
+ {
+ break;
+ }
+
+ if (address < (ulong)opCode.Address)
+ {
+ right = middle - 1;
+ }
+ else
+ {
+ left = middle + 1;
+ }
+ }
+
+ return middle;
+ }
+
+ public OpCode GetLastOp()
+ {
+ if (OpCodes.Count > 0)
+ {
+ return OpCodes[OpCodes.Count - 1];
+ }
+
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/Condition.cs b/ARMeilleure/Decoders/Condition.cs
new file mode 100644
index 00000000..727f897d
--- /dev/null
+++ b/ARMeilleure/Decoders/Condition.cs
@@ -0,0 +1,32 @@
+namespace ARMeilleure.Decoders
+{
+ enum Condition
+ {
+ 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
+ }
+
+ static class ConditionExtensions
+ {
+ public static Condition Invert(this Condition cond)
+ {
+ // Bit 0 of all conditions is basically a negation bit, so
+ // inverting this bit has the effect of inverting the condition.
+ return (Condition)((int)cond ^ 1);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/DataOp.cs b/ARMeilleure/Decoders/DataOp.cs
new file mode 100644
index 00000000..464d0089
--- /dev/null
+++ b/ARMeilleure/Decoders/DataOp.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.Decoders
+{
+ enum DataOp
+ {
+ Adr = 0,
+ Arithmetic = 1,
+ Logical = 2,
+ BitField = 3
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/Decoder.cs b/ARMeilleure/Decoders/Decoder.cs
new file mode 100644
index 00000000..2311e9e9
--- /dev/null
+++ b/ARMeilleure/Decoders/Decoder.cs
@@ -0,0 +1,351 @@
+using ARMeilleure.Instructions;
+using ARMeilleure.Memory;
+using ARMeilleure.State;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Reflection.Emit;
+
+namespace ARMeilleure.Decoders
+{
+ static class Decoder
+ {
+ 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)
+ {
+ Block block = new Block(address);
+
+ FillBlock(memory, mode, block, ulong.MaxValue);
+
+ return new Block[] { block };
+ }
+
+ public static Block[] DecodeFunction(MemoryManager memory, ulong address, ExecutionMode mode)
+ {
+ List<Block> blocks = new List<Block>();
+
+ Queue<Block> workQueue = new Queue<Block>();
+
+ Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>();
+
+ Block GetBlock(ulong blkAddress)
+ {
+ if (!visited.TryGetValue(blkAddress, out Block block))
+ {
+ block = new Block(blkAddress);
+
+ workQueue.Enqueue(block);
+
+ visited.Add(blkAddress, block);
+ }
+
+ return block;
+ }
+
+ GetBlock(address);
+
+ while (workQueue.TryDequeue(out Block currBlock))
+ {
+ // Check if the current block is inside another block.
+ if (BinarySearch(blocks, currBlock.Address, out int nBlkIndex))
+ {
+ Block nBlock = blocks[nBlkIndex];
+
+ if (nBlock.Address == currBlock.Address)
+ {
+ throw new InvalidOperationException("Found duplicate block address on the list.");
+ }
+
+ nBlock.Split(currBlock);
+
+ blocks.Insert(nBlkIndex + 1, currBlock);
+
+ continue;
+ }
+
+ // If we have a block after the current one, set the limit address.
+ ulong limitAddress = ulong.MaxValue;
+
+ if (nBlkIndex != blocks.Count)
+ {
+ Block nBlock = blocks[nBlkIndex];
+
+ int nextIndex = nBlkIndex + 1;
+
+ if (nBlock.Address < currBlock.Address && nextIndex < blocks.Count)
+ {
+ limitAddress = blocks[nextIndex].Address;
+ }
+ else if (nBlock.Address > currBlock.Address)
+ {
+ limitAddress = blocks[nBlkIndex].Address;
+ }
+ }
+
+ FillBlock(memory, mode, currBlock, limitAddress);
+
+ if (currBlock.OpCodes.Count != 0)
+ {
+ // 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.
+ OpCode lastOp = currBlock.GetLastOp();
+
+ bool isCall = IsCall(lastOp);
+
+ if (lastOp is IOpCodeBImm op && !isCall)
+ {
+ currBlock.Branch = GetBlock((ulong)op.Immediate);
+ }
+
+ if (!IsUnconditionalBranch(lastOp) /*|| isCall*/)
+ {
+ currBlock.Next = GetBlock(currBlock.EndAddress);
+ }
+ }
+
+ // Insert the new block on the list (sorted by address).
+ if (blocks.Count != 0)
+ {
+ Block nBlock = blocks[nBlkIndex];
+
+ blocks.Insert(nBlkIndex + (nBlock.Address < currBlock.Address ? 1 : 0), currBlock);
+ }
+ else
+ {
+ blocks.Add(currBlock);
+ }
+ }
+
+ return blocks.ToArray();
+ }
+
+ private static bool BinarySearch(List<Block> blocks, ulong address, out int index)
+ {
+ index = 0;
+
+ int left = 0;
+ int right = blocks.Count - 1;
+
+ while (left <= right)
+ {
+ int size = right - left;
+
+ int middle = left + (size >> 1);
+
+ Block block = blocks[middle];
+
+ index = middle;
+
+ if (address >= block.Address && address < block.EndAddress)
+ {
+ return true;
+ }
+
+ if (address < block.Address)
+ {
+ right = middle - 1;
+ }
+ else
+ {
+ left = middle + 1;
+ }
+ }
+
+ return false;
+ }
+
+ private static void FillBlock(
+ MemoryManager memory,
+ ExecutionMode mode,
+ Block block,
+ ulong limitAddress)
+ {
+ ulong address = block.Address;
+
+ OpCode opCode;
+
+ do
+ {
+ if (address >= limitAddress)
+ {
+ break;
+ }
+
+ opCode = DecodeOpCode(memory, address, mode);
+
+ block.OpCodes.Add(opCode);
+
+ address += (ulong)opCode.OpCodeSizeInBytes;
+ }
+ while (!(IsBranch(opCode) || IsException(opCode)));
+
+ block.EndAddress = address;
+ }
+
+ private static bool IsBranch(OpCode opCode)
+ {
+ return opCode is OpCodeBImm ||
+ opCode is OpCodeBReg || IsAarch32Branch(opCode);
+ }
+
+ private static bool IsUnconditionalBranch(OpCode opCode)
+ {
+ return opCode is OpCodeBImmAl ||
+ opCode is OpCodeBReg || IsAarch32UnconditionalBranch(opCode);
+ }
+
+ private static bool IsAarch32UnconditionalBranch(OpCode opCode)
+ {
+ if (!(opCode is OpCode32 op))
+ {
+ return false;
+ }
+
+ // Note: On ARM32, most instructions have conditional execution,
+ // so there's no "Always" (unconditional) branch like on ARM64.
+ // We need to check if the condition is "Always" instead.
+ return IsAarch32Branch(op) && op.Cond >= Condition.Al;
+ }
+
+ private static bool IsAarch32Branch(OpCode opCode)
+ {
+ // Note: On ARM32, most ALU operations can write to R15 (PC),
+ // so we must consider such operations as a branch in potential aswell.
+ if (opCode is IOpCode32Alu opAlu && opAlu.Rd == RegisterAlias.Aarch32Pc)
+ {
+ return true;
+ }
+
+ // Same thing for memory operations. We have the cases where PC is a target
+ // register (Rt == 15 or (mask & (1 << 15)) != 0), and cases where there is
+ // a write back to PC (wback == true && Rn == 15), however the later may
+ // be "undefined" depending on the CPU, so compilers should not produce that.
+ if (opCode is IOpCode32Mem || opCode is IOpCode32MemMult)
+ {
+ int rt, rn;
+
+ bool wBack, isLoad;
+
+ if (opCode is IOpCode32Mem opMem)
+ {
+ rt = opMem.Rt;
+ rn = opMem.Rn;
+ wBack = opMem.WBack;
+ isLoad = opMem.IsLoad;
+
+ // For the dual load, we also need to take into account the
+ // case were Rt2 == 15 (PC).
+ if (rt == 14 && opMem.Instruction.Name == InstName.Ldrd)
+ {
+ rt = RegisterAlias.Aarch32Pc;
+ }
+ }
+ else if (opCode is IOpCode32MemMult opMemMult)
+ {
+ const int pcMask = 1 << RegisterAlias.Aarch32Pc;
+
+ rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0;
+ rn = opMemMult.Rn;
+ wBack = opMemMult.PostOffset != 0;
+ isLoad = opMemMult.IsLoad;
+ }
+ else
+ {
+ throw new NotImplementedException($"The type \"{opCode.GetType().Name}\" is not implemented on the decoder.");
+ }
+
+ if ((rt == RegisterAlias.Aarch32Pc && isLoad) ||
+ (rn == RegisterAlias.Aarch32Pc && wBack))
+ {
+ return true;
+ }
+ }
+
+ // Explicit branch instructions.
+ return opCode is IOpCode32BImm ||
+ opCode is IOpCode32BReg;
+ }
+
+ private static bool IsCall(OpCode opCode)
+ {
+ // TODO (CQ): ARM32 support.
+ return opCode.Instruction.Name == InstName.Bl ||
+ opCode.Instruction.Name == InstName.Blr;
+ }
+
+ private static bool IsException(OpCode opCode)
+ {
+ return opCode.Instruction.Name == InstName.Brk ||
+ opCode.Instruction.Name == InstName.Svc ||
+ opCode.Instruction.Name == InstName.Und;
+ }
+
+ public static OpCode DecodeOpCode(MemoryManager memory, ulong address, ExecutionMode mode)
+ {
+ int opCode = memory.ReadInt32((long)address);
+
+ InstDescriptor inst;
+
+ Type type;
+
+ if (mode == ExecutionMode.Aarch64)
+ {
+ (inst, type) = OpCodeTable.GetInstA64(opCode);
+ }
+ else
+ {
+ if (mode == ExecutionMode.Aarch32Arm)
+ {
+ (inst, type) = OpCodeTable.GetInstA32(opCode);
+ }
+ else /* if (mode == ExecutionMode.Aarch32Thumb) */
+ {
+ (inst, type) = OpCodeTable.GetInstT32(opCode);
+ }
+ }
+
+ if (type != null)
+ {
+ return MakeOpCode(inst, type, address, opCode);
+ }
+ else
+ {
+ 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));
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/DecoderHelper.cs b/ARMeilleure/Decoders/DecoderHelper.cs
new file mode 100644
index 00000000..3cbd4912
--- /dev/null
+++ b/ARMeilleure/Decoders/DecoderHelper.cs
@@ -0,0 +1,113 @@
+using ARMeilleure.Common;
+using System;
+
+namespace ARMeilleure.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.HighestBitSet((~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 DecodeImm24_2(int opCode)
+ {
+ return ((long)opCode << 40) >> 38;
+ }
+
+ 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/ARMeilleure/Decoders/IOpCode.cs b/ARMeilleure/Decoders/IOpCode.cs
new file mode 100644
index 00000000..37ba7a4c
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode.cs
@@ -0,0 +1,17 @@
+using ARMeilleure.IntermediateRepresentation;
+
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode
+ {
+ ulong Address { get; }
+
+ InstDescriptor Instruction { get; }
+
+ RegisterSize RegisterSize { get; }
+
+ int GetBitsCount();
+
+ OperandType GetOperandType();
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCode32.cs b/ARMeilleure/Decoders/IOpCode32.cs
new file mode 100644
index 00000000..126c1069
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32.cs
@@ -0,0 +1,9 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32 : IOpCode
+ {
+ Condition Cond { get; }
+
+ uint GetPc();
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCode32Alu.cs b/ARMeilleure/Decoders/IOpCode32Alu.cs
new file mode 100644
index 00000000..72aea30e
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32Alu.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32Alu : IOpCode32
+ {
+ int Rd { get; }
+ int Rn { get; }
+
+ bool SetFlags { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCode32BImm.cs b/ARMeilleure/Decoders/IOpCode32BImm.cs
new file mode 100644
index 00000000..ec7db2c2
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32BImm.cs
@@ -0,0 +1,4 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32BImm : IOpCode32, IOpCodeBImm { }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCode32BReg.cs b/ARMeilleure/Decoders/IOpCode32BReg.cs
new file mode 100644
index 00000000..097ab427
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32BReg.cs
@@ -0,0 +1,7 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32BReg : IOpCode32
+ {
+ int Rm { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCode32Mem.cs b/ARMeilleure/Decoders/IOpCode32Mem.cs
new file mode 100644
index 00000000..0585ab53
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32Mem.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32Mem : IOpCode32
+ {
+ int Rt { get; }
+ int Rn { get; }
+
+ bool WBack { get; }
+
+ bool IsLoad { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCode32MemMult.cs b/ARMeilleure/Decoders/IOpCode32MemMult.cs
new file mode 100644
index 00000000..18fd3f6b
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32MemMult.cs
@@ -0,0 +1,13 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32MemMult : IOpCode32
+ {
+ int Rn { get; }
+
+ int RegisterMask { get; }
+
+ int PostOffset { get; }
+
+ bool IsLoad { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCodeAlu.cs b/ARMeilleure/Decoders/IOpCodeAlu.cs
new file mode 100644
index 00000000..b8c28513
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCodeAlu.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCodeAlu : IOpCode
+ {
+ int Rd { get; }
+ int Rn { get; }
+
+ DataOp DataOp { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCodeAluImm.cs b/ARMeilleure/Decoders/IOpCodeAluImm.cs
new file mode 100644
index 00000000..02f4c997
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCodeAluImm.cs
@@ -0,0 +1,7 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCodeAluImm : IOpCodeAlu
+ {
+ long Immediate { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCodeAluRs.cs b/ARMeilleure/Decoders/IOpCodeAluRs.cs
new file mode 100644
index 00000000..22540b11
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCodeAluRs.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCodeAluRs : IOpCodeAlu
+ {
+ int Shift { get; }
+ int Rm { get; }
+
+ ShiftType ShiftType { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCodeAluRx.cs b/ARMeilleure/Decoders/IOpCodeAluRx.cs
new file mode 100644
index 00000000..9d16be78
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCodeAluRx.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCodeAluRx : IOpCodeAlu
+ {
+ int Shift { get; }
+ int Rm { get; }
+
+ IntType IntType { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCodeBImm.cs b/ARMeilleure/Decoders/IOpCodeBImm.cs
new file mode 100644
index 00000000..958bff28
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCodeBImm.cs
@@ -0,0 +1,7 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCodeBImm : IOpCode
+ {
+ long Immediate { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCodeCond.cs b/ARMeilleure/Decoders/IOpCodeCond.cs
new file mode 100644
index 00000000..9808f7c0
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCodeCond.cs
@@ -0,0 +1,7 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCodeCond : IOpCode
+ {
+ Condition Cond { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCodeLit.cs b/ARMeilleure/Decoders/IOpCodeLit.cs
new file mode 100644
index 00000000..74084a45
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCodeLit.cs
@@ -0,0 +1,11 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCodeLit : IOpCode
+ {
+ int Rt { get; }
+ long Immediate { get; }
+ int Size { get; }
+ bool Signed { get; }
+ bool Prefetch { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCodeSimd.cs b/ARMeilleure/Decoders/IOpCodeSimd.cs
new file mode 100644
index 00000000..056ef045
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCodeSimd.cs
@@ -0,0 +1,7 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCodeSimd : IOpCode
+ {
+ int Size { get; }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/InstDescriptor.cs b/ARMeilleure/Decoders/InstDescriptor.cs
new file mode 100644
index 00000000..ee2b1c2e
--- /dev/null
+++ b/ARMeilleure/Decoders/InstDescriptor.cs
@@ -0,0 +1,18 @@
+using ARMeilleure.Instructions;
+
+namespace ARMeilleure.Decoders
+{
+ struct InstDescriptor
+ {
+ public static InstDescriptor Undefined => new InstDescriptor(InstName.Und, null);
+
+ public InstName Name { get; }
+ public InstEmitter Emitter { get; }
+
+ public InstDescriptor(InstName name, InstEmitter emitter)
+ {
+ Name = name;
+ Emitter = emitter;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/InstEmitter.cs b/ARMeilleure/Decoders/InstEmitter.cs
new file mode 100644
index 00000000..a8b52656
--- /dev/null
+++ b/ARMeilleure/Decoders/InstEmitter.cs
@@ -0,0 +1,6 @@
+using ARMeilleure.Translation;
+
+namespace ARMeilleure.Decoders
+{
+ delegate void InstEmitter(ArmEmitterContext context);
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IntType.cs b/ARMeilleure/Decoders/IntType.cs
new file mode 100644
index 00000000..244e9680
--- /dev/null
+++ b/ARMeilleure/Decoders/IntType.cs
@@ -0,0 +1,14 @@
+namespace ARMeilleure.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/ARMeilleure/Decoders/OpCode.cs b/ARMeilleure/Decoders/OpCode.cs
new file mode 100644
index 00000000..0bfc2456
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode.cs
@@ -0,0 +1,48 @@
+using ARMeilleure.IntermediateRepresentation;
+using System;
+
+namespace ARMeilleure.Decoders
+{
+ class OpCode : IOpCode
+ {
+ public ulong Address { get; private set; }
+ public int RawOpCode { get; private set; }
+
+ public int OpCodeSizeInBytes { get; protected set; } = 4;
+
+ public InstDescriptor Instruction { get; protected set; }
+
+ public RegisterSize RegisterSize { get; protected set; }
+
+ public OpCode(InstDescriptor inst, ulong address, int opCode)
+ {
+ Address = address;
+ RawOpCode = opCode;
+
+ Instruction = inst;
+
+ RegisterSize = RegisterSize.Int64;
+ }
+
+ public int GetPairsCount() => GetBitsCount() / 16;
+ public int GetBytesCount() => GetBitsCount() / 8;
+
+ 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();
+ }
+
+ public OperandType GetOperandType()
+ {
+ return RegisterSize == RegisterSize.Int32 ? OperandType.I32 : OperandType.I64;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32.cs b/ARMeilleure/Decoders/OpCode32.cs
new file mode 100644
index 00000000..20927d5e
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32.cs
@@ -0,0 +1,21 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32 : OpCode
+ {
+ public Condition Cond { get; protected set; }
+
+ public OpCode32(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ RegisterSize = RegisterSize.Int32;
+
+ Cond = (Condition)((uint)opCode >> 28);
+ }
+
+ public uint GetPc()
+ {
+ // Due to backwards compatibility and legacy behavior of ARMv4 CPUs pipeline,
+ // the PC actually points 2 instructions ahead.
+ return (uint)Address + (uint)OpCodeSizeInBytes * 2;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32Alu.cs b/ARMeilleure/Decoders/OpCode32Alu.cs
new file mode 100644
index 00000000..8d03badd
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32Alu.cs
@@ -0,0 +1,18 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32Alu : OpCode32, IOpCode32Alu
+ {
+ public int Rd { get; private set; }
+ public int Rn { get; private set; }
+
+ public bool SetFlags { get; private set; }
+
+ public OpCode32Alu(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rd = (opCode >> 12) & 0xf;
+ Rn = (opCode >> 16) & 0xf;
+
+ SetFlags = ((opCode >> 20) & 1) != 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32AluImm.cs b/ARMeilleure/Decoders/OpCode32AluImm.cs
new file mode 100644
index 00000000..bba03e4d
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32AluImm.cs
@@ -0,0 +1,21 @@
+using ARMeilleure.Common;
+
+namespace ARMeilleure.Decoders
+{
+ class OpCode32AluImm : OpCode32Alu
+ {
+ public int Immediate { get; private set; }
+
+ public bool IsRotated { get; private set; }
+
+ public OpCode32AluImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int value = (opCode >> 0) & 0xff;
+ int shift = (opCode >> 8) & 0xf;
+
+ Immediate = BitUtils.RotateRight(value, shift * 2, 32);
+
+ IsRotated = shift != 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32AluRsImm.cs b/ARMeilleure/Decoders/OpCode32AluRsImm.cs
new file mode 100644
index 00000000..779d6cec
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32AluRsImm.cs
@@ -0,0 +1,18 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32AluRsImm : OpCode32Alu
+ {
+ public int Rm { get; private set; }
+ public int Imm { get; private set; }
+
+ public ShiftType ShiftType { get; private set; }
+
+ public OpCode32AluRsImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rm = (opCode >> 0) & 0xf;
+ Imm = (opCode >> 7) & 0x1f;
+
+ ShiftType = (ShiftType)((opCode >> 5) & 3);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32BImm.cs b/ARMeilleure/Decoders/OpCode32BImm.cs
new file mode 100644
index 00000000..ea6443bc
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32BImm.cs
@@ -0,0 +1,27 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32BImm : OpCode32, IOpCode32BImm
+ {
+ public long Immediate { get; private set; }
+
+ public OpCode32BImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ uint pc = GetPc();
+
+ // When the condition is never, the instruction is BLX to Thumb mode.
+ if (Cond != Condition.Nv)
+ {
+ pc &= ~3u;
+ }
+
+ Immediate = pc + DecoderHelper.DecodeImm24_2(opCode);
+
+ if (Cond == Condition.Nv)
+ {
+ long H = (opCode >> 23) & 2;
+
+ Immediate |= H;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32BReg.cs b/ARMeilleure/Decoders/OpCode32BReg.cs
new file mode 100644
index 00000000..ffb48707
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32BReg.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32BReg : OpCode32, IOpCode32BReg
+ {
+ public int Rm { get; private set; }
+
+ public OpCode32BReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rm = opCode & 0xf;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32Mem.cs b/ARMeilleure/Decoders/OpCode32Mem.cs
new file mode 100644
index 00000000..f4e88d59
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32Mem.cs
@@ -0,0 +1,37 @@
+using ARMeilleure.Instructions;
+
+namespace ARMeilleure.Decoders
+{
+ class OpCode32Mem : OpCode32, IOpCode32Mem
+ {
+ public int Rt { get; private set; }
+ public int Rn { get; private set; }
+
+ public int Immediate { get; protected set; }
+
+ public bool Index { get; private set; }
+ public bool Add { get; private set; }
+ public bool WBack { get; private set; }
+ public bool Unprivileged { get; private set; }
+
+ public bool IsLoad { get; private set; }
+
+ public OpCode32Mem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rt = (opCode >> 12) & 0xf;
+ Rn = (opCode >> 16) & 0xf;
+
+ bool isLoad = (opCode & (1 << 20)) != 0;
+ bool w = (opCode & (1 << 21)) != 0;
+ bool u = (opCode & (1 << 23)) != 0;
+ bool p = (opCode & (1 << 24)) != 0;
+
+ Index = p;
+ Add = u;
+ WBack = !p || w;
+ Unprivileged = !p && w;
+
+ IsLoad = isLoad || inst.Name == InstName.Ldrd;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32MemImm.cs b/ARMeilleure/Decoders/OpCode32MemImm.cs
new file mode 100644
index 00000000..f79c6319
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32MemImm.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32MemImm : OpCode32Mem
+ {
+ public OpCode32MemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Immediate = opCode & 0xfff;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32MemImm8.cs b/ARMeilleure/Decoders/OpCode32MemImm8.cs
new file mode 100644
index 00000000..08027fb7
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32MemImm8.cs
@@ -0,0 +1,13 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32MemImm8 : OpCode32Mem
+ {
+ public OpCode32MemImm8(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int imm4L = (opCode >> 0) & 0xf;
+ int imm4H = (opCode >> 8) & 0xf;
+
+ Immediate = imm4L | (imm4H << 4);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32MemMult.cs b/ARMeilleure/Decoders/OpCode32MemMult.cs
new file mode 100644
index 00000000..b61b50ea
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32MemMult.cs
@@ -0,0 +1,55 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32MemMult : OpCode32, IOpCode32MemMult
+ {
+ public int Rn { get; private set; }
+
+ public int RegisterMask { get; private set; }
+ public int Offset { get; private set; }
+ public int PostOffset { get; private set; }
+
+ public bool IsLoad { get; private set; }
+
+ public OpCode32MemMult(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rn = (opCode >> 16) & 0xf;
+
+ bool isLoad = (opCode & (1 << 20)) != 0;
+ bool w = (opCode & (1 << 21)) != 0;
+ bool u = (opCode & (1 << 23)) != 0;
+ bool p = (opCode & (1 << 24)) != 0;
+
+ RegisterMask = opCode & 0xffff;
+
+ int regsSize = 0;
+
+ for (int index = 0; index < 16; index++)
+ {
+ regsSize += (RegisterMask >> index) & 1;
+ }
+
+ regsSize *= 4;
+
+ if (!u)
+ {
+ Offset -= regsSize;
+ }
+
+ if (u == p)
+ {
+ Offset += 4;
+ }
+
+ if (w)
+ {
+ PostOffset = u ? regsSize : -regsSize;
+ }
+ else
+ {
+ PostOffset = 0;
+ }
+
+ IsLoad = isLoad;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeAdr.cs b/ARMeilleure/Decoders/OpCodeAdr.cs
new file mode 100644
index 00000000..fc8219f6
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeAdr.cs
@@ -0,0 +1,17 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeAdr : OpCode
+ {
+ public int Rd { get; private set; }
+
+ public long Immediate { get; private set; }
+
+ public OpCodeAdr(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rd = opCode & 0x1f;
+
+ Immediate = DecoderHelper.DecodeImmS19_2(opCode);
+ Immediate |= ((long)opCode >> 29) & 3;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeAlu.cs b/ARMeilleure/Decoders/OpCodeAlu.cs
new file mode 100644
index 00000000..171662a0
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeAlu.cs
@@ -0,0 +1,21 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeAlu : OpCode, IOpCodeAlu
+ {
+ public int Rd { get; protected set; }
+ public int Rn { get; private set; }
+
+ public DataOp DataOp { get; private set; }
+
+ public OpCodeAlu(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rd = (opCode >> 0) & 0x1f;
+ Rn = (opCode >> 5) & 0x1f;
+ DataOp = (DataOp)((opCode >> 24) & 0x3);
+
+ RegisterSize = (opCode >> 31) != 0
+ ? RegisterSize.Int64
+ : RegisterSize.Int32;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeAluBinary.cs b/ARMeilleure/Decoders/OpCodeAluBinary.cs
new file mode 100644
index 00000000..2bdf1d79
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeAluBinary.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeAluBinary : OpCodeAlu
+ {
+ public int Rm { get; private set; }
+
+ public OpCodeAluBinary(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rm = (opCode >> 16) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeAluImm.cs b/ARMeilleure/Decoders/OpCodeAluImm.cs
new file mode 100644
index 00000000..35c83fcc
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeAluImm.cs
@@ -0,0 +1,38 @@
+using System;
+
+namespace ARMeilleure.Decoders
+{
+ class OpCodeAluImm : OpCodeAlu, IOpCodeAluImm
+ {
+ public long Immediate { get; private set; }
+
+ public OpCodeAluImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ if (DataOp == DataOp.Arithmetic)
+ {
+ Immediate = (opCode >> 10) & 0xfff;
+
+ int shift = (opCode >> 22) & 3;
+
+ Immediate <<= shift * 12;
+ }
+ else if (DataOp == DataOp.Logical)
+ {
+ var bm = DecoderHelper.DecodeBitMask(opCode, true);
+
+ if (bm.IsUndefined)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ Immediate = bm.WMask;
+ }
+ else
+ {
+ throw new ArgumentException(nameof(opCode));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeAluRs.cs b/ARMeilleure/Decoders/OpCodeAluRs.cs
new file mode 100644
index 00000000..84fb6ac6
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeAluRs.cs
@@ -0,0 +1,27 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeAluRs : OpCodeAlu, IOpCodeAluRs
+ {
+ public int Shift { get; private set; }
+ public int Rm { get; private set; }
+
+ public ShiftType ShiftType { get; private set; }
+
+ public OpCodeAluRs(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int shift = (opCode >> 10) & 0x3f;
+
+ if (shift >= GetBitsCount())
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ Shift = shift;
+
+ Rm = (opCode >> 16) & 0x1f;
+ ShiftType = (ShiftType)((opCode >> 22) & 0x3);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeAluRx.cs b/ARMeilleure/Decoders/OpCodeAluRx.cs
new file mode 100644
index 00000000..5c8d427e
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeAluRx.cs
@@ -0,0 +1,17 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeAluRx : OpCodeAlu, IOpCodeAluRx
+ {
+ public int Shift { get; private set; }
+ public int Rm { get; private set; }
+
+ public IntType IntType { get; private set; }
+
+ public OpCodeAluRx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Shift = (opCode >> 10) & 0x7;
+ IntType = (IntType)((opCode >> 13) & 0x7);
+ Rm = (opCode >> 16) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeBImm.cs b/ARMeilleure/Decoders/OpCodeBImm.cs
new file mode 100644
index 00000000..2821a624
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeBImm.cs
@@ -0,0 +1,9 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeBImm : OpCode, IOpCodeBImm
+ {
+ public long Immediate { get; protected set; }
+
+ public OpCodeBImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeBImmAl.cs b/ARMeilleure/Decoders/OpCodeBImmAl.cs
new file mode 100644
index 00000000..94bcea88
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeBImmAl.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeBImmAl : OpCodeBImm
+ {
+ public OpCodeBImmAl(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Immediate = (long)address + DecoderHelper.DecodeImm26_2(opCode);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeBImmCmp.cs b/ARMeilleure/Decoders/OpCodeBImmCmp.cs
new file mode 100644
index 00000000..2b7c2834
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeBImmCmp.cs
@@ -0,0 +1,18 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeBImmCmp : OpCodeBImm
+ {
+ public int Rt { get; private set; }
+
+ public OpCodeBImmCmp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rt = opCode & 0x1f;
+
+ Immediate = (long)address + DecoderHelper.DecodeImmS19_2(opCode);
+
+ RegisterSize = (opCode >> 31) != 0
+ ? RegisterSize.Int64
+ : RegisterSize.Int32;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeBImmCond.cs b/ARMeilleure/Decoders/OpCodeBImmCond.cs
new file mode 100644
index 00000000..f898821a
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeBImmCond.cs
@@ -0,0 +1,23 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeBImmCond : OpCodeBImm, IOpCodeCond
+ {
+ public Condition Cond { get; private set; }
+
+ public OpCodeBImmCond(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int o0 = (opCode >> 4) & 1;
+
+ if (o0 != 0)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ Cond = (Condition)(opCode & 0xf);
+
+ Immediate = (long)address + DecoderHelper.DecodeImmS19_2(opCode);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeBImmTest.cs b/ARMeilleure/Decoders/OpCodeBImmTest.cs
new file mode 100644
index 00000000..6687c2e7
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeBImmTest.cs
@@ -0,0 +1,18 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeBImmTest : OpCodeBImm
+ {
+ public int Rt { get; private set; }
+ public int Bit { get; private set; }
+
+ public OpCodeBImmTest(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rt = opCode & 0x1f;
+
+ Immediate = (long)address + DecoderHelper.DecodeImmS14_2(opCode);
+
+ Bit = (opCode >> 19) & 0x1f;
+ Bit |= (opCode >> 26) & 0x20;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeBReg.cs b/ARMeilleure/Decoders/OpCodeBReg.cs
new file mode 100644
index 00000000..00c51ec7
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeBReg.cs
@@ -0,0 +1,22 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeBReg : OpCode
+ {
+ public int Rn { get; private set; }
+
+ public OpCodeBReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int op4 = (opCode >> 0) & 0x1f;
+ int op2 = (opCode >> 16) & 0x1f;
+
+ if (op2 != 0b11111 || op4 != 0b00000)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ Rn = (opCode >> 5) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeBfm.cs b/ARMeilleure/Decoders/OpCodeBfm.cs
new file mode 100644
index 00000000..2ae8edf5
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeBfm.cs
@@ -0,0 +1,27 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeBfm : OpCodeAlu
+ {
+ 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 OpCodeBfm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ var bm = DecoderHelper.DecodeBitMask(opCode, false);
+
+ if (bm.IsUndefined)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ WMask = bm.WMask;
+ TMask = bm.TMask;
+ Pos = bm.Pos;
+ Shift = bm.Shift;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeCcmp.cs b/ARMeilleure/Decoders/OpCodeCcmp.cs
new file mode 100644
index 00000000..c302f6a3
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeCcmp.cs
@@ -0,0 +1,30 @@
+using ARMeilleure.State;
+
+namespace ARMeilleure.Decoders
+{
+ class OpCodeCcmp : OpCodeAlu, IOpCodeCond
+ {
+ public int Nzcv { get; private set; }
+ protected int RmImm;
+
+ public Condition Cond { get; private set; }
+
+ public OpCodeCcmp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int o3 = (opCode >> 4) & 1;
+
+ if (o3 != 0)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ Nzcv = (opCode >> 0) & 0xf;
+ Cond = (Condition)((opCode >> 12) & 0xf);
+ RmImm = (opCode >> 16) & 0x1f;
+
+ Rd = RegisterAlias.Zr;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeCcmpImm.cs b/ARMeilleure/Decoders/OpCodeCcmpImm.cs
new file mode 100644
index 00000000..4a2d01f4
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeCcmpImm.cs
@@ -0,0 +1,9 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeCcmpImm : OpCodeCcmp, IOpCodeAluImm
+ {
+ public long Immediate => RmImm;
+
+ public OpCodeCcmpImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeCcmpReg.cs b/ARMeilleure/Decoders/OpCodeCcmpReg.cs
new file mode 100644
index 00000000..0e2b922c
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeCcmpReg.cs
@@ -0,0 +1,13 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeCcmpReg : OpCodeCcmp, IOpCodeAluRs
+ {
+ public int Rm => RmImm;
+
+ public int Shift => 0;
+
+ public ShiftType ShiftType => ShiftType.Lsl;
+
+ public OpCodeCcmpReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeCsel.cs b/ARMeilleure/Decoders/OpCodeCsel.cs
new file mode 100644
index 00000000..fd07e6fd
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeCsel.cs
@@ -0,0 +1,15 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeCsel : OpCodeAlu, IOpCodeCond
+ {
+ public int Rm { get; private set; }
+
+ public Condition Cond { get; private set; }
+
+ public OpCodeCsel(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rm = (opCode >> 16) & 0x1f;
+ Cond = (Condition)((opCode >> 12) & 0xf);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeException.cs b/ARMeilleure/Decoders/OpCodeException.cs
new file mode 100644
index 00000000..9781c543
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeException.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeException : OpCode
+ {
+ public int Id { get; private set; }
+
+ public OpCodeException(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Id = (opCode >> 5) & 0xffff;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeMem.cs b/ARMeilleure/Decoders/OpCodeMem.cs
new file mode 100644
index 00000000..5a7ab482
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeMem.cs
@@ -0,0 +1,17 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeMem : OpCode
+ {
+ 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 OpCodeMem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rt = (opCode >> 0) & 0x1f;
+ Rn = (opCode >> 5) & 0x1f;
+ Size = (opCode >> 30) & 0x3;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeMemEx.cs b/ARMeilleure/Decoders/OpCodeMemEx.cs
new file mode 100644
index 00000000..5956f367
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeMemEx.cs
@@ -0,0 +1,14 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeMemEx : OpCodeMem
+ {
+ public int Rt2 { get; private set; }
+ public int Rs { get; private set; }
+
+ public OpCodeMemEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rt2 = (opCode >> 10) & 0x1f;
+ Rs = (opCode >> 16) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeMemImm.cs b/ARMeilleure/Decoders/OpCodeMemImm.cs
new file mode 100644
index 00000000..517434f2
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeMemImm.cs
@@ -0,0 +1,51 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeMemImm : OpCodeMem
+ {
+ public long Immediate { 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 OpCodeMemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, 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.
+ Immediate = (opCode << 11) >> 23;
+ }
+ else
+ {
+ // 12-bits Unsigned Immediate.
+ Immediate = ((opCode >> 10) & 0xfff) << Size;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeMemLit.cs b/ARMeilleure/Decoders/OpCodeMemLit.cs
new file mode 100644
index 00000000..b80585cb
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeMemLit.cs
@@ -0,0 +1,26 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeMemLit : OpCode, IOpCodeLit
+ {
+ public int Rt { get; private set; }
+ public long Immediate { get; private set; }
+ public int Size { get; private set; }
+ public bool Signed { get; private set; }
+ public bool Prefetch { get; private set; }
+
+ public OpCodeMemLit(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rt = opCode & 0x1f;
+
+ Immediate = (long)address + 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/ARMeilleure/Decoders/OpCodeMemPair.cs b/ARMeilleure/Decoders/OpCodeMemPair.cs
new file mode 100644
index 00000000..ea329a1d
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeMemPair.cs
@@ -0,0 +1,23 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeMemPair : OpCodeMemImm
+ {
+ public int Rt2 { get; private set; }
+
+ public OpCodeMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, 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)
+ {
+ Immediate = ((long)(opCode >> 15) << 57) >> (57 - Size);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeMemReg.cs b/ARMeilleure/Decoders/OpCodeMemReg.cs
new file mode 100644
index 00000000..f5c2f991
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeMemReg.cs
@@ -0,0 +1,18 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeMemReg : OpCodeMem
+ {
+ public bool Shift { get; private set; }
+ public int Rm { get; private set; }
+
+ public IntType IntType { get; private set; }
+
+ public OpCodeMemReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, 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/ARMeilleure/Decoders/OpCodeMov.cs b/ARMeilleure/Decoders/OpCodeMov.cs
new file mode 100644
index 00000000..b65178cf
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeMov.cs
@@ -0,0 +1,36 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeMov : OpCode
+ {
+ public int Rd { get; private set; }
+
+ public long Immediate { get; private set; }
+
+ public int Bit { get; private set; }
+
+ public OpCodeMov(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int p1 = (opCode >> 22) & 1;
+ int sf = (opCode >> 31) & 1;
+
+ if (sf == 0 && p1 != 0)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ Rd = (opCode >> 0) & 0x1f;
+ Immediate = (opCode >> 5) & 0xffff;
+ Bit = (opCode >> 21) & 0x3;
+
+ Bit <<= 4;
+
+ Immediate <<= Bit;
+
+ RegisterSize = (opCode >> 31) != 0
+ ? RegisterSize.Int64
+ : RegisterSize.Int32;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeMul.cs b/ARMeilleure/Decoders/OpCodeMul.cs
new file mode 100644
index 00000000..3eb4dc97
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeMul.cs
@@ -0,0 +1,14 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeMul : OpCodeAlu
+ {
+ public int Rm { get; private set; }
+ public int Ra { get; private set; }
+
+ public OpCodeMul(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Ra = (opCode >> 10) & 0x1f;
+ Rm = (opCode >> 16) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimd.cs b/ARMeilleure/Decoders/OpCodeSimd.cs
new file mode 100644
index 00000000..a258446c
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimd.cs
@@ -0,0 +1,22 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimd : OpCode, IOpCodeSimd
+ {
+ 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 OpCodeSimd(InstDescriptor inst, ulong address, int opCode) : base(inst, address, 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/ARMeilleure/Decoders/OpCodeSimdCvt.cs b/ARMeilleure/Decoders/OpCodeSimdCvt.cs
new file mode 100644
index 00000000..15658bb8
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdCvt.cs
@@ -0,0 +1,19 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdCvt : OpCodeSimd
+ {
+ public int FBits { get; private set; }
+
+ public OpCodeSimdCvt(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int scale = (opCode >> 10) & 0x3f;
+ int sf = (opCode >> 31) & 0x1;
+
+ FBits = 64 - scale;
+
+ RegisterSize = sf != 0
+ ? RegisterSize.Int64
+ : RegisterSize.Int32;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdExt.cs b/ARMeilleure/Decoders/OpCodeSimdExt.cs
new file mode 100644
index 00000000..d585449c
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdExt.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdExt : OpCodeSimdReg
+ {
+ public int Imm4 { get; private set; }
+
+ public OpCodeSimdExt(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Imm4 = (opCode >> 11) & 0xf;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdFcond.cs b/ARMeilleure/Decoders/OpCodeSimdFcond.cs
new file mode 100644
index 00000000..9e7a5f3b
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdFcond.cs
@@ -0,0 +1,15 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdFcond : OpCodeSimdReg, IOpCodeCond
+ {
+ public int Nzcv { get; private set; }
+
+ public Condition Cond { get; private set; }
+
+ public OpCodeSimdFcond(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Nzcv = (opCode >> 0) & 0xf;
+ Cond = (Condition)((opCode >> 12) & 0xf);
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCodeSimdFmov.cs b/ARMeilleure/Decoders/OpCodeSimdFmov.cs
new file mode 100644
index 00000000..61a3f077
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdFmov.cs
@@ -0,0 +1,31 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdFmov : OpCode, IOpCodeSimd
+ {
+ public int Rd { get; private set; }
+ public long Immediate { get; private set; }
+ public int Size { get; private set; }
+
+ public OpCodeSimdFmov(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int imm5 = (opCode >> 5) & 0x1f;
+ int type = (opCode >> 22) & 0x3;
+
+ if (imm5 != 0b00000 || type > 1)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ Size = type;
+
+ long imm;
+
+ Rd = (opCode >> 0) & 0x1f;
+ imm = (opCode >> 13) & 0xff;
+
+ Immediate = DecoderHelper.DecodeImm8Float(imm, type);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdImm.cs b/ARMeilleure/Decoders/OpCodeSimdImm.cs
new file mode 100644
index 00000000..ecad906d
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdImm.cs
@@ -0,0 +1,98 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdImm : OpCode, IOpCodeSimd
+ {
+ public int Rd { get; private set; }
+ public long Immediate { get; private set; }
+ public int Size { get; private set; }
+
+ public OpCodeSimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, 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;
+ }
+
+ Immediate = imm;
+
+ RegisterSize = ((opCode >> 30) & 1) != 0
+ ? RegisterSize.Simd128
+ : 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/ARMeilleure/Decoders/OpCodeSimdIns.cs b/ARMeilleure/Decoders/OpCodeSimdIns.cs
new file mode 100644
index 00000000..78328adb
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdIns.cs
@@ -0,0 +1,34 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdIns : OpCodeSimd
+ {
+ public int SrcIndex { get; private set; }
+ public int DstIndex { get; private set; }
+
+ public OpCodeSimdIns(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int imm4 = (opCode >> 11) & 0xf;
+ int imm5 = (opCode >> 16) & 0x1f;
+
+ if (imm5 == 0b10000)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ 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/ARMeilleure/Decoders/OpCodeSimdMemImm.cs b/ARMeilleure/Decoders/OpCodeSimdMemImm.cs
new file mode 100644
index 00000000..6b9e66d9
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdMemImm.cs
@@ -0,0 +1,17 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdMemImm : OpCodeMemImm, IOpCodeSimd
+ {
+ public OpCodeSimdMemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Size |= (opCode >> 21) & 4;
+
+ if (!WBack && !Unscaled && Size >= 4)
+ {
+ Immediate <<= 4;
+ }
+
+ Extend64 = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdMemLit.cs b/ARMeilleure/Decoders/OpCodeSimdMemLit.cs
new file mode 100644
index 00000000..607df139
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdMemLit.cs
@@ -0,0 +1,29 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdMemLit : OpCode, IOpCodeSimd, IOpCodeLit
+ {
+ public int Rt { get; private set; }
+ public long Immediate { get; private set; }
+ public int Size { get; private set; }
+ public bool Signed => false;
+ public bool Prefetch => false;
+
+ public OpCodeSimdMemLit(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int opc = (opCode >> 30) & 3;
+
+ if (opc == 3)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ Rt = opCode & 0x1f;
+
+ Immediate = (long)address + DecoderHelper.DecodeImmS19_2(opCode);
+
+ Size = opc + 2;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdMemMs.cs b/ARMeilleure/Decoders/OpCodeSimdMemMs.cs
new file mode 100644
index 00000000..9fa5ff42
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdMemMs.cs
@@ -0,0 +1,46 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdMemMs : OpCodeMemReg, IOpCodeSimd
+ {
+ 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 OpCodeSimdMemMs(InstDescriptor inst, ulong address, int opCode) : base(inst, address, 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: Instruction = InstDescriptor.Undefined; return;
+ }
+
+ Size = (opCode >> 10) & 3;
+ WBack = ((opCode >> 23) & 1) != 0;
+
+ bool q = ((opCode >> 30) & 1) != 0;
+
+ if (!q && Size == 3 && SElems != 1)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ Extend64 = false;
+
+ RegisterSize = q
+ ? RegisterSize.Simd128
+ : RegisterSize.Simd64;
+
+ Elems = (GetBitsCount() >> 3) >> Size;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdMemPair.cs b/ARMeilleure/Decoders/OpCodeSimdMemPair.cs
new file mode 100644
index 00000000..a4af49d0
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdMemPair.cs
@@ -0,0 +1,14 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdMemPair : OpCodeMemPair, IOpCodeSimd
+ {
+ public OpCodeSimdMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Size = ((opCode >> 30) & 3) + 2;
+
+ Extend64 = false;
+
+ DecodeImm(opCode);
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdMemReg.cs b/ARMeilleure/Decoders/OpCodeSimdMemReg.cs
new file mode 100644
index 00000000..7b783d63
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdMemReg.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdMemReg : OpCodeMemReg, IOpCodeSimd
+ {
+ public OpCodeSimdMemReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Size |= (opCode >> 21) & 4;
+
+ Extend64 = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdMemSs.cs b/ARMeilleure/Decoders/OpCodeSimdMemSs.cs
new file mode 100644
index 00000000..302decbc
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdMemSs.cs
@@ -0,0 +1,95 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdMemSs : OpCodeMemReg, IOpCodeSimd
+ {
+ 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 OpCodeSimdMemSs(InstDescriptor inst, ulong address, int opCode) : base(inst, address, 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)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ index >>= 1;
+
+ break;
+ }
+
+ case 2:
+ {
+ if ((size & 2) != 0 ||
+ ((size & 1) != 0 && s != 0))
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ if ((size & 1) != 0)
+ {
+ index >>= 3;
+
+ scale = 3;
+ }
+ else
+ {
+ index >>= 2;
+ }
+
+ break;
+ }
+
+ case 3:
+ {
+ if (l == 0 || s != 0)
+ {
+ Instruction = InstDescriptor.Undefined;
+
+ return;
+ }
+
+ scale = size;
+
+ Replicate = true;
+
+ break;
+ }
+ }
+
+ Index = index;
+ SElems = sElems;
+ Size = scale;
+
+ Extend64 = false;
+
+ WBack = ((opCode >> 23) & 1) != 0;
+
+ RegisterSize = q != 0
+ ? RegisterSize.Simd128
+ : RegisterSize.Simd64;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdReg.cs b/ARMeilleure/Decoders/OpCodeSimdReg.cs
new file mode 100644
index 00000000..d076806a
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdReg.cs
@@ -0,0 +1,16 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdReg : OpCodeSimd
+ {
+ public bool Bit3 { get; private set; }
+ public int Ra { get; private set; }
+ public int Rm { get; protected set; }
+
+ public OpCodeSimdReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Bit3 = ((opCode >> 3) & 0x1) != 0;
+ Ra = (opCode >> 10) & 0x1f;
+ Rm = (opCode >> 16) & 0x1f;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdRegElem.cs b/ARMeilleure/Decoders/OpCodeSimdRegElem.cs
new file mode 100644
index 00000000..d2f1583d
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdRegElem.cs
@@ -0,0 +1,29 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdRegElem : OpCodeSimdReg
+ {
+ public int Index { get; private set; }
+
+ public OpCodeSimdRegElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, 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: Instruction = InstDescriptor.Undefined; break;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSimdRegElemF.cs b/ARMeilleure/Decoders/OpCodeSimdRegElemF.cs
new file mode 100644
index 00000000..365b7717
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdRegElemF.cs
@@ -0,0 +1,31 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdRegElemF : OpCodeSimdReg
+ {
+ public int Index { get; private set; }
+
+ public OpCodeSimdRegElemF(InstDescriptor inst, ulong address, int opCode) : base(inst, address, 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: Instruction = InstDescriptor.Undefined; break;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCodeSimdShImm.cs b/ARMeilleure/Decoders/OpCodeSimdShImm.cs
new file mode 100644
index 00000000..d260c4b3
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdShImm.cs
@@ -0,0 +1,16 @@
+using ARMeilleure.Common;
+
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdShImm : OpCodeSimd
+ {
+ public int Imm { get; private set; }
+
+ public OpCodeSimdShImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Imm = (opCode >> 16) & 0x7f;
+
+ Size = BitUtils.HighestBitSetNibble(Imm >> 3);
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCodeSimdTbl.cs b/ARMeilleure/Decoders/OpCodeSimdTbl.cs
new file mode 100644
index 00000000..14fdd648
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdTbl.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSimdTbl : OpCodeSimdReg
+ {
+ public OpCodeSimdTbl(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Size = ((opCode >> 13) & 3) + 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeSystem.cs b/ARMeilleure/Decoders/OpCodeSystem.cs
new file mode 100644
index 00000000..cf7c5cc1
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSystem.cs
@@ -0,0 +1,22 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeSystem : OpCode
+ {
+ 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 OpCodeSystem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, 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/ARMeilleure/Decoders/OpCodeT16.cs b/ARMeilleure/Decoders/OpCodeT16.cs
new file mode 100644
index 00000000..e7b7aff5
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT16.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeT16 : OpCode32
+ {
+ public OpCodeT16(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Cond = Condition.Al;
+
+ OpCodeSizeInBytes = 2;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeT16AluImm8.cs b/ARMeilleure/Decoders/OpCodeT16AluImm8.cs
new file mode 100644
index 00000000..197d3b09
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT16AluImm8.cs
@@ -0,0 +1,20 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeT16AluImm8 : OpCodeT16, IOpCode32Alu
+ {
+ private int _rdn;
+
+ public int Rd => _rdn;
+ public int Rn => _rdn;
+
+ public bool SetFlags => false;
+
+ public int Immediate { get; private set; }
+
+ public OpCodeT16AluImm8(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Immediate = (opCode >> 0) & 0xff;
+ _rdn = (opCode >> 8) & 0x7;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeT16BReg.cs b/ARMeilleure/Decoders/OpCodeT16BReg.cs
new file mode 100644
index 00000000..1fb39759
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT16BReg.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCodeT16BReg : OpCodeT16, IOpCode32BReg
+ {
+ public int Rm { get; private set; }
+
+ public OpCodeT16BReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rm = (opCode >> 3) & 0xf;
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs
new file mode 100644
index 00000000..22c762d6
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeTable.cs
@@ -0,0 +1,787 @@
+using ARMeilleure.Instructions;
+using ARMeilleure.State;
+using System;
+using System.Collections.Generic;
+
+namespace ARMeilleure.Decoders
+{
+ static class OpCodeTable
+ {
+ private const int FastLookupSize = 0x1000;
+
+ private struct InstInfo
+ {
+ public int Mask { get; }
+ public int Value { get; }
+
+ public InstDescriptor Inst { get; }
+
+ public Type Type { get; }
+
+ public InstInfo(int mask, int value, InstDescriptor inst, Type type)
+ {
+ Mask = mask;
+ Value = value;
+ Inst = inst;
+ Type = type;
+ }
+ }
+
+ private static List<InstInfo> _allInstA32 = new List<InstInfo>();
+ private static List<InstInfo> _allInstT32 = new List<InstInfo>();
+ private static List<InstInfo> _allInstA64 = new List<InstInfo>();
+
+ private static InstInfo[][] _instA32FastLookup = new InstInfo[FastLookupSize][];
+ private static InstInfo[][] _instT32FastLookup = new InstInfo[FastLookupSize][];
+ private static InstInfo[][] _instA64FastLookup = new InstInfo[FastLookupSize][];
+
+ static OpCodeTable()
+ {
+#region "OpCode Table (AArch64)"
+ // Base
+ SetA64("x0011010000xxxxx000000xxxxxxxxxx", InstName.Adc, InstEmit.Adc, typeof(OpCodeAluRs));
+ SetA64("x0111010000xxxxx000000xxxxxxxxxx", InstName.Adcs, InstEmit.Adcs, typeof(OpCodeAluRs));
+ SetA64("x00100010xxxxxxxxxxxxxxxxxxxxxxx", InstName.Add, InstEmit.Add, typeof(OpCodeAluImm));
+ SetA64("00001011<<0xxxxx0xxxxxxxxxxxxxxx", InstName.Add, InstEmit.Add, typeof(OpCodeAluRs));
+ SetA64("10001011<<0xxxxxxxxxxxxxxxxxxxxx", InstName.Add, InstEmit.Add, typeof(OpCodeAluRs));
+ SetA64("x0001011001xxxxxxxx0xxxxxxxxxxxx", InstName.Add, InstEmit.Add, typeof(OpCodeAluRx));
+ SetA64("x0001011001xxxxxxxx100xxxxxxxxxx", InstName.Add, InstEmit.Add, typeof(OpCodeAluRx));
+ SetA64("x01100010xxxxxxxxxxxxxxxxxxxxxxx", InstName.Adds, InstEmit.Adds, typeof(OpCodeAluImm));
+ SetA64("00101011<<0xxxxx0xxxxxxxxxxxxxxx", InstName.Adds, InstEmit.Adds, typeof(OpCodeAluRs));
+ SetA64("10101011<<0xxxxxxxxxxxxxxxxxxxxx", InstName.Adds, InstEmit.Adds, typeof(OpCodeAluRs));
+ SetA64("x0101011001xxxxxxxx0xxxxxxxxxxxx", InstName.Adds, InstEmit.Adds, typeof(OpCodeAluRx));
+ SetA64("x0101011001xxxxxxxx100xxxxxxxxxx", InstName.Adds, InstEmit.Adds, typeof(OpCodeAluRx));
+ SetA64("0xx10000xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Adr, InstEmit.Adr, typeof(OpCodeAdr));
+ SetA64("1xx10000xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Adrp, InstEmit.Adrp, typeof(OpCodeAdr));
+ SetA64("0001001000xxxxxxxxxxxxxxxxxxxxxx", InstName.And, InstEmit.And, typeof(OpCodeAluImm));
+ SetA64("100100100xxxxxxxxxxxxxxxxxxxxxxx", InstName.And, InstEmit.And, typeof(OpCodeAluImm));
+ SetA64("00001010xx0xxxxx0xxxxxxxxxxxxxxx", InstName.And, InstEmit.And, typeof(OpCodeAluRs));
+ SetA64("10001010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.And, InstEmit.And, typeof(OpCodeAluRs));
+ SetA64("0111001000xxxxxxxxxxxxxxxxxxxxxx", InstName.Ands, InstEmit.Ands, typeof(OpCodeAluImm));
+ SetA64("111100100xxxxxxxxxxxxxxxxxxxxxxx", InstName.Ands, InstEmit.Ands, typeof(OpCodeAluImm));
+ SetA64("01101010xx0xxxxx0xxxxxxxxxxxxxxx", InstName.Ands, InstEmit.Ands, typeof(OpCodeAluRs));
+ SetA64("11101010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Ands, InstEmit.Ands, typeof(OpCodeAluRs));
+ SetA64("x0011010110xxxxx001010xxxxxxxxxx", InstName.Asrv, InstEmit.Asrv, typeof(OpCodeAluRs));
+ SetA64("000101xxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.B, InstEmit.B, typeof(OpCodeBImmAl));
+ SetA64("01010100xxxxxxxxxxxxxxxxxxx0xxxx", InstName.B_Cond, InstEmit.B_Cond, typeof(OpCodeBImmCond));
+ SetA64("00110011000xxxxx0xxxxxxxxxxxxxxx", InstName.Bfm, InstEmit.Bfm, typeof(OpCodeBfm));
+ SetA64("1011001101xxxxxxxxxxxxxxxxxxxxxx", InstName.Bfm, InstEmit.Bfm, typeof(OpCodeBfm));
+ SetA64("00001010xx1xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit.Bic, typeof(OpCodeAluRs));
+ SetA64("10001010xx1xxxxxxxxxxxxxxxxxxxxx", InstName.Bic, InstEmit.Bic, typeof(OpCodeAluRs));
+ SetA64("01101010xx1xxxxx0xxxxxxxxxxxxxxx", InstName.Bics, InstEmit.Bics, typeof(OpCodeAluRs));
+ SetA64("11101010xx1xxxxxxxxxxxxxxxxxxxxx", InstName.Bics, InstEmit.Bics, typeof(OpCodeAluRs));
+ SetA64("100101xxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bl, InstEmit.Bl, typeof(OpCodeBImmAl));
+ SetA64("1101011000111111000000xxxxx00000", InstName.Blr, InstEmit.Blr, typeof(OpCodeBReg));
+ SetA64("1101011000011111000000xxxxx00000", InstName.Br, InstEmit.Br, typeof(OpCodeBReg));
+ SetA64("11010100001xxxxxxxxxxxxxxxx00000", InstName.Brk, InstEmit.Brk, typeof(OpCodeException));
+ SetA64("x0110101xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cbnz, InstEmit.Cbnz, typeof(OpCodeBImmCmp));
+ SetA64("x0110100xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cbz, InstEmit.Cbz, typeof(OpCodeBImmCmp));
+ SetA64("x0111010010xxxxxxxxx10xxxxx0xxxx", InstName.Ccmn, InstEmit.Ccmn, typeof(OpCodeCcmpImm));
+ SetA64("x0111010010xxxxxxxxx00xxxxx0xxxx", InstName.Ccmn, InstEmit.Ccmn, typeof(OpCodeCcmpReg));
+ SetA64("x1111010010xxxxxxxxx10xxxxx0xxxx", InstName.Ccmp, InstEmit.Ccmp, typeof(OpCodeCcmpImm));
+ SetA64("x1111010010xxxxxxxxx00xxxxx0xxxx", InstName.Ccmp, InstEmit.Ccmp, typeof(OpCodeCcmpReg));
+ SetA64("11010101000000110011xxxx01011111", InstName.Clrex, InstEmit.Clrex, typeof(OpCodeSystem));
+ SetA64("x101101011000000000101xxxxxxxxxx", InstName.Cls, InstEmit.Cls, typeof(OpCodeAlu));
+ SetA64("x101101011000000000100xxxxxxxxxx", InstName.Clz, InstEmit.Clz, typeof(OpCodeAlu));
+ SetA64("00011010110xxxxx010000xxxxxxxxxx", InstName.Crc32b, InstEmit.Crc32b, typeof(OpCodeAluBinary));
+ SetA64("00011010110xxxxx010001xxxxxxxxxx", InstName.Crc32h, InstEmit.Crc32h, typeof(OpCodeAluBinary));
+ SetA64("00011010110xxxxx010010xxxxxxxxxx", InstName.Crc32w, InstEmit.Crc32w, typeof(OpCodeAluBinary));
+ SetA64("10011010110xxxxx010011xxxxxxxxxx", InstName.Crc32x, InstEmit.Crc32x, typeof(OpCodeAluBinary));
+ SetA64("00011010110xxxxx010100xxxxxxxxxx", InstName.Crc32cb, InstEmit.Crc32cb, typeof(OpCodeAluBinary));
+ SetA64("00011010110xxxxx010101xxxxxxxxxx", InstName.Crc32ch, InstEmit.Crc32ch, typeof(OpCodeAluBinary));
+ SetA64("00011010110xxxxx010110xxxxxxxxxx", InstName.Crc32cw, InstEmit.Crc32cw, typeof(OpCodeAluBinary));
+ SetA64("10011010110xxxxx010111xxxxxxxxxx", InstName.Crc32cx, InstEmit.Crc32cx, typeof(OpCodeAluBinary));
+ SetA64("x0011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csel, InstEmit.Csel, typeof(OpCodeCsel));
+ SetA64("x0011010100xxxxxxxxx01xxxxxxxxxx", InstName.Csinc, InstEmit.Csinc, typeof(OpCodeCsel));
+ SetA64("x1011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csinv, InstEmit.Csinv, typeof(OpCodeCsel));
+ SetA64("x1011010100xxxxxxxxx01xxxxxxxxxx", InstName.Csneg, InstEmit.Csneg, typeof(OpCodeCsel));
+ SetA64("11010101000000110011xxxx10111111", InstName.Dmb, InstEmit.Dmb, typeof(OpCodeSystem));
+ SetA64("11010101000000110011xxxx10011111", InstName.Dsb, InstEmit.Dsb, typeof(OpCodeSystem));
+ SetA64("01001010xx1xxxxx0xxxxxxxxxxxxxxx", InstName.Eon, InstEmit.Eon, typeof(OpCodeAluRs));
+ SetA64("11001010xx1xxxxxxxxxxxxxxxxxxxxx", InstName.Eon, InstEmit.Eon, typeof(OpCodeAluRs));
+ SetA64("0101001000xxxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit.Eor, typeof(OpCodeAluImm));
+ SetA64("110100100xxxxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit.Eor, typeof(OpCodeAluImm));
+ SetA64("01001010xx0xxxxx0xxxxxxxxxxxxxxx", InstName.Eor, InstEmit.Eor, typeof(OpCodeAluRs));
+ SetA64("11001010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit.Eor, typeof(OpCodeAluRs));
+ SetA64("00010011100xxxxx0xxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, typeof(OpCodeAluRs));
+ SetA64("10010011110xxxxxxxxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, typeof(OpCodeAluRs));
+ SetA64("11010101000000110010xxxxxxx11111", InstName.Hint, InstEmit.Hint, typeof(OpCodeSystem));
+ SetA64("11010101000000110011xxxx11011111", InstName.Isb, InstEmit.Isb, typeof(OpCodeSystem));
+ SetA64("xx001000110xxxxx1xxxxxxxxxxxxxxx", InstName.Ldar, InstEmit.Ldar, typeof(OpCodeMemEx));
+ SetA64("1x001000011xxxxx1xxxxxxxxxxxxxxx", InstName.Ldaxp, InstEmit.Ldaxp, typeof(OpCodeMemEx));
+ SetA64("xx001000010xxxxx1xxxxxxxxxxxxxxx", InstName.Ldaxr, InstEmit.Ldaxr, typeof(OpCodeMemEx));
+ SetA64("<<10100xx1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldp, InstEmit.Ldp, typeof(OpCodeMemPair));
+ SetA64("xx111000010xxxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeMemImm));
+ SetA64("xx11100101xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeMemImm));
+ SetA64("xx111000011xxxxxxxxx10xxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeMemReg));
+ SetA64("xx011000xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr_Literal, InstEmit.Ldr_Literal, typeof(OpCodeMemLit));
+ SetA64("0x1110001x0xxxxxxxxxxxxxxxxxxxxx", InstName.Ldrs, InstEmit.Ldrs, typeof(OpCodeMemImm));
+ SetA64("0x1110011xxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldrs, InstEmit.Ldrs, typeof(OpCodeMemImm));
+ SetA64("10111000100xxxxxxxxxxxxxxxxxxxxx", InstName.Ldrs, InstEmit.Ldrs, typeof(OpCodeMemImm));
+ SetA64("1011100110xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldrs, InstEmit.Ldrs, typeof(OpCodeMemImm));
+ SetA64("0x1110001x1xxxxxxxxx10xxxxxxxxxx", InstName.Ldrs, InstEmit.Ldrs, typeof(OpCodeMemReg));
+ SetA64("10111000101xxxxxxxxx10xxxxxxxxxx", InstName.Ldrs, InstEmit.Ldrs, typeof(OpCodeMemReg));
+ SetA64("xx001000010xxxxx0xxxxxxxxxxxxxxx", InstName.Ldxr, InstEmit.Ldxr, typeof(OpCodeMemEx));
+ SetA64("1x001000011xxxxx0xxxxxxxxxxxxxxx", InstName.Ldxp, InstEmit.Ldxp, typeof(OpCodeMemEx));
+ SetA64("x0011010110xxxxx001000xxxxxxxxxx", InstName.Lslv, InstEmit.Lslv, typeof(OpCodeAluRs));
+ SetA64("x0011010110xxxxx001001xxxxxxxxxx", InstName.Lsrv, InstEmit.Lsrv, typeof(OpCodeAluRs));
+ SetA64("x0011011000xxxxx0xxxxxxxxxxxxxxx", InstName.Madd, InstEmit.Madd, typeof(OpCodeMul));
+ SetA64("0111001010xxxxxxxxxxxxxxxxxxxxxx", InstName.Movk, InstEmit.Movk, typeof(OpCodeMov));
+ SetA64("111100101xxxxxxxxxxxxxxxxxxxxxxx", InstName.Movk, InstEmit.Movk, typeof(OpCodeMov));
+ SetA64("0001001010xxxxxxxxxxxxxxxxxxxxxx", InstName.Movn, InstEmit.Movn, typeof(OpCodeMov));
+ SetA64("100100101xxxxxxxxxxxxxxxxxxxxxxx", InstName.Movn, InstEmit.Movn, typeof(OpCodeMov));
+ SetA64("0101001010xxxxxxxxxxxxxxxxxxxxxx", InstName.Movz, InstEmit.Movz, typeof(OpCodeMov));
+ SetA64("110100101xxxxxxxxxxxxxxxxxxxxxxx", InstName.Movz, InstEmit.Movz, typeof(OpCodeMov));
+ SetA64("110101010011xxxxxxxxxxxxxxxxxxxx", InstName.Mrs, InstEmit.Mrs, typeof(OpCodeSystem));
+ SetA64("110101010001xxxxxxxxxxxxxxxxxxxx", InstName.Msr, InstEmit.Msr, typeof(OpCodeSystem));
+ SetA64("x0011011000xxxxx1xxxxxxxxxxxxxxx", InstName.Msub, InstEmit.Msub, typeof(OpCodeMul));
+ SetA64("11010101000000110010000000011111", InstName.Nop, InstEmit.Nop, typeof(OpCodeSystem));
+ SetA64("00101010xx1xxxxx0xxxxxxxxxxxxxxx", InstName.Orn, InstEmit.Orn, typeof(OpCodeAluRs));
+ SetA64("10101010xx1xxxxxxxxxxxxxxxxxxxxx", InstName.Orn, InstEmit.Orn, typeof(OpCodeAluRs));
+ SetA64("0011001000xxxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, typeof(OpCodeAluImm));
+ SetA64("101100100xxxxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, typeof(OpCodeAluImm));
+ SetA64("00101010xx0xxxxx0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, typeof(OpCodeAluRs));
+ SetA64("10101010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, typeof(OpCodeAluRs));
+ SetA64("1111100110xxxxxxxxxxxxxxxxxxxxxx", InstName.Pfrm, InstEmit.Pfrm, typeof(OpCodeMemImm));
+ SetA64("11111000100xxxxxxxxx00xxxxxxxxxx", InstName.Pfrm, InstEmit.Pfrm, typeof(OpCodeMemImm));
+ SetA64("11011000xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pfrm, InstEmit.Pfrm, typeof(OpCodeMemLit));
+ SetA64("x101101011000000000000xxxxxxxxxx", InstName.Rbit, InstEmit.Rbit, typeof(OpCodeAlu));
+ SetA64("1101011001011111000000xxxxx00000", InstName.Ret, InstEmit.Ret, typeof(OpCodeBReg));
+ SetA64("x101101011000000000001xxxxxxxxxx", InstName.Rev16, InstEmit.Rev16, typeof(OpCodeAlu));
+ SetA64("x101101011000000000010xxxxxxxxxx", InstName.Rev32, InstEmit.Rev32, typeof(OpCodeAlu));
+ SetA64("1101101011000000000011xxxxxxxxxx", InstName.Rev64, InstEmit.Rev64, typeof(OpCodeAlu));
+ SetA64("x0011010110xxxxx001011xxxxxxxxxx", InstName.Rorv, InstEmit.Rorv, typeof(OpCodeAluRs));
+ SetA64("x1011010000xxxxx000000xxxxxxxxxx", InstName.Sbc, InstEmit.Sbc, typeof(OpCodeAluRs));
+ SetA64("x1111010000xxxxx000000xxxxxxxxxx", InstName.Sbcs, InstEmit.Sbcs, typeof(OpCodeAluRs));
+ SetA64("00010011000xxxxx0xxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, typeof(OpCodeBfm));
+ SetA64("1001001101xxxxxxxxxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, typeof(OpCodeBfm));
+ SetA64("x0011010110xxxxx000011xxxxxxxxxx", InstName.Sdiv, InstEmit.Sdiv, typeof(OpCodeAluBinary));
+ SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", InstName.Smaddl, InstEmit.Smaddl, typeof(OpCodeMul));
+ SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", InstName.Smsubl, InstEmit.Smsubl, typeof(OpCodeMul));
+ SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", InstName.Smulh, InstEmit.Smulh, typeof(OpCodeMul));
+ SetA64("xx001000100xxxxx1xxxxxxxxxxxxxxx", InstName.Stlr, InstEmit.Stlr, typeof(OpCodeMemEx));
+ SetA64("1x001000001xxxxx1xxxxxxxxxxxxxxx", InstName.Stlxp, InstEmit.Stlxp, typeof(OpCodeMemEx));
+ SetA64("xx001000000xxxxx1xxxxxxxxxxxxxxx", InstName.Stlxr, InstEmit.Stlxr, typeof(OpCodeMemEx));
+ SetA64("x010100xx0xxxxxxxxxxxxxxxxxxxxxx", InstName.Stp, InstEmit.Stp, typeof(OpCodeMemPair));
+ SetA64("xx111000000xxxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeMemImm));
+ SetA64("xx11100100xxxxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeMemImm));
+ SetA64("xx111000001xxxxxxxxx10xxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeMemReg));
+ SetA64("1x001000001xxxxx0xxxxxxxxxxxxxxx", InstName.Stxp, InstEmit.Stxp, typeof(OpCodeMemEx));
+ SetA64("xx001000000xxxxx0xxxxxxxxxxxxxxx", InstName.Stxr, InstEmit.Stxr, typeof(OpCodeMemEx));
+ SetA64("x10100010xxxxxxxxxxxxxxxxxxxxxxx", InstName.Sub, InstEmit.Sub, typeof(OpCodeAluImm));
+ SetA64("01001011<<0xxxxx0xxxxxxxxxxxxxxx", InstName.Sub, InstEmit.Sub, typeof(OpCodeAluRs));
+ SetA64("11001011<<0xxxxxxxxxxxxxxxxxxxxx", InstName.Sub, InstEmit.Sub, typeof(OpCodeAluRs));
+ SetA64("x1001011001xxxxxxxx0xxxxxxxxxxxx", InstName.Sub, InstEmit.Sub, typeof(OpCodeAluRx));
+ SetA64("x1001011001xxxxxxxx100xxxxxxxxxx", InstName.Sub, InstEmit.Sub, typeof(OpCodeAluRx));
+ SetA64("x11100010xxxxxxxxxxxxxxxxxxxxxxx", InstName.Subs, InstEmit.Subs, typeof(OpCodeAluImm));
+ SetA64("01101011<<0xxxxx0xxxxxxxxxxxxxxx", InstName.Subs, InstEmit.Subs, typeof(OpCodeAluRs));
+ SetA64("11101011<<0xxxxxxxxxxxxxxxxxxxxx", InstName.Subs, InstEmit.Subs, typeof(OpCodeAluRs));
+ SetA64("x1101011001xxxxxxxx0xxxxxxxxxxxx", InstName.Subs, InstEmit.Subs, typeof(OpCodeAluRx));
+ SetA64("x1101011001xxxxxxxx100xxxxxxxxxx", InstName.Subs, InstEmit.Subs, typeof(OpCodeAluRx));
+ SetA64("11010100000xxxxxxxxxxxxxxxx00001", InstName.Svc, InstEmit.Svc, typeof(OpCodeException));
+ SetA64("1101010100001xxxxxxxxxxxxxxxxxxx", InstName.Sys, InstEmit.Sys, typeof(OpCodeSystem));
+ SetA64("x0110111xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tbnz, InstEmit.Tbnz, typeof(OpCodeBImmTest));
+ SetA64("x0110110xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tbz, InstEmit.Tbz, typeof(OpCodeBImmTest));
+ SetA64("01010011000xxxxx0xxxxxxxxxxxxxxx", InstName.Ubfm, InstEmit.Ubfm, typeof(OpCodeBfm));
+ SetA64("1101001101xxxxxxxxxxxxxxxxxxxxxx", InstName.Ubfm, InstEmit.Ubfm, typeof(OpCodeBfm));
+ SetA64("x0011010110xxxxx000010xxxxxxxxxx", InstName.Udiv, InstEmit.Udiv, typeof(OpCodeAluBinary));
+ SetA64("10011011101xxxxx0xxxxxxxxxxxxxxx", InstName.Umaddl, InstEmit.Umaddl, typeof(OpCodeMul));
+ SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", InstName.Umsubl, InstEmit.Umsubl, typeof(OpCodeMul));
+ SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstName.Umulh, InstEmit.Umulh, typeof(OpCodeMul));
+
+ // FP & SIMD
+ SetA64("0101111011100000101110xxxxxxxxxx", InstName.Abs_S, InstEmit.Abs_S, typeof(OpCodeSimd));
+ SetA64("0>001110<<100000101110xxxxxxxxxx", InstName.Abs_V, InstEmit.Abs_V, typeof(OpCodeSimd));
+ SetA64("01011110111xxxxx100001xxxxxxxxxx", InstName.Add_S, InstEmit.Add_S, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<1xxxxx100001xxxxxxxxxx", InstName.Add_V, InstEmit.Add_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<1xxxxx010000xxxxxxxxxx", InstName.Addhn_V, InstEmit.Addhn_V, typeof(OpCodeSimdReg));
+ SetA64("0101111011110001101110xxxxxxxxxx", InstName.Addp_S, InstEmit.Addp_S, typeof(OpCodeSimd));
+ SetA64("0>001110<<1xxxxx101111xxxxxxxxxx", InstName.Addp_V, InstEmit.Addp_V, typeof(OpCodeSimdReg));
+ SetA64("000011100x110001101110xxxxxxxxxx", InstName.Addv_V, InstEmit.Addv_V, typeof(OpCodeSimd));
+ SetA64("01001110<<110001101110xxxxxxxxxx", InstName.Addv_V, InstEmit.Addv_V, typeof(OpCodeSimd));
+ SetA64("0100111000101000010110xxxxxxxxxx", InstName.Aesd_V, InstEmit.Aesd_V, typeof(OpCodeSimd));
+ SetA64("0100111000101000010010xxxxxxxxxx", InstName.Aese_V, InstEmit.Aese_V, typeof(OpCodeSimd));
+ SetA64("0100111000101000011110xxxxxxxxxx", InstName.Aesimc_V, InstEmit.Aesimc_V, typeof(OpCodeSimd));
+ SetA64("0100111000101000011010xxxxxxxxxx", InstName.Aesmc_V, InstEmit.Aesmc_V, typeof(OpCodeSimd));
+ SetA64("0x001110001xxxxx000111xxxxxxxxxx", InstName.And_V, InstEmit.And_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110011xxxxx000111xxxxxxxxxx", InstName.Bic_V, InstEmit.Bic_V, typeof(OpCodeSimdReg));
+ SetA64("0x10111100000xxx0xx101xxxxxxxxxx", InstName.Bic_Vi, InstEmit.Bic_Vi, typeof(OpCodeSimdImm));
+ SetA64("0x10111100000xxx10x101xxxxxxxxxx", InstName.Bic_Vi, InstEmit.Bic_Vi, typeof(OpCodeSimdImm));
+ SetA64("0x101110111xxxxx000111xxxxxxxxxx", InstName.Bif_V, InstEmit.Bif_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110101xxxxx000111xxxxxxxxxx", InstName.Bit_V, InstEmit.Bit_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110011xxxxx000111xxxxxxxxxx", InstName.Bsl_V, InstEmit.Bsl_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<100000010010xxxxxxxxxx", InstName.Cls_V, InstEmit.Cls_V, typeof(OpCodeSimd));
+ SetA64("0x101110<<100000010010xxxxxxxxxx", InstName.Clz_V, InstEmit.Clz_V, typeof(OpCodeSimd));
+ SetA64("01111110111xxxxx100011xxxxxxxxxx", InstName.Cmeq_S, InstEmit.Cmeq_S, typeof(OpCodeSimdReg));
+ SetA64("0101111011100000100110xxxxxxxxxx", InstName.Cmeq_S, InstEmit.Cmeq_S, typeof(OpCodeSimd));
+ SetA64("0>101110<<1xxxxx100011xxxxxxxxxx", InstName.Cmeq_V, InstEmit.Cmeq_V, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<100000100110xxxxxxxxxx", InstName.Cmeq_V, InstEmit.Cmeq_V, typeof(OpCodeSimd));
+ SetA64("01011110111xxxxx001111xxxxxxxxxx", InstName.Cmge_S, InstEmit.Cmge_S, typeof(OpCodeSimdReg));
+ SetA64("0111111011100000100010xxxxxxxxxx", InstName.Cmge_S, InstEmit.Cmge_S, typeof(OpCodeSimd));
+ SetA64("0>001110<<1xxxxx001111xxxxxxxxxx", InstName.Cmge_V, InstEmit.Cmge_V, typeof(OpCodeSimdReg));
+ SetA64("0>101110<<100000100010xxxxxxxxxx", InstName.Cmge_V, InstEmit.Cmge_V, typeof(OpCodeSimd));
+ SetA64("01011110111xxxxx001101xxxxxxxxxx", InstName.Cmgt_S, InstEmit.Cmgt_S, typeof(OpCodeSimdReg));
+ SetA64("0101111011100000100010xxxxxxxxxx", InstName.Cmgt_S, InstEmit.Cmgt_S, typeof(OpCodeSimd));
+ SetA64("0>001110<<1xxxxx001101xxxxxxxxxx", InstName.Cmgt_V, InstEmit.Cmgt_V, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<100000100010xxxxxxxxxx", InstName.Cmgt_V, InstEmit.Cmgt_V, typeof(OpCodeSimd));
+ SetA64("01111110111xxxxx001101xxxxxxxxxx", InstName.Cmhi_S, InstEmit.Cmhi_S, typeof(OpCodeSimdReg));
+ SetA64("0>101110<<1xxxxx001101xxxxxxxxxx", InstName.Cmhi_V, InstEmit.Cmhi_V, typeof(OpCodeSimdReg));
+ SetA64("01111110111xxxxx001111xxxxxxxxxx", InstName.Cmhs_S, InstEmit.Cmhs_S, typeof(OpCodeSimdReg));
+ SetA64("0>101110<<1xxxxx001111xxxxxxxxxx", InstName.Cmhs_V, InstEmit.Cmhs_V, typeof(OpCodeSimdReg));
+ SetA64("0111111011100000100110xxxxxxxxxx", InstName.Cmle_S, InstEmit.Cmle_S, typeof(OpCodeSimd));
+ SetA64("0>101110<<100000100110xxxxxxxxxx", InstName.Cmle_V, InstEmit.Cmle_V, typeof(OpCodeSimd));
+ SetA64("0101111011100000101010xxxxxxxxxx", InstName.Cmlt_S, InstEmit.Cmlt_S, typeof(OpCodeSimd));
+ SetA64("0>001110<<100000101010xxxxxxxxxx", InstName.Cmlt_V, InstEmit.Cmlt_V, typeof(OpCodeSimd));
+ SetA64("01011110111xxxxx100011xxxxxxxxxx", InstName.Cmtst_S, InstEmit.Cmtst_S, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<1xxxxx100011xxxxxxxxxx", InstName.Cmtst_V, InstEmit.Cmtst_V, typeof(OpCodeSimdReg));
+ SetA64("0x00111000100000010110xxxxxxxxxx", InstName.Cnt_V, InstEmit.Cnt_V, typeof(OpCodeSimd));
+ SetA64("0>001110000x<>>>000011xxxxxxxxxx", InstName.Dup_Gp, InstEmit.Dup_Gp, typeof(OpCodeSimdIns));
+ SetA64("01011110000xxxxx000001xxxxxxxxxx", InstName.Dup_S, InstEmit.Dup_S, typeof(OpCodeSimdIns));
+ SetA64("0>001110000x<>>>000001xxxxxxxxxx", InstName.Dup_V, InstEmit.Dup_V, typeof(OpCodeSimdIns));
+ SetA64("0x101110001xxxxx000111xxxxxxxxxx", InstName.Eor_V, InstEmit.Eor_V, typeof(OpCodeSimdReg));
+ SetA64("0>101110000xxxxx0<xxx0xxxxxxxxxx", InstName.Ext_V, InstEmit.Ext_V, typeof(OpCodeSimdExt));
+ SetA64("011111101x1xxxxx110101xxxxxxxxxx", InstName.Fabd_S, InstEmit.Fabd_S, typeof(OpCodeSimdReg));
+ SetA64("0>1011101<1xxxxx110101xxxxxxxxxx", InstName.Fabd_V, InstEmit.Fabd_V, typeof(OpCodeSimdReg));
+ SetA64("000111100x100000110000xxxxxxxxxx", InstName.Fabs_S, InstEmit.Fabs_S, typeof(OpCodeSimd));
+ SetA64("0>0011101<100000111110xxxxxxxxxx", InstName.Fabs_V, InstEmit.Fabs_V, typeof(OpCodeSimd));
+ SetA64("000111100x1xxxxx001010xxxxxxxxxx", InstName.Fadd_S, InstEmit.Fadd_S, typeof(OpCodeSimdReg));
+ SetA64("0>0011100<1xxxxx110101xxxxxxxxxx", InstName.Fadd_V, InstEmit.Fadd_V, typeof(OpCodeSimdReg));
+ SetA64("011111100x110000110110xxxxxxxxxx", InstName.Faddp_S, InstEmit.Faddp_S, typeof(OpCodeSimd));
+ SetA64("0>1011100<1xxxxx110101xxxxxxxxxx", InstName.Faddp_V, InstEmit.Faddp_V, typeof(OpCodeSimdReg));
+ SetA64("000111100x1xxxxxxxxx01xxxxx0xxxx", InstName.Fccmp_S, InstEmit.Fccmp_S, typeof(OpCodeSimdFcond));
+ SetA64("000111100x1xxxxxxxxx01xxxxx1xxxx", InstName.Fccmpe_S, InstEmit.Fccmpe_S, typeof(OpCodeSimdFcond));
+ SetA64("010111100x1xxxxx111001xxxxxxxxxx", InstName.Fcmeq_S, InstEmit.Fcmeq_S, typeof(OpCodeSimdReg));
+ SetA64("010111101x100000110110xxxxxxxxxx", InstName.Fcmeq_S, InstEmit.Fcmeq_S, typeof(OpCodeSimd));
+ SetA64("0>0011100<1xxxxx111001xxxxxxxxxx", InstName.Fcmeq_V, InstEmit.Fcmeq_V, typeof(OpCodeSimdReg));
+ SetA64("0>0011101<100000110110xxxxxxxxxx", InstName.Fcmeq_V, InstEmit.Fcmeq_V, typeof(OpCodeSimd));
+ SetA64("011111100x1xxxxx111001xxxxxxxxxx", InstName.Fcmge_S, InstEmit.Fcmge_S, typeof(OpCodeSimdReg));
+ SetA64("011111101x100000110010xxxxxxxxxx", InstName.Fcmge_S, InstEmit.Fcmge_S, typeof(OpCodeSimd));
+ SetA64("0>1011100<1xxxxx111001xxxxxxxxxx", InstName.Fcmge_V, InstEmit.Fcmge_V, typeof(OpCodeSimdReg));
+ SetA64("0>1011101<100000110010xxxxxxxxxx", InstName.Fcmge_V, InstEmit.Fcmge_V, typeof(OpCodeSimd));
+ SetA64("011111101x1xxxxx111001xxxxxxxxxx", InstName.Fcmgt_S, InstEmit.Fcmgt_S, typeof(OpCodeSimdReg));
+ SetA64("010111101x100000110010xxxxxxxxxx", InstName.Fcmgt_S, InstEmit.Fcmgt_S, typeof(OpCodeSimd));
+ SetA64("0>1011101<1xxxxx111001xxxxxxxxxx", InstName.Fcmgt_V, InstEmit.Fcmgt_V, typeof(OpCodeSimdReg));
+ SetA64("0>0011101<100000110010xxxxxxxxxx", InstName.Fcmgt_V, InstEmit.Fcmgt_V, typeof(OpCodeSimd));
+ SetA64("011111101x100000110110xxxxxxxxxx", InstName.Fcmle_S, InstEmit.Fcmle_S, typeof(OpCodeSimd));
+ SetA64("0>1011101<100000110110xxxxxxxxxx", InstName.Fcmle_V, InstEmit.Fcmle_V, typeof(OpCodeSimd));
+ SetA64("010111101x100000111010xxxxxxxxxx", InstName.Fcmlt_S, InstEmit.Fcmlt_S, typeof(OpCodeSimd));
+ SetA64("0>0011101<100000111010xxxxxxxxxx", InstName.Fcmlt_V, InstEmit.Fcmlt_V, typeof(OpCodeSimd));
+ SetA64("000111100x1xxxxx001000xxxxx0x000", InstName.Fcmp_S, InstEmit.Fcmp_S, typeof(OpCodeSimdReg));
+ SetA64("000111100x1xxxxx001000xxxxx1x000", InstName.Fcmpe_S, InstEmit.Fcmpe_S, typeof(OpCodeSimdReg));
+ SetA64("000111100x1xxxxxxxxx11xxxxxxxxxx", InstName.Fcsel_S, InstEmit.Fcsel_S, typeof(OpCodeSimdFcond));
+ SetA64("00011110xx10001xx10000xxxxxxxxxx", InstName.Fcvt_S, InstEmit.Fcvt_S, typeof(OpCodeSimd));
+ SetA64("x00111100x100100000000xxxxxxxxxx", InstName.Fcvtas_Gp, InstEmit.Fcvtas_Gp, typeof(OpCodeSimdCvt));
+ SetA64("x00111100x100101000000xxxxxxxxxx", InstName.Fcvtau_Gp, InstEmit.Fcvtau_Gp, typeof(OpCodeSimdCvt));
+ SetA64("0x0011100x100001011110xxxxxxxxxx", InstName.Fcvtl_V, InstEmit.Fcvtl_V, typeof(OpCodeSimd));
+ SetA64("x00111100x110000000000xxxxxxxxxx", InstName.Fcvtms_Gp, InstEmit.Fcvtms_Gp, typeof(OpCodeSimdCvt));
+ SetA64("x00111100x110001000000xxxxxxxxxx", InstName.Fcvtmu_Gp, InstEmit.Fcvtmu_Gp, typeof(OpCodeSimdCvt));
+ SetA64("0x0011100x100001011010xxxxxxxxxx", InstName.Fcvtn_V, InstEmit.Fcvtn_V, typeof(OpCodeSimd));
+ SetA64("010111100x100001101010xxxxxxxxxx", InstName.Fcvtns_S, InstEmit.Fcvtns_S, typeof(OpCodeSimd));
+ SetA64("0>0011100<100001101010xxxxxxxxxx", InstName.Fcvtns_V, InstEmit.Fcvtns_V, typeof(OpCodeSimd));
+ SetA64("011111100x100001101010xxxxxxxxxx", InstName.Fcvtnu_S, InstEmit.Fcvtnu_S, typeof(OpCodeSimd));
+ SetA64("0>1011100<100001101010xxxxxxxxxx", InstName.Fcvtnu_V, InstEmit.Fcvtnu_V, typeof(OpCodeSimd));
+ SetA64("x00111100x101000000000xxxxxxxxxx", InstName.Fcvtps_Gp, InstEmit.Fcvtps_Gp, typeof(OpCodeSimdCvt));
+ SetA64("x00111100x101001000000xxxxxxxxxx", InstName.Fcvtpu_Gp, InstEmit.Fcvtpu_Gp, typeof(OpCodeSimdCvt));
+ SetA64("x00111100x111000000000xxxxxxxxxx", InstName.Fcvtzs_Gp, InstEmit.Fcvtzs_Gp, typeof(OpCodeSimdCvt));
+ SetA64(">00111100x011000>xxxxxxxxxxxxxxx", InstName.Fcvtzs_Gp_Fixed, InstEmit.Fcvtzs_Gp_Fixed, typeof(OpCodeSimdCvt));
+ SetA64("010111101x100001101110xxxxxxxxxx", InstName.Fcvtzs_S, InstEmit.Fcvtzs_S, typeof(OpCodeSimd));
+ SetA64("0>0011101<100001101110xxxxxxxxxx", InstName.Fcvtzs_V, InstEmit.Fcvtzs_V, typeof(OpCodeSimd));
+ SetA64("0x001111001xxxxx111111xxxxxxxxxx", InstName.Fcvtzs_V_Fixed, InstEmit.Fcvtzs_V_Fixed, typeof(OpCodeSimdShImm));
+ SetA64("0100111101xxxxxx111111xxxxxxxxxx", InstName.Fcvtzs_V_Fixed, InstEmit.Fcvtzs_V_Fixed, typeof(OpCodeSimdShImm));
+ SetA64("x00111100x111001000000xxxxxxxxxx", InstName.Fcvtzu_Gp, InstEmit.Fcvtzu_Gp, typeof(OpCodeSimdCvt));
+ SetA64(">00111100x011001>xxxxxxxxxxxxxxx", InstName.Fcvtzu_Gp_Fixed, InstEmit.Fcvtzu_Gp_Fixed, typeof(OpCodeSimdCvt));
+ SetA64("011111101x100001101110xxxxxxxxxx", InstName.Fcvtzu_S, InstEmit.Fcvtzu_S, typeof(OpCodeSimd));
+ SetA64("0>1011101<100001101110xxxxxxxxxx", InstName.Fcvtzu_V, InstEmit.Fcvtzu_V, typeof(OpCodeSimd));
+ SetA64("0x101111001xxxxx111111xxxxxxxxxx", InstName.Fcvtzu_V_Fixed, InstEmit.Fcvtzu_V_Fixed, typeof(OpCodeSimdShImm));
+ SetA64("0110111101xxxxxx111111xxxxxxxxxx", InstName.Fcvtzu_V_Fixed, InstEmit.Fcvtzu_V_Fixed, typeof(OpCodeSimdShImm));
+ SetA64("000111100x1xxxxx000110xxxxxxxxxx", InstName.Fdiv_S, InstEmit.Fdiv_S, typeof(OpCodeSimdReg));
+ SetA64("0>1011100<1xxxxx111111xxxxxxxxxx", InstName.Fdiv_V, InstEmit.Fdiv_V, typeof(OpCodeSimdReg));
+ SetA64("000111110x0xxxxx0xxxxxxxxxxxxxxx", InstName.Fmadd_S, InstEmit.Fmadd_S, typeof(OpCodeSimdReg));
+ SetA64("000111100x1xxxxx010010xxxxxxxxxx", InstName.Fmax_S, InstEmit.Fmax_S, typeof(OpCodeSimdReg));
+ SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstName.Fmax_V, InstEmit.Fmax_V, typeof(OpCodeSimdReg));
+ SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstName.Fmaxnm_S, InstEmit.Fmaxnm_S, typeof(OpCodeSimdReg));
+ SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnm_V, InstEmit.Fmaxnm_V, typeof(OpCodeSimdReg));
+ SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstName.Fmaxp_V, InstEmit.Fmaxp_V, typeof(OpCodeSimdReg));
+ SetA64("000111100x1xxxxx010110xxxxxxxxxx", InstName.Fmin_S, InstEmit.Fmin_S, typeof(OpCodeSimdReg));
+ SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstName.Fmin_V, InstEmit.Fmin_V, typeof(OpCodeSimdReg));
+ SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstName.Fminnm_S, InstEmit.Fminnm_S, typeof(OpCodeSimdReg));
+ SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnm_V, InstEmit.Fminnm_V, typeof(OpCodeSimdReg));
+ SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstName.Fminp_V, InstEmit.Fminp_V, typeof(OpCodeSimdReg));
+ SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Se, InstEmit.Fmla_Se, typeof(OpCodeSimdRegElemF));
+ SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", InstName.Fmla_V, InstEmit.Fmla_V, typeof(OpCodeSimdReg));
+ SetA64("0>0011111<xxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Ve, InstEmit.Fmla_Ve, typeof(OpCodeSimdRegElemF));
+ SetA64("010111111xxxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Se, InstEmit.Fmls_Se, typeof(OpCodeSimdRegElemF));
+ SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", InstName.Fmls_V, InstEmit.Fmls_V, typeof(OpCodeSimdReg));
+ SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Ve, InstEmit.Fmls_Ve, typeof(OpCodeSimdRegElemF));
+ SetA64("000111100x100000010000xxxxxxxxxx", InstName.Fmov_S, InstEmit.Fmov_S, typeof(OpCodeSimd));
+ SetA64("000111100x1xxxxxxxx10000000xxxxx", InstName.Fmov_Si, InstEmit.Fmov_Si, typeof(OpCodeSimdFmov));
+ SetA64("0x00111100000xxx111101xxxxxxxxxx", InstName.Fmov_Vi, InstEmit.Fmov_Vi, typeof(OpCodeSimdImm));
+ SetA64("0110111100000xxx111101xxxxxxxxxx", InstName.Fmov_Vi, InstEmit.Fmov_Vi, typeof(OpCodeSimdImm));
+ SetA64("0001111000100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimd));
+ SetA64("1001111001100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimd));
+ SetA64("0001111000100111000000xxxxxxxxxx", InstName.Fmov_Itof, InstEmit.Fmov_Itof, typeof(OpCodeSimd));
+ SetA64("1001111001100111000000xxxxxxxxxx", InstName.Fmov_Itof, InstEmit.Fmov_Itof, typeof(OpCodeSimd));
+ SetA64("1001111010101110000000xxxxxxxxxx", InstName.Fmov_Ftoi1, InstEmit.Fmov_Ftoi1, typeof(OpCodeSimd));
+ SetA64("1001111010101111000000xxxxxxxxxx", InstName.Fmov_Itof1, InstEmit.Fmov_Itof1, typeof(OpCodeSimd));
+ SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", InstName.Fmsub_S, InstEmit.Fmsub_S, typeof(OpCodeSimdReg));
+ SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstName.Fmul_S, InstEmit.Fmul_S, typeof(OpCodeSimdReg));
+ SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Se, InstEmit.Fmul_Se, typeof(OpCodeSimdRegElemF));
+ SetA64("0>1011100<1xxxxx110111xxxxxxxxxx", InstName.Fmul_V, InstEmit.Fmul_V, typeof(OpCodeSimdReg));
+ SetA64("0>0011111<xxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Ve, InstEmit.Fmul_Ve, typeof(OpCodeSimdRegElemF));
+ SetA64("010111100x1xxxxx110111xxxxxxxxxx", InstName.Fmulx_S, InstEmit.Fmulx_S, typeof(OpCodeSimdReg));
+ SetA64("011111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmulx_Se, InstEmit.Fmulx_Se, typeof(OpCodeSimdRegElemF));
+ SetA64("0>0011100<1xxxxx110111xxxxxxxxxx", InstName.Fmulx_V, InstEmit.Fmulx_V, typeof(OpCodeSimdReg));
+ SetA64("0>1011111<xxxxxx1001x0xxxxxxxxxx", InstName.Fmulx_Ve, InstEmit.Fmulx_Ve, typeof(OpCodeSimdRegElemF));
+ SetA64("000111100x100001010000xxxxxxxxxx", InstName.Fneg_S, InstEmit.Fneg_S, typeof(OpCodeSimd));
+ SetA64("0>1011101<100000111110xxxxxxxxxx", InstName.Fneg_V, InstEmit.Fneg_V, typeof(OpCodeSimd));
+ SetA64("000111110x1xxxxx0xxxxxxxxxxxxxxx", InstName.Fnmadd_S, InstEmit.Fnmadd_S, typeof(OpCodeSimdReg));
+ SetA64("000111110x1xxxxx1xxxxxxxxxxxxxxx", InstName.Fnmsub_S, InstEmit.Fnmsub_S, typeof(OpCodeSimdReg));
+ SetA64("000111100x1xxxxx100010xxxxxxxxxx", InstName.Fnmul_S, InstEmit.Fnmul_S, typeof(OpCodeSimdReg));
+ SetA64("010111101x100001110110xxxxxxxxxx", InstName.Frecpe_S, InstEmit.Frecpe_S, typeof(OpCodeSimd));
+ SetA64("0>0011101<100001110110xxxxxxxxxx", InstName.Frecpe_V, InstEmit.Frecpe_V, typeof(OpCodeSimd));
+ SetA64("010111100x1xxxxx111111xxxxxxxxxx", InstName.Frecps_S, InstEmit.Frecps_S, typeof(OpCodeSimdReg));
+ SetA64("0>0011100<1xxxxx111111xxxxxxxxxx", InstName.Frecps_V, InstEmit.Frecps_V, typeof(OpCodeSimdReg));
+ SetA64("010111101x100001111110xxxxxxxxxx", InstName.Frecpx_S, InstEmit.Frecpx_S, typeof(OpCodeSimd));
+ SetA64("000111100x100110010000xxxxxxxxxx", InstName.Frinta_S, InstEmit.Frinta_S, typeof(OpCodeSimd));
+ SetA64("0>1011100<100001100010xxxxxxxxxx", InstName.Frinta_V, InstEmit.Frinta_V, typeof(OpCodeSimd));
+ SetA64("000111100x100111110000xxxxxxxxxx", InstName.Frinti_S, InstEmit.Frinti_S, typeof(OpCodeSimd));
+ SetA64("0>1011101<100001100110xxxxxxxxxx", InstName.Frinti_V, InstEmit.Frinti_V, typeof(OpCodeSimd));
+ SetA64("000111100x100101010000xxxxxxxxxx", InstName.Frintm_S, InstEmit.Frintm_S, typeof(OpCodeSimd));
+ SetA64("0>0011100<100001100110xxxxxxxxxx", InstName.Frintm_V, InstEmit.Frintm_V, typeof(OpCodeSimd));
+ SetA64("000111100x100100010000xxxxxxxxxx", InstName.Frintn_S, InstEmit.Frintn_S, typeof(OpCodeSimd));
+ SetA64("0>0011100<100001100010xxxxxxxxxx", InstName.Frintn_V, InstEmit.Frintn_V, typeof(OpCodeSimd));
+ SetA64("000111100x100100110000xxxxxxxxxx", InstName.Frintp_S, InstEmit.Frintp_S, typeof(OpCodeSimd));
+ SetA64("0>0011101<100001100010xxxxxxxxxx", InstName.Frintp_V, InstEmit.Frintp_V, typeof(OpCodeSimd));
+ SetA64("000111100x100111010000xxxxxxxxxx", InstName.Frintx_S, InstEmit.Frintx_S, typeof(OpCodeSimd));
+ SetA64("0>1011100<100001100110xxxxxxxxxx", InstName.Frintx_V, InstEmit.Frintx_V, typeof(OpCodeSimd));
+ SetA64("000111100x100101110000xxxxxxxxxx", InstName.Frintz_S, InstEmit.Frintz_S, typeof(OpCodeSimd));
+ SetA64("0>0011101<100001100110xxxxxxxxxx", InstName.Frintz_V, InstEmit.Frintz_V, typeof(OpCodeSimd));
+ SetA64("011111101x100001110110xxxxxxxxxx", InstName.Frsqrte_S, InstEmit.Frsqrte_S, typeof(OpCodeSimd));
+ SetA64("0>1011101<100001110110xxxxxxxxxx", InstName.Frsqrte_V, InstEmit.Frsqrte_V, typeof(OpCodeSimd));
+ SetA64("010111101x1xxxxx111111xxxxxxxxxx", InstName.Frsqrts_S, InstEmit.Frsqrts_S, typeof(OpCodeSimdReg));
+ SetA64("0>0011101<1xxxxx111111xxxxxxxxxx", InstName.Frsqrts_V, InstEmit.Frsqrts_V, typeof(OpCodeSimdReg));
+ SetA64("000111100x100001110000xxxxxxxxxx", InstName.Fsqrt_S, InstEmit.Fsqrt_S, typeof(OpCodeSimd));
+ SetA64("0>1011101<100001111110xxxxxxxxxx", InstName.Fsqrt_V, InstEmit.Fsqrt_V, typeof(OpCodeSimd));
+ SetA64("000111100x1xxxxx001110xxxxxxxxxx", InstName.Fsub_S, InstEmit.Fsub_S, typeof(OpCodeSimdReg));
+ SetA64("0>0011101<1xxxxx110101xxxxxxxxxx", InstName.Fsub_V, InstEmit.Fsub_V, typeof(OpCodeSimdReg));
+ SetA64("01001110000xxxxx000111xxxxxxxxxx", InstName.Ins_Gp, InstEmit.Ins_Gp, typeof(OpCodeSimdIns));
+ SetA64("01101110000xxxxx0xxxx1xxxxxxxxxx", InstName.Ins_V, InstEmit.Ins_V, typeof(OpCodeSimdIns));
+ SetA64("0x00110001000000xxxxxxxxxxxxxxxx", InstName.Ld__Vms, InstEmit.Ld__Vms, typeof(OpCodeSimdMemMs));
+ SetA64("0x001100110xxxxxxxxxxxxxxxxxxxxx", InstName.Ld__Vms, InstEmit.Ld__Vms, typeof(OpCodeSimdMemMs));
+ SetA64("0x00110101x00000xxxxxxxxxxxxxxxx", InstName.Ld__Vss, InstEmit.Ld__Vss, typeof(OpCodeSimdMemSs));
+ SetA64("0x00110111xxxxxxxxxxxxxxxxxxxxxx", InstName.Ld__Vss, InstEmit.Ld__Vss, typeof(OpCodeSimdMemSs));
+ SetA64("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldp, InstEmit.Ldp, typeof(OpCodeSimdMemPair));
+ SetA64("xx111100x10xxxxxxxxx00xxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeSimdMemImm));
+ SetA64("xx111100x10xxxxxxxxx01xxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeSimdMemImm));
+ SetA64("xx111100x10xxxxxxxxx11xxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeSimdMemImm));
+ SetA64("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeSimdMemImm));
+ SetA64("xx111100x11xxxxxxxxx10xxxxxxxxxx", InstName.Ldr, InstEmit.Ldr, typeof(OpCodeSimdMemReg));
+ SetA64("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr_Literal, InstEmit.Ldr_Literal, typeof(OpCodeSimdMemLit));
+ SetA64("0x001110<<1xxxxx100101xxxxxxxxxx", InstName.Mla_V, InstEmit.Mla_V, typeof(OpCodeSimdReg));
+ SetA64("0x101111xxxxxxxx0000x0xxxxxxxxxx", InstName.Mla_Ve, InstEmit.Mla_Ve, typeof(OpCodeSimdRegElem));
+ SetA64("0x101110<<1xxxxx100101xxxxxxxxxx", InstName.Mls_V, InstEmit.Mls_V, typeof(OpCodeSimdReg));
+ SetA64("0x101111xxxxxxxx0100x0xxxxxxxxxx", InstName.Mls_Ve, InstEmit.Mls_Ve, typeof(OpCodeSimdRegElem));
+ SetA64("0x00111100000xxx0xx001xxxxxxxxxx", InstName.Movi_V, InstEmit.Movi_V, typeof(OpCodeSimdImm));
+ SetA64("0x00111100000xxx10x001xxxxxxxxxx", InstName.Movi_V, InstEmit.Movi_V, typeof(OpCodeSimdImm));
+ SetA64("0x00111100000xxx110x01xxxxxxxxxx", InstName.Movi_V, InstEmit.Movi_V, typeof(OpCodeSimdImm));
+ SetA64("0xx0111100000xxx111001xxxxxxxxxx", InstName.Movi_V, InstEmit.Movi_V, typeof(OpCodeSimdImm));
+ SetA64("0x001110<<1xxxxx100111xxxxxxxxxx", InstName.Mul_V, InstEmit.Mul_V, typeof(OpCodeSimdReg));
+ SetA64("0x001111xxxxxxxx1000x0xxxxxxxxxx", InstName.Mul_Ve, InstEmit.Mul_Ve, typeof(OpCodeSimdRegElem));
+ SetA64("0x10111100000xxx0xx001xxxxxxxxxx", InstName.Mvni_V, InstEmit.Mvni_V, typeof(OpCodeSimdImm));
+ SetA64("0x10111100000xxx10x001xxxxxxxxxx", InstName.Mvni_V, InstEmit.Mvni_V, typeof(OpCodeSimdImm));
+ SetA64("0x10111100000xxx110x01xxxxxxxxxx", InstName.Mvni_V, InstEmit.Mvni_V, typeof(OpCodeSimdImm));
+ SetA64("0111111011100000101110xxxxxxxxxx", InstName.Neg_S, InstEmit.Neg_S, typeof(OpCodeSimd));
+ SetA64("0>101110<<100000101110xxxxxxxxxx", InstName.Neg_V, InstEmit.Neg_V, typeof(OpCodeSimd));
+ SetA64("0x10111000100000010110xxxxxxxxxx", InstName.Not_V, InstEmit.Not_V, typeof(OpCodeSimd));
+ SetA64("0x001110111xxxxx000111xxxxxxxxxx", InstName.Orn_V, InstEmit.Orn_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110101xxxxx000111xxxxxxxxxx", InstName.Orr_V, InstEmit.Orr_V, typeof(OpCodeSimdReg));
+ SetA64("0x00111100000xxx0xx101xxxxxxxxxx", InstName.Orr_Vi, InstEmit.Orr_Vi, typeof(OpCodeSimdImm));
+ SetA64("0x00111100000xxx10x101xxxxxxxxxx", InstName.Orr_Vi, InstEmit.Orr_Vi, typeof(OpCodeSimdImm));
+ SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", InstName.Raddhn_V, InstEmit.Raddhn_V, typeof(OpCodeSimdReg));
+ SetA64("0x10111001100000010110xxxxxxxxxx", InstName.Rbit_V, InstEmit.Rbit_V, typeof(OpCodeSimd));
+ SetA64("0x00111000100000000110xxxxxxxxxx", InstName.Rev16_V, InstEmit.Rev16_V, typeof(OpCodeSimd));
+ SetA64("0x1011100x100000000010xxxxxxxxxx", InstName.Rev32_V, InstEmit.Rev32_V, typeof(OpCodeSimd));
+ SetA64("0x001110<<100000000010xxxxxxxxxx", InstName.Rev64_V, InstEmit.Rev64_V, typeof(OpCodeSimd));
+ SetA64("0x00111100>>>xxx100011xxxxxxxxxx", InstName.Rshrn_V, InstEmit.Rshrn_V, typeof(OpCodeSimdShImm));
+ SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", InstName.Rsubhn_V, InstEmit.Rsubhn_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<1xxxxx011111xxxxxxxxxx", InstName.Saba_V, InstEmit.Saba_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<1xxxxx010100xxxxxxxxxx", InstName.Sabal_V, InstEmit.Sabal_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<1xxxxx011101xxxxxxxxxx", InstName.Sabd_V, InstEmit.Sabd_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<1xxxxx011100xxxxxxxxxx", InstName.Sabdl_V, InstEmit.Sabdl_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<100000011010xxxxxxxxxx", InstName.Sadalp_V, InstEmit.Sadalp_V, typeof(OpCodeSimd));
+ SetA64("0x001110<<1xxxxx000000xxxxxxxxxx", InstName.Saddl_V, InstEmit.Saddl_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<100000001010xxxxxxxxxx", InstName.Saddlp_V, InstEmit.Saddlp_V, typeof(OpCodeSimd));
+ SetA64("000011100x110000001110xxxxxxxxxx", InstName.Saddlv_V, InstEmit.Saddlv_V, typeof(OpCodeSimd));
+ SetA64("01001110<<110000001110xxxxxxxxxx", InstName.Saddlv_V, InstEmit.Saddlv_V, typeof(OpCodeSimd));
+ SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", InstName.Saddw_V, InstEmit.Saddw_V, typeof(OpCodeSimdReg));
+ SetA64("x00111100x100010000000xxxxxxxxxx", InstName.Scvtf_Gp, InstEmit.Scvtf_Gp, typeof(OpCodeSimdCvt));
+ SetA64(">00111100x000010>xxxxxxxxxxxxxxx", InstName.Scvtf_Gp_Fixed, InstEmit.Scvtf_Gp_Fixed, typeof(OpCodeSimdCvt));
+ SetA64("010111100x100001110110xxxxxxxxxx", InstName.Scvtf_S, InstEmit.Scvtf_S, typeof(OpCodeSimd));
+ SetA64("0>0011100<100001110110xxxxxxxxxx", InstName.Scvtf_V, InstEmit.Scvtf_V, typeof(OpCodeSimd));
+ SetA64("0x001111001xxxxx111001xxxxxxxxxx", InstName.Scvtf_V_Fixed, InstEmit.Scvtf_V_Fixed, typeof(OpCodeSimdShImm));
+ SetA64("0100111101xxxxxx111001xxxxxxxxxx", InstName.Scvtf_V_Fixed, InstEmit.Scvtf_V_Fixed, typeof(OpCodeSimdShImm));
+ SetA64("01011110000xxxxx000000xxxxxxxxxx", InstName.Sha1c_V, InstEmit.Sha1c_V, typeof(OpCodeSimdReg));
+ SetA64("0101111000101000000010xxxxxxxxxx", InstName.Sha1h_V, InstEmit.Sha1h_V, typeof(OpCodeSimd));
+ SetA64("01011110000xxxxx001000xxxxxxxxxx", InstName.Sha1m_V, InstEmit.Sha1m_V, typeof(OpCodeSimdReg));
+ SetA64("01011110000xxxxx000100xxxxxxxxxx", InstName.Sha1p_V, InstEmit.Sha1p_V, typeof(OpCodeSimdReg));
+ SetA64("01011110000xxxxx001100xxxxxxxxxx", InstName.Sha1su0_V, InstEmit.Sha1su0_V, typeof(OpCodeSimdReg));
+ SetA64("0101111000101000000110xxxxxxxxxx", InstName.Sha1su1_V, InstEmit.Sha1su1_V, typeof(OpCodeSimd));
+ SetA64("01011110000xxxxx010000xxxxxxxxxx", InstName.Sha256h_V, InstEmit.Sha256h_V, typeof(OpCodeSimdReg));
+ SetA64("01011110000xxxxx010100xxxxxxxxxx", InstName.Sha256h2_V, InstEmit.Sha256h2_V, typeof(OpCodeSimdReg));
+ SetA64("0101111000101000001010xxxxxxxxxx", InstName.Sha256su0_V, InstEmit.Sha256su0_V, typeof(OpCodeSimd));
+ SetA64("01011110000xxxxx011000xxxxxxxxxx", InstName.Sha256su1_V, InstEmit.Sha256su1_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<1xxxxx000001xxxxxxxxxx", InstName.Shadd_V, InstEmit.Shadd_V, typeof(OpCodeSimdReg));
+ SetA64("0101111101xxxxxx010101xxxxxxxxxx", InstName.Shl_S, InstEmit.Shl_S, typeof(OpCodeSimdShImm));
+ SetA64("0x00111100>>>xxx010101xxxxxxxxxx", InstName.Shl_V, InstEmit.Shl_V, typeof(OpCodeSimdShImm));
+ SetA64("0100111101xxxxxx010101xxxxxxxxxx", InstName.Shl_V, InstEmit.Shl_V, typeof(OpCodeSimdShImm));
+ SetA64("0x101110<<100001001110xxxxxxxxxx", InstName.Shll_V, InstEmit.Shll_V, typeof(OpCodeSimd));
+ SetA64("0x00111100>>>xxx100001xxxxxxxxxx", InstName.Shrn_V, InstEmit.Shrn_V, typeof(OpCodeSimdShImm));
+ SetA64("0x001110<<1xxxxx001001xxxxxxxxxx", InstName.Shsub_V, InstEmit.Shsub_V, typeof(OpCodeSimdReg));
+ SetA64("0x10111100>>>xxx010101xxxxxxxxxx", InstName.Sli_V, InstEmit.Sli_V, typeof(OpCodeSimdShImm));
+ SetA64("0110111101xxxxxx010101xxxxxxxxxx", InstName.Sli_V, InstEmit.Sli_V, typeof(OpCodeSimdShImm));
+ SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstName.Smax_V, InstEmit.Smax_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstName.Smaxp_V, InstEmit.Smaxp_V, typeof(OpCodeSimdReg));
+ SetA64("000011100x110000101010xxxxxxxxxx", InstName.Smaxv_V, InstEmit.Smaxv_V, typeof(OpCodeSimd));
+ SetA64("01001110<<110000101010xxxxxxxxxx", InstName.Smaxv_V, InstEmit.Smaxv_V, typeof(OpCodeSimd));
+ SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", InstName.Smin_V, InstEmit.Smin_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", InstName.Sminp_V, InstEmit.Sminp_V, typeof(OpCodeSimdReg));
+ SetA64("000011100x110001101010xxxxxxxxxx", InstName.Sminv_V, InstEmit.Sminv_V, typeof(OpCodeSimd));
+ SetA64("01001110<<110001101010xxxxxxxxxx", InstName.Sminv_V, InstEmit.Sminv_V, typeof(OpCodeSimd));
+ SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", InstName.Smlal_V, InstEmit.Smlal_V, typeof(OpCodeSimdReg));
+ SetA64("0x001111xxxxxxxx0010x0xxxxxxxxxx", InstName.Smlal_Ve, InstEmit.Smlal_Ve, typeof(OpCodeSimdRegElem));
+ SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", InstName.Smlsl_V, InstEmit.Smlsl_V, typeof(OpCodeSimdReg));
+ SetA64("0x001111xxxxxxxx0110x0xxxxxxxxxx", InstName.Smlsl_Ve, InstEmit.Smlsl_Ve, typeof(OpCodeSimdRegElem));
+ SetA64("0x001110000xxxxx001011xxxxxxxxxx", InstName.Smov_S, InstEmit.Smov_S, typeof(OpCodeSimdIns));
+ SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", InstName.Smull_V, InstEmit.Smull_V, typeof(OpCodeSimdReg));
+ SetA64("0x001111xxxxxxxx1010x0xxxxxxxxxx", InstName.Smull_Ve, InstEmit.Smull_Ve, typeof(OpCodeSimdRegElem));
+ SetA64("01011110xx100000011110xxxxxxxxxx", InstName.Sqabs_S, InstEmit.Sqabs_S, typeof(OpCodeSimd));
+ SetA64("0>001110<<100000011110xxxxxxxxxx", InstName.Sqabs_V, InstEmit.Sqabs_V, typeof(OpCodeSimd));
+ SetA64("01011110xx1xxxxx000011xxxxxxxxxx", InstName.Sqadd_S, InstEmit.Sqadd_S, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<1xxxxx000011xxxxxxxxxx", InstName.Sqadd_V, InstEmit.Sqadd_V, typeof(OpCodeSimdReg));
+ SetA64("01011110011xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_S, InstEmit.Sqdmulh_S, typeof(OpCodeSimdReg));
+ SetA64("01011110101xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_S, InstEmit.Sqdmulh_S, typeof(OpCodeSimdReg));
+ SetA64("0x001110011xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_V, InstEmit.Sqdmulh_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110101xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_V, InstEmit.Sqdmulh_V, typeof(OpCodeSimdReg));
+ SetA64("01111110xx100000011110xxxxxxxxxx", InstName.Sqneg_S, InstEmit.Sqneg_S, typeof(OpCodeSimd));
+ SetA64("0>101110<<100000011110xxxxxxxxxx", InstName.Sqneg_V, InstEmit.Sqneg_V, typeof(OpCodeSimd));
+ SetA64("01111110011xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_S, InstEmit.Sqrdmulh_S, typeof(OpCodeSimdReg));
+ SetA64("01111110101xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_S, InstEmit.Sqrdmulh_S, typeof(OpCodeSimdReg));
+ SetA64("0x101110011xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_V, InstEmit.Sqrdmulh_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110101xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_V, InstEmit.Sqrdmulh_V, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<1xxxxx010111xxxxxxxxxx", InstName.Sqrshl_V, InstEmit.Sqrshl_V, typeof(OpCodeSimdReg));
+ SetA64("0101111100>>>xxx100111xxxxxxxxxx", InstName.Sqrshrn_S, InstEmit.Sqrshrn_S, typeof(OpCodeSimdShImm));
+ SetA64("0x00111100>>>xxx100111xxxxxxxxxx", InstName.Sqrshrn_V, InstEmit.Sqrshrn_V, typeof(OpCodeSimdShImm));
+ SetA64("0111111100>>>xxx100011xxxxxxxxxx", InstName.Sqrshrun_S, InstEmit.Sqrshrun_S, typeof(OpCodeSimdShImm));
+ SetA64("0x10111100>>>xxx100011xxxxxxxxxx", InstName.Sqrshrun_V, InstEmit.Sqrshrun_V, typeof(OpCodeSimdShImm));
+ SetA64("0>001110<<1xxxxx010011xxxxxxxxxx", InstName.Sqshl_V, InstEmit.Sqshl_V, typeof(OpCodeSimdReg));
+ SetA64("0101111100>>>xxx100101xxxxxxxxxx", InstName.Sqshrn_S, InstEmit.Sqshrn_S, typeof(OpCodeSimdShImm));
+ SetA64("0x00111100>>>xxx100101xxxxxxxxxx", InstName.Sqshrn_V, InstEmit.Sqshrn_V, typeof(OpCodeSimdShImm));
+ SetA64("0111111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_S, InstEmit.Sqshrun_S, typeof(OpCodeSimdShImm));
+ SetA64("0x10111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_V, InstEmit.Sqshrun_V, typeof(OpCodeSimdShImm));
+ SetA64("01011110xx1xxxxx001011xxxxxxxxxx", InstName.Sqsub_S, InstEmit.Sqsub_S, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<1xxxxx001011xxxxxxxxxx", InstName.Sqsub_V, InstEmit.Sqsub_V, typeof(OpCodeSimdReg));
+ SetA64("01011110<<100001010010xxxxxxxxxx", InstName.Sqxtn_S, InstEmit.Sqxtn_S, typeof(OpCodeSimd));
+ SetA64("0x001110<<100001010010xxxxxxxxxx", InstName.Sqxtn_V, InstEmit.Sqxtn_V, typeof(OpCodeSimd));
+ SetA64("01111110<<100001001010xxxxxxxxxx", InstName.Sqxtun_S, InstEmit.Sqxtun_S, typeof(OpCodeSimd));
+ SetA64("0x101110<<100001001010xxxxxxxxxx", InstName.Sqxtun_V, InstEmit.Sqxtun_V, typeof(OpCodeSimd));
+ SetA64("0x001110<<1xxxxx000101xxxxxxxxxx", InstName.Srhadd_V, InstEmit.Srhadd_V, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<1xxxxx010101xxxxxxxxxx", InstName.Srshl_V, InstEmit.Srshl_V, typeof(OpCodeSimdReg));
+ SetA64("0101111101xxxxxx001001xxxxxxxxxx", InstName.Srshr_S, InstEmit.Srshr_S, typeof(OpCodeSimdShImm));
+ SetA64("0x00111100>>>xxx001001xxxxxxxxxx", InstName.Srshr_V, InstEmit.Srshr_V, typeof(OpCodeSimdShImm));
+ SetA64("0100111101xxxxxx001001xxxxxxxxxx", InstName.Srshr_V, InstEmit.Srshr_V, typeof(OpCodeSimdShImm));
+ SetA64("0101111101xxxxxx001101xxxxxxxxxx", InstName.Srsra_S, InstEmit.Srsra_S, typeof(OpCodeSimdShImm));
+ SetA64("0x00111100>>>xxx001101xxxxxxxxxx", InstName.Srsra_V, InstEmit.Srsra_V, typeof(OpCodeSimdShImm));
+ SetA64("0100111101xxxxxx001101xxxxxxxxxx", InstName.Srsra_V, InstEmit.Srsra_V, typeof(OpCodeSimdShImm));
+ SetA64("0>001110<<1xxxxx010001xxxxxxxxxx", InstName.Sshl_V, InstEmit.Sshl_V, typeof(OpCodeSimdReg));
+ SetA64("0x00111100>>>xxx101001xxxxxxxxxx", InstName.Sshll_V, InstEmit.Sshll_V, typeof(OpCodeSimdShImm));
+ SetA64("0101111101xxxxxx000001xxxxxxxxxx", InstName.Sshr_S, InstEmit.Sshr_S, typeof(OpCodeSimdShImm));
+ SetA64("0x00111100>>>xxx000001xxxxxxxxxx", InstName.Sshr_V, InstEmit.Sshr_V, typeof(OpCodeSimdShImm));
+ SetA64("0100111101xxxxxx000001xxxxxxxxxx", InstName.Sshr_V, InstEmit.Sshr_V, typeof(OpCodeSimdShImm));
+ SetA64("0101111101xxxxxx000101xxxxxxxxxx", InstName.Ssra_S, InstEmit.Ssra_S, typeof(OpCodeSimdShImm));
+ SetA64("0x00111100>>>xxx000101xxxxxxxxxx", InstName.Ssra_V, InstEmit.Ssra_V, typeof(OpCodeSimdShImm));
+ SetA64("0100111101xxxxxx000101xxxxxxxxxx", InstName.Ssra_V, InstEmit.Ssra_V, typeof(OpCodeSimdShImm));
+ SetA64("0x001110<<1xxxxx001000xxxxxxxxxx", InstName.Ssubl_V, InstEmit.Ssubl_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<1xxxxx001100xxxxxxxxxx", InstName.Ssubw_V, InstEmit.Ssubw_V, typeof(OpCodeSimdReg));
+ SetA64("0x00110000000000xxxxxxxxxxxxxxxx", InstName.St__Vms, InstEmit.St__Vms, typeof(OpCodeSimdMemMs));
+ SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", InstName.St__Vms, InstEmit.St__Vms, typeof(OpCodeSimdMemMs));
+ SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", InstName.St__Vss, InstEmit.St__Vss, typeof(OpCodeSimdMemSs));
+ SetA64("0x00110110xxxxxxxxxxxxxxxxxxxxxx", InstName.St__Vss, InstEmit.St__Vss, typeof(OpCodeSimdMemSs));
+ SetA64("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", InstName.Stp, InstEmit.Stp, typeof(OpCodeSimdMemPair));
+ SetA64("xx111100x00xxxxxxxxx00xxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeSimdMemImm));
+ SetA64("xx111100x00xxxxxxxxx01xxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeSimdMemImm));
+ SetA64("xx111100x00xxxxxxxxx11xxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeSimdMemImm));
+ SetA64("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeSimdMemImm));
+ SetA64("xx111100x01xxxxxxxxx10xxxxxxxxxx", InstName.Str, InstEmit.Str, typeof(OpCodeSimdMemReg));
+ SetA64("01111110111xxxxx100001xxxxxxxxxx", InstName.Sub_S, InstEmit.Sub_S, typeof(OpCodeSimdReg));
+ SetA64("0>101110<<1xxxxx100001xxxxxxxxxx", InstName.Sub_V, InstEmit.Sub_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<1xxxxx011000xxxxxxxxxx", InstName.Subhn_V, InstEmit.Subhn_V, typeof(OpCodeSimdReg));
+ SetA64("01011110xx100000001110xxxxxxxxxx", InstName.Suqadd_S, InstEmit.Suqadd_S, typeof(OpCodeSimd));
+ SetA64("0>001110<<100000001110xxxxxxxxxx", InstName.Suqadd_V, InstEmit.Suqadd_V, typeof(OpCodeSimd));
+ SetA64("0x001110000xxxxx0xx000xxxxxxxxxx", InstName.Tbl_V, InstEmit.Tbl_V, typeof(OpCodeSimdTbl));
+ SetA64("0>001110<<0xxxxx001010xxxxxxxxxx", InstName.Trn1_V, InstEmit.Trn1_V, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<0xxxxx011010xxxxxxxxxx", InstName.Trn2_V, InstEmit.Trn2_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<1xxxxx011111xxxxxxxxxx", InstName.Uaba_V, InstEmit.Uaba_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<1xxxxx010100xxxxxxxxxx", InstName.Uabal_V, InstEmit.Uabal_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<1xxxxx011101xxxxxxxxxx", InstName.Uabd_V, InstEmit.Uabd_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<1xxxxx011100xxxxxxxxxx", InstName.Uabdl_V, InstEmit.Uabdl_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<100000011010xxxxxxxxxx", InstName.Uadalp_V, InstEmit.Uadalp_V, typeof(OpCodeSimd));
+ SetA64("0x101110<<1xxxxx000000xxxxxxxxxx", InstName.Uaddl_V, InstEmit.Uaddl_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<100000001010xxxxxxxxxx", InstName.Uaddlp_V, InstEmit.Uaddlp_V, typeof(OpCodeSimd));
+ SetA64("001011100x110000001110xxxxxxxxxx", InstName.Uaddlv_V, InstEmit.Uaddlv_V, typeof(OpCodeSimd));
+ SetA64("01101110<<110000001110xxxxxxxxxx", InstName.Uaddlv_V, InstEmit.Uaddlv_V, typeof(OpCodeSimd));
+ SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", InstName.Uaddw_V, InstEmit.Uaddw_V, typeof(OpCodeSimdReg));
+ SetA64("x00111100x100011000000xxxxxxxxxx", InstName.Ucvtf_Gp, InstEmit.Ucvtf_Gp, typeof(OpCodeSimdCvt));
+ SetA64(">00111100x000011>xxxxxxxxxxxxxxx", InstName.Ucvtf_Gp_Fixed, InstEmit.Ucvtf_Gp_Fixed, typeof(OpCodeSimdCvt));
+ SetA64("011111100x100001110110xxxxxxxxxx", InstName.Ucvtf_S, InstEmit.Ucvtf_S, typeof(OpCodeSimd));
+ SetA64("0>1011100<100001110110xxxxxxxxxx", InstName.Ucvtf_V, InstEmit.Ucvtf_V, typeof(OpCodeSimd));
+ SetA64("0x101111001xxxxx111001xxxxxxxxxx", InstName.Ucvtf_V_Fixed, InstEmit.Ucvtf_V_Fixed, typeof(OpCodeSimdShImm));
+ SetA64("0110111101xxxxxx111001xxxxxxxxxx", InstName.Ucvtf_V_Fixed, InstEmit.Ucvtf_V_Fixed, typeof(OpCodeSimdShImm));
+ SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", InstName.Uhadd_V, InstEmit.Uhadd_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", InstName.Uhsub_V, InstEmit.Uhsub_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", InstName.Umax_V, InstEmit.Umax_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<1xxxxx101001xxxxxxxxxx", InstName.Umaxp_V, InstEmit.Umaxp_V, typeof(OpCodeSimdReg));
+ SetA64("001011100x110000101010xxxxxxxxxx", InstName.Umaxv_V, InstEmit.Umaxv_V, typeof(OpCodeSimd));
+ SetA64("01101110<<110000101010xxxxxxxxxx", InstName.Umaxv_V, InstEmit.Umaxv_V, typeof(OpCodeSimd));
+ SetA64("0x101110<<1xxxxx011011xxxxxxxxxx", InstName.Umin_V, InstEmit.Umin_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", InstName.Uminp_V, InstEmit.Uminp_V, typeof(OpCodeSimdReg));
+ SetA64("001011100x110001101010xxxxxxxxxx", InstName.Uminv_V, InstEmit.Uminv_V, typeof(OpCodeSimd));
+ SetA64("01101110<<110001101010xxxxxxxxxx", InstName.Uminv_V, InstEmit.Uminv_V, typeof(OpCodeSimd));
+ SetA64("0x101110<<1xxxxx100000xxxxxxxxxx", InstName.Umlal_V, InstEmit.Umlal_V, typeof(OpCodeSimdReg));
+ SetA64("0x101111xxxxxxxx0010x0xxxxxxxxxx", InstName.Umlal_Ve, InstEmit.Umlal_Ve, typeof(OpCodeSimdRegElem));
+ SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", InstName.Umlsl_V, InstEmit.Umlsl_V, typeof(OpCodeSimdReg));
+ SetA64("0x101111xxxxxxxx0110x0xxxxxxxxxx", InstName.Umlsl_Ve, InstEmit.Umlsl_Ve, typeof(OpCodeSimdRegElem));
+ SetA64("0x001110000xxxxx001111xxxxxxxxxx", InstName.Umov_S, InstEmit.Umov_S, typeof(OpCodeSimdIns));
+ SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", InstName.Umull_V, InstEmit.Umull_V, typeof(OpCodeSimdReg));
+ SetA64("0x101111xxxxxxxx1010x0xxxxxxxxxx", InstName.Umull_Ve, InstEmit.Umull_Ve, typeof(OpCodeSimdRegElem));
+ SetA64("01111110xx1xxxxx000011xxxxxxxxxx", InstName.Uqadd_S, InstEmit.Uqadd_S, typeof(OpCodeSimdReg));
+ SetA64("0>101110<<1xxxxx000011xxxxxxxxxx", InstName.Uqadd_V, InstEmit.Uqadd_V, typeof(OpCodeSimdReg));
+ SetA64("0>101110<<1xxxxx010111xxxxxxxxxx", InstName.Uqrshl_V, InstEmit.Uqrshl_V, typeof(OpCodeSimdReg));
+ SetA64("0111111100>>>xxx100111xxxxxxxxxx", InstName.Uqrshrn_S, InstEmit.Uqrshrn_S, typeof(OpCodeSimdShImm));
+ SetA64("0x10111100>>>xxx100111xxxxxxxxxx", InstName.Uqrshrn_V, InstEmit.Uqrshrn_V, typeof(OpCodeSimdShImm));
+ SetA64("0>101110<<1xxxxx010011xxxxxxxxxx", InstName.Uqshl_V, InstEmit.Uqshl_V, typeof(OpCodeSimdReg));
+ SetA64("0111111100>>>xxx100101xxxxxxxxxx", InstName.Uqshrn_S, InstEmit.Uqshrn_S, typeof(OpCodeSimdShImm));
+ SetA64("0x10111100>>>xxx100101xxxxxxxxxx", InstName.Uqshrn_V, InstEmit.Uqshrn_V, typeof(OpCodeSimdShImm));
+ SetA64("01111110xx1xxxxx001011xxxxxxxxxx", InstName.Uqsub_S, InstEmit.Uqsub_S, typeof(OpCodeSimdReg));
+ SetA64("0>101110<<1xxxxx001011xxxxxxxxxx", InstName.Uqsub_V, InstEmit.Uqsub_V, typeof(OpCodeSimdReg));
+ SetA64("01111110<<100001010010xxxxxxxxxx", InstName.Uqxtn_S, InstEmit.Uqxtn_S, typeof(OpCodeSimd));
+ SetA64("0x101110<<100001010010xxxxxxxxxx", InstName.Uqxtn_V, InstEmit.Uqxtn_V, typeof(OpCodeSimd));
+ SetA64("0x101110<<1xxxxx000101xxxxxxxxxx", InstName.Urhadd_V, InstEmit.Urhadd_V, typeof(OpCodeSimdReg));
+ SetA64("0>101110<<1xxxxx010101xxxxxxxxxx", InstName.Urshl_V, InstEmit.Urshl_V, typeof(OpCodeSimdReg));
+ SetA64("0111111101xxxxxx001001xxxxxxxxxx", InstName.Urshr_S, InstEmit.Urshr_S, typeof(OpCodeSimdShImm));
+ SetA64("0x10111100>>>xxx001001xxxxxxxxxx", InstName.Urshr_V, InstEmit.Urshr_V, typeof(OpCodeSimdShImm));
+ SetA64("0110111101xxxxxx001001xxxxxxxxxx", InstName.Urshr_V, InstEmit.Urshr_V, typeof(OpCodeSimdShImm));
+ SetA64("0111111101xxxxxx001101xxxxxxxxxx", InstName.Ursra_S, InstEmit.Ursra_S, typeof(OpCodeSimdShImm));
+ SetA64("0x10111100>>>xxx001101xxxxxxxxxx", InstName.Ursra_V, InstEmit.Ursra_V, typeof(OpCodeSimdShImm));
+ SetA64("0110111101xxxxxx001101xxxxxxxxxx", InstName.Ursra_V, InstEmit.Ursra_V, typeof(OpCodeSimdShImm));
+ SetA64("0>101110<<1xxxxx010001xxxxxxxxxx", InstName.Ushl_V, InstEmit.Ushl_V, typeof(OpCodeSimdReg));
+ SetA64("0x10111100>>>xxx101001xxxxxxxxxx", InstName.Ushll_V, InstEmit.Ushll_V, typeof(OpCodeSimdShImm));
+ SetA64("0111111101xxxxxx000001xxxxxxxxxx", InstName.Ushr_S, InstEmit.Ushr_S, typeof(OpCodeSimdShImm));
+ SetA64("0x10111100>>>xxx000001xxxxxxxxxx", InstName.Ushr_V, InstEmit.Ushr_V, typeof(OpCodeSimdShImm));
+ SetA64("0110111101xxxxxx000001xxxxxxxxxx", InstName.Ushr_V, InstEmit.Ushr_V, typeof(OpCodeSimdShImm));
+ SetA64("01111110xx100000001110xxxxxxxxxx", InstName.Usqadd_S, InstEmit.Usqadd_S, typeof(OpCodeSimd));
+ SetA64("0>101110<<100000001110xxxxxxxxxx", InstName.Usqadd_V, InstEmit.Usqadd_V, typeof(OpCodeSimd));
+ SetA64("0111111101xxxxxx000101xxxxxxxxxx", InstName.Usra_S, InstEmit.Usra_S, typeof(OpCodeSimdShImm));
+ SetA64("0x10111100>>>xxx000101xxxxxxxxxx", InstName.Usra_V, InstEmit.Usra_V, typeof(OpCodeSimdShImm));
+ SetA64("0110111101xxxxxx000101xxxxxxxxxx", InstName.Usra_V, InstEmit.Usra_V, typeof(OpCodeSimdShImm));
+ SetA64("0x101110<<1xxxxx001000xxxxxxxxxx", InstName.Usubl_V, InstEmit.Usubl_V, typeof(OpCodeSimdReg));
+ SetA64("0x101110<<1xxxxx001100xxxxxxxxxx", InstName.Usubw_V, InstEmit.Usubw_V, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<0xxxxx000110xxxxxxxxxx", InstName.Uzp1_V, InstEmit.Uzp1_V, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<0xxxxx010110xxxxxxxxxx", InstName.Uzp2_V, InstEmit.Uzp2_V, typeof(OpCodeSimdReg));
+ SetA64("0x001110<<100001001010xxxxxxxxxx", InstName.Xtn_V, InstEmit.Xtn_V, typeof(OpCodeSimd));
+ SetA64("0>001110<<0xxxxx001110xxxxxxxxxx", InstName.Zip1_V, InstEmit.Zip1_V, typeof(OpCodeSimdReg));
+ SetA64("0>001110<<0xxxxx011110xxxxxxxxxx", InstName.Zip2_V, InstEmit.Zip2_V, typeof(OpCodeSimdReg));
+#endregion
+
+#region "OpCode Table (AArch32)"
+ // Base
+ SetA32("<<<<0010100xxxxxxxxxxxxxxxxxxxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluImm));
+ SetA32("<<<<0000100xxxxxxxxxxxxxxxx0xxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluRsImm));
+ SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", InstName.B, InstEmit32.B, typeof(OpCode32BImm));
+ SetA32("<<<<1011xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bl, InstEmit32.Bl, typeof(OpCode32BImm));
+ SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Blx, InstEmit32.Blx, typeof(OpCode32BImm));
+ SetA32("<<<<000100101111111111110001xxxx", InstName.Bx, InstEmit32.Bx, typeof(OpCode32BReg));
+ SetT32("xxxxxxxxxxxxxxxx010001110xxxx000", InstName.Bx, InstEmit32.Bx, typeof(OpCodeT16BReg));
+ SetA32("<<<<00110101xxxx0000xxxxxxxxxxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluImm));
+ SetA32("<<<<00010101xxxx0000xxxxxxx0xxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluRsImm));
+ SetA32("<<<<100xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, typeof(OpCode32MemMult));
+ SetA32("<<<<010xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, typeof(OpCode32MemImm));
+ SetA32("<<<<010xx1x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, typeof(OpCode32MemImm));
+ SetA32("<<<<000xx1x0xxxxxxxxxxxx1101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemImm8));
+ SetA32("<<<<000xx1x1xxxxxxxxxxxx1011xxxx", InstName.Ldrh, InstEmit32.Ldrh, typeof(OpCode32MemImm8));
+ SetA32("<<<<000xx1x1xxxxxxxxxxxx1101xxxx", InstName.Ldrsb, InstEmit32.Ldrsb, typeof(OpCode32MemImm8));
+ SetA32("<<<<000xx1x1xxxxxxxxxxxx1111xxxx", InstName.Ldrsh, InstEmit32.Ldrsh, typeof(OpCode32MemImm8));
+ SetA32("<<<<0011101x0000xxxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluImm));
+ SetA32("<<<<0001101x0000xxxxxxxxxxx0xxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluRsImm));
+ SetT32("xxxxxxxxxxxxxxxx00100xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCodeT16AluImm8));
+ SetA32("<<<<100xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, typeof(OpCode32MemMult));
+ SetA32("<<<<010xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, typeof(OpCode32MemImm));
+ SetA32("<<<<010xx1x0xxxxxxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, typeof(OpCode32MemImm));
+ SetA32("<<<<000xx1x0xxxxxxxxxxxx1111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemImm8));
+ SetA32("<<<<000xx1x0xxxxxxxxxxxx1011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemImm8));
+ SetA32("<<<<0010010xxxxxxxxxxxxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluImm));
+ SetA32("<<<<0000010xxxxxxxxxxxxxxxx0xxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluRsImm));
+#endregion
+
+ FillFastLookupTable(_instA32FastLookup, _allInstA32);
+ FillFastLookupTable(_instT32FastLookup, _allInstT32);
+ FillFastLookupTable(_instA64FastLookup, _allInstA64);
+ }
+
+ private static void FillFastLookupTable(InstInfo[][] table, List<InstInfo> allInsts)
+ {
+ List<InstInfo>[] temp = new List<InstInfo>[FastLookupSize];
+
+ for (int index = 0; index < FastLookupSize; index++)
+ {
+ temp[index] = new List<InstInfo>();
+ }
+
+ foreach (InstInfo inst in allInsts)
+ {
+ int mask = ToFastLookupIndex(inst.Mask);
+ int value = ToFastLookupIndex(inst.Value);
+
+ for (int index = 0; index < FastLookupSize; index++)
+ {
+ if ((index & mask) == value)
+ {
+ temp[index].Add(inst);
+ }
+ }
+ }
+
+ for (int index = 0; index < FastLookupSize; index++)
+ {
+ table[index] = temp[index].ToArray();
+ }
+ }
+
+ private static void SetA32(string encoding, InstName name, InstEmitter emitter, Type type)
+ {
+ Set(encoding, ExecutionMode.Aarch32Arm, new InstDescriptor(name, emitter), type);
+ }
+
+ private static void SetT32(string encoding, InstName name, InstEmitter emitter, Type type)
+ {
+ Set(encoding, ExecutionMode.Aarch32Thumb, new InstDescriptor(name, emitter), type);
+ }
+
+ private static void SetA64(string encoding, InstName name, InstEmitter emitter, Type type)
+ {
+ Set(encoding, ExecutionMode.Aarch64, new InstDescriptor(name, emitter), type);
+ }
+
+ private static void Set(string encoding, ExecutionMode mode, InstDescriptor inst, Type type)
+ {
+ int bit = encoding.Length - 1;
+ int value = 0;
+ int xMask = 0;
+ int xBits = 0;
+
+ int[] xPos = new int[encoding.Length];
+
+ int blacklisted = 0;
+
+ for (int index = 0; index < encoding.Length; index++, bit--)
+ {
+ // Note: < and > are used on special encodings.
+ // The < means that we should never have ALL bits with the '<' set.
+ // So, when the encoding has <<, it means that 00, 01, and 10 are valid,
+ // but not 11. <<< is 000, 001, ..., 110 but NOT 111, and so on...
+ // For >, the invalid value is zero. So, for >> 01, 10 and 11 are valid,
+ // but 00 isn't.
+ char chr = encoding[index];
+
+ if (chr == '1')
+ {
+ value |= 1 << bit;
+ }
+ else if (chr == 'x')
+ {
+ xMask |= 1 << bit;
+ }
+ else if (chr == '>')
+ {
+ xPos[xBits++] = bit;
+ }
+ else if (chr == '<')
+ {
+ xPos[xBits++] = bit;
+
+ blacklisted |= 1 << bit;
+ }
+ else if (chr != '0')
+ {
+ throw new ArgumentException(nameof(encoding));
+ }
+ }
+
+ xMask = ~xMask;
+
+ if (xBits == 0)
+ {
+ InsertInst(new InstInfo(xMask, value, inst, type), mode);
+
+ return;
+ }
+
+ for (int index = 0; index < (1 << xBits); index++)
+ {
+ int mask = 0;
+
+ for (int x = 0; x < xBits; x++)
+ {
+ mask |= ((index >> x) & 1) << xPos[x];
+ }
+
+ if (mask != blacklisted)
+ {
+ InsertInst(new InstInfo(xMask, value | mask, inst, type), mode);
+ }
+ }
+ }
+
+ private static void InsertInst(InstInfo info, ExecutionMode mode)
+ {
+ switch (mode)
+ {
+ case ExecutionMode.Aarch32Arm: _allInstA32.Add(info); break;
+ case ExecutionMode.Aarch32Thumb: _allInstT32.Add(info); break;
+ case ExecutionMode.Aarch64: _allInstA64.Add(info); break;
+ }
+ }
+
+ public static (InstDescriptor inst, Type type) GetInstA32(int opCode)
+ {
+ return GetInstFromList(_instA32FastLookup[ToFastLookupIndex(opCode)], opCode);
+ }
+
+ public static (InstDescriptor inst, Type type) GetInstT32(int opCode)
+ {
+ return GetInstFromList(_instT32FastLookup[ToFastLookupIndex(opCode)], opCode);
+ }
+
+ public static (InstDescriptor inst, Type type) GetInstA64(int opCode)
+ {
+ return GetInstFromList(_instA64FastLookup[ToFastLookupIndex(opCode)], opCode);
+ }
+
+ private static (InstDescriptor inst, Type type) GetInstFromList(InstInfo[] insts, int opCode)
+ {
+ foreach (InstInfo info in insts)
+ {
+ if ((opCode & info.Mask) == info.Value)
+ {
+ return (info.Inst, info.Type);
+ }
+ }
+
+ return (new InstDescriptor(InstName.Und, InstEmit.Und), typeof(OpCode));
+ }
+
+ private static int ToFastLookupIndex(int value)
+ {
+ return ((value >> 10) & 0x00F) | ((value >> 18) & 0xFF0);
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/RegisterSize.cs b/ARMeilleure/Decoders/RegisterSize.cs
new file mode 100644
index 00000000..c9cea03e
--- /dev/null
+++ b/ARMeilleure/Decoders/RegisterSize.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.Decoders
+{
+ enum RegisterSize
+ {
+ Int32,
+ Int64,
+ Simd64,
+ Simd128
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/ShiftType.cs b/ARMeilleure/Decoders/ShiftType.cs
new file mode 100644
index 00000000..8583f16a
--- /dev/null
+++ b/ARMeilleure/Decoders/ShiftType.cs
@@ -0,0 +1,10 @@
+namespace ARMeilleure.Decoders
+{
+ enum ShiftType
+ {
+ Lsl = 0,
+ Lsr = 1,
+ Asr = 2,
+ Ror = 3
+ }
+} \ No newline at end of file