diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs
index 60646d0ee..d32bd9cd2 100644
--- a/ChocolArm64/AOpCodeTable.cs
+++ b/ChocolArm64/AOpCodeTable.cs
@@ -42,6 +42,14 @@ namespace ChocolArm64
             Set("x1111010010xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ccmp,          typeof(AOpCodeCcmpReg));
             Set("11010101000000110011xxxx01011111", AInstEmit.Clrex,         typeof(AOpCodeSystem));
             Set("x101101011000000000100xxxxxxxxxx", AInstEmit.Clz,           typeof(AOpCodeAlu));
+            Set("x0011010110xxxxx010000xxxxxxxxxx", AInstEmit.Crc32b,        typeof(AOpCodeAluRs));
+            Set("x0011010110xxxxx010001xxxxxxxxxx", AInstEmit.Crc32h,        typeof(AOpCodeAluRs));
+            Set("x0011010110xxxxx010010xxxxxxxxxx", AInstEmit.Crc32w,        typeof(AOpCodeAluRs));
+            Set("x0011010110xxxxx010011xxxxxxxxxx", AInstEmit.Crc32x,        typeof(AOpCodeAluRs));
+            Set("x0011010110xxxxx010100xxxxxxxxxx", AInstEmit.Crc32cb,       typeof(AOpCodeAluRs));
+            Set("x0011010110xxxxx010101xxxxxxxxxx", AInstEmit.Crc32ch,       typeof(AOpCodeAluRs));
+            Set("x0011010110xxxxx010110xxxxxxxxxx", AInstEmit.Crc32cw,       typeof(AOpCodeAluRs));
+            Set("x0011010110xxxxx010111xxxxxxxxxx", AInstEmit.Crc32cx,       typeof(AOpCodeAluRs));
             Set("x0011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csel,          typeof(AOpCodeCsel));
             Set("x0011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csinc,         typeof(AOpCodeCsel));
             Set("x1011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csinv,         typeof(AOpCodeCsel));
@@ -243,6 +251,7 @@ namespace ChocolArm64
             Set("0x0011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_V,         typeof(AOpCodeSimdShImm));
             Set("0x101110<<100001001110xxxxxxxxxx", AInstEmit.Shll_V,        typeof(AOpCodeSimd));
             Set("0x00111100>>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V,        typeof(AOpCodeSimdShImm));
+            Set("0x1011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Sli_V,         typeof(AOpCodeSimdShImm));
             Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V,        typeof(AOpCodeSimdReg));
             Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V,        typeof(AOpCodeSimdReg));
             Set("0x001110<<1xxxxx100000xxxxxxxxxx", AInstEmit.Smlal_V,       typeof(AOpCodeSimdReg));
diff --git a/ChocolArm64/Instruction/AInstEmitHash.cs b/ChocolArm64/Instruction/AInstEmitHash.cs
new file mode 100644
index 000000000..fd98f5632
--- /dev/null
+++ b/ChocolArm64/Instruction/AInstEmitHash.cs
@@ -0,0 +1,74 @@
+using ChocolArm64.Decoder;
+using ChocolArm64.State;
+using ChocolArm64.Translation;
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Instruction
+{
+    static partial class AInstEmit
+    {
+        
+        public static void Crc32b(AILEmitterCtx Context)
+        {
+            EmitCrc32(Context, nameof(ASoftFallback.Crc32b));
+        }
+
+        public static void Crc32h(AILEmitterCtx Context)
+        {
+            EmitCrc32(Context, nameof(ASoftFallback.Crc32h));
+        }
+
+        public static void Crc32w(AILEmitterCtx Context)
+        {
+            EmitCrc32(Context, nameof(ASoftFallback.Crc32w));
+        }
+
+        public static void Crc32x(AILEmitterCtx Context)
+        {
+            EmitCrc32(Context, nameof(ASoftFallback.Crc32x));
+        }
+
+        public static void Crc32cb(AILEmitterCtx Context)
+        {
+            EmitCrc32(Context, nameof(ASoftFallback.Crc32cb));
+        }
+
+        public static void Crc32ch(AILEmitterCtx Context)
+        {
+            EmitCrc32(Context, nameof(ASoftFallback.Crc32ch));
+        }
+
+        public static void Crc32cw(AILEmitterCtx Context)
+        {
+            EmitCrc32(Context, nameof(ASoftFallback.Crc32cw));
+        }
+
+        public static void Crc32cx(AILEmitterCtx Context)
+        {
+            EmitCrc32(Context, nameof(ASoftFallback.Crc32cx));
+        }
+
+        private static void EmitCrc32(AILEmitterCtx Context, string Name)
+        {
+            AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp;
+
+            Context.EmitLdintzr(Op.Rn);
+
+            if (Op.RegisterSize != ARegisterSize.Int32)
+            {
+                Context.Emit(OpCodes.Conv_U4);
+            }
+
+            Context.EmitLdintzr(Op.Rm);
+
+            ASoftFallback.EmitCall(Context, Name);
+
+            if (Op.RegisterSize != ARegisterSize.Int32)
+            {
+                Context.Emit(OpCodes.Conv_U8);
+            }
+
+            Context.EmitStintzr(Op.Rd);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitSimdShift.cs b/ChocolArm64/Instruction/AInstEmitSimdShift.cs
index bb8a8f178..bffed57ed 100644
--- a/ChocolArm64/Instruction/AInstEmitSimdShift.cs
+++ b/ChocolArm64/Instruction/AInstEmitSimdShift.cs
@@ -29,7 +29,7 @@ namespace ChocolArm64.Instruction
 
             int Shift = Op.Imm - (8 << Op.Size);
 
-            EmitVectorBinaryShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
+            EmitVectorShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
         }
 
         public static void Shll_V(AILEmitterCtx Context)
@@ -50,6 +50,40 @@ namespace ChocolArm64.Instruction
             EmitVectorShImmNarrowBinaryZx(Context, () => Context.Emit(OpCodes.Shr_Un), Shift);
         }
 
+        public static void Sli_V(AILEmitterCtx Context)
+        {
+            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
+
+            int Bytes = Context.CurrOp.GetBitsCount() >> 3;
+
+            int Shift = Op.Imm - (8 << Op.Size);
+
+            ulong Mask = ulong.MaxValue >> (64 - Shift);            
+
+            for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
+            {
+                EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
+
+                Context.EmitLdc_I4(Shift);
+
+                Context.Emit(OpCodes.Shl);
+
+                EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);
+
+                Context.EmitLdc_I8((long)Mask);
+
+                Context.Emit(OpCodes.And);
+                Context.Emit(OpCodes.Or);
+
+                EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
+            }
+
+            if (Op.RegisterSize == ARegisterSize.SIMD64)
+            {
+                EmitVectorZeroUpper(Context, Op.Rd);
+            }
+        }
+
         public static void Sshl_V(AILEmitterCtx Context)
         {
             EmitVectorShl(Context, Signed: true);
@@ -83,7 +117,7 @@ namespace ChocolArm64.Instruction
 
             int Shift = (8 << (Op.Size + 1)) - Op.Imm;
 
-            EmitVectorBinaryShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift);
+            EmitVectorShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift);
         }
 
         public static void Ssra_V(AILEmitterCtx Context)
@@ -98,7 +132,7 @@ namespace ChocolArm64.Instruction
                 Context.Emit(OpCodes.Add);
             };
 
-            EmitVectorTernaryShImmBinarySx(Context, Emit, Shift);
+            EmitVectorShImmTernarySx(Context, Emit, Shift);
         }
 
         public static void Ushl_V(AILEmitterCtx Context)
@@ -217,22 +251,22 @@ namespace ChocolArm64.Instruction
             }
         }
 
