diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/ARMeilleure/Instructions/InstEmitSimdHelper.cs
index 27b5c13020..80dfc6889d 100644
--- a/ARMeilleure/Instructions/InstEmitSimdHelper.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdHelper.cs
@@ -1533,29 +1533,88 @@ namespace ARMeilleure.Instructions
             context.Copy(d, res);
         }
 
-        // TSrc (16bit, 32bit, 64bit; signed) > TDst (8bit, 16bit, 32bit; signed, unsigned).
-        // long SignedSrcSignedDstSatQ(long op, int size); ulong SignedSrcUnsignedDstSatQ(long op, int size);
-        public static Operand EmitSignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
+        // long SignedSignSatQ(long op, int size);
+        public static Operand EmitSignedSignSatQ(ArmEmitterContext context, Operand op, int size)
         {
-            Debug.Assert(op.Type == OperandType.I64 && (uint)sizeDst <= 2u);
+            int eSize = 8 << size;
+
+            Debug.Assert(op.Type == OperandType.I64);
+            Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
 
             Operand lbl1 = Label();
             Operand lblEnd = Label();
 
-            int eSize = 8 << sizeDst;
+            Operand zeroL = Const(0L);
+            Operand maxT = Const((1L << (eSize - 1)) - 1L);
+            Operand minT = Const(-(1L << (eSize - 1)));
 
-            Operand maxT = signedDst ? Const((1L << (eSize - 1)) - 1L) : Const((1UL << eSize) - 1UL);
-            Operand minT = signedDst ? Const(-(1L << (eSize - 1))) : Const(0UL);
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroL);
 
-            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
-
-            context.BranchIf(lbl1, res, maxT, Comparison.LessOrEqual);
+            context.BranchIf(lbl1, op, zeroL, Comparison.LessOrEqual);
             context.Copy(res, maxT);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
 
             context.MarkLabel(lbl1);
-            context.BranchIf(lblEnd, res, minT, Comparison.GreaterOrEqual);
+            context.BranchIf(lblEnd, op, zeroL, Comparison.GreaterOrEqual);
+            context.Copy(res, minT);
+            context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+            context.Branch(lblEnd);
+
+            context.MarkLabel(lblEnd);
+
+            return res;
+        }
+
+        // private static ulong UnsignedSignSatQ(ulong op, int size);
+        public static Operand EmitUnsignedSignSatQ(ArmEmitterContext context, Operand op, int size)
+        {
+            int eSize = 8 << size;
+
+            Debug.Assert(op.Type == OperandType.I64);
+            Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
+
+            Operand lblEnd = Label();
+
+            Operand zeroUL = Const(0UL);
+            Operand maxT = Const(ulong.MaxValue >> (64 - eSize));
+
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroUL);
+
+            context.BranchIf(lblEnd, op, zeroUL, Comparison.LessOrEqualUI);
+            context.Copy(res, maxT);
+            context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+            context.Branch(lblEnd);
+
+            context.MarkLabel(lblEnd);
+
+            return res;
+        }
+
+        // TSrc (16bit, 32bit, 64bit; signed) > TDst (8bit, 16bit, 32bit; signed, unsigned).
+        // long SignedSrcSignedDstSatQ(long op, int size); ulong SignedSrcUnsignedDstSatQ(long op, int size);
+        public static Operand EmitSignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
+        {
+            int eSizeDst = 8 << sizeDst;
+
+            Debug.Assert(op.Type == OperandType.I64);
+            Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
+
+            Operand lbl1 = Label();
+            Operand lblEnd = Label();
+
+            Operand maxT = signedDst ? Const((1L << (eSizeDst - 1)) - 1L) : Const((1UL << eSizeDst) - 1UL);
+            Operand minT = signedDst ? Const(-(1L << (eSizeDst - 1))) : Const(0UL);
+
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
+
+            context.BranchIf(lbl1, op, maxT, Comparison.LessOrEqual);
+            context.Copy(res, maxT);
+            context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+            context.Branch(lblEnd);
+
+            context.MarkLabel(lbl1);
+            context.BranchIf(lblEnd, op, minT, Comparison.GreaterOrEqual);
             context.Copy(res, minT);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
@@ -1569,18 +1628,19 @@ namespace ARMeilleure.Instructions
         // long UnsignedSrcSignedDstSatQ(ulong op, int size); ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size);
         public static Operand EmitUnsignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
         {
-            Debug.Assert(op.Type == OperandType.I64 && (uint)sizeDst <= 2u);
+            int eSizeDst = 8 << sizeDst;
+
+            Debug.Assert(op.Type == OperandType.I64);
+            Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
 
             Operand lblEnd = Label();
 
-            int eSize = 8 << sizeDst;
-
-            Operand maxL = signedDst ? Const((1L << (eSize - 1)) - 1L) : Const((1UL << eSize) - 1UL);
+            Operand maxT = signedDst ? Const((1L << (eSizeDst - 1)) - 1L) : Const((1UL << eSizeDst) - 1UL);
 
             Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
 
-            context.BranchIf(lblEnd, res, maxL, Comparison.LessOrEqualUI);
-            context.Copy(res, maxL);
+            context.BranchIf(lblEnd, op, maxT, Comparison.LessOrEqualUI);
+            context.Copy(res, maxT);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
 
@@ -1601,7 +1661,7 @@ namespace ARMeilleure.Instructions
 
             Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
 
-            context.BranchIf(lblEnd, res, minL, Comparison.NotEqual);
+            context.BranchIf(lblEnd, op, minL, Comparison.NotEqual);
             context.Copy(res, maxL);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
@@ -1620,15 +1680,16 @@ namespace ARMeilleure.Instructions
 
             Operand minL = Const(long.MinValue);
             Operand maxL = Const(long.MaxValue);
-            Operand zero = Const(0L);
+            Operand zeroL = Const(0L);
 
-            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
+            Operand add = context.Add(op1, op2);
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
 
             Operand left = context.BitwiseNot(context.BitwiseExclusiveOr(op1, op2));
-            Operand right = context.BitwiseExclusiveOr(op1, res);
-            context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zero, Comparison.GreaterOrEqual);
+            Operand right = context.BitwiseExclusiveOr(op1, add);
+            context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zeroL, Comparison.GreaterOrEqual);
 
