diff --git a/ARMeilleure/Decoders/OpCode32Sat.cs b/ARMeilleure/Decoders/OpCode32Sat.cs
new file mode 100644
index 0000000000..b5ddab32d4
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32Sat.cs
@@ -0,0 +1,22 @@
+namespace ARMeilleure.Decoders
+{
+    class OpCode32Sat : OpCode32
+    {
+        public int Rn { get; private set; }
+        public int Imm5 { get; private set; }
+        public int Rd { get; private set; }
+        public int SatImm { get; private set; }
+
+        public ShiftType ShiftType { get; private set; }
+
+        public OpCode32Sat(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Rn = (opCode >> 0) & 0xf;
+            Imm5 = (opCode >> 7) & 0x1f;
+            Rd = (opCode >> 12) & 0xf;
+            SatImm = (opCode >> 16) & 0x1f;
+
+            ShiftType = (ShiftType)((opCode >> 5) & 2);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCode32Sat16.cs b/ARMeilleure/Decoders/OpCode32Sat16.cs
new file mode 100644
index 0000000000..c25f6ceee9
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCode32Sat16.cs
@@ -0,0 +1,16 @@
+namespace ARMeilleure.Decoders
+{
+    class OpCode32Sat16 : OpCode32
+    {
+        public int Rn { get; private set; }
+        public int Rd { get; private set; }
+        public int SatImm { get; private set; }
+
+        public OpCode32Sat16(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Rn = (opCode >> 0) & 0xf;
+            Rd = (opCode >> 12) & 0xf;
+            SatImm = (opCode >> 16) & 0xf;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs
index 96847dd8ea..d163808e43 100644
--- a/ARMeilleure/Decoders/OpCodeTable.cs
+++ b/ARMeilleure/Decoders/OpCodeTable.cs
@@ -158,7 +158,7 @@ namespace ARMeilleure.Decoders
             SetA64("x0011010110xxxxx000011xxxxxxxxxx", InstName.Sdiv,            InstEmit.Sdiv,            typeof(OpCodeAluBinary));
             SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", InstName.Smaddl,          InstEmit.Smaddl,          typeof(OpCodeMul));
             SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", InstName.Smsubl,          InstEmit.Smsubl,          typeof(OpCodeMul));
-            SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", InstName.Smulh,           InstEmit.Smulh,           typeof(OpCodeMul));
+            SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", InstName.Smul__,           InstEmit.Smulh,           typeof(OpCodeMul));
             SetA64("xx001000100xxxxx1xxxxxxxxxxxxxxx", InstName.Stlr,            InstEmit.Stlr,            typeof(OpCodeMemEx));
             SetA64("1x001000001xxxxx1xxxxxxxxxxxxxxx", InstName.Stlxp,           InstEmit.Stlxp,           typeof(OpCodeMemEx));
             SetA64("xx001000000xxxxx1xxxxxxxxxxxxxxx", InstName.Stlxr,           InstEmit.Stlxr,           typeof(OpCodeMemEx));
@@ -603,147 +603,153 @@ namespace ARMeilleure.Decoders
 
 #region "OpCode Table (AArch32)"
             // Base
-            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));
+            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.Smla__,  InstEmit32.Smla__,  typeof(OpCode32AluMla));
+            SetA32("<<<<0000111xxxxxxxxxxxxx1001xxxx", InstName.Smlal,   InstEmit32.Smlal,   typeof(OpCode32AluUmull));
+            SetA32("<<<<00010100xxxxxxxxxxxx1xx0xxxx", InstName.Smlal__, InstEmit32.Smlal__, typeof(OpCode32AluUmull));
+            SetA32("<<<<00010010xxxxxxxxxxxx1x00xxxx", InstName.Smlaw_,  InstEmit32.Smlaw_,  typeof(OpCode32AluMla));
+            SetA32("<<<<01110101xxxxxxxxxxxx00x1xxxx", InstName.Smmla,   InstEmit32.Smmla,   typeof(OpCode32AluMla));
+            SetA32("<<<<01110101xxxxxxxxxxxx11x1xxxx", InstName.Smmls,   InstEmit32.Smmls,   typeof(OpCode32AluMla));
+            SetA32("<<<<00010110xxxxxxxxxxxx1xx0xxxx", InstName.Smul__,  InstEmit32.Smul__,  typeof(OpCode32AluMla));
+            SetA32("<<<<0000110xxxxxxxxxxxxx1001xxxx", InstName.Smull,   InstEmit32.Smull,   typeof(OpCode32AluUmull));
+            SetA32("<<<<00010010xxxx0000xxxx1x10xxxx", InstName.Smulw_,  InstEmit32.Smulw_,  typeof(OpCode32AluMla));
+            SetA32("<<<<0110101xxxxxxxxxxxxxxx01xxxx", InstName.Ssat,    InstEmit32.Ssat,    typeof(OpCode32Sat));
+            SetA32("<<<<01101010xxxxxxxx11110011xxxx", InstName.Ssat16,  InstEmit32.Ssat16,  typeof(OpCode32Sat16));
+            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("<<<<0110111xxxxxxxxxxxxxxx01xxxx", InstName.Usat,    InstEmit32.Usat,    typeof(OpCode32Sat));
+            SetA32("<<<<01101110xxxxxxxx11110011xxxx", InstName.Usat16,  InstEmit32.Usat16,  typeof(OpCode32Sat16));
+            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));
diff --git a/ARMeilleure/Instructions/InstEmitAlu32.cs b/ARMeilleure/Instructions/InstEmitAlu32.cs
index 4d03f5c24a..469a18a036 100644
--- a/ARMeilleure/Instructions/InstEmitAlu32.cs
+++ b/ARMeilleure/Instructions/InstEmitAlu32.cs
@@ -389,6 +389,20 @@ namespace ARMeilleure.Instructions
             EmitDiv(context, false);
         }
 