-        private static void EmitVectorBinaryShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
+        private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
         {
-            EmitVectorShImmBinaryOp(Context, Emit, Imm, false, true);
+            EmitVectorShImmOp(Context, Emit, Imm, false, true);
         }
 
-        private static void EmitVectorTernaryShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
+        private static void EmitVectorShImmTernarySx(AILEmitterCtx Context, Action Emit, int Imm)
         {
-            EmitVectorShImmBinaryOp(Context, Emit, Imm, true, true);
+            EmitVectorShImmOp(Context, Emit, Imm, true, true);
         }
 
-        private static void EmitVectorBinaryShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
+        private static void EmitVectorShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
         {
-            EmitVectorShImmBinaryOp(Context, Emit, Imm, false, false);
+            EmitVectorShImmOp(Context, Emit, Imm, false, false);
         }
 
-        private static void EmitVectorShImmBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Ternary, bool Signed)
+        private static void EmitVectorShImmOp(AILEmitterCtx Context, Action Emit, int Imm, bool Ternary, bool Signed)
         {
             AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
 
diff --git a/ChocolArm64/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs
index 797d81573..7e5b3dba2 100644
--- a/ChocolArm64/Instruction/ASoftFallback.cs
+++ b/ChocolArm64/Instruction/ASoftFallback.cs
@@ -38,6 +38,84 @@ namespace ChocolArm64.Instruction
             return (ulong)Size;
         }
 