-            Operand isPositive = context.ICompareGreaterOrEqual(op1, zero);
+            Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
             context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
@@ -1647,9 +1708,10 @@ namespace ARMeilleure.Instructions
 
             Operand maxUL = Const(ulong.MaxValue);
 
-            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
+            Operand add = context.Add(op1, op2);
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
 
-            context.BranchIf(lblEnd, res, op1, Comparison.GreaterOrEqualUI);
+            context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
             context.Copy(res, maxUL);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
@@ -1668,15 +1730,16 @@ namespace ARMeilleure.Instructions
 
             Operand minL = Const(long.MinValue);
             Operand maxL = Const(long.MaxValue);
-            Operand zero = Const(0L);
+            Operand zeroL = Const(0L);
 
-            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Subtract(op1, op2));
+            Operand sub = context.Subtract(op1, op2);
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sub);
 
             Operand left = context.BitwiseExclusiveOr(op1, op2);
-            Operand right = context.BitwiseExclusiveOr(op1, res);
-            context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zero, Comparison.GreaterOrEqual);
+            Operand right = context.BitwiseExclusiveOr(op1, sub);
+            context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zeroL, Comparison.GreaterOrEqual);
 
-            Operand isPositive = context.ICompareGreaterOrEqual(op1, zero);
+            Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
             context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
@@ -1693,12 +1756,13 @@ namespace ARMeilleure.Instructions
 
             Operand lblEnd = Label();
 
-            Operand zero = Const(0L);
+            Operand zeroL = Const(0L);
 
-            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Subtract(op1, op2));
+            Operand sub = context.Subtract(op1, op2);
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sub);
 
             context.BranchIf(lblEnd, op1, op2, Comparison.GreaterOrEqualUI);
-            context.Copy(res, zero);
+            context.Copy(res, zeroL);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
 
@@ -1717,25 +1781,26 @@ namespace ARMeilleure.Instructions
             Operand lblEnd = Label();
 
             Operand maxL = Const(long.MaxValue);
-            Operand zero = Const(0L);
+            Operand zeroL = Const(0L);
 
-            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
+            Operand add = context.Add(op1, op2);
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
 
             context.BranchIf(lbl1, op1, maxL, Comparison.GreaterUI);
-            Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), res);
-            context.BranchIf(lblEnd, notOp2AndRes, zero, Comparison.GreaterOrEqual);
+            Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), add);
+            context.BranchIf(lblEnd, notOp2AndRes, zeroL, Comparison.GreaterOrEqual);
             context.Copy(res, maxL);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
 
             context.MarkLabel(lbl1);
-            context.BranchIf(lbl2, op2, zero, Comparison.Less);
+            context.BranchIf(lbl2, op2, zeroL, Comparison.Less);
             context.Copy(res, maxL);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
 
             context.MarkLabel(lbl2);
-            context.BranchIf(lblEnd, res, maxL, Comparison.LessOrEqualUI);
+            context.BranchIf(lblEnd, add, maxL, Comparison.LessOrEqualUI);
             context.Copy(res, maxL);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
@@ -1755,20 +1820,21 @@ namespace ARMeilleure.Instructions
 
             Operand maxUL = Const(ulong.MaxValue);
             Operand maxL = Const(long.MaxValue);