+        public static void Ssat(ArmEmitterContext context)
+        {
+            OpCode32Sat op = (OpCode32Sat)context.CurrOp;
+
+            EmitSat(context, -(1 << op.SatImm), (1 << op.SatImm) - 1);
+        }
+
+        public static void Ssat16(ArmEmitterContext context)
+        {
+            OpCode32Sat16 op = (OpCode32Sat16)context.CurrOp;
+
+            EmitSat16(context, -(1 << op.SatImm), (1 << op.SatImm) - 1);
+        }
+
         public static void Sub(ArmEmitterContext context)
         {
             IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
@@ -460,6 +474,20 @@ namespace ARMeilleure.Instructions
             EmitDiv(context, true);
         }
 
+        public static void Usat(ArmEmitterContext context)
+        {
+            OpCode32Sat op = (OpCode32Sat)context.CurrOp;
+
+            EmitSat(context, 0, op.SatImm == 32 ? (int)(~0) : (1 << op.SatImm) - 1);
+        }
+
+        public static void Usat16(ArmEmitterContext context)
+        {
+            OpCode32Sat16 op = (OpCode32Sat16)context.CurrOp;
+
+            EmitSat16(context, 0, (1 << op.SatImm) - 1);
+        }
+
         public static void Uxtb(ArmEmitterContext context)
         {
             EmitSignExtend(context, false, 8);
@@ -553,7 +581,7 @@ namespace ARMeilleure.Instructions
                     lowAdd = context.ZeroExtend16(OperandType.I32, n);
                     highAdd = context.ZeroExtend16(OperandType.I32, context.ShiftRightUI(n, Const(16)));
                 }
-                
+
                 low16 = context.Add(low16, lowAdd);
                 high16 = context.Add(high16, highAdd);
             }
@@ -615,9 +643,116 @@ namespace ARMeilleure.Instructions
             context.MarkLabel(lblEnd);
         }
 
