aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Decoders
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/Decoders')
-rw-r--r--ARMeilleure/Decoders/Decoder.cs5
-rw-r--r--ARMeilleure/Decoders/DecoderHelper.cs15
-rw-r--r--ARMeilleure/Decoders/IOpCode32AluBf.cs11
-rw-r--r--ARMeilleure/Decoders/IOpCode32AluReg.cs7
-rw-r--r--ARMeilleure/Decoders/IOpCode32AluUx.cs8
-rw-r--r--ARMeilleure/Decoders/IOpCode32Mem.cs1
-rw-r--r--ARMeilleure/Decoders/IOpCode32MemEx.cs7
-rw-r--r--ARMeilleure/Decoders/IOpCode32Simd.cs4
-rw-r--r--ARMeilleure/Decoders/IOpCode32SimdImm.cs9
-rw-r--r--ARMeilleure/Decoders/OpCode32AluBf.cs24
-rw-r--r--ARMeilleure/Decoders/OpCode32AluImm16.cs15
-rw-r--r--ARMeilleure/Decoders/OpCode32AluMla.cs28
-rw-r--r--ARMeilleure/Decoders/OpCode32AluReg.cs12
-rw-r--r--ARMeilleure/Decoders/OpCode32AluRsImm.cs8
-rw-r--r--ARMeilleure/Decoders/OpCode32AluRsReg.cs18
-rw-r--r--ARMeilleure/Decoders/OpCode32AluUmull.cs30
-rw-r--r--ARMeilleure/Decoders/OpCode32AluUx.cs16
-rw-r--r--ARMeilleure/Decoders/OpCode32Exception.cs12
-rw-r--r--ARMeilleure/Decoders/OpCode32Mem.cs2
-rw-r--r--ARMeilleure/Decoders/OpCode32MemLdEx.cs12
-rw-r--r--ARMeilleure/Decoders/OpCode32MemReg.cs12
-rw-r--r--ARMeilleure/Decoders/OpCode32MemRsImm.cs16
-rw-r--r--ARMeilleure/Decoders/OpCode32MemStEx.cs13
-rw-r--r--ARMeilleure/Decoders/OpCode32Simd.cs30
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdBase.cs52
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdBinary.cs18
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdCmpZ.cs15
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdCvtFI.cs13
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdDupElem.cs40
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdDupGP.cs31
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdExt.cs17
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdImm.cs37
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdImm44.cs36
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdMemImm.cs35
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdMemMult.cs71
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdMemPair.cs46
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdMemSingle.cs46
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdMovGp.cs26
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdMovGpDouble.cs31
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdMovGpElem.cs46
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdReg.cs22
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdRegElem.cs21
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdRegS.cs20
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdRev.cs14
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdS.cs31
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdSel.cs20
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdShImm.cs44
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdSpecial.cs14
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdSqrte.cs16
-rw-r--r--ARMeilleure/Decoders/OpCode32SimdTbl.cs21
-rw-r--r--ARMeilleure/Decoders/OpCode32System.cs26
-rw-r--r--ARMeilleure/Decoders/OpCodeSimdHelper.cs88
-rw-r--r--ARMeilleure/Decoders/OpCodeTable.cs303
53 files changed, 1481 insertions, 34 deletions
diff --git a/ARMeilleure/Decoders/Decoder.cs b/ARMeilleure/Decoders/Decoder.cs
index 8eb2a99d..913d5082 100644
--- a/ARMeilleure/Decoders/Decoder.cs
+++ b/ARMeilleure/Decoders/Decoder.cs
@@ -292,15 +292,16 @@ namespace ARMeilleure.Decoders
private static bool IsCall(OpCode opCode)
{
- // TODO (CQ): ARM32 support.
return opCode.Instruction.Name == InstName.Bl ||
- opCode.Instruction.Name == InstName.Blr;
+ opCode.Instruction.Name == InstName.Blr ||
+ opCode.Instruction.Name == InstName.Blx;
}
private static bool IsException(OpCode opCode)
{
return opCode.Instruction.Name == InstName.Brk ||
opCode.Instruction.Name == InstName.Svc ||
+ opCode.Instruction.Name == InstName.Trap ||
opCode.Instruction.Name == InstName.Und;
}
diff --git a/ARMeilleure/Decoders/DecoderHelper.cs b/ARMeilleure/Decoders/DecoderHelper.cs
index bc41c61c..6fe4678f 100644
--- a/ARMeilleure/Decoders/DecoderHelper.cs
+++ b/ARMeilleure/Decoders/DecoderHelper.cs
@@ -148,5 +148,20 @@ namespace ARMeilleure.Decoders
{
return (((long)opCode << 45) >> 48) & ~3;
}
+
+ public static bool VectorArgumentsInvalid(bool q, params int[] args)
+ {
+ if (q)
+ {
+ for (int i = 0; i < args.Length; i++)
+ {
+ if ((args[i] & 1) == 1)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCode32AluBf.cs b/ARMeilleure/Decoders/IOpCode32AluBf.cs
new file mode 100644
index 00000000..18de3eb6
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32AluBf.cs
@@ -0,0 +1,11 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32AluBf
+ {
+ int Rd { get; }
+ int Rn { get; }
+
+ int Msb { get; }
+ int Lsb { get; }
+ }
+}
diff --git a/ARMeilleure/Decoders/IOpCode32AluReg.cs b/ARMeilleure/Decoders/IOpCode32AluReg.cs
new file mode 100644
index 00000000..1612cc5c
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32AluReg.cs
@@ -0,0 +1,7 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32AluReg : IOpCode32Alu
+ {
+ int Rm { get; }
+ }
+}
diff --git a/ARMeilleure/Decoders/IOpCode32AluUx.cs b/ARMeilleure/Decoders/IOpCode32AluUx.cs
new file mode 100644
index 00000000..d03c7e21
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32AluUx.cs
@@ -0,0 +1,8 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32AluUx : IOpCode32AluReg
+ {
+ int RotateBits { get; }
+ bool Add { get; }
+ }
+}
diff --git a/ARMeilleure/Decoders/IOpCode32Mem.cs b/ARMeilleure/Decoders/IOpCode32Mem.cs
index 0585ab53..8fdc9dad 100644
--- a/ARMeilleure/Decoders/IOpCode32Mem.cs
+++ b/ARMeilleure/Decoders/IOpCode32Mem.cs
@@ -6,7 +6,6 @@ namespace ARMeilleure.Decoders
int Rn { get; }
bool WBack { get; }
-
bool IsLoad { get; }
}
} \ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCode32MemEx.cs b/ARMeilleure/Decoders/IOpCode32MemEx.cs
new file mode 100644
index 00000000..aca7200a
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32MemEx.cs
@@ -0,0 +1,7 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32MemEx : IOpCode32Mem
+ {
+ int Rd { get; }
+ }
+}
diff --git a/ARMeilleure/Decoders/IOpCode32Simd.cs b/ARMeilleure/Decoders/IOpCode32Simd.cs
new file mode 100644
index 00000000..687254d9
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32Simd.cs
@@ -0,0 +1,4 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32Simd : IOpCode32, IOpCodeSimd { }
+}
diff --git a/ARMeilleure/Decoders/IOpCode32SimdImm.cs b/ARMeilleure/Decoders/IOpCode32SimdImm.cs
new file mode 100644
index 00000000..a0cb669c
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32SimdImm.cs
@@ -0,0 +1,9 @@
+namespace ARMeilleure.Decoders
+{
+ interface IOpCode32SimdImm : IOpCode32Simd
+ {
+ int Vd { get; }
+ long Immediate { get; }
+ int Elems { get; }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32AluBf.cs b/ARMeilleure/Decoders/OpCode32AluBf.cs
new file mode 100644
index 00000000..7ee0ee34
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32AluBf.cs
@@ -0,0 +1,24 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32AluBf : OpCode32, IOpCode32AluBf
+ {
+ public int Rd { get; private set; }
+ public int Rn { get; private set; }
+
+ public int Msb { get; private set; }
+
+ public int Lsb { get; private set; }
+
+ public int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb));
+ public int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb);
+
+ public OpCode32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rd = (opCode >> 12) & 0xf;
+ Rn = (opCode >> 0) & 0xf;
+
+ Msb = (opCode >> 16) & 0x1f;
+ Lsb = (opCode >> 7) & 0x1f;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32AluImm16.cs b/ARMeilleure/Decoders/OpCode32AluImm16.cs
new file mode 100644
index 00000000..dbc02932
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32AluImm16.cs
@@ -0,0 +1,15 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32AluImm16 : OpCode32Alu
+ {
+ public int Immediate { get; private set; }
+
+ public OpCode32AluImm16(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ int imm12 = opCode & 0xfff;
+ int imm4 = (opCode >> 16) & 0xf;
+
+ Immediate = (imm4 << 12) | imm12;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32AluMla.cs b/ARMeilleure/Decoders/OpCode32AluMla.cs
new file mode 100644
index 00000000..4570aa4e
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32AluMla.cs
@@ -0,0 +1,28 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32AluMla : OpCode32, IOpCode32AluReg
+ {
+ public int Rn { get; private set; }
+ public int Rm { get; private set; }
+ public int Ra { get; private set; }
+ public int Rd { get; private set; }
+
+ public bool NHigh { get; private set; }
+ public bool MHigh { get; private set; }
+ public bool R { get; private set; }
+ public bool SetFlags { get; private set; }
+
+ public OpCode32AluMla(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rn = (opCode >> 0) & 0xf;
+ Rm = (opCode >> 8) & 0xf;
+ Ra = (opCode >> 12) & 0xf;
+ Rd = (opCode >> 16) & 0xf;
+ R = (opCode & (1 << 5)) != 0;
+
+ NHigh = ((opCode >> 5) & 0x1) == 1;
+ MHigh = ((opCode >> 6) & 0x1) == 1;
+ SetFlags = ((opCode >> 20) & 1) != 0;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32AluReg.cs b/ARMeilleure/Decoders/OpCode32AluReg.cs
new file mode 100644
index 00000000..e378dd05
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32AluReg.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32AluReg : OpCode32Alu, IOpCode32AluReg
+ {
+ public int Rm { get; private set; }
+
+ public OpCode32AluReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rm = (opCode >> 0) & 0xf;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32AluRsImm.cs b/ARMeilleure/Decoders/OpCode32AluRsImm.cs
index 779d6cec..68ca0d0c 100644
--- a/ARMeilleure/Decoders/OpCode32AluRsImm.cs
+++ b/ARMeilleure/Decoders/OpCode32AluRsImm.cs
@@ -2,15 +2,15 @@ namespace ARMeilleure.Decoders
{
class OpCode32AluRsImm : OpCode32Alu
{
- public int Rm { get; private set; }
- public int Imm { get; private set; }
+ public int Rm { get; private set; }
+ public int Immediate { 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;
+ Rm = (opCode >> 0) & 0xf;
+ Immediate = (opCode >> 7) & 0x1f;
ShiftType = (ShiftType)((opCode >> 5) & 3);
}
diff --git a/ARMeilleure/Decoders/OpCode32AluRsReg.cs b/ARMeilleure/Decoders/OpCode32AluRsReg.cs
new file mode 100644
index 00000000..d195987b
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32AluRsReg.cs
@@ -0,0 +1,18 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32AluRsReg : OpCode32Alu
+ {
+ public int Rm { get; private set; }
+ public int Rs { get; private set; }
+
+ public ShiftType ShiftType { get; private set; }
+
+ public OpCode32AluRsReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rm = (opCode >> 0) & 0xf;
+ Rs = (opCode >> 8) & 0xf;
+
+ ShiftType = (ShiftType)((opCode >> 5) & 3);
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32AluUmull.cs b/ARMeilleure/Decoders/OpCode32AluUmull.cs
new file mode 100644
index 00000000..c98d9305
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32AluUmull.cs
@@ -0,0 +1,30 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32AluUmull : OpCode32
+ {
+ public int RdLo { get; private set; }
+ public int RdHi { get; private set; }
+ public int Rn { get; private set; }
+ public int Rm { get; private set; }
+
+ public bool NHigh { get; private set; }
+ public bool MHigh { get; private set; }
+
+ public bool SetFlags { get; private set; }
+ public DataOp DataOp { get; private set; }
+
+ public OpCode32AluUmull(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ RdLo = (opCode >> 12) & 0xf;
+ RdHi = (opCode >> 16) & 0xf;
+ Rm = (opCode >> 8) & 0xf;
+ Rn = (opCode >> 0) & 0xf;
+
+ NHigh = ((opCode >> 5) & 0x1) == 1;
+ MHigh = ((opCode >> 6) & 0x1) == 1;
+
+ SetFlags = ((opCode >> 20) & 0x1) != 0;
+ DataOp = DataOp.Arithmetic;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32AluUx.cs b/ARMeilleure/Decoders/OpCode32AluUx.cs
new file mode 100644
index 00000000..55c10209
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32AluUx.cs
@@ -0,0 +1,16 @@
+using ARMeilleure.State;
+
+namespace ARMeilleure.Decoders
+{
+ class OpCode32AluUx : OpCode32AluReg, IOpCode32AluUx
+ {
+ public int Rotate { get; private set; }
+ public int RotateBits => Rotate * 8;
+ public bool Add => Rn != RegisterAlias.Aarch32Pc;
+
+ public OpCode32AluUx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rotate = (opCode >> 10) & 0x3;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32Exception.cs b/ARMeilleure/Decoders/OpCode32Exception.cs
new file mode 100644
index 00000000..1acdf5b1
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32Exception.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32Exception : OpCode32
+ {
+ public int Id { get; private set; }
+
+ public OpCode32Exception(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Id = opCode & 0xFFFFFF;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32Mem.cs b/ARMeilleure/Decoders/OpCode32Mem.cs
index f4e88d59..b749f3db 100644
--- a/ARMeilleure/Decoders/OpCode32Mem.cs
+++ b/ARMeilleure/Decoders/OpCode32Mem.cs
@@ -4,7 +4,7 @@ namespace ARMeilleure.Decoders
{
class OpCode32Mem : OpCode32, IOpCode32Mem
{
- public int Rt { get; private set; }
+ public int Rt { get; protected set; }
public int Rn { get; private set; }
public int Immediate { get; protected set; }
diff --git a/ARMeilleure/Decoders/OpCode32MemLdEx.cs b/ARMeilleure/Decoders/OpCode32MemLdEx.cs
new file mode 100644
index 00000000..42d1a33a
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32MemLdEx.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32MemLdEx : OpCode32Mem, IOpCode32MemEx
+ {
+ public int Rd { get; private set; }
+
+ public OpCode32MemLdEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rd = opCode & 0xf;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32MemReg.cs b/ARMeilleure/Decoders/OpCode32MemReg.cs
new file mode 100644
index 00000000..ccc05a87
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32MemReg.cs
@@ -0,0 +1,12 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32MemReg : OpCode32Mem
+ {
+ public int Rm { get; private set; }
+
+ public OpCode32MemReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rm = (opCode >> 0) & 0xf;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32MemRsImm.cs b/ARMeilleure/Decoders/OpCode32MemRsImm.cs
new file mode 100644
index 00000000..299e83e2
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32MemRsImm.cs
@@ -0,0 +1,16 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32MemRsImm : OpCode32Mem
+ {
+ public int Rm { get; private set; }
+ public ShiftType ShiftType { get; private set; }
+
+ public OpCode32MemRsImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rm = (opCode >> 0) & 0xf;
+ Immediate = (opCode >> 7) & 0x1f;
+
+ ShiftType = (ShiftType)((opCode >> 5) & 3);
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32MemStEx.cs b/ARMeilleure/Decoders/OpCode32MemStEx.cs
new file mode 100644
index 00000000..b9c6d4f4
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32MemStEx.cs
@@ -0,0 +1,13 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32MemStEx : OpCode32Mem, IOpCode32MemEx
+ {
+ public int Rd { get; private set; }
+
+ public OpCode32MemStEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rd = (opCode >> 12) & 0xf;
+ Rt = (opCode >> 0) & 0xf;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32Simd.cs b/ARMeilleure/Decoders/OpCode32Simd.cs
new file mode 100644
index 00000000..cda10c3c
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32Simd.cs
@@ -0,0 +1,30 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32Simd : OpCode32SimdBase
+ {
+ public int Opc { get; protected set; }
+ public bool Q { get; protected set; }
+ public bool F { get; protected set; }
+ public bool U { get; private set; }
+
+ public OpCode32Simd(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Size = (opCode >> 20) & 0x3;
+ Q = ((opCode >> 6) & 0x1) != 0;
+ F = ((opCode >> 10) & 0x1) != 0;
+ U = ((opCode >> 24) & 0x1) != 0;
+ Opc = (opCode >> 7) & 0x3;
+
+ RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
+
+ Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
+ Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf);
+
+ // Subclasses have their own handling of Vx to account for before checking.
+ if (GetType() == typeof(OpCode32Simd) && DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdBase.cs b/ARMeilleure/Decoders/OpCode32SimdBase.cs
new file mode 100644
index 00000000..10b54659
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdBase.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace ARMeilleure.Decoders
+{
+ abstract class OpCode32SimdBase : OpCode32, IOpCode32Simd
+ {
+ public int Vd { get; protected set; }
+ public int Vm { get; protected set; }
+ public int Size { get; protected set; }
+
+ // Helpers to index doublewords within quad words. Essentially, looping over the vector starts at quadword Q and index Fx or Ix within it,
+ // depending on instruction type.
+ //
+ // Qx: The quadword register that the target vector is contained in.
+ // Ix: The starting index of the target vector within the quadword, with size treated as integer.
+ // Fx: The starting index of the target vector within the quadword, with size treated as floating point. (16 or 32)
+ public int Qd => GetQuadwordIndex(Vd);
+ public int Id => GetQuadwordSubindex(Vd) << (3 - Size);
+ public int Fd => GetQuadwordSubindex(Vd) << (1 - (Size & 1)); // When the top bit is truncated, 1 is fp16 which is an optional extension in ARMv8.2. We always assume 64.
+
+ public int Qm => GetQuadwordIndex(Vm);
+ public int Im => GetQuadwordSubindex(Vm) << (3 - Size);
+ public int Fm => GetQuadwordSubindex(Vm) << (1 - (Size & 1));
+
+ protected int GetQuadwordIndex(int index)
+ {
+ switch (RegisterSize)
+ {
+ case RegisterSize.Simd128:
+ case RegisterSize.Simd64:
+ return index >> 1;
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ protected int GetQuadwordSubindex(int index)
+ {
+ switch (RegisterSize)
+ {
+ case RegisterSize.Simd128:
+ return 0;
+ case RegisterSize.Simd64:
+ return index & 1;
+ }
+
+ throw new InvalidOperationException();
+ }
+
+ public OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdBinary.cs b/ARMeilleure/Decoders/OpCode32SimdBinary.cs
new file mode 100644
index 00000000..66f63dc5
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdBinary.cs
@@ -0,0 +1,18 @@
+namespace ARMeilleure.Decoders
+{
+ /// <summary>
+ /// A special alias that always runs in 64 bit int, to speed up binary ops a little.
+ /// </summary>
+ class OpCode32SimdBinary : OpCode32SimdReg
+ {
+ public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Size = 3;
+
+ if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdCmpZ.cs b/ARMeilleure/Decoders/OpCode32SimdCmpZ.cs
new file mode 100644
index 00000000..567147fb
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdCmpZ.cs
@@ -0,0 +1,15 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdCmpZ : OpCode32Simd
+ {
+ public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Size = (opCode >> 18) & 0x3;
+
+ if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdCvtFI.cs b/ARMeilleure/Decoders/OpCode32SimdCvtFI.cs
new file mode 100644
index 00000000..aaedcb3c
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdCvtFI.cs
@@ -0,0 +1,13 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdCvtFI : OpCode32SimdS
+ {
+ public int Opc2 { get; private set; }
+
+ public OpCode32SimdCvtFI(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Opc2 = (opCode >> 16) & 0x7;
+ Opc = (opCode >> 7) & 0x1;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdDupElem.cs b/ARMeilleure/Decoders/OpCode32SimdDupElem.cs
new file mode 100644
index 00000000..fd83aee5
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdDupElem.cs
@@ -0,0 +1,40 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdDupElem : OpCode32Simd
+ {
+ public int Index { get; private set; }
+
+ public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ var opc = (opCode >> 16) & 0xf;
+
+ if ((opc & 0b1) == 1)
+ {
+ Size = 0;
+ Index = (opc >> 1) & 0x7;
+ }
+ else if ((opc & 0b11) == 0b10)
+ {
+ Size = 1;
+ Index = (opc >> 2) & 0x3;
+ }
+ else if ((opc & 0b111) == 0b100)
+ {
+ Size = 2;
+ Index = (opc >> 3) & 0x1;
+ }
+ else
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+
+ Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
+ Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf);
+
+ if (DecoderHelper.VectorArgumentsInvalid(Q, Vd))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdDupGP.cs b/ARMeilleure/Decoders/OpCode32SimdDupGP.cs
new file mode 100644
index 00000000..58a8a7fe
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdDupGP.cs
@@ -0,0 +1,31 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdDupGP : OpCode32, IOpCode32Simd
+ {
+ public int Size { get; private set; }
+ public int Vd { get; private set; }
+ public int Rt { get; private set; }
+ public bool Q { get; private set; }
+
+ public OpCode32SimdDupGP(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); // B:E - 0 for 32, 16 then 8.
+ if (Size == -1)
+ {
+ Instruction = InstDescriptor.Undefined;
+ return;
+ }
+ Q = ((opCode >> 21) & 0x1) != 0;
+
+ RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
+
+ Vd = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);
+ Rt = ((opCode >> 12) & 0xf);
+
+ if (DecoderHelper.VectorArgumentsInvalid(Q, Vd))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdExt.cs b/ARMeilleure/Decoders/OpCode32SimdExt.cs
new file mode 100644
index 00000000..1ee0485e
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdExt.cs
@@ -0,0 +1,17 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdExt : OpCode32SimdReg
+ {
+ public int Immediate { get; private set; }
+
+ public OpCode32SimdExt(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Immediate = (opCode >> 8) & 0xf;
+ Size = 0;
+ if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn) || (!Q && Immediate > 7))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdImm.cs b/ARMeilleure/Decoders/OpCode32SimdImm.cs
new file mode 100644
index 00000000..72fca59c
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdImm.cs
@@ -0,0 +1,37 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdImm : OpCode32, IOpCode32SimdImm
+ {
+ public int Vd { get; private set; }
+ public bool Q { get; private set; }
+ public long Immediate { get; private set; }
+ public int Size { get; private set; }
+ public int Elems => GetBytesCount() >> Size;
+
+ public OpCode32SimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Vd = (opCode >> 12) & 0xf;
+ Vd |= (opCode >> 18) & 0x10;
+
+ Q = ((opCode >> 6) & 0x1) > 0;
+
+ int cMode = (opCode >> 8) & 0xf;
+ int op = (opCode >> 5) & 0x1;
+
+ long imm;
+
+ imm = ((uint)opCode >> 0) & 0xf;
+ imm |= ((uint)opCode >> 12) & 0x70;
+ imm |= ((uint)opCode >> 17) & 0x80;
+
+ (Immediate, Size) = OpCodeSimdHelper.GetSimdImmediateAndSize(cMode, op, imm, fpBaseSize: 2);
+
+ RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
+
+ if (DecoderHelper.VectorArgumentsInvalid(Q, Vd))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdImm44.cs b/ARMeilleure/Decoders/OpCode32SimdImm44.cs
new file mode 100644
index 00000000..f8f73bbb
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdImm44.cs
@@ -0,0 +1,36 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdImm44 : OpCode32, IOpCode32SimdImm
+ {
+ public int Vd { get; private set; }
+ public long Immediate { get; private set; }
+ public int Size { get; private set; }
+ public int Elems { get; private set; }
+
+ public OpCode32SimdImm44(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Size = (opCode >> 8) & 0x3;
+
+ bool single = Size != 3;
+
+ if (single)
+ {
+ Vd = ((opCode >> 22) & 0x1) | ((opCode >> 11) & 0x1e);
+ }
+ else
+ {
+ Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
+ }
+
+ long imm;
+
+ imm = ((uint)opCode >> 0) & 0xf;
+ imm |= ((uint)opCode >> 12) & 0xf0;
+
+ Immediate = (Size == 3) ? (long)DecoderHelper.Imm8ToFP64Table[(int)imm] : DecoderHelper.Imm8ToFP32Table[(int)imm];
+
+ RegisterSize = (!single) ? RegisterSize.Int64 : RegisterSize.Int32;
+ Elems = 1;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdMemImm.cs b/ARMeilleure/Decoders/OpCode32SimdMemImm.cs
new file mode 100644
index 00000000..630566cc
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdMemImm.cs
@@ -0,0 +1,35 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdMemImm : OpCode32, IOpCode32Simd
+ {
+ public int Vd { get; private set; }
+ public int Rn { get; private set; }
+ public int Size { get; private set; }
+ public bool Add { get; private set; }
+ public int Immediate { get; private set; }
+
+ public OpCode32SimdMemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Immediate = opCode & 0xff;
+
+ Rn = (opCode >> 16) & 0xf;
+ Size = (opCode >> 8) & 0x3;
+
+ Immediate <<= (Size == 1) ? 1 : 2;
+
+ bool u = (opCode & (1 << 23)) != 0;
+ Add = u;
+
+ bool single = Size != 3;
+
+ if (single)
+ {
+ Vd = ((opCode >> 22) & 0x1) | ((opCode >> 11) & 0x1e);
+ }
+ else
+ {
+ Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdMemMult.cs b/ARMeilleure/Decoders/OpCode32SimdMemMult.cs
new file mode 100644
index 00000000..9d43a71e
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdMemMult.cs
@@ -0,0 +1,71 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdMemMult : OpCode32
+ {
+ public int Rn { get; private set; }
+ public int Vd { get; private set; }
+
+ public int RegisterRange { get; private set; }
+ public int Offset { get; private set; }
+ public int PostOffset { get; private set; }
+ public bool IsLoad { get; private set; }
+ public bool DoubleWidth { get; private set; }
+ public bool Add { get; private set; }
+
+ public OpCode32SimdMemMult(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;
+
+ if (p == u && w)
+ {
+ Instruction = InstDescriptor.Undefined;
+ return;
+ }
+
+ DoubleWidth = (opCode & (1 << 8)) != 0;
+
+ if (!DoubleWidth)
+ {
+ Vd = ((opCode >> 22) & 0x1) | ((opCode >> 11) & 0x1e);
+ }
+ else
+ {
+ Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
+ }
+
+ Add = u;
+
+ RegisterRange = opCode & 0xff;
+
+ int regsSize = RegisterRange * 4; // Double mode is still measured in single register size.
+
+ if (!u)
+ {
+ Offset -= regsSize;
+ }
+
+ if (w)
+ {
+ PostOffset = u ? regsSize : -regsSize;
+ }
+ else
+ {
+ PostOffset = 0;
+ }
+
+ IsLoad = isLoad;
+
+ int regs = DoubleWidth ? RegisterRange / 2 : RegisterRange;
+
+ if (RegisterRange == 0 || RegisterRange > 32 || Vd + regs > 32)
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdMemPair.cs b/ARMeilleure/Decoders/OpCode32SimdMemPair.cs
new file mode 100644
index 00000000..93320e7f
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdMemPair.cs
@@ -0,0 +1,46 @@
+using ARMeilleure.State;
+using System;
+
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
+ {
+ private static int[] RegsMap =
+ {
+ 1, 1, 4, 2,
+ 1, 1, 3, 1,
+ 1, 1, 2, 1,
+ 1, 1, 1, 1
+ };
+
+ public int Vd { get; private set; }
+ public int Rn { get; private set; }
+ public int Rm { get; private set; }
+ public int Align { get; private set; }
+ public bool WBack { get; private set; }
+ public bool RegisterIndex { get; private set; }
+ public int Size { get; private set; }
+ public int Elems => 8 >> Size;
+ public int Regs { get; private set; }
+ public int Increment { get; private set; }
+
+ public OpCode32SimdMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Vd = (opCode >> 12) & 0xf;
+ Vd |= (opCode >> 18) & 0x10;
+
+ Size = (opCode >> 6) & 0x3;
+
+ Align = (opCode >> 4) & 0x3;
+ Rm = (opCode >> 0) & 0xf;
+ Rn = (opCode >> 16) & 0xf;
+
+ WBack = Rm != RegisterAlias.Aarch32Pc;
+ RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp;
+
+ Regs = RegsMap[(opCode >> 8) & 0xf];
+
+ Increment = Math.Min(Regs, ((opCode >> 8) & 0x1) + 1);
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs b/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs
new file mode 100644
index 00000000..8cdd3743
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdMemSingle.cs
@@ -0,0 +1,46 @@
+using ARMeilleure.State;
+
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdMemSingle : OpCode32, IOpCode32Simd
+ {
+ public int Vd { get; private set; }
+ public int Rn { get; private set; }
+ public int Rm { get; private set; }
+ public int IndexAlign { get; private set; }
+ public int Index { get; private set; }
+ public bool WBack { get; private set; }
+ public bool RegisterIndex { get; private set; }
+ public int Size { get; private set; }
+ public bool Replicate { get; private set; }
+ public int Increment { get; private set; }
+
+ public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Vd = (opCode >> 12) & 0xf;
+ Vd |= (opCode >> 18) & 0x10;
+
+ IndexAlign = (opCode >> 4) & 0xf;
+
+ Size = (opCode >> 10) & 0x3;
+ Replicate = Size == 3;
+ if (Replicate)
+ {
+ Size = (opCode >> 6) & 0x3;
+ Increment = ((opCode >> 5) & 1) + 1;
+ Index = 0;
+ }
+ else
+ {
+ Increment = (((IndexAlign >> Size) & 1) == 0) ? 1 : 2;
+ Index = IndexAlign >> (1 + Size);
+ }
+
+ Rm = (opCode >> 0) & 0xf;
+ Rn = (opCode >> 16) & 0xf;
+
+ WBack = Rm != RegisterAlias.Aarch32Pc;
+ RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdMovGp.cs b/ARMeilleure/Decoders/OpCode32SimdMovGp.cs
new file mode 100644
index 00000000..918291a1
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdMovGp.cs
@@ -0,0 +1,26 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdMovGp : OpCode32, IOpCode32Simd
+ {
+ public int Size => 2;
+
+ public int Vn { get; private set; }
+ public int Rt { get; private set; }
+ public int Op { get; private set; }
+
+ public int Opc1 { get; private set; }
+ public int Opc2 { get; private set; }
+
+ public OpCode32SimdMovGp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ // Which one is used is instruction dependant.
+ Op = (opCode >> 20) & 0x1;
+
+ Opc1 = (opCode >> 21) & 0x3;
+ Opc2 = (opCode >> 5) & 0x3;
+
+ Vn = ((opCode >> 7) & 0x1) | ((opCode >> 15) & 0x1e);
+ Rt = (opCode >> 12) & 0xf;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdMovGpDouble.cs b/ARMeilleure/Decoders/OpCode32SimdMovGpDouble.cs
new file mode 100644
index 00000000..5f2725e1
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdMovGpDouble.cs
@@ -0,0 +1,31 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdMovGpDouble : OpCode32, IOpCode32Simd
+ {
+ public int Size => 3;
+
+ public int Vm { get; private set; }
+ public int Rt { get; private set; }
+ public int Rt2 { get; private set; }
+ public int Op { get; private set; }
+
+ public OpCode32SimdMovGpDouble(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ // Which one is used is instruction dependant.
+ Op = (opCode >> 20) & 0x1;
+
+ Rt = (opCode >> 12) & 0xf;
+ Rt2 = (opCode >> 16) & 0xf;
+
+ bool single = (opCode & (1 << 8)) == 0;
+ if (single)
+ {
+ Vm = ((opCode >> 5) & 0x1) | ((opCode << 1) & 0x1e);
+ }
+ else
+ {
+ Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf);
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdMovGpElem.cs b/ARMeilleure/Decoders/OpCode32SimdMovGpElem.cs
new file mode 100644
index 00000000..350d5c84
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdMovGpElem.cs
@@ -0,0 +1,46 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdMovGpElem : OpCode32, IOpCode32Simd
+ {
+ public int Size { get; private set; }
+
+ public int Vd { get; private set; }
+ public int Rt { get; private set; }
+ public int Op { get; private set; }
+ public bool U { get; private set; }
+
+ public int Index { get; private set; }
+
+ public OpCode32SimdMovGpElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Op = (opCode >> 20) & 0x1;
+ U = ((opCode >> 23) & 1) != 0;
+
+ var opc = (((opCode >> 23) & 1) << 4) | (((opCode >> 21) & 0x3) << 2) | ((opCode >> 5) & 0x3);
+
+ if ((opc & 0b01000) == 0b01000)
+ {
+ Size = 0;
+ Index = opc & 0x7;
+ }
+ else if ((opc & 0b01001) == 0b00001)
+ {
+ Size = 1;
+ Index = (opc >> 1) & 0x3;
+ }
+ else if ((opc & 0b11011) == 0)
+ {
+ Size = 2;
+ Index = (opc >> 2) & 0x1;
+ }
+ else
+ {
+ Instruction = InstDescriptor.Undefined;
+ return;
+ }
+
+ Vd = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);
+ Rt = (opCode >> 12) & 0xf;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdReg.cs b/ARMeilleure/Decoders/OpCode32SimdReg.cs
new file mode 100644
index 00000000..da1d2e36
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdReg.cs
@@ -0,0 +1,22 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdReg : OpCode32Simd
+ {
+ public int Vn { get; private set; }
+
+ public int Qn => GetQuadwordIndex(Vn);
+ public int In => GetQuadwordSubindex(Vn) << (3 - Size);
+ public int Fn => GetQuadwordSubindex(Vn) << (1 - (Size & 1));
+
+ public OpCode32SimdReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);
+
+ // Subclasses have their own handling of Vx to account for before checking.
+ if (GetType() == typeof(OpCode32SimdReg) && DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm, Vn))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdRegElem.cs b/ARMeilleure/Decoders/OpCode32SimdRegElem.cs
new file mode 100644
index 00000000..4bf15cca
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdRegElem.cs
@@ -0,0 +1,21 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdRegElem : OpCode32SimdReg
+ {
+ public OpCode32SimdRegElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Q = ((opCode >> 24) & 0x1) != 0;
+ F = ((opCode >> 8) & 0x1) != 0;
+ Size = ((opCode >> 20) & 0x3);
+
+ RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
+
+ Vm = ((opCode >> 5) & 0x1) | ((opCode << 1) & 0x1e);
+
+ if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vn) || Size == 0 || (Size == 1 && F))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdRegS.cs b/ARMeilleure/Decoders/OpCode32SimdRegS.cs
new file mode 100644
index 00000000..b4ffad80
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdRegS.cs
@@ -0,0 +1,20 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdRegS : OpCode32SimdS
+ {
+ public int Vn { get; private set; }
+
+ public OpCode32SimdRegS(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ bool single = Size != 3;
+ if (single)
+ {
+ Vn = ((opCode >> 7) & 0x1) | ((opCode >> 15) & 0x1e);
+ }
+ else
+ {
+ Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdRev.cs b/ARMeilleure/Decoders/OpCode32SimdRev.cs
new file mode 100644
index 00000000..6cdf9f57
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdRev.cs
@@ -0,0 +1,14 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdRev : OpCode32SimdCmpZ
+ {
+ public OpCode32SimdRev(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ // Currently, this instruction is treated as though it's OPCODE is the true size,
+ // which lets us deal with reversing vectors on a single element basis (eg. math magic an I64 rather than insert lots of I8s).
+ int tempSize = Size;
+ Size = 3 - Opc; // Op 0 is 64 bit, 1 is 32 and so on.
+ Opc = tempSize;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdS.cs b/ARMeilleure/Decoders/OpCode32SimdS.cs
new file mode 100644
index 00000000..2e860d9c
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdS.cs
@@ -0,0 +1,31 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdS : OpCode32, IOpCode32Simd
+ {
+ public int Vd { get; private set; }
+ public int Vm { get; private set; }
+ public int Opc { get; protected set; }
+ public int Size { get; protected set; }
+
+ public OpCode32SimdS(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Opc = (opCode >> 15) & 0x3;
+ Size = (opCode >> 8) & 0x3;
+
+ bool single = Size != 3;
+
+ RegisterSize = single ? RegisterSize.Int32 : RegisterSize.Int64;
+
+ if (single)
+ {
+ Vm = ((opCode >> 5) & 0x1) | ((opCode << 1) & 0x1e);
+ Vd = ((opCode >> 22) & 0x1) | ((opCode >> 11) & 0x1e);
+ }
+ else
+ {
+ Vm = ((opCode >> 1) & 0x10) | ((opCode >> 0) & 0xf);
+ Vd = ((opCode >> 18) & 0x10) | ((opCode >> 12) & 0xf);
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdSel.cs b/ARMeilleure/Decoders/OpCode32SimdSel.cs
new file mode 100644
index 00000000..aefe138f
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdSel.cs
@@ -0,0 +1,20 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdSel : OpCode32SimdRegS
+ {
+ public OpCode32SimdSelMode Cc { get; private set; }
+
+ public OpCode32SimdSel(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Cc = (OpCode32SimdSelMode)((opCode >> 20) & 3);
+ }
+ }
+
+ enum OpCode32SimdSelMode : int
+ {
+ Eq = 0,
+ Vs,
+ Ge,
+ Gt
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdShImm.cs b/ARMeilleure/Decoders/OpCode32SimdShImm.cs
new file mode 100644
index 00000000..b19a601f
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdShImm.cs
@@ -0,0 +1,44 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdShImm : OpCode32Simd
+ {
+ public int Immediate { get; private set; }
+ public int Shift { get; private set; }
+
+ public OpCode32SimdShImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Immediate = (opCode >> 16) & 0x3f;
+ var limm = ((opCode >> 1) & 0x40) | Immediate;
+
+ if ((limm & 0x40) == 0b1000000)
+ {
+ Size = 3;
+ Shift = Immediate;
+ }
+ else if ((limm & 0x60) == 0b0100000)
+ {
+ Size = 2;
+ Shift = Immediate - 32;
+ }
+ else if ((limm & 0x70) == 0b0010000)
+ {
+ Size = 1;
+ Shift = Immediate - 16;
+ }
+ else if ((limm & 0x78) == 0b0001000)
+ {
+ Size = 0;
+ Shift = Immediate - 8;
+ }
+ else
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+
+ if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdSpecial.cs b/ARMeilleure/Decoders/OpCode32SimdSpecial.cs
new file mode 100644
index 00000000..986afcf9
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdSpecial.cs
@@ -0,0 +1,14 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdSpecial : OpCode32
+ {
+ public int Rt { get; private set; }
+ public int Sreg { get; private set; }
+
+ public OpCode32SimdSpecial(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Rt = (opCode >> 12) & 0xf;
+ Sreg = (opCode >> 16) & 0xf;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdSqrte.cs b/ARMeilleure/Decoders/OpCode32SimdSqrte.cs
new file mode 100644
index 00000000..9eb7f775
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdSqrte.cs
@@ -0,0 +1,16 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdSqrte : OpCode32Simd
+ {
+ public OpCode32SimdSqrte(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Size = (opCode >> 18) & 0x1;
+ F = ((opCode >> 8) & 0x1) != 0;
+
+ if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32SimdTbl.cs b/ARMeilleure/Decoders/OpCode32SimdTbl.cs
new file mode 100644
index 00000000..e59627c3
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32SimdTbl.cs
@@ -0,0 +1,21 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32SimdTbl : OpCode32SimdReg
+ {
+ public int Length { get; private set; }
+
+ public OpCode32SimdTbl(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Length = (opCode >> 8) & 3;
+ Size = 0;
+ Opc = Q ? 1 : 0;
+ Q = false;
+ RegisterSize = RegisterSize.Simd64;
+
+ if (Vn + Length + 1 > 32)
+ {
+ Instruction = InstDescriptor.Undefined;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCode32System.cs b/ARMeilleure/Decoders/OpCode32System.cs
new file mode 100644
index 00000000..bf438301
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32System.cs
@@ -0,0 +1,26 @@
+namespace ARMeilleure.Decoders
+{
+ class OpCode32System : OpCode32
+ {
+ public int Opc1 { get; private set; }
+ public int CRn { get; private set; }
+ public int Rt { get; private set; }
+ public int Opc2 { get; private set; }
+ public int CRm { get; private set; }
+ public int MrrcOp { get; private set; }
+
+ public int Coproc { get; private set; }
+
+ public OpCode32System(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+ {
+ Opc1 = (opCode >> 21) & 0x7;
+ CRn = (opCode >> 16) & 0xf;
+ Rt = (opCode >> 12) & 0xf;
+ Opc2 = (opCode >> 5) & 0x7;
+ CRm = (opCode >> 0) & 0xf;
+ MrrcOp = (opCode >> 4) & 0xf;
+
+ Coproc = (opCode >> 8) & 0xf;
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCodeSimdHelper.cs b/ARMeilleure/Decoders/OpCodeSimdHelper.cs
new file mode 100644
index 00000000..3e5a7f65
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeSimdHelper.cs
@@ -0,0 +1,88 @@
+namespace ARMeilleure.Decoders
+{
+ public static class OpCodeSimdHelper
+ {
+ public static (long Immediate, int Size) GetSimdImmediateAndSize(int cMode, int op, long imm, int fpBaseSize = 0)
+ {
+ int modeLow = cMode & 1;
+ int modeHigh = cMode >> 1;
+ int size = 0;
+
+ if (modeHigh == 0b111)
+ {
+ switch (op | (modeLow << 1))
+ {
+ case 0:
+ // 64-bits Immediate.
+ // Transform abcd efgh into abcd efgh abcd efgh ...
+ size = 3;
+ imm = (long)((ulong)imm * 0x0101010101010101);
+ break;
+
+ case 1:
+ // 64-bits Immediate.
+ // Transform abcd efgh into aaaa aaaa bbbb bbbb ...
+ size = 3;
+ 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:
+ // 2 x 32-bits floating point Immediate.
+ size = 3;
+ imm = (long)DecoderHelper.Imm8ToFP32Table[(int)imm];
+ imm |= imm << 32;
+ break;
+
+ case 3:
+ // 64-bits floating point Immediate.
+ size = 3;
+ imm = (long)DecoderHelper.Imm8ToFP64Table[(int)imm];
+ 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;
+ }
+
+ return (imm, size);
+ }
+
+ private static long ShlOnes(long value, int shift)
+ {
+ if (shift != 0)
+ {
+ return value << shift | (long)(ulong.MaxValue >> (64 - shift));
+ }
+ else
+ {
+ return value;
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs
index 2fa7702d..3915ac87 100644
--- a/ARMeilleure/Decoders/OpCodeTable.cs
+++ b/ARMeilleure/Decoders/OpCodeTable.cs
@@ -599,32 +599,283 @@ namespace ARMeilleure.Decoders
#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));
+ SetA32("<<<<0010101xxxxxxxxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, typeof(OpCode32AluImm));
+ SetA32("<<<<0000101xxxxxxxxxxxxxxxx0xxxx", InstName.Adc, InstEmit32.Adc, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0000101xxxxxxxxxxxxx0xx1xxxx", InstName.Adc, InstEmit32.Adc, typeof(OpCode32AluRsReg));
+ SetA32("<<<<0010100xxxxxxxxxxxxxxxxxxxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluImm));
+ SetA32("<<<<0000100xxxxxxxxxxxxxxxx0xxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0000100xxxxxxxxxxxxx0xx1xxxx", InstName.Add, InstEmit32.Add, typeof(OpCode32AluRsReg));
+ SetA32("<<<<0010000xxxxxxxxxxxxxxxxxxxxx", InstName.And, InstEmit32.And, typeof(OpCode32AluImm));
+ SetA32("<<<<0000000xxxxxxxxxxxxxxxx0xxxx", InstName.And, InstEmit32.And, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0000000xxxxxxxxxxxxx0xx1xxxx", InstName.And, InstEmit32.And, typeof(OpCode32AluRsReg));
+ SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", InstName.B, InstEmit32.B, typeof(OpCode32BImm));
+ SetA32("<<<<0111110xxxxxxxxxxxxxx0011111", InstName.Bfc, InstEmit32.Bfc, typeof(OpCode32AluBf));
+ SetA32("<<<<0111110xxxxxxxxxxxxxx001xxxx", InstName.Bfi, InstEmit32.Bfi, typeof(OpCode32AluBf));
+ SetA32("<<<<0011110xxxxxxxxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, typeof(OpCode32AluImm));
+ SetA32("<<<<0001110xxxxxxxxxxxxxxxx0xxxx", InstName.Bic, InstEmit32.Bic, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0001110xxxxxxxxxxxxx0xx1xxxx", InstName.Bic, InstEmit32.Bic, typeof(OpCode32AluRsReg));
+ SetA32("<<<<1011xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bl, InstEmit32.Bl, typeof(OpCode32BImm));
+ SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Blx, InstEmit32.Blx, typeof(OpCode32BImm));
+ SetA32("<<<<000100101111111111110011xxxx", InstName.Blx, InstEmit32.Blxr, typeof(OpCode32BReg));
+ SetA32("<<<<000100101111111111110001xxxx", InstName.Bx, InstEmit32.Bx, typeof(OpCode32BReg));
+ SetT32("xxxxxxxxxxxxxxxx010001110xxxx000", InstName.Bx, InstEmit32.Bx, typeof(OpCodeT16BReg));
+ SetA32("11110101011111111111000000011111", InstName.Clrex, InstEmit32.Clrex, typeof(OpCode32));
+ SetA32("<<<<000101101111xxxx11110001xxxx", InstName.Clz, InstEmit32.Clz, typeof(OpCode32AluReg));
+ SetA32("<<<<00110111xxxx0000xxxxxxxxxxxx", InstName.Cmn, InstEmit32.Cmn, typeof(OpCode32AluImm));
+ SetA32("<<<<00010111xxxx0000xxxxxxx0xxxx", InstName.Cmn, InstEmit32.Cmn, typeof(OpCode32AluRsImm));
+ SetA32("<<<<00110101xxxx0000xxxxxxxxxxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluImm));
+ SetA32("<<<<00010101xxxx0000xxxxxxx0xxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluRsImm));
+ SetA32("<<<<00010101xxxx0000xxxx0xx1xxxx", InstName.Cmp, InstEmit32.Cmp, typeof(OpCode32AluRsReg));
+ SetA32("1111010101111111111100000101xxxx", InstName.Dmb, InstEmit32.Dmb, typeof(OpCode32));
+ SetA32("1111010101111111111100000100xxxx", InstName.Dsb, InstEmit32.Dsb, typeof(OpCode32));
+ SetA32("<<<<0010001xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit32.Eor, typeof(OpCode32AluImm));
+ SetA32("<<<<0000001xxxxxxxxxxxxxxxx0xxxx", InstName.Eor, InstEmit32.Eor, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0000001xxxxxxxxxxxxx0xx1xxxx", InstName.Eor, InstEmit32.Eor, typeof(OpCode32AluRsReg));
+ SetA32("1111010101111111111100000110xxxx", InstName.Isb, InstEmit32.Nop, typeof(OpCode32));
+ SetA32("<<<<00011001xxxxxxxx110010011111", InstName.Lda, InstEmit32.Lda, typeof(OpCode32MemLdEx));
+ SetA32("<<<<00011101xxxxxxxx110010011111", InstName.Ldab, InstEmit32.Ldab, typeof(OpCode32MemLdEx));
+ SetA32("<<<<00011001xxxxxxxx111010011111", InstName.Ldaex, InstEmit32.Ldaex, typeof(OpCode32MemLdEx));
+ SetA32("<<<<00011101xxxxxxxx111010011111", InstName.Ldaexb, InstEmit32.Ldaexb, typeof(OpCode32MemLdEx));
+ SetA32("<<<<00011011xxxxxxxx111010011111", InstName.Ldaexd, InstEmit32.Ldaexd, typeof(OpCode32MemLdEx));
+ SetA32("<<<<00011111xxxxxxxx111010011111", InstName.Ldaexh, InstEmit32.Ldaexh, typeof(OpCode32MemLdEx));
+ SetA32("<<<<00011111xxxxxxxx110010011111", InstName.Ldah, InstEmit32.Ldah, typeof(OpCode32MemLdEx));
+ SetA32("<<<<100xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, typeof(OpCode32MemMult));
+ SetA32("<<<<010xx0x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, typeof(OpCode32MemImm));
+ SetA32("<<<<011xx0x1xxxxxxxxxxxxxxx0xxxx", InstName.Ldr, InstEmit32.Ldr, typeof(OpCode32MemRsImm));
+ SetA32("<<<<010xx1x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, typeof(OpCode32MemImm));
+ SetA32("<<<<011xx1x1xxxxxxxxxxxxxxx0xxxx", InstName.Ldrb, InstEmit32.Ldrb, typeof(OpCode32MemRsImm));
+ SetA32("<<<<000xx1x0xxxxxxxxxxxx1101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemImm8));
+ SetA32("<<<<000xx0x0xxxxxxxx00001101xxxx", InstName.Ldrd, InstEmit32.Ldrd, typeof(OpCode32MemReg));
+ SetA32("<<<<00011001xxxxxxxx111110011111", InstName.Ldrex, InstEmit32.Ldrex, typeof(OpCode32MemLdEx));
+ SetA32("<<<<00011101xxxxxxxx111110011111", InstName.Ldrexb, InstEmit32.Ldrexb, typeof(OpCode32MemLdEx));
+ SetA32("<<<<00011011xxxxxxxx111110011111", InstName.Ldrexd, InstEmit32.Ldrexd, typeof(OpCode32MemLdEx));
+ SetA32("<<<<00011111xxxxxxxx111110011111", InstName.Ldrexh, InstEmit32.Ldrexh, typeof(OpCode32MemLdEx));
+ SetA32("<<<<000xx1x1xxxxxxxxxxxx1011xxxx", InstName.Ldrh, InstEmit32.Ldrh, typeof(OpCode32MemImm8));
+ SetA32("<<<<000xx0x1xxxxxxxx00001011xxxx", InstName.Ldrh, InstEmit32.Ldrh, typeof(OpCode32MemReg));
+ SetA32("<<<<000xx1x1xxxxxxxxxxxx1101xxxx", InstName.Ldrsb, InstEmit32.Ldrsb, typeof(OpCode32MemImm8));
+ SetA32("<<<<000xx0x1xxxxxxxx00001101xxxx", InstName.Ldrsb, InstEmit32.Ldrsb, typeof(OpCode32MemReg));
+ SetA32("<<<<000xx1x1xxxxxxxxxxxx1111xxxx", InstName.Ldrsh, InstEmit32.Ldrsh, typeof(OpCode32MemImm8));
+ SetA32("<<<<000xx0x1xxxxxxxx00001111xxxx", InstName.Ldrsh, InstEmit32.Ldrsh, typeof(OpCode32MemReg));
+ SetA32("<<<<1110xxx0xxxxxxxx111xxxx1xxxx", InstName.Mcr, InstEmit32.Mcr, typeof(OpCode32System));
+ SetA32("<<<<0000001xxxxxxxxxxxxx1001xxxx", InstName.Mla, InstEmit32.Mla, typeof(OpCode32AluMla));
+ SetA32("<<<<00000110xxxxxxxxxxxx1001xxxx", InstName.Mls, InstEmit32.Mls, typeof(OpCode32AluMla));
+ SetA32("<<<<0011101x0000xxxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluImm));
+ SetA32("<<<<0001101x0000xxxxxxxxxxx0xxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0001101x0000xxxxxxxx0xx1xxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluRsReg));
+ SetA32("<<<<00110000xxxxxxxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCode32AluImm16));
+ SetT32("xxxxxxxxxxxxxxxx00100xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, typeof(OpCodeT16AluImm8));
+ SetA32("<<<<00110100xxxxxxxxxxxxxxxxxxxx", InstName.Movt, InstEmit32.Movt, typeof(OpCode32AluImm16));
+ SetA32("<<<<1110xxx1xxxxxxxx111xxxx1xxxx", InstName.Mrc, InstEmit32.Mrc, typeof(OpCode32System));
+ SetA32("<<<<11000101xxxxxxxx111xxxxxxxxx", InstName.Mrrc, InstEmit32.Mrrc, typeof(OpCode32System));
+ SetA32("<<<<0000000xxxxx0000xxxx1001xxxx", InstName.Mul, InstEmit32.Mul, typeof(OpCode32AluMla));
+ SetA32("<<<<0011111x0000xxxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, typeof(OpCode32AluImm));
+ SetA32("<<<<0001111x0000xxxxxxxxxxx0xxxx", InstName.Mvn, InstEmit32.Mvn, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0001111x0000xxxxxxxx0xx1xxxx", InstName.Mvn, InstEmit32.Mvn, typeof(OpCode32AluRsReg));
+ SetA32("<<<<0011100xxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, typeof(OpCode32AluImm));
+ SetA32("<<<<0001100xxxxxxxxxxxxxxxx0xxxx", InstName.Orr, InstEmit32.Orr, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0001100xxxxxxxxxxxxx0xx1xxxx", InstName.Orr, InstEmit32.Orr, typeof(OpCode32AluRsReg));
+ SetA32("<<<<01101000xxxxxxxxxxxxxx01xxxx", InstName.Pkh, InstEmit32.Pkh, typeof(OpCode32AluRsImm));
+ SetA32("11110101xx01xxxx1111xxxxxxxxxxxx", InstName.Pld, InstEmit32.Nop, typeof(OpCode32));
+ SetA32("11110111xx01xxxx1111xxxxxxx0xxxx", InstName.Pld, InstEmit32.Nop, typeof(OpCode32));
+ SetA32("<<<<011011111111xxxx11110011xxxx", InstName.Rbit, InstEmit32.Rbit, typeof(OpCode32AluReg));
+ SetA32("<<<<011010111111xxxx11110011xxxx", InstName.Rev, InstEmit32.Rev, typeof(OpCode32AluReg));
+ SetA32("<<<<011010111111xxxx11111011xxxx", InstName.Rev16, InstEmit32.Rev16, typeof(OpCode32AluReg));
+ SetA32("<<<<011011111111xxxx11111011xxxx", InstName.Revsh, InstEmit32.Revsh, typeof(OpCode32AluReg));
+ SetA32("<<<<0010011xxxxxxxxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluImm));
+ SetA32("<<<<0000011xxxxxxxxxxxxxxxx0xxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0000011xxxxxxxxxxxxx0xx1xxxx", InstName.Rsb, InstEmit32.Rsb, typeof(OpCode32AluRsReg));
+ SetA32("<<<<0010111xxxxxxxxxxxxxxxxxxxxx", InstName.Rsc, InstEmit32.Rsc, typeof(OpCode32AluImm));
+ SetA32("<<<<0000111xxxxxxxxxxxxxxxx0xxxx", InstName.Rsc, InstEmit32.Rsc, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0000111xxxxxxxxxxxxx0xx1xxxx", InstName.Rsc, InstEmit32.Rsc, typeof(OpCode32AluRsReg));
+ SetA32("<<<<0010110xxxxxxxxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluImm));
+ SetA32("<<<<0000110xxxxxxxxxxxxxxxx0xxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, typeof(OpCode32AluRsReg));
+ SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, typeof(OpCode32AluBf));
+ SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, typeof(OpCode32AluMla));
+ SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smlab, InstEmit32.Smlab, typeof(OpCode32AluMla));
+ SetA32("<<<<0000111xxxxxxxxxxxxx1001xxxx", InstName.Smlal, InstEmit32.Smlal, typeof(OpCode32AluUmull));
+ SetA32("<<<<00010100xxxxxxxxxxxx1xx0xxxx", InstName.Smlalh, InstEmit32.Smlalh, typeof(OpCode32AluUmull));
+ SetA32("<<<<01110101xxxxxxxxxxxx00x1xxxx", InstName.Smmla, InstEmit32.Smmla, typeof(OpCode32AluMla));
+ SetA32("<<<<01110101xxxxxxxxxxxx11x1xxxx", InstName.Smmls, InstEmit32.Smmls, typeof(OpCode32AluMla));
+ SetA32("<<<<00010110xxxxxxxxxxxx1xx0xxxx", InstName.Smulh, InstEmit32.Smulh, typeof(OpCode32AluMla));
+ SetA32("<<<<0000110xxxxxxxxxxxxx1001xxxx", InstName.Smull, InstEmit32.Smull, typeof(OpCode32AluUmull));
+ SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, typeof(OpCode32MemStEx));
+ SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, typeof(OpCode32MemStEx));
+ SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, typeof(OpCode32MemStEx));
+ SetA32("<<<<00011100xxxxxxxx11101001xxxx", InstName.Stlexb, InstEmit32.Stlexb, typeof(OpCode32MemStEx));
+ SetA32("<<<<00011010xxxxxxxx11101001xxxx", InstName.Stlexd, InstEmit32.Stlexd, typeof(OpCode32MemStEx));
+ SetA32("<<<<00011110xxxxxxxx11101001xxxx", InstName.Stlexh, InstEmit32.Stlexh, typeof(OpCode32MemStEx));
+ SetA32("<<<<00011110xxxx111111001001xxxx", InstName.Stlh, InstEmit32.Stlh, typeof(OpCode32MemStEx));
+ SetA32("<<<<100xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, typeof(OpCode32MemMult));
+ SetA32("<<<<010xx0x0xxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, typeof(OpCode32MemImm));
+ SetA32("<<<<011xx0x0xxxxxxxxxxxxxxx0xxxx", InstName.Str, InstEmit32.Str, typeof(OpCode32MemRsImm));
+ SetA32("<<<<010xx1x0xxxxxxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, typeof(OpCode32MemImm));
+ SetA32("<<<<011xx1x0xxxxxxxxxxxxxxx0xxxx", InstName.Strb, InstEmit32.Strb, typeof(OpCode32MemRsImm));
+ SetA32("<<<<000xx1x0xxxxxxxxxxxx1111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemImm8));
+ SetA32("<<<<000xx0x0xxxxxxxx00001111xxxx", InstName.Strd, InstEmit32.Strd, typeof(OpCode32MemReg));
+ SetA32("<<<<00011000xxxxxxxx11111001xxxx", InstName.Strex, InstEmit32.Strex, typeof(OpCode32MemStEx));
+ SetA32("<<<<00011100xxxxxxxx11111001xxxx", InstName.Strexb, InstEmit32.Strexb, typeof(OpCode32MemStEx));
+ SetA32("<<<<00011010xxxxxxxx11111001xxxx", InstName.Strexd, InstEmit32.Strexd, typeof(OpCode32MemStEx));
+ SetA32("<<<<00011110xxxxxxxx11111001xxxx", InstName.Strexh, InstEmit32.Strexh, typeof(OpCode32MemStEx));
+ SetA32("<<<<000xx1x0xxxxxxxxxxxx1011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemImm8));
+ SetA32("<<<<000xx0x0xxxxxxxx00001011xxxx", InstName.Strh, InstEmit32.Strh, typeof(OpCode32MemReg));
+ SetA32("<<<<0010010xxxxxxxxxxxxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluImm));
+ SetA32("<<<<0000010xxxxxxxxxxxxxxxx0xxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluRsImm));
+ SetA32("<<<<0000010xxxxxxxxxxxxx0xx1xxxx", InstName.Sub, InstEmit32.Sub, typeof(OpCode32AluRsReg));
+ SetA32("<<<<1111xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Svc, InstEmit32.Svc, typeof(OpCode32Exception));
+ SetA32("<<<<01101010xxxxxxxxxx000111xxxx", InstName.Sxtb, InstEmit32.Sxtb, typeof(OpCode32AluUx));
+ SetA32("<<<<01101000xxxxxxxxxx000111xxxx", InstName.Sxtb16, InstEmit32.Sxtb16, typeof(OpCode32AluUx));
+ SetA32("<<<<01101011xxxxxxxxxx000111xxxx", InstName.Sxth, InstEmit32.Sxth, typeof(OpCode32AluUx));
+ SetA32("<<<<00110011xxxx0000xxxxxxxxxxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluImm));
+ SetA32("<<<<00010011xxxx0000xxxxxxx0xxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluRsImm));
+ SetA32("<<<<00010011xxxx0000xxxx0xx1xxxx", InstName.Teq, InstEmit32.Teq, typeof(OpCode32AluRsReg));
+ SetA32("<<<<0111111111111101111011111110", InstName.Trap, InstEmit32.Trap, typeof(OpCode32Exception));
+ SetA32("<<<<00110001xxxx0000xxxxxxxxxxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluImm));
+ SetA32("<<<<00010001xxxx0000xxxxxxx0xxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluRsImm));
+ SetA32("<<<<00010001xxxx0000xxxx0xx1xxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluRsReg));
+ SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, typeof(OpCode32AluBf));
+ SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, typeof(OpCode32AluMla));
+ SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, typeof(OpCode32AluUmull));
+ SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, typeof(OpCode32AluUmull));
+ SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, typeof(OpCode32AluUx));
+ SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, typeof(OpCode32AluUx));
+ SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, typeof(OpCode32AluUx));
+
+ // FP & SIMD
+ SetA32("<<<<11101x110000xxxx10xx11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, typeof(OpCode32SimdRegS));
+ SetA32("111100111x11xx01xxxx0x110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, typeof(OpCode32SimdReg));
+ SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, typeof(OpCode32SimdReg));
+ SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, typeof(OpCode32SimdRegS));
+ SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, typeof(OpCode32SimdReg));
+ SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, typeof(OpCode32SimdBinary));
+ SetA32("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, typeof(OpCode32SimdBinary));
+ SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, typeof(OpCode32SimdBinary));
+ SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, typeof(OpCode32SimdBinary));
+ SetA32("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, typeof(OpCode32SimdReg));
+ SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, typeof(OpCode32SimdReg));
+ SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, typeof(OpCode32SimdCmpZ));
+ SetA32("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, typeof(OpCode32SimdReg));
+ SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, typeof(OpCode32SimdReg));
+ SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, typeof(OpCode32SimdCmpZ));
+ SetA32("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, typeof(OpCode32SimdReg));
+ SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, typeof(OpCode32SimdReg));
+ SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, typeof(OpCode32SimdCmpZ));
+ SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, typeof(OpCode32SimdCmpZ));
+ SetA32("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, typeof(OpCode32SimdCmpZ));
+ SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, typeof(OpCode32SimdS));
+ SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, typeof(OpCode32SimdS));
+ SetA32("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, typeof(OpCode32SimdS)); // FP 32 and 64, scalar.
+ SetA32("<<<<11101x11110xxxxx10xx11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // FP32 to int.
+ SetA32("<<<<11101x111000xxxx10xxx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, typeof(OpCode32SimdCvtFI)); // Int to FP32.
+ SetA32("111111101x1111xxxxxx10>>x1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_R, typeof(OpCode32SimdCvtFI)); // The many FP32 to int encodings (fp).
+ SetA32("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, typeof(OpCode32SimdCmpZ)); // FP and integer, vector.
+ SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, typeof(OpCode32SimdRegS));
+ SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, typeof(OpCode32SimdDupGP));
+ SetA32("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, typeof(OpCode32SimdDupElem));
+ SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, typeof(OpCode32SimdExt));
+ SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemSingle));
+ SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 1.
+ SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 2.
+ SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 3.
+ SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 4.
+ SetA32("111101001x10xxxxxxxxxx01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemSingle));
+ SetA32("111101000x10xxxxxxxx100xxxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemPair)); // Regs = 1, inc = 1/2 (itype).
+ SetA32("111101000x10xxxxxxxx0011xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, typeof(OpCode32SimdMemPair)); // Regs = 2, inc = 2.
+ SetA32("111101001x10xxxxxxxxxx10xxxxxxxx", InstName.Vld3, InstEmit32.Vld3, typeof(OpCode32SimdMemSingle));
+ SetA32("111101000x10xxxxxxxx010xxxxxxxxx", InstName.Vld3, InstEmit32.Vld3, typeof(OpCode32SimdMemPair)); // Inc = 1/2 (itype).
+ SetA32("111101001x10xxxxxxxxxx11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, typeof(OpCode32SimdMemSingle));
+ SetA32("111101000x10xxxxxxxx000xxxxxxxxx", InstName.Vld4, InstEmit32.Vld4, typeof(OpCode32SimdMemPair)); // Inc = 1/2 (itype).
+ SetA32("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<11001x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<11010x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<11001x01xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<11001x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<11010x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, typeof(OpCode32SimdMemImm));
+ SetA32("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, typeof(OpCode32SimdReg));
+ SetA32("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, typeof(OpCode32SimdReg));
+ SetA32("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, typeof(OpCode32SimdReg));
+ SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, typeof(OpCode32SimdReg));
+ SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_S, typeof(OpCode32SimdRegS));
+ SetA32("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, typeof(OpCode32SimdReg));
+ SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.Vminnm_S, typeof(OpCode32SimdRegS));
+ SetA32("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, typeof(OpCode32SimdReg));
+ SetA32("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, typeof(OpCode32SimdRegElem));
+ SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, typeof(OpCode32SimdReg));
+ SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, typeof(OpCode32SimdRegS));
+ SetA32("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, typeof(OpCode32SimdReg));
+ SetA32("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, typeof(OpCode32SimdRegElem));
+ SetA32("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, typeof(OpCode32SimdRegS));
+ SetA32("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, typeof(OpCode32SimdReg));
+ SetA32("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, typeof(OpCode32SimdReg));
+ SetA32("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, typeof(OpCode32SimdMovGpElem)); // From gen purpose.
+ SetA32("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, typeof(OpCode32SimdMovGpElem)); // To gen purpose.
+ SetA32("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, typeof(OpCode32SimdMovGpDouble)); // To/from gen purpose x2 and single precision x2.
+ SetA32("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, typeof(OpCode32SimdMovGpDouble)); // To/from gen purpose x2 and double precision.
+ SetA32("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, typeof(OpCode32SimdMovGp)); // To/from gen purpose and single precision.
+ SetA32("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); // D/Q vector I32.
+ SetA32("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm44)); // Scalar f16/32/64 based on size 01 10 11.
+ SetA32("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); // D/Q I16.
+ SetA32("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); // D/Q (dt - from cmode).
+ SetA32("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, typeof(OpCode32SimdImm)); // D/Q I64.
+ SetA32("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, typeof(OpCode32SimdS));
+ SetA32("111100111x11xx10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, typeof(OpCode32SimdCmpZ));
+ SetA32("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, typeof(OpCode32SimdSpecial));
+ SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, typeof(OpCode32SimdSpecial));
+ SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, typeof(OpCode32SimdRegElem));
+ SetA32("1111001x0xxxxxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, typeof(OpCode32SimdReg));
+ SetA32("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, typeof(OpCode32SimdRegS));
+ SetA32("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, typeof(OpCode32SimdReg));
+ SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm)); // D/Q vector I32.
+ SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm));
+ SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, typeof(OpCode32SimdImm));
+ SetA32("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, typeof(OpCode32SimdS));
+ SetA32("111100111x11xx01xxxx0x111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, typeof(OpCode32Simd));
+ SetA32("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, typeof(OpCode32SimdRegS));
+ SetA32("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, typeof(OpCode32SimdRegS));
+ SetA32("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, typeof(OpCode32SimdRegS));
+ SetA32("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, typeof(OpCode32SimdBinary));
+ SetA32("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, typeof(OpCode32SimdReg));
+ SetA32("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, typeof(OpCode32SimdReg));
+ SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, typeof(OpCode32SimdSqrte));
+ SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, typeof(OpCode32SimdReg));
+ SetA32("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, typeof(OpCode32SimdRev));
+ SetA32("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, typeof(OpCode32SimdCvtFI));
+ SetA32("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, typeof(OpCode32SimdCvtFI));
+ SetA32("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, typeof(OpCode32SimdSqrte));
+ SetA32("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, typeof(OpCode32SimdReg));
+ SetA32("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, typeof(OpCode32SimdSel));
+ SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, typeof(OpCode32SimdShImm));
+ SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, typeof(OpCode32SimdReg));
+ SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, typeof(OpCode32SimdShImm));
+ SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, typeof(OpCode32SimdShImm));
+ SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, typeof(OpCode32SimdS));
+ SetA32("111101001x00xxxxxxxx<<00xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemSingle));
+ SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 1.
+ SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 2.
+ SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 3.
+ SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, typeof(OpCode32SimdMemPair)); // Regs = 4.
+ SetA32("111101001x00xxxxxxxx<<01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemSingle));
+ SetA32("111101000x00xxxxxxxx100xxxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemPair)); // Regs = 1, inc = 1/2 (itype).
+ SetA32("111101000x00xxxxxxxx0011xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, typeof(OpCode32SimdMemPair)); // Regs = 2, inc = 2.
+ SetA32("111101001x00xxxxxxxx<<10xxxxxxxx", InstName.Vst3, InstEmit32.Vst3, typeof(OpCode32SimdMemSingle));
+ SetA32("111101000x00xxxxxxxx010xxxxxxxxx", InstName.Vst3, InstEmit32.Vst3, typeof(OpCode32SimdMemPair)); // Inc = 1/2 (itype).
+ SetA32("111101001x00xxxxxxxx<<11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, typeof(OpCode32SimdMemSingle));
+ SetA32("111101000x00xxxxxxxx000xxxxxxxxx", InstName.Vst4, InstEmit32.Vst4, typeof(OpCode32SimdMemPair)); // Inc = 1/2 (itype).
+ SetA32("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<11001x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<11010x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<11001x00xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, typeof(OpCode32SimdMemMult));
+ SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, typeof(OpCode32SimdMemImm));
+ SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, typeof(OpCode32SimdReg));
+ SetA32("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, typeof(OpCode32SimdRegS));
+ SetA32("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, typeof(OpCode32SimdReg));
+ SetA32("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, typeof(OpCode32SimdTbl));
+ SetA32("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, typeof(OpCode32SimdCmpZ));
+ SetA32("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, typeof(OpCode32SimdCmpZ));
+ SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, typeof(OpCode32SimdCmpZ));
#endregion
FillFastLookupTable(_instA32FastLookup, _allInstA32);