-            Operand zero = Const(0L);
+            Operand zeroL = Const(0L);
 
-            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
+            Operand add = context.Add(op1, op2);
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
 
-            context.BranchIf(lbl1, op1, zero, Comparison.Less);
-            context.BranchIf(lblEnd, res, op1, Comparison.GreaterOrEqualUI);
+            context.BranchIf(lbl1, op1, zeroL, Comparison.Less);
+            context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
             context.Copy(res, maxUL);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
 
             context.MarkLabel(lbl1);
             context.BranchIf(lblEnd, op2, maxL, Comparison.GreaterUI);
-            context.BranchIf(lblEnd, res, zero, Comparison.GreaterOrEqual);
-            context.Copy(res, zero);
+            context.BranchIf(lblEnd, add, zeroL, Comparison.GreaterOrEqual);
+            context.Copy(res, zeroL);
             context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
             context.Branch(lblEnd);
 
diff --git a/ARMeilleure/Instructions/InstEmitSimdShift.cs b/ARMeilleure/Instructions/InstEmitSimdShift.cs
index 1a95200db2..146aeafa73 100644
--- a/ARMeilleure/Instructions/InstEmitSimdShift.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdShift.cs
@@ -188,23 +188,7 @@ namespace ARMeilleure.Instructions
 
         public static void Sqrshl_V(ArmEmitterContext context)
         {
-            OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
-            Operand res = context.VectorZero();
-
-            int elems = op.GetBytesCount() >> op.Size;
-
-            for (int index = 0; index < elems; index++)
-            {
-                Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
-                Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
-
-                Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)), ne, me, Const(1), Const(op.Size));
-
-                res = EmitVectorInsert(context, res, e, index, op.Size);
-            }
-
-            context.Copy(GetVec(op.Rd), res);
+            EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round | ShlRegFlags.Saturating);
         }
 
         public static void Sqrshrn_S(ArmEmitterContext context)
@@ -229,23 +213,7 @@ namespace ARMeilleure.Instructions
 
         public static void Sqshl_V(ArmEmitterContext context)
         {
-            OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
-            Operand res = context.VectorZero();
-
-            int elems = op.GetBytesCount() >> op.Size;
-
-            for (int index = 0; index < elems; index++)
-            {
-                Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
-                Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
-
-                Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)), ne, me, Const(0), Const(op.Size));
-
-                res = EmitVectorInsert(context, res, e, index, op.Size);
-            }
-
-            context.Copy(GetVec(op.Rd), res);
+            EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Saturating);
         }
 
         public static void Sqshrn_S(ArmEmitterContext context)
@@ -280,23 +248,7 @@ namespace ARMeilleure.Instructions
 
         public static void Srshl_V(ArmEmitterContext context)
         {
-            OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
-            Operand res = context.VectorZero();
-
-            int elems = op.GetBytesCount() >> op.Size;
-
-            for (int index = 0; index < elems; index++)
-            {
-                Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
-                Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
-
-                Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)), ne, me, Const(1), Const(op.Size));
-
-                res = EmitVectorInsert(context, res, e, index, op.Size);
-            }
-
-            context.Copy(GetVec(op.Rd), res);
+            EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round);
         }
 
         public static void Srshr_S(ArmEmitterContext context)
@@ -393,12 +345,12 @@ namespace ARMeilleure.Instructions
 
         public static void Sshl_S(ArmEmitterContext context)
         {
-            EmitSshlOrUshl(context, signed: true, scalar: true);
+            EmitShlRegOp(context, ShlRegFlags.Scalar | ShlRegFlags.Signed);
         }
 
         public static void Sshl_V(ArmEmitterContext context)
         {
-            EmitSshlOrUshl(context, signed: true, scalar: false);
+            EmitShlRegOp(context, ShlRegFlags.Signed);
         }
 
         public static void Sshll_V(ArmEmitterContext context)
@@ -506,23 +458,7 @@ namespace ARMeilleure.Instructions
 
         public static void Uqrshl_V(ArmEmitterContext context)
         {
-            OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
-            Operand res = context.VectorZero();
-
-            int elems = op.GetBytesCount() >> op.Size;
-
-            for (int index = 0; index < elems; index++)
-            {
-                Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
-                Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
-
-                Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)), ne, me, Const(1), Const(op.Size));
-
-                res = EmitVectorInsert(context, res, e, index, op.Size);
-            }
-
-            context.Copy(GetVec(op.Rd), res);
+            EmitShlRegOp(context, ShlRegFlags.Round | ShlRegFlags.Saturating);
         }
 
         public static void Uqrshrn_S(ArmEmitterContext context)