+        private static void EmitSat(ArmEmitterContext context, int intMin, int intMax)
+        {
+            OpCode32Sat op = (OpCode32Sat)context.CurrOp;
+
+            Operand n = GetIntA32(context, op.Rn);
+
+            int shift = DecodeImmShift(op.ShiftType, op.Imm5);
+
+            switch (op.ShiftType)
+            {
+                case ShiftType.Lsl:
+                    if (shift == 32)
+                    {
+                        n = Const(0);
+                    }
+                    else
+                    {
+                        n = context.ShiftLeft(n, Const(shift));
+                    }
+                    break;
+                case ShiftType.Asr:
+                    if (shift == 32)
+                    {
+                        n = context.ShiftRightSI(n, Const(31));
+                    }
+                    else
+                    {
+                        n = context.ShiftRightSI(n, Const(shift));
+                    }
+                    break;
+            }
+
+            Operand lblCheckLtIntMin = Label();
+            Operand lblNoSat = Label();
+            Operand lblEnd = Label();
+
+            context.BranchIfFalse(lblCheckLtIntMin, context.ICompareGreater(n, Const(intMax)));
+
+            SetFlag(context, PState.QFlag, Const(1));
+            SetIntA32(context, op.Rd, Const(intMax));
+            context.Branch(lblEnd);
+
+            context.MarkLabel(lblCheckLtIntMin);
+            context.BranchIfFalse(lblNoSat, context.ICompareLess(n, Const(intMin)));
+
+            SetFlag(context, PState.QFlag, Const(1));
+            SetIntA32(context, op.Rd, Const(intMin));
+            context.Branch(lblEnd);
+
+            context.MarkLabel(lblNoSat);
+
+            SetIntA32(context, op.Rd, n);
+
+            context.MarkLabel(lblEnd);
+        }
+
+        private static void EmitSat16(ArmEmitterContext context, int intMin, int intMax)
+        {
+            OpCode32Sat16 op = (OpCode32Sat16)context.CurrOp;
+
+            void SetD(int part, Operand value)
+            {
+                if (part == 0)
+                {
+                    SetIntA32(context, op.Rd, context.ZeroExtend16(OperandType.I32, value));
+                }
+                else
+                {
+                    SetIntA32(context, op.Rd, context.BitwiseOr(GetIntA32(context, op.Rd), context.ShiftLeft(value, Const(16))));
+                }
+            }
+
+            Operand n = GetIntA32(context, op.Rn);
+
+            Operand nLow = context.SignExtend16(OperandType.I32, n);
+            Operand nHigh = context.ShiftRightSI(n, Const(16));
+
+            for (int part = 0; part < 2; part++)
+            {
+                Operand nPart = part == 0 ? nLow : nHigh;
+
+                Operand lblCheckLtIntMin = Label();
+                Operand lblNoSat = Label();
+                Operand lblEnd = Label();
+
+                context.BranchIfFalse(lblCheckLtIntMin, context.ICompareGreater(nPart, Const(intMax)));
+
+                SetFlag(context, PState.QFlag, Const(1));
+                SetD(part, Const(intMax));
+                context.Branch(lblEnd);
+
+                context.MarkLabel(lblCheckLtIntMin);
+                context.BranchIfFalse(lblNoSat, context.ICompareLess(nPart, Const(intMin)));
+
+                SetFlag(context, PState.QFlag, Const(1));
+                SetD(part, Const(intMin));
+                context.Branch(lblEnd);
+
+                context.MarkLabel(lblNoSat);
+
+                SetD(part, nPart);
+
+                context.MarkLabel(lblEnd);
+            }
+        }
+
         private static void EmitAluStore(ArmEmitterContext context, Operand value)
         {
             IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
+
             EmitGenericAluStoreA32(context, op.Rd, op.SetFlags, value);
         }
     }
diff --git a/ARMeilleure/Instructions/InstEmitAluHelper.cs b/ARMeilleure/Instructions/InstEmitAluHelper.cs
index 3bb87f2738..916a1da5a9 100644
--- a/ARMeilleure/Instructions/InstEmitAluHelper.cs
+++ b/ARMeilleure/Instructions/InstEmitAluHelper.cs
@@ -297,6 +297,21 @@ namespace ARMeilleure.Instructions
             return m;
         }
 
+        public static int DecodeImmShift(ShiftType shiftType, int shift)
+        {
+            if (shift == 0)
+            {
+                switch (shiftType)
+                {
+                    case ShiftType.Lsr: shift = 32; break;
+                    case ShiftType.Asr: shift = 32; break;
+                    case ShiftType.Ror: shift = 1;  break;
+                }
+            }
+
+            return shift;
+        }
+
         public static Operand GetMShiftedByReg(ArmEmitterContext context, OpCode32AluRsReg op, bool setCarry)
         {
             Operand m = GetIntA32(context, op.Rm);
@@ -328,7 +343,7 @@ namespace ARMeilleure.Instructions
             if (expected)
             {
                 context.BranchIfFalse(endLabel, boolValue);
-            } 
+            }
             else
             {
                 context.BranchIfTrue(endLabel, boolValue);
@@ -411,7 +426,7 @@ namespace ARMeilleure.Instructions
                     SetFlag(context, PState.CFlag, cOut);
                 }, false);
             }
-            
+
             return context.ConditionalSelect(shiftLarge, Const(0), result);
         }
 
diff --git a/ARMeilleure/Instructions/InstEmitMul32.cs b/ARMeilleure/Instructions/InstEmitMul32.cs
index e64f3568ee..6714c5fd0d 100644
--- a/ARMeilleure/Instructions/InstEmitMul32.cs
+++ b/ARMeilleure/Instructions/InstEmitMul32.cs
@@ -1,5 +1,6 @@
 using ARMeilleure.Decoders;
 using ARMeilleure.IntermediateRepresentation;
