|
|
@@ -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;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|