@@ -537,23 +473,7 @@ namespace ARMeilleure.Instructions
 
         public static void Uqshl_V(ArmEmitterContext context)
         {
-            OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
-            Operand res = context.VectorZero();
-
-            int elems = op.GetBytesCount() >> op.Size;
-
-            for (int index = 0; index < elems; index++)
-            {
-                Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
-                Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
-
-                Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)), ne, me, Const(0), Const(op.Size));
-
-                res = EmitVectorInsert(context, res, e, index, op.Size);
-            }
-
-            context.Copy(GetVec(op.Rd), res);
+            EmitShlRegOp(context, ShlRegFlags.Saturating);
         }
 
         public static void Uqshrn_S(ArmEmitterContext context)
@@ -568,23 +488,7 @@ namespace ARMeilleure.Instructions
 
         public static void Urshl_V(ArmEmitterContext context)
         {
-            OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
-            Operand res = context.VectorZero();
-
-            int elems = op.GetBytesCount() >> op.Size;
-
-            for (int index = 0; index < elems; index++)
-            {
-                Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
-                Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
-
-                Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)), ne, me, Const(1), Const(op.Size));
-
-                res = EmitVectorInsert(context, res, e, index, op.Size);
-            }
-
-            context.Copy(GetVec(op.Rd), res);
+            EmitShlRegOp(context, ShlRegFlags.Round);
         }
 
         public static void Urshr_S(ArmEmitterContext context)
@@ -677,12 +581,12 @@ namespace ARMeilleure.Instructions
 
         public static void Ushl_S(ArmEmitterContext context)
         {
-            EmitSshlOrUshl(context, signed: false, scalar: true);
+            EmitShlRegOp(context, ShlRegFlags.Scalar);
         }
 
         public static void Ushl_V(ArmEmitterContext context)
         {
-            EmitSshlOrUshl(context, signed: false, scalar: false);
+            EmitShlRegOp(context, ShlRegFlags.None);
         }
 
         public static void Ushll_V(ArmEmitterContext context)
@@ -872,43 +776,6 @@ namespace ARMeilleure.Instructions
             context.Copy(GetVec(op.Rd), res);
         }
 
-        private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool signed)
-        {
-            Debug.Assert(op.Type       == OperandType.I64);
-            Debug.Assert(shiftLsB.Type == OperandType.I32);
-            Debug.Assert((uint)size < 4u);
-
-            Operand negShiftLsB = context.Negate(shiftLsB);
-
-            Operand isInRange = context.BitwiseAnd(
-                context.ICompareLess(shiftLsB,    Const(8 << size)),
-                context.ICompareLess(negShiftLsB, Const(8 << size)));
-
-            Operand isPositive = context.ICompareGreaterOrEqual(shiftLsB, Const(0));
-
-            Operand shl = context.ShiftLeft(op, shiftLsB);
-
-            Operand sarOrShr = signed
-                ? context.ShiftRightSI(op, negShiftLsB)
-                : context.ShiftRightUI(op, negShiftLsB);
-
-            Operand res = context.ConditionalSelect(isPositive, shl, sarOrShr);
-
-            if (signed)
-            {
-                Operand isPositive2 = context.ICompareGreaterOrEqual(op, Const(0L));
-
-                Operand res2 = context.ConditionalSelect(isPositive2, Const(0L), Const(-1L));
-                        res2 = context.ConditionalSelect(isPositive,  Const(0L), res2);
-
-                return context.ConditionalSelect(isInRange, res, res2);
-            }
-            else
-            {
-                return context.ConditionalSelect(isInRange, res, Const(0UL));
-            }
-        }
-
         private static void EmitVectorShrImmNarrowOpZx(ArmEmitterContext context, bool round)
         {
             OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@@ -1168,8 +1035,23 @@ namespace ARMeilleure.Instructions
             }
         }
 
-        private static void EmitSshlOrUshl(ArmEmitterContext context, bool signed, bool scalar)
+        [Flags]
+        private enum ShlRegFlags
         {
+            None = 0,
+            Scalar = 1 << 0,
+            Signed = 1 << 1,
+            Round = 1 << 2,
+            Saturating = 1 << 3
+        }
+
+        private static void EmitShlRegOp(ArmEmitterContext context, ShlRegFlags flags = ShlRegFlags.None)
+        {
+            bool scalar = flags.HasFlag(ShlRegFlags.Scalar);
+            bool signed = flags.HasFlag(ShlRegFlags.Signed);
+            bool round = flags.HasFlag(ShlRegFlags.Round);
+            bool saturating = flags.HasFlag(ShlRegFlags.Saturating);
+
             OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
 
             Operand res = context.VectorZero();
@@ -1178,15 +1060,225 @@ namespace ARMeilleure.Instructions
 
             for (int index = 0; index < elems; index++)
             {
-                Operand ne = EmitVectorExtract  (context, op.Rn, index, op.Size, signed);
-                Operand me = EmitVectorExtractSx(context, op.Rm, index << op.Size, 0);
+                Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size, signed);
+                Operand me = EmitVectorExtractSx(context, op.Rm, index << op.Size, size: 0);
 
-                Operand e = EmitShlRegOp(context, ne, context.ConvertI64ToI32(me), op.Size, signed);
+                Operand e = !saturating
+                    ? EmitShlReg(context, ne, context.ConvertI64ToI32(me), round, op.Size, signed)
+                    : EmitShlRegSatQ(context, ne, context.ConvertI64ToI32(me), round, op.Size, signed);
 
                 res = EmitVectorInsert(context, res, e, index, op.Size);
             }
 
             context.Copy(GetVec(op.Rd), res);
         }