+using ARMeilleure.State;
 using ARMeilleure.Translation;
 using System;
 
@@ -53,27 +54,6 @@ namespace ARMeilleure.Instructions
             EmitAluStore(context, res);
         }
 
-        public static void Smull(ArmEmitterContext context)
-        {
-            OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
-
-            Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn));
-            Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm));
-
-            Operand res = context.Multiply(n, m);
-
-            Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32)));
-            Operand lo = context.ConvertI64ToI32(res);
-
-            if (op.SetFlags)
-            {
-                EmitNZFlagsCheck(context, res);
-            }
-
-            EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
-            EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
-        }
-
         public static void Smmla(ArmEmitterContext context)
         {
             EmitSmmul(context, MullFlags.SignedAdd);
@@ -101,7 +81,7 @@ namespace ARMeilleure.Instructions
             if (flags.HasFlag(MullFlags.Add) && op.Ra != 0xf)
             {
                 res = context.Add(context.ShiftLeft(context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Ra)), Const(32)), res);
-            } 
+            }
             else if (flags.HasFlag(MullFlags.Subtract))
             {
                 res = context.Subtract(context.ShiftLeft(context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Ra)), Const(32)), res);
@@ -117,37 +97,40 @@ namespace ARMeilleure.Instructions
             EmitGenericAluStoreA32(context, op.Rd, false, hi);
         }
 
-        public static void Smlab(ArmEmitterContext context)
+        public static void Smla__(ArmEmitterContext context)
         {
             OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
 
             Operand n = GetIntA32(context, op.Rn);
             Operand m = GetIntA32(context, op.Rm);
+            Operand a = GetIntA32(context, op.Ra);
 
             if (op.NHigh)
             {
-                n = context.SignExtend16(OperandType.I32, context.ShiftRightUI(n, Const(16)));
+                n = context.SignExtend16(OperandType.I64, context.ShiftRightUI(n, Const(16)));
             }
             else
             {
-                n = context.SignExtend16(OperandType.I32, n);
+                n = context.SignExtend16(OperandType.I64, n);
             }
 
             if (op.MHigh)
             {
-                m = context.SignExtend16(OperandType.I32, context.ShiftRightUI(m, Const(16)));
+                m = context.SignExtend16(OperandType.I64, context.ShiftRightUI(m, Const(16)));
             }
             else
             {
-                m = context.SignExtend16(OperandType.I32, m);
+                m = context.SignExtend16(OperandType.I64, m);
             }
 
             Operand res = context.Multiply(n, m);
 
-            Operand a = GetIntA32(context, op.Ra);
-            res = context.Add(res, a);
+            Operand toAdd = context.SignExtend32(OperandType.I64, a);
+            res = context.Add(res, toAdd);
+            Operand q = context.ICompareNotEqual(res, context.SignExtend32(OperandType.I64, res));
+            res = context.ConvertI64ToI32(res);
 
-            // TODO: set Q flag when last addition overflows (saturation)?
+            UpdateQFlag(context, q);
 
             EmitGenericAluStoreA32(context, op.Rd, false, res);
         }
@@ -157,7 +140,7 @@ namespace ARMeilleure.Instructions
             EmitMlal(context, true);
         }
 
-        public static void Smlalh(ArmEmitterContext context)
+        public static void Smlal__(ArmEmitterContext context)
         {
             OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
 
@@ -167,7 +150,7 @@ namespace ARMeilleure.Instructions
             if (op.NHigh)
             {
                 n = context.SignExtend16(OperandType.I64, context.ShiftRightUI(n, Const(16)));
-            } 
+            }
             else
             {
                 n = context.SignExtend16(OperandType.I64, n);
@@ -176,7 +159,7 @@ namespace ARMeilleure.Instructions
             if (op.MHigh)
             {
                 m = context.SignExtend16(OperandType.I64, context.ShiftRightUI(m, Const(16)));
-            } 
+            }
             else
             {
                 m = context.SignExtend16(OperandType.I64, m);
@@ -195,7 +178,37 @@ namespace ARMeilleure.Instructions
             EmitGenericAluStoreA32(context, op.RdLo, false, lo);
         }
 