+        private const uint Crc32RevPoly  = 0xedb88320;
+        private const uint Crc32cRevPoly = 0x82f63b78;
+
+        public static uint Crc32b(uint Crc, byte Val) => Crc32 (Crc, Crc32RevPoly, Val);
+        public static uint Crc32h(uint Crc, byte Val) => Crc32h(Crc, Crc32RevPoly, Val);
+        public static uint Crc32w(uint Crc, byte Val) => Crc32w(Crc, Crc32RevPoly, Val);
+        public static uint Crc32x(uint Crc, byte Val) => Crc32x(Crc, Crc32RevPoly, Val);
+
+        public static uint Crc32cb(uint Crc, byte Val) => Crc32 (Crc, Crc32cRevPoly, Val);
+        public static uint Crc32ch(uint Crc, byte Val) => Crc32h(Crc, Crc32cRevPoly, Val);
+        public static uint Crc32cw(uint Crc, byte Val) => Crc32w(Crc, Crc32cRevPoly, Val);
+        public static uint Crc32cx(uint Crc, byte Val) => Crc32x(Crc, Crc32cRevPoly, Val);
+
+        private static uint Crc32h(uint Crc, uint Poly, ushort Val)
+        {
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 0));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 8));
+
+            return Crc;
+        }
+
+        private static uint Crc32w(uint Crc, uint Poly, uint Val)
+        {
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 0));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 8));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
+
+            return Crc;
+        }
+
+        private static uint Crc32x(uint Crc, uint Poly, ulong Val)
+        {
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 0));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 8));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 32));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 40));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 48));
+            Crc = Crc32(Crc, Poly, (byte)(Val >> 56));
+
+            return Crc;
+        }
+
+        private static uint Crc32(uint Crc, uint Poly, byte Val)
+        {
+            Crc ^= Val;
+
+            for (int Bit = 7; Bit >= 0; Bit--)
+            {
+                uint Mask = (uint)(-(int)(Crc & 1));
+
+                Crc = (Crc >> 1) ^ (Poly & Mask);
+            }
+
+            return Crc;
+        }
+
+        public static uint ReverseBits8(uint Value)
+        {
+            Value = ((Value & 0xaa) >> 1) | ((Value & 0x55) << 1);
+            Value = ((Value & 0xcc) >> 2) | ((Value & 0x33) << 2);
+            Value = ((Value & 0xf0) >> 4) | ((Value & 0x0f) << 4);
+
+            return Value;
+        }
+
+        public static uint ReverseBits16(uint Value)
+        {
+            Value = ((Value & 0xaaaa) >> 1) | ((Value & 0x5555) << 1);
+            Value = ((Value & 0xcccc) >> 2) | ((Value & 0x3333) << 2);
+            Value = ((Value & 0xf0f0) >> 4) | ((Value & 0x0f0f) << 4);
+            Value = ((Value & 0xff00) >> 8) | ((Value & 0x00ff) << 8);
+
+            return Value;
+        }
+
         public static uint ReverseBits32(uint Value)
         {
             Value = ((Value & 0xaaaaaaaa) >> 1) | ((Value & 0x55555555) << 1);