diff --git a/ARMeilleure/Decoders/IOpCode32AluBf.cs b/ARMeilleure/Decoders/IOpCode32AluBf.cs
index 18de3eb652..206c2965e6 100644
--- a/ARMeilleure/Decoders/IOpCode32AluBf.cs
+++ b/ARMeilleure/Decoders/IOpCode32AluBf.cs
@@ -7,5 +7,8 @@
 
         int Msb { get; }
         int Lsb { get; }
+
+        int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb));
+        int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb);
     }
 }
diff --git a/ARMeilleure/Decoders/IOpCode32AluImm16.cs b/ARMeilleure/Decoders/IOpCode32AluImm16.cs
new file mode 100644
index 0000000000..cd128f657c
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32AluImm16.cs
@@ -0,0 +1,7 @@
+namespace ARMeilleure.Decoders
+{
+    interface IOpCode32AluImm16 : IOpCode32Alu
+    {
+        int Immediate { get; }
+    }
+}
\ No newline at end of file
diff --git a/ARMeilleure/Decoders/IOpCode32AluMla.cs b/ARMeilleure/Decoders/IOpCode32AluMla.cs
new file mode 100644
index 0000000000..79b1642575
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32AluMla.cs
@@ -0,0 +1,11 @@
+namespace ARMeilleure.Decoders
+{
+    interface IOpCode32AluMla : IOpCode32AluReg
+    {
+        int Ra { get; }
+
+        bool NHigh { get; }
+        bool MHigh { get; }
+        bool R { get; }
+    }
+}
diff --git a/ARMeilleure/Decoders/IOpCode32AluUmull.cs b/ARMeilleure/Decoders/IOpCode32AluUmull.cs
new file mode 100644
index 0000000000..79d2bb9ba7
--- /dev/null
+++ b/ARMeilleure/Decoders/IOpCode32AluUmull.cs
@@ -0,0 +1,13 @@
+namespace ARMeilleure.Decoders
+{
+    interface IOpCode32AluUmull : IOpCode32, IOpCode32HasSetFlags
+    {
+        int RdLo { get; }
+        int RdHi { get; }
+        int Rn { get; }
+        int Rm { get; }
+
+        bool NHigh { get; }
+        bool MHigh { get; }
+    }
+}
diff --git a/ARMeilleure/Decoders/OpCode32AluBf.cs b/ARMeilleure/Decoders/OpCode32AluBf.cs
index f8dc6db0d4..0cee34e6dd 100644
--- a/ARMeilleure/Decoders/OpCode32AluBf.cs
+++ b/ARMeilleure/Decoders/OpCode32AluBf.cs
@@ -6,12 +6,8 @@
         public int Rn { get; }
 
         public int Msb { get; }
-
         public int Lsb { get; }
 
-        public int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb));
-        public int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb);
-
         public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluBf(inst, address, opCode);
 
         public OpCode32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