-        public static void Smulh(ArmEmitterContext context)
+        public static void Smlaw_(ArmEmitterContext context)
+        {
+            OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
+
+            Operand n = GetIntA32(context, op.Rn);
+            Operand m = GetIntA32(context, op.Rm);
+            Operand a = GetIntA32(context, op.Ra);
+
+            if (op.MHigh)
+            {
+                m = context.SignExtend16(OperandType.I64, context.ShiftRightUI(m, Const(16)));
+            }
+            else
+            {
+                m = context.SignExtend16(OperandType.I64, m);
+            }
+
+            Operand res = context.Multiply(context.SignExtend32(OperandType.I64, n), m);
+
+            Operand toAdd = context.ShiftLeft(context.SignExtend32(OperandType.I64, a), Const(16));
+            res = context.Add(res, toAdd);
+            res = context.ShiftRightSI(res, Const(16));
+            Operand q = context.ICompareNotEqual(res, context.SignExtend32(OperandType.I64, res));
+            res = context.ConvertI64ToI32(res);
+
+            UpdateQFlag(context, q);
+
+            EmitGenericAluStoreA32(context, op.Rd, false, res);
+        }
+
+        public static void Smul__(ArmEmitterContext context)
         {
             OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
 
@@ -225,6 +238,51 @@ namespace ARMeilleure.Instructions
             EmitGenericAluStoreA32(context, op.Rd, false, res);
         }
 
+        public static void Smull(ArmEmitterContext context)
+        {
+            OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
+
+            Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn));
+            Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm));
+
+            Operand res = context.Multiply(n, m);
+
+            Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32)));
+            Operand lo = context.ConvertI64ToI32(res);
+
+            if (op.SetFlags)
+            {
+                EmitNZFlagsCheck(context, res);
+            }
+
+            EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
+            EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
+        }
+
+        public static void Smulw_(ArmEmitterContext context)
+        {
+            OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
+
+            Operand n = GetIntA32(context, op.Rn);
+            Operand m = GetIntA32(context, op.Rm);
+
+            if (op.MHigh)
+            {
+                m = context.SignExtend16(OperandType.I64, context.ShiftRightUI(m, Const(16)));
+            }
+            else
+            {
+                m = context.SignExtend16(OperandType.I64, m);
+            }
+
+            Operand res = context.Multiply(context.SignExtend32(OperandType.I64, n), m);
+
+            res = context.ShiftRightUI(res, Const(16));
+            res = context.ConvertI64ToI32(res);
+
+            EmitGenericAluStoreA32(context, op.Rd, false, res);
+        }
+
         public static void Umlal(ArmEmitterContext context)
         {
             EmitMlal(context, false);
@@ -286,5 +344,16 @@ namespace ARMeilleure.Instructions
             EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi);
             EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo);
         }
+
+        private static void UpdateQFlag(ArmEmitterContext context, Operand q)
+        {
+            Operand lblSkipSetQ = Label();
+
+            context.BranchIfFalse(lblSkipSetQ, q);
+
+            SetFlag(context, PState.QFlag, Const(1));
+
+            context.MarkLabel(lblSkipSetQ);
+        }
     }
 }
diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs
index 157feacfa0..049c956dc3 100644
--- a/ARMeilleure/Instructions/InstName.cs
+++ b/ARMeilleure/Instructions/InstName.cs
@@ -81,8 +81,11 @@ namespace ARMeilleure.Instructions
         Sdiv,
         Smaddl,
         Smsubl,
-        Smulh,
+        Smul__,
         Smull,
+        Smulw_,
+        Ssat,
+        Ssat16,
         Stlr,
         Stlxp,
         Stlxr,
@@ -491,9 +494,10 @@ namespace ARMeilleure.Instructions
         Rsb,
         Rsc,
         Sbfx,
-        Smlab,
+        Smla__,
         Smlal,
-        Smlalh,
+        Smlal__,
+        Smlaw_,
         Smmla,
         Smmls,
         Smmul,
@@ -519,6 +523,8 @@ namespace ARMeilleure.Instructions
         Ubfx,
         Umlal,
         Umull,
+        Usat,
+        Usat16,
         Uxtb,
         Uxtb16,
         Uxth,
diff --git a/ARMeilleure/State/PState.cs b/ARMeilleure/State/PState.cs
index ce755e952b..8dbd84df25 100644
--- a/ARMeilleure/State/PState.cs
+++ b/ARMeilleure/State/PState.cs
@@ -7,7 +7,7 @@ namespace ARMeilleure.State
     {
         TFlag = 5,
         EFlag = 9,
-
+        QFlag = 27,
         VFlag = 28,
         CFlag = 29,
         ZFlag = 30,
diff --git a/Ryujinx.Tests.Unicorn/UnicornAArch32.cs b/Ryujinx.Tests.Unicorn/UnicornAArch32.cs
index d7ae90d6e9..45d2da7a4e 100644
--- a/Ryujinx.Tests.Unicorn/UnicornAArch32.cs
+++ b/Ryujinx.Tests.Unicorn/UnicornAArch32.cs
@@ -45,10 +45,10 @@ namespace Ryujinx.Tests.Unicorn
             set => SetRegister(Arm32Register.PC, value);
         }
 
