aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Instructions/InstEmitSimdShift.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/Instructions/InstEmitSimdShift.cs')
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdShift.cs98
1 files changed, 56 insertions, 42 deletions
diff --git a/ARMeilleure/Instructions/InstEmitSimdShift.cs b/ARMeilleure/Instructions/InstEmitSimdShift.cs
index 0b3d85ae..62363fde 100644
--- a/ARMeilleure/Instructions/InstEmitSimdShift.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdShift.cs
@@ -391,25 +391,14 @@ namespace ARMeilleure.Instructions
}
}
- public static void Sshl_V(ArmEmitterContext context)
+ public static void Sshl_S(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(0), Const(op.Size));
-
- res = EmitVectorInsert(context, res, e, index, op.Size);
- }
+ EmitSshlOrUshl(context, signed: true, scalar: true);
+ }
- context.Copy(GetVec(op.Rd), res);
+ public static void Sshl_V(ArmEmitterContext context)
+ {
+ EmitSshlOrUshl(context, signed: true, scalar: false);
}
public static void Sshll_V(ArmEmitterContext context)
@@ -686,25 +675,14 @@ namespace ARMeilleure.Instructions
}
}
- public static void Ushl_V(ArmEmitterContext context)
+ public static void Ushl_S(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 = EmitVectorExtractSx(context, op.Rm, index << op.Size, 0);
-
- Operand e = EmitUnsignedShlRegOp(context, ne, context.ConvertI64ToI32(me), op.Size);
-
- res = EmitVectorInsert(context, res, e, index, op.Size);
- }
+ EmitSshlOrUshl(context, signed: false, scalar: true);
+ }
- context.Copy(GetVec(op.Rd), res);
+ public static void Ushl_V(ArmEmitterContext context)
+ {
+ EmitSshlOrUshl(context, signed: false, scalar: false);
}
public static void Ushll_V(ArmEmitterContext context)
@@ -894,7 +872,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res);
}
- private static Operand EmitUnsignedShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size)
+ 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);
@@ -902,18 +880,33 @@ namespace ARMeilleure.Instructions
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 shr = context.ShiftRightUI(op, negShiftLsB);
+ Operand shl = context.ShiftLeft(op, shiftLsB);
+
+ Operand sarOrShr = signed
+ ? context.ShiftRightSI(op, negShiftLsB)
+ : context.ShiftRightUI(op, negShiftLsB);
- Operand res = context.ConditionalSelect(isPositive, shl, shr);
+ Operand res = context.ConditionalSelect(isPositive, shl, sarOrShr);
- Operand isOutOfRange = context.BitwiseOr(
- context.ICompareGreaterOrEqual(shiftLsB, Const(8 << size)),
- context.ICompareGreaterOrEqual(negShiftLsB, Const(8 << size)));
+ 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(isOutOfRange, Const(0UL), res);
+ return context.ConditionalSelect(isInRange, res, res2);
+ }
+ else
+ {
+ return context.ConditionalSelect(isInRange, res, Const(0UL));
+ }
}
private static void EmitVectorShrImmNarrowOpZx(ArmEmitterContext context, bool round)
@@ -1174,5 +1167,26 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res);
}
}
+
+ private static void EmitSshlOrUshl(ArmEmitterContext context, bool signed, bool scalar)
+ {
+ OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
+
+ Operand res = context.VectorZero();
+
+ int elems = !scalar ? op.GetBytesCount() >> op.Size : 1;
+
+ 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 e = EmitShlRegOp(context, ne, context.ConvertI64ToI32(me), op.Size, signed);
+
+ res = EmitVectorInsert(context, res, e, index, op.Size);
+ }
+
+ context.Copy(GetVec(op.Rd), res);
+ }
}
}