+
+        // long SignedShlReg(long op, int shiftLsB, bool round, int size);
+        // ulong UnsignedShlReg(ulong op, int shiftLsB, bool round, int size);
+        private static Operand EmitShlReg(ArmEmitterContext context, Operand op, Operand shiftLsB, bool round, int size, bool signed)
+        {
+            int eSize = 8 << size;
+
+            Debug.Assert(op.Type == OperandType.I64);
+            Debug.Assert(shiftLsB.Type == OperandType.I32);
+            Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
+
+            Operand lbl1 = Label();
+            Operand lblEnd = Label();
+
+            Operand eSizeOp = Const(eSize);
+            Operand zero = Const(0);
+            Operand zeroL = Const(0L);
+
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
+
+            context.BranchIf(lbl1, shiftLsB, zero, Comparison.GreaterOrEqual);
+            context.Copy(res, signed
+                ? EmitSignedShrReg(context, op, context.Negate(shiftLsB), round, eSize)
+                : EmitUnsignedShrReg(context, op, context.Negate(shiftLsB), round, eSize));
+            context.Branch(lblEnd);
+
+            context.MarkLabel(lbl1);
+            context.BranchIf(lblEnd, shiftLsB, zero, Comparison.LessOrEqual);
+            Operand shl = context.ShiftLeft(op, shiftLsB);
+            Operand isGreaterOrEqual = context.ICompareGreaterOrEqual(shiftLsB, eSizeOp);
+            context.Copy(res, context.ConditionalSelect(isGreaterOrEqual, zeroL, shl));
+            context.Branch(lblEnd);
+
+            context.MarkLabel(lblEnd);
+
+            return res;
+        }
+
+        // long SignedShlRegSatQ(long op, int shiftLsB, bool round, int size);
+        // ulong UnsignedShlRegSatQ(ulong op, int shiftLsB, bool round, int size);
+        private static Operand EmitShlRegSatQ(ArmEmitterContext context, Operand op, Operand shiftLsB, bool round, int size, bool signed)
+        {
+            int eSize = 8 << size;
+
+            Debug.Assert(op.Type == OperandType.I64);
+            Debug.Assert(shiftLsB.Type == OperandType.I32);
+            Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
+
+            Operand lbl1 = Label();
+            Operand lbl2 = Label();
+            Operand lblEnd = Label();
+
+            Operand eSizeOp = Const(eSize);
+            Operand zero = Const(0);
+
+            Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
+
+            context.BranchIf(lbl1, shiftLsB, zero, Comparison.GreaterOrEqual);
+            context.Copy(res, signed
+                ? EmitSignedShrReg(context, op, context.Negate(shiftLsB), round, eSize)
+                : EmitUnsignedShrReg(context, op, context.Negate(shiftLsB), round, eSize));
+            context.Branch(lblEnd);
+
+            context.MarkLabel(lbl1);
+            context.BranchIf(lblEnd, shiftLsB, zero, Comparison.LessOrEqual);
+            context.BranchIf(lbl2, shiftLsB, eSizeOp, Comparison.Less);
+            context.Copy(res, signed
+                ? EmitSignedSignSatQ(context, op, size)
+                : EmitUnsignedSignSatQ(context, op, size));
+            context.Branch(lblEnd);
+
+            context.MarkLabel(lbl2);
+            Operand shl = context.ShiftLeft(op, shiftLsB);
+            if (eSize == 64)
+            {
+                Operand sarOrShr = signed
+                    ? context.ShiftRightSI(shl, shiftLsB)
+                    : context.ShiftRightUI(shl, shiftLsB);
+                context.Copy(res, shl);
+                context.BranchIf(lblEnd, sarOrShr, op, Comparison.Equal);
+                context.Copy(res, signed
+                    ? EmitSignedSignSatQ(context, op, size)
+                    : EmitUnsignedSignSatQ(context, op, size));
+            }
+            else
+            {
+                context.Copy(res, signed
+                    ? EmitSignedSrcSatQ(context, shl, size, signedDst: true)
+                    : EmitUnsignedSrcSatQ(context, shl, size, signedDst: false));
+            }
+            context.Branch(lblEnd);
+
+            context.MarkLabel(lblEnd);
+
+            return res;
+        }
+
+        // shift := [1, 128]; eSize := {8, 16, 32, 64}.
+        // long SignedShrReg(long op, int shift, bool round, int eSize);
+        private static Operand EmitSignedShrReg(ArmEmitterContext context, Operand op, Operand shift, bool round, int eSize)
+        {
+            if (round)
+            {
+                Operand lblEnd = Label();
+
+                Operand eSizeOp = Const(eSize);
+                Operand zeroL = Const(0L);
+                Operand one = Const(1);
+                Operand oneL = Const(1L);
+
+                Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroL);
+
+                context.BranchIf(lblEnd, shift, eSizeOp, Comparison.GreaterOrEqual);
+                Operand roundConst = context.ShiftLeft(oneL, context.Subtract(shift, one));
+                Operand add = context.Add(op, roundConst);
+                Operand sar = context.ShiftRightSI(add, shift);
+                if (eSize == 64)
+                {
+                    Operand shr = context.ShiftRightUI(add, shift);
+                    Operand left = context.BitwiseAnd(context.Negate(op), context.BitwiseExclusiveOr(op, add));
+                    Operand isLess = context.ICompareLess(left, zeroL);
+                    context.Copy(res, context.ConditionalSelect(isLess, shr, sar));
+                }
+                else
+                {
+                    context.Copy(res, sar);
+                }
+                context.Branch(lblEnd);
+
+                context.MarkLabel(lblEnd);
+
+                return res;
+            }
+            else
+            {
+                Operand lblEnd = Label();
+
+                Operand eSizeOp = Const(eSize);
+                Operand zeroL = Const(0L);
+                Operand negOneL = Const(-1L);
+
+                Operand sar = context.ShiftRightSI(op, shift);
+                Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sar);
+
+                context.BranchIf(lblEnd, shift, eSizeOp, Comparison.Less);
+                Operand isLess = context.ICompareLess(op, zeroL);
+                context.Copy(res, context.ConditionalSelect(isLess, negOneL, zeroL));
+                context.Branch(lblEnd);
+
+                context.MarkLabel(lblEnd);
+
+                return res;
+            }
+        }
+
+        // shift := [1, 128]; eSize := {8, 16, 32, 64}.
+        // ulong UnsignedShrReg(ulong op, int shift, bool round, int eSize);
+        private static Operand EmitUnsignedShrReg(ArmEmitterContext context, Operand op, Operand shift, bool round, int eSize)
+        {
+            if (round)
+            {
+                Operand lblEnd = Label();
+
+                Operand zeroUL = Const(0UL);
+                Operand one = Const(1);
+                Operand oneUL = Const(1UL);
+                Operand eSizeMaxOp = Const(64);
+                Operand oneShl63UL = Const(1UL << 63);
+
+                Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroUL);
+
+                context.BranchIf(lblEnd, shift, eSizeMaxOp, Comparison.Greater);
+                Operand roundConst = context.ShiftLeft(oneUL, context.Subtract(shift, one));
+                Operand add = context.Add(op, roundConst);
+                Operand shr = context.ShiftRightUI(add, shift);
+                Operand isEqual = context.ICompareEqual(shift, eSizeMaxOp);
+                context.Copy(res, context.ConditionalSelect(isEqual, zeroUL, shr));
+                if (eSize == 64)
+                {
+                    context.BranchIf(lblEnd, add, op, Comparison.GreaterOrEqualUI);
+                    Operand right = context.BitwiseOr(shr, context.ShiftRightUI(oneShl63UL, context.Subtract(shift, one)));
+                    context.Copy(res, context.ConditionalSelect(isEqual, oneUL, right));
+                }
+                context.Branch(lblEnd);
+
+                context.MarkLabel(lblEnd);
+
+                return res;
+            }
+            else
+            {
+                Operand lblEnd = Label();
+
+                Operand eSizeOp = Const(eSize);
+                Operand zeroUL = Const(0UL);
+
+                Operand shr = context.ShiftRightUI(op, shift);
+                Operand res = context.Copy(context.AllocateLocal(OperandType.I64), shr);
+
+                context.BranchIf(lblEnd, shift, eSizeOp, Comparison.Less);
+                context.Copy(res, zeroUL);
+                context.Branch(lblEnd);
+
+                context.MarkLabel(lblEnd);
+
+                return res;
+            }
+        }
     }
 }