-        public uint APSR
+        public uint CPSR
         {
-            get => (uint)GetRegister(Arm32Register.APSR);
-            set => SetRegister(Arm32Register.APSR, (uint)value);
+            get => (uint)GetRegister(Arm32Register.CPSR);
+            set => SetRegister(Arm32Register.CPSR, (uint)value);
         }
 
         public int Fpscr
@@ -57,28 +57,34 @@ namespace Ryujinx.Tests.Unicorn
             set => SetRegister(Arm32Register.FPSCR, (uint)value);
         }
 
+        public bool QFlag
+        {
+            get => (CPSR & 0x8000000u) != 0;
+            set => CPSR = (CPSR & ~0x8000000u) | (value ? 0x8000000u : 0u);
+        }
+
         public bool OverflowFlag
         {
-            get => (APSR & 0x10000000u) != 0;
-            set => APSR = (APSR & ~0x10000000u) | (value ? 0x10000000u : 0u);
+            get => (CPSR & 0x10000000u) != 0;
+            set => CPSR = (CPSR & ~0x10000000u) | (value ? 0x10000000u : 0u);
         }
 
         public bool CarryFlag
         {
-            get => (APSR & 0x20000000u) != 0;
-            set => APSR = (APSR & ~0x20000000u) | (value ? 0x20000000u : 0u);
+            get => (CPSR & 0x20000000u) != 0;
+            set => CPSR = (CPSR & ~0x20000000u) | (value ? 0x20000000u : 0u);
         }
 
         public bool ZeroFlag
         {
-            get => (APSR & 0x40000000u) != 0;
-            set => APSR = (APSR & ~0x40000000u) | (value ? 0x40000000u : 0u);
+            get => (CPSR & 0x40000000u) != 0;
+            set => CPSR = (CPSR & ~0x40000000u) | (value ? 0x40000000u : 0u);
         }
 
         public bool NegativeFlag
         {
-            get => (APSR & 0x80000000u) != 0;
-            set => APSR = (APSR & ~0x80000000u) | (value ? 0x80000000u : 0u);
+            get => (CPSR & 0x80000000u) != 0;
+            set => CPSR = (CPSR & ~0x80000000u) | (value ? 0x80000000u : 0u);
         }
 
         public UnicornAArch32()
diff --git a/Ryujinx.Tests/Cpu/CpuTest32.cs b/Ryujinx.Tests/Cpu/CpuTest32.cs
index ed1d23d37b..a039d280fd 100644
--- a/Ryujinx.Tests/Cpu/CpuTest32.cs
+++ b/Ryujinx.Tests/Cpu/CpuTest32.cs
@@ -348,6 +348,7 @@ namespace Ryujinx.Tests.Cpu
 
             Assert.That((int)_context.Fpcr | ((int)_context.Fpsr & (int)fpsrMask), Is.EqualTo(_unicornEmu.Fpscr));
 
+            Assert.That(_context.GetPstateFlag(PState.QFlag), Is.EqualTo(_unicornEmu.QFlag));
             Assert.That(_context.GetPstateFlag(PState.VFlag), Is.EqualTo(_unicornEmu.OverflowFlag));
             Assert.That(_context.GetPstateFlag(PState.CFlag), Is.EqualTo(_unicornEmu.CarryFlag));
             Assert.That(_context.GetPstateFlag(PState.ZFlag), Is.EqualTo(_unicornEmu.ZeroFlag));
@@ -358,7 +359,7 @@ namespace Ryujinx.Tests.Cpu
                 byte[] meilleureMem = _memory.ReadBytes((long)(0x2000), _size);
                 byte[] unicornMem = _unicornEmu.MemoryRead((ulong)(0x2000), (ulong)_size);
 
-                for (int i = 0; i < _size; i++) 
+                for (int i = 0; i < _size; i++)
                 {
                     Assert.AreEqual(meilleureMem[i], unicornMem[i]);
                 }
diff --git a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs
index 145417ae2c..c21bbe1013 100644
--- a/Ryujinx.Tests/Cpu/CpuTestAlu32.cs
+++ b/Ryujinx.Tests/Cpu/CpuTestAlu32.cs
@@ -11,6 +11,26 @@ namespace Ryujinx.Tests.Cpu
 #if Alu32
 
 #region "ValueSource (Opcodes)"
