diff options
Diffstat (limited to 'ARMeilleure/Instructions/InstEmitSimdHelper.cs')
-rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdHelper.cs | 148 |
1 files changed, 107 insertions, 41 deletions
diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/ARMeilleure/Instructions/InstEmitSimdHelper.cs index 27b5c130..80dfc688 100644 --- a/ARMeilleure/Instructions/InstEmitSimdHelper.cs +++ b/ARMeilleure/Instructions/InstEmitSimdHelper.cs @@ -1533,29 +1533,88 @@ namespace ARMeilleure.Instructions context.Copy(d, res); } + // long SignedSignSatQ(long op, int size); + public static Operand EmitSignedSignSatQ(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 lbl1 = Label(); + Operand lblEnd = Label(); + + Operand zeroL = Const(0L); + Operand maxT = Const((1L << (eSize - 1)) - 1L); + Operand minT = Const(-(1L << (eSize - 1))); + + Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroL); + + 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, 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) { - 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 lbl1 = Label(); Operand lblEnd = Label(); - int eSize = 8 << sizeDst; - - Operand maxT = signedDst ? Const((1L << (eSize - 1)) - 1L) : Const((1UL << eSize) - 1UL); - Operand minT = signedDst ? Const(-(1L << (eSize - 1))) : Const(0UL); + 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, res, maxT, Comparison.LessOrEqual); + 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, res, minT, Comparison.GreaterOrEqual); + 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; - Operand lblEnd = Label(); + Debug.Assert(op.Type == OperandType.I64); + Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32); - int eSize = 8 << sizeDst; + Operand lblEnd = Label(); - 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); |