diff --git a/ARMeilleure/Instructions/SoftFallback.cs b/ARMeilleure/Instructions/SoftFallback.cs
index 829dd37a3f..d5e1ab65dd 100644
--- a/ARMeilleure/Instructions/SoftFallback.cs
+++ b/ARMeilleure/Instructions/SoftFallback.cs
@@ -5,287 +5,6 @@ namespace ARMeilleure.Instructions
 {
     static class SoftFallback
     {
-#region "ShlReg"
-        public static long SignedShlReg(long value, long shift, bool round, int size)
-        {
-            int eSize = 8 << size;
-
-            int shiftLsB = (sbyte)shift;
-
-            if (shiftLsB < 0)
-            {
-                return SignedShrReg(value, -shiftLsB, round, eSize);
-            }
-            else if (shiftLsB > 0)
-            {
-                if (shiftLsB >= eSize)
-                {
-                    return 0L;
-                }
-
-                return value << shiftLsB;
-            }
-            else /* if (shiftLsB == 0) */
-            {
-                return value;
-            }
-        }
-
-        public static ulong UnsignedShlReg(ulong value, ulong shift, bool round, int size)
-        {
-            int eSize = 8 << size;
-
-            int shiftLsB = (sbyte)shift;
-
-            if (shiftLsB < 0)
-            {
-                return UnsignedShrReg(value, -shiftLsB, round, eSize);
-            }
-            else if (shiftLsB > 0)
-            {
-                if (shiftLsB >= eSize)
-                {
-                    return 0UL;
-                }
-
-                return value << shiftLsB;
-            }
-            else /* if (shiftLsB == 0) */
-            {
-                return value;
-            }
-        }
-
-        public static long SignedShlRegSatQ(long value, long shift, bool round, int size)
-        {
-            ExecutionContext context = NativeInterface.GetContext();
-
-            int eSize = 8 << size;
-
-            int shiftLsB = (sbyte)shift;
-
-            if (shiftLsB < 0)
-            {
-                return SignedShrReg(value, -shiftLsB, round, eSize);
-            }
-            else if (shiftLsB > 0)
-            {
-                if (shiftLsB >= eSize)
-                {
-                    return SignedSignSatQ(value, eSize, context);
-                }
-
-                if (eSize == 64)
-                {
-                    long shl = value << shiftLsB;
-                    long shr = shl   >> shiftLsB;
-
-                    if (shr != value)
-                    {
-                        return SignedSignSatQ(value, eSize, context);
-                    }
-                    else /* if (shr == value) */
-                    {
-                        return shl;
-                    }
-                }
-                else /* if (eSize != 64) */
-                {
-                    return SignedSrcSignedDstSatQ(value << shiftLsB, size); // InstEmitSimdHelper.EmitSignedSrcSatQ(signedDst: true).
-                }
-            }
-            else /* if (shiftLsB == 0) */
-            {
-                return value;
-            }
-        }
-
-        public static ulong UnsignedShlRegSatQ(ulong value, ulong shift, bool round, int size)
-        {
-            ExecutionContext context = NativeInterface.GetContext();
-
-            int eSize = 8 << size;
-
-            int shiftLsB = (sbyte)shift;
-
-            if (shiftLsB < 0)
-            {
-                return UnsignedShrReg(value, -shiftLsB, round, eSize);
-            }
-            else if (shiftLsB > 0)
-            {
-                if (shiftLsB >= eSize)
-                {
-                    return UnsignedSignSatQ(value, eSize, context);
-                }
-
-                if (eSize == 64)
-                {
-                    ulong shl = value << shiftLsB;
-                    ulong shr = shl   >> shiftLsB;
-
-                    if (shr != value)
-                    {
-                        return UnsignedSignSatQ(value, eSize, context);
-                    }
-                    else /* if (shr == value) */
-                    {
-                        return shl;
-                    }
-                }
-                else /* if (eSize != 64) */
-                {
-                    return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size); // InstEmitSimdHelper.EmitUnsignedSrcSatQ(signedDst: false).
-                }
-            }
-            else /* if (shiftLsB == 0) */
-            {
-                return value;
-            }
-        }
-
-        private static long SignedShrReg(long value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
-        {
-            if (round)
-            {
-                if (shift >= eSize)
-                {
-                    return 0L;
-                }
-
-                long roundConst = 1L << (shift - 1);
-
-                long add = value + roundConst;
-
-                if (eSize == 64)
-                {
-                    if ((~value & (value ^ add)) < 0L)
-                    {
-                        return (long)((ulong)add >> shift);
-                    }
-                    else
-                    {
-                        return add >> shift;
-                    }
-                }
-                else /* if (eSize != 64) */
-                {
-                    return add >> shift;
-                }
-            }
-            else /* if (!round) */
-            {
-                if (shift >= eSize)
-                {
-                    if (value < 0L)
-                    {
-                        return -1L;
-                    }
-                    else /* if (value >= 0L) */
-                    {
-                        return 0L;
-                    }
-                }
-
-                return value >> shift;
-            }
-        }
-
-        private static ulong UnsignedShrReg(ulong value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
-        {
-            if (round)
-            {
-                if (shift > 64)
-                {
-                    return 0UL;
-                }
-
-                ulong roundConst = 1UL << (shift - 1);
-
-                ulong add = value + roundConst;
-
-                if (eSize == 64)
-                {
-                    if ((add < value) && (add < roundConst))
-                    {
-                        if (shift == 64)
-                        {
-                            return 1UL;
-                        }
-
-                        return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
-                    }
-                    else
-                    {
-                        if (shift == 64)
-                        {
-                            return 0UL;
-                        }
-
-                        return add >> shift;
-                    }
-                }
-                else /* if (eSize != 64) */
-                {
-                    if (shift == 64)
-                    {
-                        return 0UL;
-                    }
-
-                    return add >> shift;
-                }
-            }
-            else /* if (!round) */
-            {
-                if (shift >= eSize)
-                {
-                    return 0UL;
-                }
-
-                return value >> shift;
-            }
-        }
-
-        private static long SignedSignSatQ(long op, int eSize, ExecutionContext context) // eSize := {8, 16, 32, 64}.
-        {
-            long tMaxValue =  (1L << (eSize - 1)) - 1L;
-            long tMinValue = -(1L << (eSize - 1));
-
-            if (op > 0L)
-            {
-                context.Fpsr |= FPSR.Qc;
-
-                return tMaxValue;
-            }
-            else if (op < 0L)
-            {
-                context.Fpsr |= FPSR.Qc;
-
-                return tMinValue;
-            }
-            else
-            {
-                return 0L;
-            }
-        }
-
-        private static ulong UnsignedSignSatQ(ulong op, int eSize, ExecutionContext context) // eSize := {8, 16, 32, 64}.
-        {
-            ulong tMaxValue = ulong.MaxValue >> (64 - eSize);
-
-            if (op > 0UL)
-            {
-                context.Fpsr |= FPSR.Qc;
-
-                return tMaxValue;
-            }
-            else
-            {
-                return 0UL;
-            }
-        }
-#endregion
-
 #region "ShrImm64"
         public static long SignedShrImm64(long value, long roundConst, int shift)
         {
@@ -508,55 +227,6 @@ namespace ARMeilleure.Instructions
         }
 #endregion
 
-#region "Saturating"
-        private static long SignedSrcSignedDstSatQ(long op, int size)
-        {
-            ExecutionContext context = NativeInterface.GetContext();
-
-            int eSize = 8 << size;
-
-            long tMaxValue =  (1L << (eSize - 1)) - 1L;
-            long tMinValue = -(1L << (eSize - 1));
-
-            if (op > tMaxValue)
-            {
-                context.Fpsr |= FPSR.Qc;
-
-                return tMaxValue;
-            }
-            else if (op < tMinValue)
-            {
-                context.Fpsr |= FPSR.Qc;
-
-                return tMinValue;
-            }
-            else
-            {
-                return op;
-            }
-        }
-
-        private static ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size)
-        {
-            ExecutionContext context = NativeInterface.GetContext();
-
-            int eSize = 8 << size;
-
-            ulong tMaxValue = (1UL << eSize) - 1UL;
-
-            if (op > tMaxValue)
-            {
-                context.Fpsr |= FPSR.Qc;
-
-                return tMaxValue;
-            }
-            else
-            {
-                return op;
-            }
-        }
-#endregion
-
 #region "Count"
         public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
         {
diff --git a/ARMeilleure/Translation/Delegates.cs b/ARMeilleure/Translation/Delegates.cs
index b36472b835..0da69ebc37 100644
--- a/ARMeilleure/Translation/Delegates.cs
+++ b/ARMeilleure/Translation/Delegates.cs
@@ -179,8 +179,6 @@ namespace ARMeilleure.Translation
             SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)));
             SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)));
             SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)));
-            SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)));
-            SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)));
             SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
             SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
             SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
@@ -190,8 +188,6 @@ namespace ARMeilleure.Translation
             SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
             SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
             SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
-            SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)));
-            SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)));
             SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
 
             SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs
index 71f69ef7cc..01f0898822 100644
--- a/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/ARMeilleure/Translation/PTC/Ptc.cs
@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
         private const string OuterHeaderMagicString = "PTCohd\0\0";
         private const string InnerHeaderMagicString = "PTCihd\0\0";
 
-        private const uint InternalVersion = 3695; //! To be incremented manually for each change to the ARMeilleure project.
+        private const uint InternalVersion = 3700; //! To be incremented manually for each change to the ARMeilleure project.
 
         private const string ActualDir = "0";
         private const string BackupDir = "1";