+        private static uint[] _Ssat_Usat_()
+        {
+            return new uint[]
+            {
+                0xe6a00010u, // SSAT R0, #1, R0, LSL #0
+                0xe6a00050u, // SSAT R0, #1, R0, ASR #32
+                0xe6e00010u, // USAT R0, #0, R0, LSL #0
+                0xe6e00050u  // USAT R0, #0, R0, ASR #32
+            };
+        }
+
+        private static uint[] _Ssat16_Usat16_()
+        {
+            return new uint[]
+            {
+                0xe6a00f30u, // SSAT16 R0, #1, R0
+                0xe6e00f30u, // USAT16 R0, #0, R0
+            };
+        }
+
         private static uint[] _Lsr_Lsl_Asr_Ror_()
         {
             return new uint[]
@@ -56,6 +76,41 @@ namespace Ryujinx.Tests.Cpu
 
             CompareAgainstUnicorn();
         }
+
+        [Test, Pairwise]
+        public void Ssat_Usat([ValueSource("_Ssat_Usat_")] uint opcode,
+                              [Values(0u, 0xdu)] uint rd,
+                              [Values(1u, 0xdu)] uint rn,
+                              [Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint sat,
+                              [Values(0u, 7u, 8u, 0xfu, 0x10u, 0x1fu)] uint shift,
+                              [Values(0x00000000u, 0x7FFFFFFFu,
+                                      0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn)
+        {
+            opcode |= ((rn & 15) << 0) | ((shift & 31) << 7) | ((rd & 15) << 12) | ((sat & 31) << 16);
+
+            uint w31 = TestContext.CurrentContext.Random.NextUInt();
+
+            SingleOpcode(opcode, r1: wn, sp: w31);
+
+            CompareAgainstUnicorn();
+        }
+
+        [Test, Pairwise]
+        public void Ssat16_Usat16([ValueSource("_Ssat16_Usat16_")] uint opcode,
+                                  [Values(0u, 0xdu)] uint rd,
+                                  [Values(1u, 0xdu)] uint rn,
+                                  [Values(0u, 7u, 8u, 0xfu)] uint sat,
+                                  [Values(0x00000000u, 0x7FFFFFFFu,
+                                          0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn)
+        {
+            opcode |= ((rn & 15) << 0) | ((rd & 15) << 12) | ((sat & 15) << 16);
+
+            uint w31 = TestContext.CurrentContext.Random.NextUInt();
+
+            SingleOpcode(opcode, r1: wn, sp: w31);
+
+            CompareAgainstUnicorn();
+        }
 #endif
     }
 }
diff --git a/Ryujinx.Tests/Cpu/CpuTestMul32.cs b/Ryujinx.Tests/Cpu/CpuTestMul32.cs
new file mode 100644
index 0000000000..4bdb2ae282
--- /dev/null
+++ b/Ryujinx.Tests/Cpu/CpuTestMul32.cs
@@ -0,0 +1,140 @@
+#define Mul32
+
+using NUnit.Framework;
+using System;
+
+namespace Ryujinx.Tests.Cpu
+{
+    [Category("Mul32")]
+    public sealed class CpuTestMul32 : CpuTest32
+    {
+#if Mul32
+
+#region "ValueSource (Opcodes)"
+        private static uint[] _Smlabb_Smlabt_Smlatb_Smlatt_()
+        {
+            return new uint[]
+            {
+                0xe1000080u, // SMLABB R0, R0, R0, R0
+                0xe10000C0u, // SMLABT R0, R0, R0, R0
+                0xe10000A0u, // SMLATB R0, R0, R0, R0
+                0xe10000E0u, // SMLATT R0, R0, R0, R0
+            };
+        }
+
+        private static uint[] _Smlawb_Smlawt_()
+        {
+            return new uint[]
+            {
+                0xe1200080u, // SMLAWB R0, R0, R0, R0
+                0xe12000C0u, // SMLAWT R0, R0, R0, R0
+            };
+        }
+
+        private static uint[] _Smulbb_Smulbt_Smultb_Smultt_()
+        {
+            return new uint[]
+            {
+                0xe1600080u, // SMULBB R0, R0, R0
+                0xe16000C0u, // SMULBT R0, R0, R0
+                0xe16000A0u, // SMULTB R0, R0, R0
+                0xe16000E0u, // SMULTT R0, R0, R0
+            };
+        }
+
+        private static uint[] _Smulwb_Smulwt_()
+        {
+            return new uint[]
+            {
+                0xe12000a0u, // SMULWB R0, R0, R0
+                0xe12000e0u, // SMULWT R0, R0, R0
+            };
+        }
+#endregion
+
+        private const int RndCnt = 2;
+
+        [Test, Pairwise, Description("SMLA<x><y> <Rd>, <Rn>, <Rm>, <Ra>")]
+        public void Smla___32bit([ValueSource("_Smlabb_Smlabt_Smlatb_Smlatt_")] uint opcode,
+                                 [Values(0u, 0xdu)] uint rn,
+                                 [Values(1u, 0xdu)] uint rm,
+                                 [Values(2u, 0xdu)] uint ra,
+                                 [Values(3u, 0xdu)] uint rd,
+                                 [Values(0x00000000u, 0x7FFFFFFFu,
+                                         0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
+                                 [Values(0x00000000u, 0x7FFFFFFFu,
+                                         0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
+                                 [Values(0x00000000u, 0x7FFFFFFFu,
+                                         0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wa)
+        {
+            opcode |= ((rn & 15) << 0) | ((rm & 15) << 8) | ((ra & 15) << 12) | ((rd & 15) << 16);
+
+            uint w31 = TestContext.CurrentContext.Random.NextUInt();
+
+            SingleOpcode(opcode, r0: wn, r1: wm, r2: wa, sp: w31);
+
+            CompareAgainstUnicorn();
+        }
+
+        [Test, Pairwise, Description("SMLAW<x> <Rd>, <Rn>, <Rm>, <Ra>")]
+        public void Smlaw__32bit([ValueSource("_Smlawb_Smlawt_")] uint opcode,
+                                 [Values(0u, 0xdu)] uint rn,
+                                 [Values(1u, 0xdu)] uint rm,
+                                 [Values(2u, 0xdu)] uint ra,
+                                 [Values(3u, 0xdu)] uint rd,
+                                 [Values(0x00000000u, 0x7FFFFFFFu,
+                                         0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
+                                 [Values(0x00000000u, 0x7FFFFFFFu,
+                                         0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm,
+                                 [Values(0x00000000u, 0x7FFFFFFFu,
+                                         0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wa)
+        {
+            opcode |= ((rn & 15) << 0) | ((rm & 15) << 8) | ((ra & 15) << 12) | ((rd & 15) << 16);
+
+            uint w31 = TestContext.CurrentContext.Random.NextUInt();
+
+            SingleOpcode(opcode, r0: wn, r1: wm, r2: wa, sp: w31);
+
+            CompareAgainstUnicorn();
+        }
+
+        [Test, Pairwise, Description("SMUL<x><y> <Rd>, <Rn>, <Rm>")]
+        public void Smul___32bit([ValueSource("_Smulbb_Smulbt_Smultb_Smultt_")] uint opcode,
+                                 [Values(0u, 0xdu)] uint rn,
+                                 [Values(1u, 0xdu)] uint rm,
+                                 [Values(2u, 0xdu)] uint rd,
+                                 [Values(0x00000000u, 0x7FFFFFFFu,
+                                         0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
+                                 [Values(0x00000000u, 0x7FFFFFFFu,
+                                         0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm)
+        {
+            opcode |= ((rn & 15) << 0) | ((rm & 15) << 8) | ((rd & 15) << 16);
+
+            uint w31 = TestContext.CurrentContext.Random.NextUInt();
+
+            SingleOpcode(opcode, r0: wn, r1: wm, sp: w31);
+
+            CompareAgainstUnicorn();
+        }
+
+        [Test, Pairwise, Description("SMULW<x> <Rd>, <Rn>, <Rm>")]
+        public void Smulw__32bit([ValueSource("_Smulwb_Smulwt_")] uint opcode,
+                                 [Values(0u, 0xdu)] uint rn,
+                                 [Values(1u, 0xdu)] uint rm,
+                                 [Values(2u, 0xdu)] uint rd,
+                                 [Values(0x00000000u, 0x7FFFFFFFu,
+                                         0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wn,
+                                 [Values(0x00000000u, 0x7FFFFFFFu,
+                                         0x80000000u, 0xFFFFFFFFu)] [Random(RndCnt)] uint wm)
+        {
+            opcode |= ((rn & 15) << 0) | ((rm & 15) << 8) | ((rd & 15) << 16);
+
+            uint w31 = TestContext.CurrentContext.Random.NextUInt();
+
+            SingleOpcode(opcode, r0: wn, r1: wm, sp: w31);
+
+            CompareAgainstUnicorn();
+        }
+#endif
+    }
+}