diff --git a/ARMeilleure/Decoders/OpCode32AluImm16.cs b/ARMeilleure/Decoders/OpCode32AluImm16.cs
index 662482719c..e24edeb411 100644
--- a/ARMeilleure/Decoders/OpCode32AluImm16.cs
+++ b/ARMeilleure/Decoders/OpCode32AluImm16.cs
@@ -1,6 +1,6 @@
 namespace ARMeilleure.Decoders
 {
-    class OpCode32AluImm16 : OpCode32Alu
+    class OpCode32AluImm16 : OpCode32Alu, IOpCode32AluImm16
     {
         public int Immediate { get; }
 
diff --git a/ARMeilleure/Decoders/OpCode32AluMla.cs b/ARMeilleure/Decoders/OpCode32AluMla.cs
index 7489466761..2cd2b9dcc9 100644
--- a/ARMeilleure/Decoders/OpCode32AluMla.cs
+++ b/ARMeilleure/Decoders/OpCode32AluMla.cs
@@ -1,6 +1,6 @@
 namespace ARMeilleure.Decoders
 {
-    class OpCode32AluMla : OpCode32, IOpCode32AluReg
+    class OpCode32AluMla : OpCode32, IOpCode32AluMla
     {
         public int Rn { get; }
         public int Rm { get; }
diff --git a/ARMeilleure/Decoders/OpCode32AluUmull.cs b/ARMeilleure/Decoders/OpCode32AluUmull.cs
index 1b31239be0..bf80df3ffa 100644
--- a/ARMeilleure/Decoders/OpCode32AluUmull.cs
+++ b/ARMeilleure/Decoders/OpCode32AluUmull.cs
@@ -1,6 +1,6 @@
 namespace ARMeilleure.Decoders
 {
-    class OpCode32AluUmull : OpCode32, IOpCode32HasSetFlags
+    class OpCode32AluUmull : OpCode32, IOpCode32AluUmull
     {
         public int RdLo { get; }
         public int RdHi { get; }
@@ -11,7 +11,6 @@
         public bool MHigh { get; }
 
         public bool? SetFlags { get; }
-        public DataOp DataOp { get; }
 
         public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluUmull(inst, address, opCode);
 
@@ -26,7 +25,6 @@
             MHigh = ((opCode >> 6) & 0x1) == 1;
 
             SetFlags = ((opCode >> 20) & 0x1) != 0;
-            DataOp = DataOp.Arithmetic;
         }
     }
 }
diff --git a/ARMeilleure/Decoders/OpCodeT32AluBf.cs b/ARMeilleure/Decoders/OpCodeT32AluBf.cs
new file mode 100644
index 0000000000..57ad422fdb
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT32AluBf.cs
@@ -0,0 +1,22 @@
+namespace ARMeilleure.Decoders
+{
+    class OpCodeT32AluBf : OpCodeT32, IOpCode32AluBf
+    {
+        public int Rd { get; }
+        public int Rn { get; }
+
+        public int Msb { get; }
+        public int Lsb { get; }
+
+        public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluBf(inst, address, opCode);
+
+        public OpCodeT32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Rd = (opCode >> 8) & 0xf;
+            Rn = (opCode >> 16) & 0xf;
+
+            Msb = (opCode >> 0) & 0x1f;
+            Lsb = ((opCode >> 6) & 0x3) | ((opCode >> 10) & 0x1c);
+        }
+    }
+}
diff --git a/ARMeilleure/Decoders/OpCodeT32AluMla.cs b/ARMeilleure/Decoders/OpCodeT32AluMla.cs
new file mode 100644
index 0000000000..6cb604da6d
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT32AluMla.cs
@@ -0,0 +1,29 @@
+namespace ARMeilleure.Decoders
+{
+    class OpCodeT32AluMla : OpCodeT32, IOpCode32AluMla
+    {
+        public int Rn { get; }
+        public int Rm { get; }
+        public int Ra { get; }
+        public int Rd { get; }
+
+        public bool NHigh { get; }
+        public bool MHigh { get; }
+        public bool R { get; }
+        public bool? SetFlags => false;
+
+        public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluMla(inst, address, opCode);
+
+        public OpCodeT32AluMla(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Rm = (opCode >> 0) & 0xf;
+            Rd = (opCode >> 8) & 0xf;
+            Ra = (opCode >> 12) & 0xf;
+            Rn = (opCode >> 16) & 0xf;
+            R = (opCode & (1 << 4)) != 0;
+
+            MHigh = ((opCode >> 4) & 0x1) == 1;
+            NHigh = ((opCode >> 5) & 0x1) == 1;
+        }
+    }
+}
diff --git a/ARMeilleure/Decoders/OpCodeT32AluUmull.cs b/ARMeilleure/Decoders/OpCodeT32AluUmull.cs
new file mode 100644
index 0000000000..a1b2e61203
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT32AluUmull.cs
@@ -0,0 +1,28 @@
+namespace ARMeilleure.Decoders
+{
+    class OpCodeT32AluUmull : OpCodeT32, IOpCode32AluUmull
+    {
+        public int RdLo { get; }
+        public int RdHi { get; }
+        public int Rn { get; }
+        public int Rm { get; }
+
+        public bool NHigh { get; }
+        public bool MHigh { get; }
+
+        public bool? SetFlags => false;
+
+        public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluUmull(inst, address, opCode);
+
+        public OpCodeT32AluUmull(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Rm = (opCode >> 0) & 0xf;
+            RdHi = (opCode >> 8) & 0xf;
+            RdLo = (opCode >> 12) & 0xf;
+            Rn = (opCode >> 16) & 0xf;
+
+            MHigh = ((opCode >> 4) & 0x1) == 1;
+            NHigh = ((opCode >> 5) & 0x1) == 1;
+        }
+    }
+}
diff --git a/ARMeilleure/Decoders/OpCodeT32AluUx.cs b/ARMeilleure/Decoders/OpCodeT32AluUx.cs
new file mode 100644
index 0000000000..861dc904ab
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT32AluUx.cs
@@ -0,0 +1,18 @@
+using ARMeilleure.State;
+
+namespace ARMeilleure.Decoders
+{
+    class OpCodeT32AluUx : OpCodeT32AluReg, IOpCode32AluUx
+    {
+        public int Rotate { get; }
+        public int RotateBits => Rotate * 8;
+        public bool Add => Rn != RegisterAlias.Aarch32Pc;
+
+        public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluUx(inst, address, opCode);
+
+        public OpCodeT32AluUx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Rotate = (opCode >> 4) & 0x3;
+        }
+    }
+}
diff --git a/ARMeilleure/Decoders/OpCodeT32BImm24.cs b/ARMeilleure/Decoders/OpCodeT32BImm24.cs
index 4381be4779..774ec3a641 100644
--- a/ARMeilleure/Decoders/OpCodeT32BImm24.cs
+++ b/ARMeilleure/Decoders/OpCodeT32BImm24.cs
@@ -27,7 +27,7 @@ namespace ARMeilleure.Decoders
             int i2 = j2 ^ s ^ 1;
 
             int imm32 = imm11 | (imm10 << 11) | (i2 << 21) | (i1 << 22) | (s << 23);
-            imm32 = (imm32 << 9) >> 8;
+            imm32 = (imm32 << 8) >> 7;
 
             Immediate = pc + imm32;
         }
diff --git a/ARMeilleure/Decoders/OpCodeT32MemLdEx.cs b/ARMeilleure/Decoders/OpCodeT32MemLdEx.cs
index da565f61d8..c8eb36b3ee 100644
--- a/ARMeilleure/Decoders/OpCodeT32MemLdEx.cs
+++ b/ARMeilleure/Decoders/OpCodeT32MemLdEx.cs
@@ -4,6 +4,7 @@ namespace ARMeilleure.Decoders
     {
         public int Rd => 0;
         public int Rt { get; }
+        public int Rt2 { get; }
         public int Rn { get; }
 
         public bool WBack => false;
@@ -17,6 +18,7 @@ namespace ARMeilleure.Decoders
 
         public OpCodeT32MemLdEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
         {
+            Rt2 = (opCode >> 8) & 0xf;
             Rt = (opCode >> 12) & 0xf;
             Rn = (opCode >> 16) & 0xf;
         }
diff --git a/ARMeilleure/Decoders/OpCodeT32MemStEx.cs b/ARMeilleure/Decoders/OpCodeT32MemStEx.cs
index 8fe1950ed9..6a0a6bb134 100644
--- a/ARMeilleure/Decoders/OpCodeT32MemStEx.cs
+++ b/ARMeilleure/Decoders/OpCodeT32MemStEx.cs
@@ -4,6 +4,7 @@ namespace ARMeilleure.Decoders
     {
         public int Rd { get; }
         public int Rt { get; }
+        public int Rt2 { get; }
         public int Rn { get; }
 
         public bool WBack => false;
@@ -18,6 +19,7 @@ namespace ARMeilleure.Decoders
         public OpCodeT32MemStEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
         {
             Rd = (opCode >> 0) & 0xf;
+            Rt2 = (opCode >> 8) & 0xf;
             Rt = (opCode >> 12) & 0xf;
             Rn = (opCode >> 16) & 0xf;
         }
diff --git a/ARMeilleure/Decoders/OpCodeT32MovImm16.cs b/ARMeilleure/Decoders/OpCodeT32MovImm16.cs
index 55db012ca7..5161892bb4 100644
--- a/ARMeilleure/Decoders/OpCodeT32MovImm16.cs
+++ b/ARMeilleure/Decoders/OpCodeT32MovImm16.cs
@@ -1,9 +1,6 @@
-using ARMeilleure.Common;
-using System.Runtime.Intrinsics;
-
 namespace ARMeilleure.Decoders
 {
-    class OpCodeT32MovImm16 : OpCodeT32Alu, IOpCode32AluImm
+    class OpCodeT32MovImm16 : OpCodeT32Alu, IOpCode32AluImm16
     {
         public int Immediate { get; }
 
diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs
index a7793681de..034707b9d8 100644
--- a/ARMeilleure/Decoders/OpCodeTable.cs
+++ b/ARMeilleure/Decoders/OpCodeTable.cs
@@ -1074,6 +1074,8 @@ namespace ARMeilleure.Decoders
             SetT32("11110x00000<xxxx0xxx<<<<xxxxxxxx", InstName.And,      InstEmit32.And,      OpCodeT32AluImm.Create);
             SetT32("11110x<<<xxxxxxx10x0xxxxxxxxxxxx", InstName.B,        InstEmit32.B,        OpCodeT32BImm20.Create);
             SetT32("11110xxxxxxxxxxx10x1xxxxxxxxxxxx", InstName.B,        InstEmit32.B,        OpCodeT32BImm24.Create);
+            SetT32("11110011011011110xxxxxxxxx0xxxxx", InstName.Bfc,      InstEmit32.Bfc,      OpCodeT32AluBf.Create);
+            SetT32("111100110110<<<<0xxxxxxxxx0xxxxx", InstName.Bfi,      InstEmit32.Bfi,      OpCodeT32AluBf.Create);
             SetT32("11101010001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic,      InstEmit32.Bic,      OpCodeT32AluRsImm.Create);
             SetT32("11110x00001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic,      InstEmit32.Bic,      OpCodeT32AluImm.Create);
             SetT32("11110xxxxxxxxxxx11x1xxxxxxxxxxxx", InstName.Bl,       InstEmit32.Bl,       OpCodeT32BImm24.Create);
@@ -1086,36 +1088,49 @@ namespace ARMeilleure.Decoders
             SetT32("11101010100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor,      InstEmit32.Eor,      OpCodeT32AluRsImm.Create);
             SetT32("11110x00100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor,      InstEmit32.Eor,      OpCodeT32AluImm.Create);
             SetT32("111010001101xxxxxxxx111110101111", InstName.Lda,      InstEmit32.Lda,      OpCodeT32MemLdEx.Create);
+            SetT32("111010001101xxxxxxxx111110001111", InstName.Ldab,     InstEmit32.Ldab,     OpCodeT32MemLdEx.Create);
             SetT32("111010001101xxxxxxxx111111101111", InstName.Ldaex,    InstEmit32.Ldaex,    OpCodeT32MemLdEx.Create);
+            SetT32("111010001101xxxxxxxx111111001111", InstName.Ldaexb,   InstEmit32.Ldaexb,   OpCodeT32MemLdEx.Create);
+            SetT32("111010001101xxxxxxxxxxxx11111111", InstName.Ldaexd,   InstEmit32.Ldaexd,   OpCodeT32MemLdEx.Create);
+            SetT32("111010001101xxxxxxxx111111011111", InstName.Ldaexh,   InstEmit32.Ldaexh,   OpCodeT32MemLdEx.Create);
+            SetT32("111010001101xxxxxxxx111110011111", InstName.Ldah,     InstEmit32.Ldah,     OpCodeT32MemLdEx.Create);
             SetT32("1110100010x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm,      InstEmit32.Ldm,      OpCodeT32MemMult.Create);
             SetT32("1110100100x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm,      InstEmit32.Ldm,      OpCodeT32MemMult.Create);
-            SetT32("111110000101xxxx<<<<10x1xxxxxxxx", InstName.Ldr,      InstEmit32.Ldr,      OpCodeT32MemImm8.Create);
-            SetT32("111110000101xxxx<<<<1100xxxxxxxx", InstName.Ldr,      InstEmit32.Ldr,      OpCodeT32MemImm8.Create);
-            SetT32("111110000101xxxx<<<<11x1xxxxxxxx", InstName.Ldr,      InstEmit32.Ldr,      OpCodeT32MemImm8.Create);
+            SetT32("111110000101xxxxxxxx10x1xxxxxxxx", InstName.Ldr,      InstEmit32.Ldr,      OpCodeT32MemImm8.Create);
+            SetT32("111110000101xxxxxxxx1100xxxxxxxx", InstName.Ldr,      InstEmit32.Ldr,      OpCodeT32MemImm8.Create);
+            SetT32("111110000101xxxxxxxx11x1xxxxxxxx", InstName.Ldr,      InstEmit32.Ldr,      OpCodeT32MemImm8.Create);
             SetT32("111110001101xxxxxxxxxxxxxxxxxxxx", InstName.Ldr,      InstEmit32.Ldr,      OpCodeT32MemImm12.Create);
             SetT32("111110000101<<<<xxxx000000xxxxxx", InstName.Ldr,      InstEmit32.Ldr,      OpCodeT32MemRsImm.Create);
-            SetT32("111110000001xxxx<<<<10x1xxxxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemImm8.Create);
-            SetT32("111110000001xxxx<<<<1100xxxxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemImm8.Create);
-            SetT32("111110000001xxxx<<<<11x1xxxxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemImm8.Create);
+            SetT32("111110000001xxxxxxxx10x1xxxxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemImm8.Create);
+            SetT32("111110000001xxxxxxxx1100xxxxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemImm8.Create);
+            SetT32("111110000001xxxxxxxx11x1xxxxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemImm8.Create);
             SetT32("111110001001xxxxxxxxxxxxxxxxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemImm12.Create);
+            SetT32("111110000001xxxx<<<<000000xxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemRsImm.Create);
             SetT32("11101000x111<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd,     InstEmit32.Ldrd,     OpCodeT32MemImm8D.Create);
             SetT32("11101001x1x1<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd,     InstEmit32.Ldrd,     OpCodeT32MemImm8D.Create);
-            SetT32("111110000011xxxx<<<<10x1xxxxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemImm8.Create);
-            SetT32("111110000011xxxx<<<<1100xxxxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemImm8.Create);
-            SetT32("111110000011xxxx<<<<11x1xxxxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemImm8.Create);
+            SetT32("111110000011xxxxxxxx10x1xxxxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemImm8.Create);
+            SetT32("111110000011xxxxxxxx1100xxxxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemImm8.Create);
+            SetT32("111110000011xxxxxxxx11x1xxxxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemImm8.Create);
             SetT32("111110001011xxxxxxxxxxxxxxxxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemImm12.Create);
-            SetT32("111110010001xxxx<<<<10x1xxxxxxxx", InstName.Ldrsb,    InstEmit32.Ldrsb,    OpCodeT32MemImm8.Create);
-            SetT32("111110010001xxxx<<<<1100xxxxxxxx", InstName.Ldrsb,    InstEmit32.Ldrsb,    OpCodeT32MemImm8.Create);
-            SetT32("111110010001xxxx<<<<11x1xxxxxxxx", InstName.Ldrsb,    InstEmit32.Ldrsb,    OpCodeT32MemImm8.Create);
+            SetT32("111110000011xxxx<<<<000000xxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemRsImm.Create);
+            SetT32("111110010001xxxxxxxx10x1xxxxxxxx", InstName.Ldrsb,    InstEmit32.Ldrsb,    OpCodeT32MemImm8.Create);
+            SetT32("111110010001xxxxxxxx1100xxxxxxxx", InstName.Ldrsb,    InstEmit32.Ldrsb,    OpCodeT32MemImm8.Create);
+            SetT32("111110010001xxxxxxxx11x1xxxxxxxx", InstName.Ldrsb,    InstEmit32.Ldrsb,    OpCodeT32MemImm8.Create);
             SetT32("111110011001xxxxxxxxxxxxxxxxxxxx", InstName.Ldrsb,    InstEmit32.Ldrsb,    OpCodeT32MemImm12.Create);
-            SetT32("111110010011xxxx<<<<10x1xxxxxxxx", InstName.Ldrsh,    InstEmit32.Ldrsh,    OpCodeT32MemImm8.Create);
-            SetT32("111110010011xxxx<<<<1100xxxxxxxx", InstName.Ldrsh,    InstEmit32.Ldrsh,    OpCodeT32MemImm8.Create);
-            SetT32("111110010011xxxx<<<<11x1xxxxxxxx", InstName.Ldrsh,    InstEmit32.Ldrsh,    OpCodeT32MemImm8.Create);
+            SetT32("111110010001xxxx<<<<000000xxxxxx", InstName.Ldrsb,    InstEmit32.Ldrsb,    OpCodeT32MemRsImm.Create);
+            SetT32("111110010011xxxxxxxx10x1xxxxxxxx", InstName.Ldrsh,    InstEmit32.Ldrsh,    OpCodeT32MemImm8.Create);
+            SetT32("111110010011xxxxxxxx1100xxxxxxxx", InstName.Ldrsh,    InstEmit32.Ldrsh,    OpCodeT32MemImm8.Create);
+            SetT32("111110010011xxxxxxxx11x1xxxxxxxx", InstName.Ldrsh,    InstEmit32.Ldrsh,    OpCodeT32MemImm8.Create);
             SetT32("111110011011xxxxxxxxxxxxxxxxxxxx", InstName.Ldrsh,    InstEmit32.Ldrsh,    OpCodeT32MemImm12.Create);
+            SetT32("111110010011xxxx<<<<000000xxxxxx", InstName.Ldrsh,    InstEmit32.Ldrsh,    OpCodeT32MemRsImm.Create);
+            SetT32("111110110000xxxx<<<<xxxx0000xxxx", InstName.Mla,      InstEmit32.Mla,      OpCodeT32AluMla.Create);
+            SetT32("111110110000xxxxxxxxxxxx0001xxxx", InstName.Mls,      InstEmit32.Mls,      OpCodeT32AluMla.Create);
             SetT32("11101010010x11110xxxxxxxxxxxxxxx", InstName.Mov,      InstEmit32.Mov,      OpCodeT32AluRsImm.Create);
             SetT32("111110100xxxxxxx1111xxxx0000xxxx", InstName.Mov,      InstEmit32.Mov,      OpCodeT32ShiftReg.Create);
             SetT32("11110x00010x11110xxxxxxxxxxxxxxx", InstName.Mov,      InstEmit32.Mov,      OpCodeT32AluImm.Create);
             SetT32("11110x100100xxxx0xxxxxxxxxxxxxxx", InstName.Mov,      InstEmit32.Mov,      OpCodeT32MovImm16.Create);
+            SetT32("11110x101100xxxx0xxxxxxxxxxxxxxx", InstName.Movt,     InstEmit32.Movt,     OpCodeT32MovImm16.Create);
+            SetT32("111110110000xxxx1111xxxx0000xxxx", InstName.Mul,      InstEmit32.Mul,      OpCodeT32AluMla.Create);
             SetT32("11101010011x11110xxxxxxxxxxxxxxx", InstName.Mvn,      InstEmit32.Mvn,      OpCodeT32AluRsImm.Create);
             SetT32("11110x00011x11110xxxxxxxxxxxxxxx", InstName.Mvn,      InstEmit32.Mvn,      OpCodeT32AluImm.Create);
             SetT32("11110011101011111000000000000000", InstName.Nop,      InstEmit32.Nop,      OpCodeT32.Create);
@@ -1127,7 +1142,24 @@ namespace ARMeilleure.Decoders
             SetT32("11110x01110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb,      InstEmit32.Rsb,      OpCodeT32AluImm.Create);
             SetT32("11101011011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc,      InstEmit32.Sbc,      OpCodeT32AluRsImm.Create);
             SetT32("11110x01011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc,      InstEmit32.Sbc,      OpCodeT32AluImm.Create);
+            SetT32("111100110100xxxx0xxxxxxxxx0xxxxx", InstName.Sbfx,     InstEmit32.Sbfx,     OpCodeT32AluBf.Create);
+            SetT32("111110111001xxxx1111xxxx1111xxxx", InstName.Sdiv,     InstEmit32.Sdiv,     OpCodeT32AluMla.Create);
+            SetT32("111110110001xxxx<<<<xxxx00xxxxxx", InstName.Smla__,   InstEmit32.Smla__,   OpCodeT32AluMla.Create);
+            SetT32("111110111100xxxxxxxxxxxx0000xxxx", InstName.Smlal,    InstEmit32.Smlal,    OpCodeT32AluUmull.Create);
+            SetT32("111110111100xxxxxxxxxxxx10xxxxxx", InstName.Smlal__,  InstEmit32.Smlal__,  OpCodeT32AluUmull.Create);
+            SetT32("111110110011xxxx<<<<xxxx000xxxxx", InstName.Smlaw_,   InstEmit32.Smlaw_,   OpCodeT32AluMla.Create);
+            SetT32("111110110101xxxx<<<<xxxx000xxxxx", InstName.Smmla,    InstEmit32.Smmla,    OpCodeT32AluMla.Create);
+            SetT32("111110110110xxxxxxxxxxxx000xxxxx", InstName.Smmls,    InstEmit32.Smmls,    OpCodeT32AluMla.Create);
+            SetT32("111110110001xxxx1111xxxx00xxxxxx", InstName.Smul__,   InstEmit32.Smul__,   OpCodeT32AluMla.Create);
+            SetT32("111110111000xxxxxxxxxxxx0000xxxx", InstName.Smull,    InstEmit32.Smull,    OpCodeT32AluUmull.Create);
+            SetT32("111110110011xxxx1111xxxx000xxxxx", InstName.Smulw_,   InstEmit32.Smulw_,   OpCodeT32AluMla.Create);
+            SetT32("111010001100xxxxxxxx111110101111", InstName.Stl,      InstEmit32.Stl,      OpCodeT32MemStEx.Create);
+            SetT32("111010001100xxxxxxxx111110001111", InstName.Stlb,     InstEmit32.Stlb,     OpCodeT32MemStEx.Create);
             SetT32("111010001100xxxxxxxx11111110xxxx", InstName.Stlex,    InstEmit32.Stlex,    OpCodeT32MemStEx.Create);
+            SetT32("111010001100xxxxxxxx11111100xxxx", InstName.Stlexb,   InstEmit32.Stlexb,   OpCodeT32MemStEx.Create);
+            SetT32("111010001100xxxxxxxxxxxx1111xxxx", InstName.Stlexd,   InstEmit32.Stlexd,   OpCodeT32MemStEx.Create);
+            SetT32("111010001100xxxxxxxx11111101xxxx", InstName.Stlexh,   InstEmit32.Stlexh,   OpCodeT32MemStEx.Create);
+            SetT32("111010001100xxxxxxxx111110011111", InstName.Stlh,     InstEmit32.Stlh,     OpCodeT32MemStEx.Create);
             SetT32("1110100010x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm,      InstEmit32.Stm,      OpCodeT32MemMult.Create);
             SetT32("1110100100x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm,      InstEmit32.Stm,      OpCodeT32MemMult.Create);
             SetT32("111110000100xxxxxxxx1<<>xxxxxxxx", InstName.Str,      InstEmit32.Str,      OpCodeT32MemImm8.Create);
@@ -1135,18 +1167,31 @@ namespace ARMeilleure.Decoders
             SetT32("111110000100<<<<xxxx000000xxxxxx", InstName.Str,      InstEmit32.Str,      OpCodeT32MemRsImm.Create);
             SetT32("111110000000xxxxxxxx1<<>xxxxxxxx", InstName.Strb,     InstEmit32.Strb,     OpCodeT32MemImm8.Create);
             SetT32("111110001000xxxxxxxxxxxxxxxxxxxx", InstName.Strb,     InstEmit32.Strb,     OpCodeT32MemImm12.Create);
+            SetT32("111110000000<<<<xxxx000000xxxxxx", InstName.Strb,     InstEmit32.Strb,     OpCodeT32MemRsImm.Create);
             SetT32("11101000x110<<<<xxxxxxxxxxxxxxxx", InstName.Strd,     InstEmit32.Strd,     OpCodeT32MemImm8D.Create);
             SetT32("11101001x1x0<<<<xxxxxxxxxxxxxxxx", InstName.Strd,     InstEmit32.Strd,     OpCodeT32MemImm8D.Create);
             SetT32("111110000010xxxxxxxx1<<>xxxxxxxx", InstName.Strh,     InstEmit32.Strh,     OpCodeT32MemImm8.Create);
             SetT32("111110001010xxxxxxxxxxxxxxxxxxxx", InstName.Strh,     InstEmit32.Strh,     OpCodeT32MemImm12.Create);
+            SetT32("111110000010<<<<xxxx000000xxxxxx", InstName.Strh,     InstEmit32.Strh,     OpCodeT32MemRsImm.Create);
             SetT32("11101011101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub,      InstEmit32.Sub,      OpCodeT32AluRsImm.Create);
             SetT32("11110x01101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub,      InstEmit32.Sub,      OpCodeT32AluImm.Create);
+            SetT32("111110100100xxxx1111xxxx10xxxxxx", InstName.Sxtb,     InstEmit32.Sxtb,     OpCodeT32AluUx.Create);
+            SetT32("111110100010xxxx1111xxxx10xxxxxx", InstName.Sxtb16,   InstEmit32.Sxtb16,   OpCodeT32AluUx.Create);
+            SetT32("111110100000xxxx1111xxxx10xxxxxx", InstName.Sxth,     InstEmit32.Sxth,     OpCodeT32AluUx.Create);
             SetT32("111010001101xxxx111100000000xxxx", InstName.Tbb,      InstEmit32.Tbb,      OpCodeT32Tb.Create);
             SetT32("111010001101xxxx111100000001xxxx", InstName.Tbh,      InstEmit32.Tbh,      OpCodeT32Tb.Create);
             SetT32("111010101001xxxx0xxx1111xxxxxxxx", InstName.Teq,      InstEmit32.Teq,      OpCodeT32AluRsImm.Create);
             SetT32("11110x001001xxxx0xxx1111xxxxxxxx", InstName.Teq,      InstEmit32.Teq,      OpCodeT32AluImm.Create);
             SetT32("111010100001xxxx0xxx1111xxxxxxxx", InstName.Tst,      InstEmit32.Tst,      OpCodeT32AluRsImm.Create);
             SetT32("11110x000001xxxx0xxx1111xxxxxxxx", InstName.Tst,      InstEmit32.Tst,      OpCodeT32AluImm.Create);
+            SetT32("111100111100xxxx0xxxxxxxxx0xxxxx", InstName.Ubfx,     InstEmit32.Ubfx,     OpCodeT32AluBf.Create);
+            SetT32("111110111011xxxx1111xxxx1111xxxx", InstName.Udiv,     InstEmit32.Udiv,     OpCodeT32AluMla.Create);
+            SetT32("111110111110xxxxxxxxxxxx0110xxxx", InstName.Umaal,    InstEmit32.Umaal,    OpCodeT32AluUmull.Create);
+            SetT32("111110111110xxxxxxxxxxxx0000xxxx", InstName.Umlal,    InstEmit32.Umlal,    OpCodeT32AluUmull.Create);
+            SetT32("111110111010xxxxxxxxxxxx0000xxxx", InstName.Umull,    InstEmit32.Umull,    OpCodeT32AluUmull.Create);
+            SetT32("111110100101xxxx1111xxxx10xxxxxx", InstName.Uxtb,     InstEmit32.Uxtb,     OpCodeT32AluUx.Create);
+            SetT32("111110100011xxxx1111xxxx10xxxxxx", InstName.Uxtb16,   InstEmit32.Uxtb16,   OpCodeT32AluUx.Create);
+            SetT32("111110100001xxxx1111xxxx10xxxxxx", InstName.Uxth,     InstEmit32.Uxth,     OpCodeT32AluUx.Create);
 #endregion
 
             FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);
diff --git a/ARMeilleure/Instructions/InstEmitAlu32.cs b/ARMeilleure/Instructions/InstEmitAlu32.cs
index a612bdf202..31d8a02cc8 100644
--- a/ARMeilleure/Instructions/InstEmitAlu32.cs
+++ b/ARMeilleure/Instructions/InstEmitAlu32.cs
@@ -74,7 +74,7 @@ namespace ARMeilleure.Instructions
 
         public static void Bfc(ArmEmitterContext context)
         {
-            OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;
+            IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
 
             Operand d = GetIntA32(context, op.Rd);
             Operand res = context.BitwiseAnd(d, Const(~op.DestMask));
@@ -84,7 +84,7 @@ namespace ARMeilleure.Instructions
 
         public static void Bfi(ArmEmitterContext context)
         {
-            OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;
+            IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
 
             Operand n = GetIntA32(context, op.Rn);
             Operand d = GetIntA32(context, op.Rd);
@@ -185,7 +185,7 @@ namespace ARMeilleure.Instructions
 
         public static void Movt(ArmEmitterContext context)
         {
-            OpCode32AluImm16 op = (OpCode32AluImm16)context.CurrOp;
+            IOpCode32AluImm16 op = (IOpCode32AluImm16)context.CurrOp;
 
             Operand d = GetIntA32(context, op.Rd);
             Operand imm = Const(op.Immediate << 16); // Immeditate value as top halfword.
@@ -389,7 +389,7 @@ namespace ARMeilleure.Instructions
 
         public static void Sbfx(ArmEmitterContext context)
         {
-            OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;
+            IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
 
             var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
 
@@ -484,7 +484,7 @@ namespace ARMeilleure.Instructions
 
         public static void Ubfx(ArmEmitterContext context)
         {
-            OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;
+            IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
 
             var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
 
diff --git a/ARMeilleure/Instructions/InstEmitAluHelper.cs b/ARMeilleure/Instructions/InstEmitAluHelper.cs
index a487895bac..88991f7d57 100644
--- a/ARMeilleure/Instructions/InstEmitAluHelper.cs
+++ b/ARMeilleure/Instructions/InstEmitAluHelper.cs
@@ -205,7 +205,7 @@ namespace ARMeilleure.Instructions
                     return Const(op.Immediate);
                 }
 
-                case OpCode32AluImm16 op: return Const(op.Immediate);
+                case IOpCode32AluImm16 op: return Const(op.Immediate);
 
                 case IOpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
                 case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry);
diff --git a/ARMeilleure/Instructions/InstEmitMemoryEx32.cs b/ARMeilleure/Instructions/InstEmitMemoryEx32.cs
index c2326cde7e..c0b6fc39de 100644
--- a/ARMeilleure/Instructions/InstEmitMemoryEx32.cs
+++ b/ARMeilleure/Instructions/InstEmitMemoryEx32.cs
@@ -172,13 +172,13 @@ namespace ARMeilleure.Instructions
                     context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
 
                     SetIntA32(context, op.Rt, valueLow);
-                    SetIntA32(context, op.Rt | 1, valueHigh);
+                    SetIntA32(context, op.Rt2, valueHigh);
 
                     context.Branch(lblEnd);
 
                     context.MarkLabel(lblBigEndian);
 
-                    SetIntA32(context, op.Rt | 1, valueLow);
+                    SetIntA32(context, op.Rt2, valueLow);
                     SetIntA32(context, op.Rt, valueHigh);
 
                     context.MarkLabel(lblEnd);
@@ -195,7 +195,7 @@ namespace ARMeilleure.Instructions
                     // Split the result into 2 words (based on endianness)
 
                     Operand lo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
-                    Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt | 1));
+                    Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt2));
 
                     Operand lblBigEndian = Label();
                     Operand lblEnd = Label();
diff --git a/ARMeilleure/Instructions/InstEmitMul32.cs b/ARMeilleure/Instructions/InstEmitMul32.cs
index 868a1f4217..0822f92c30 100644
--- a/ARMeilleure/Instructions/InstEmitMul32.cs
+++ b/ARMeilleure/Instructions/InstEmitMul32.cs
@@ -25,7 +25,7 @@ namespace ARMeilleure.Instructions
 
         public static void Mla(ArmEmitterContext context)
         {
-            OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
+            IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
 
             Operand n = GetAluN(context);
             Operand m = GetAluM(context);
@@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
 
         public static void Mls(ArmEmitterContext context)
         {
-            OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
+            IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
 
             Operand n = GetAluN(context);
             Operand m = GetAluM(context);
@@ -71,7 +71,7 @@ namespace ARMeilleure.Instructions
 
         private static void EmitSmmul(ArmEmitterContext context, MullFlags flags)
         {
-            OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
+            IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
 
             Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn));
             Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm));
@@ -99,7 +99,7 @@ namespace ARMeilleure.Instructions
 
         public static void Smla__(ArmEmitterContext context)
         {
-            OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
+            IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
 
             Operand n = GetIntA32(context, op.Rn);
             Operand m = GetIntA32(context, op.Rm);
@@ -142,7 +142,7 @@ namespace ARMeilleure.Instructions
 
         public static void Smlal__(ArmEmitterContext context)
         {
-            OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
+            IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
 
             Operand n = GetIntA32(context, op.Rn);
             Operand m = GetIntA32(context, op.Rm);
@@ -180,7 +180,7 @@ namespace ARMeilleure.Instructions
 
         public static void Smlaw_(ArmEmitterContext context)
         {
-            OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
+            IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
 
             Operand n = GetIntA32(context, op.Rn);
             Operand m = GetIntA32(context, op.Rm);
@@ -210,7 +210,7 @@ namespace ARMeilleure.Instructions
 
         public static void Smul__(ArmEmitterContext context)
         {
-            OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
+            IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
 
             Operand n = GetIntA32(context, op.Rn);
             Operand m = GetIntA32(context, op.Rm);
@@ -240,7 +240,7 @@ namespace ARMeilleure.Instructions
 
         public static void Smull(ArmEmitterContext context)
         {
-            OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
+            IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
 
             Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn));
             Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm));
@@ -261,7 +261,7 @@ namespace ARMeilleure.Instructions
 
         public static void Smulw_(ArmEmitterContext context)
         {
-            OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
+            IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
 
             Operand n = GetIntA32(context, op.Rn);
             Operand m = GetIntA32(context, op.Rm);
@@ -285,7 +285,7 @@ namespace ARMeilleure.Instructions
 
         public static void Umaal(ArmEmitterContext context)
         {
-            OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
+            IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
 
             Operand n   = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
             Operand m   = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
@@ -310,7 +310,7 @@ namespace ARMeilleure.Instructions
 
         public static void Umull(ArmEmitterContext context)
         {
-            OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
+            IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
 
             Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
             Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
@@ -331,7 +331,7 @@ namespace ARMeilleure.Instructions
 
         private static void EmitMlal(ArmEmitterContext context, bool signed)
         {
-            OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
+            IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
 
             Operand n = GetIntA32(context, op.Rn);
             Operand m = GetIntA32(context, op.Rm);