diff options
author | LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> | 2022-09-09 00:40:41 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-08 19:40:41 -0300 |
commit | 7baa08dcb4b38fe36bb19bf84b3fcd386d143463 (patch) | |
tree | bfbbd817e56b3d47a1ca9662bf0c69c0119ddd58 /ARMeilleure/Instructions | |
parent | 408bd63b08cbde8ba55bb05a39868271a9e40ba4 (diff) |
Implemented in IR the managed methods of the Saturating region ... (#3665)1.1.252
* Implemented in IR the managed methods of the Saturating region ...
... of the SoftFallback class (the SatQ ones).
The need to natively manage the Fpcr and Fpsr system registers is still a fact.
Contributes to https://github.com/Ryujinx/Ryujinx/issues/2917 ; I will open another PR to implement in Intrinsics-branchless the methods of the Saturation region as well (the SatXXXToXXX ones).
All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq.
* Ptc.InternalVersion = 3665
* Addressed PR feedback.
Diffstat (limited to 'ARMeilleure/Instructions')
-rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdHelper.cs | 293 | ||||
-rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdShift.cs | 2 | ||||
-rw-r--r-- | ARMeilleure/Instructions/SoftFallback.cs | 257 |
3 files changed, 241 insertions, 311 deletions
diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/ARMeilleure/Instructions/InstEmitSimdHelper.cs index 736d16a3..805656d2 100644 --- a/ARMeilleure/Instructions/InstEmitSimdHelper.cs +++ b/ARMeilleure/Instructions/InstEmitSimdHelper.cs @@ -1352,7 +1352,7 @@ namespace ARMeilleure.Instructions if (op.Size <= 2) { - de = EmitSatQ(context, emit(ne), op.Size, signedSrc: true, signedDst: true); + de = EmitSignedSrcSatQ(context, emit(ne), op.Size, signedDst: true); } else /* if (op.Size == 3) */ { @@ -1419,15 +1419,18 @@ namespace ARMeilleure.Instructions { Operand temp = add ? context.Add(ne, me) : context.Subtract(ne, me); - de = EmitSatQ(context, temp, op.Size, signedSrc: true, signedDst: signed); + de = EmitSignedSrcSatQ(context, temp, op.Size, signedDst: signed); } - else if (add) /* if (op.Size == 3) */ - { - de = EmitBinarySatQAdd(context, ne, me, signed); - } - else /* if (sub) */ + else /* if (op.Size == 3) */ { - de = EmitBinarySatQSub(context, ne, me, signed); + if (add) + { + de = signed ? EmitBinarySignedSatQAdd(context, ne, me) : EmitBinaryUnsignedSatQAdd(context, ne, me); + } + else /* if (sub) */ + { + de = signed ? EmitBinarySignedSatQSub(context, ne, me) : EmitBinaryUnsignedSatQSub(context, ne, me); + } } res = EmitVectorInsert(context, res, de, index, op.Size); @@ -1445,11 +1448,11 @@ namespace ARMeilleure.Instructions { Operand temp = context.Add(ne, me); - de = EmitSatQ(context, temp, op.Size, signedSrc: true, signedDst: signed); + de = EmitSignedSrcSatQ(context, temp, op.Size, signedDst: signed); } else /* if (op.Size == 3) */ { - de = EmitBinarySatQAccumulate(context, ne, me, signed); + de = signed ? EmitBinarySignedSatQAcc(context, ne, me) : EmitBinaryUnsignedSatQAcc(context, ne, me); } res = EmitVectorInsert(context, res, de, index, op.Size); @@ -1475,7 +1478,7 @@ namespace ARMeilleure.Instructions me = EmitVectorExtract(context, ((OpCodeSimdReg)op).Rm, index, op.Size, signed); } - Operand de = EmitSatQ(context, emit(ne, me), op.Size, true, signed); + Operand de = EmitSignedSrcSatQ(context, emit(ne, me), op.Size, signedDst: signed); res = EmitVectorInsert(context, res, de, index, op.Size); } @@ -1520,7 +1523,9 @@ namespace ARMeilleure.Instructions { Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size + 1, signedSrc); - Operand temp = EmitSatQ(context, ne, op.Size, signedSrc, signedDst); + Operand temp = signedSrc + ? EmitSignedSrcSatQ(context, ne, op.Size, signedDst) + : EmitUnsignedSrcSatQ(context, ne, op.Size, signedDst); res = EmitVectorInsert(context, res, temp, part + index, op.Size); } @@ -1528,74 +1533,248 @@ namespace ARMeilleure.Instructions context.Copy(d, res); } - // TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned). - public static Operand EmitSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedSrc, bool signedDst) + // 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) { - if ((uint)sizeDst > 2u) - { - throw new ArgumentOutOfRangeException(nameof(sizeDst)); - } + Debug.Assert(op.Type == OperandType.I64 && (uint)sizeDst <= 2u); - MethodInfo info; + Operand lbl1 = Label(); + Operand lblEnd = Label(); - if (signedSrc) - { - info = signedDst - ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcSignedDstSatQ)) - : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcUnsignedDstSatQ)); - } - else - { - info = signedDst - ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcSignedDstSatQ)) - : typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcUnsignedDstSatQ)); - } + 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); - return context.Call(info, op, Const(sizeDst)); + Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op); + + context.BranchIf(lbl1, res, 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.Copy(res, minT); + context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); + context.Branch(lblEnd); + + context.MarkLabel(lblEnd); + + return res; } - // TSrc (64bit) == TDst (64bit); signed. - public static Operand EmitUnarySignedSatQAbsOrNeg(ArmEmitterContext context, Operand op) + // TSrc (16bit, 32bit, 64bit; unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned). + // 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(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); + Debug.Assert(op.Type == OperandType.I64 && (uint)sizeDst <= 2u); + + Operand lblEnd = Label(); + + int eSize = 8 << sizeDst; + + Operand maxL = signedDst ? Const((1L << (eSize - 1)) - 1L) : Const((1UL << eSize) - 1UL); + + Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op); + + context.BranchIf(lblEnd, res, maxL, Comparison.LessOrEqualUI); + context.Copy(res, maxL); + context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); + context.Branch(lblEnd); - return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnarySignedSatQAbsOrNeg)), op); + context.MarkLabel(lblEnd); + + return res; } - // TSrcs (64bit) == TDst (64bit); signed, unsigned. - public static Operand EmitBinarySatQAdd(ArmEmitterContext context, Operand op1, Operand op2, bool signed) + // long UnarySignedSatQAbsOrNeg(long op); + private static Operand EmitUnarySignedSatQAbsOrNeg(ArmEmitterContext context, Operand op) { - Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); + Debug.Assert(op.Type == OperandType.I64); + + Operand lblEnd = Label(); + + Operand minL = Const(long.MinValue); + Operand maxL = Const(long.MaxValue); + + Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op); + + context.BranchIf(lblEnd, res, minL, Comparison.NotEqual); + context.Copy(res, maxL); + context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); + context.Branch(lblEnd); - MethodInfo info = signed - ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAdd)) - : typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAdd)); + context.MarkLabel(lblEnd); - return context.Call(info, op1, op2); + return res; } - // TSrcs (64bit) == TDst (64bit); signed, unsigned. - public static Operand EmitBinarySatQSub(ArmEmitterContext context, Operand op1, Operand op2, bool signed) + // long BinarySignedSatQAdd(long op1, long op2); + private static Operand EmitBinarySignedSatQAdd(ArmEmitterContext context, Operand op1, Operand op2) { - Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); + Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64); + + Operand lblEnd = Label(); + + Operand minL = Const(long.MinValue); + Operand maxL = Const(long.MaxValue); + Operand zero = Const(0L); + + Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2)); + + Operand left = context.BitwiseNot(context.BitwiseExclusiveOr(op1, op2)); + Operand right = context.BitwiseExclusiveOr(op1, res); + context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zero, Comparison.GreaterOrEqual); - MethodInfo info = signed - ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQSub)) - : typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQSub)); + Operand isPositive = context.ICompareGreaterOrEqual(op1, zero); + context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL)); + context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); + context.Branch(lblEnd); - return context.Call(info, op1, op2); + context.MarkLabel(lblEnd); + + return res; } - // TSrcs (64bit) == TDst (64bit); signed, unsigned. - public static Operand EmitBinarySatQAccumulate(ArmEmitterContext context, Operand op1, Operand op2, bool signed) + // ulong BinaryUnsignedSatQAdd(ulong op1, ulong op2); + private static Operand EmitBinaryUnsignedSatQAdd(ArmEmitterContext context, Operand op1, Operand op2) { - Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size."); + Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64); + + Operand lblEnd = Label(); + + Operand maxUL = Const(ulong.MaxValue); + + Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2)); - MethodInfo info = signed - ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAcc)) - : typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAcc)); + context.BranchIf(lblEnd, res, op1, Comparison.GreaterOrEqualUI); + context.Copy(res, maxUL); + context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); + context.Branch(lblEnd); - return context.Call(info, op1, op2); + context.MarkLabel(lblEnd); + + return res; + } + + // long BinarySignedSatQSub(long op1, long op2); + private static Operand EmitBinarySignedSatQSub(ArmEmitterContext context, Operand op1, Operand op2) + { + Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64); + + Operand lblEnd = Label(); + + Operand minL = Const(long.MinValue); + Operand maxL = Const(long.MaxValue); + Operand zero = Const(0L); + + Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Subtract(op1, op2)); + + Operand left = context.BitwiseExclusiveOr(op1, op2); + Operand right = context.BitwiseExclusiveOr(op1, res); + context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zero, Comparison.GreaterOrEqual); + + Operand isPositive = context.ICompareGreaterOrEqual(op1, zero); + context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL)); + context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); + context.Branch(lblEnd); + + context.MarkLabel(lblEnd); + + return res; + } + + // ulong BinaryUnsignedSatQSub(ulong op1, ulong op2); + private static Operand EmitBinaryUnsignedSatQSub(ArmEmitterContext context, Operand op1, Operand op2) + { + Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64); + + Operand lblEnd = Label(); + + Operand zero = Const(0L); + + Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Subtract(op1, op2)); + + context.BranchIf(lblEnd, op1, op2, Comparison.GreaterOrEqualUI); + context.Copy(res, zero); + context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); + context.Branch(lblEnd); + + context.MarkLabel(lblEnd); + + return res; + } + + // long BinarySignedSatQAcc(ulong op1, long op2); + private static Operand EmitBinarySignedSatQAcc(ArmEmitterContext context, Operand op1, Operand op2) + { + Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64); + + Operand lbl1 = Label(); + Operand lbl2 = Label(); + Operand lblEnd = Label(); + + Operand maxL = Const(long.MaxValue); + Operand zero = Const(0L); + + Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2)); + + context.BranchIf(lbl1, op1, maxL, Comparison.GreaterUI); + Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), res); + context.BranchIf(lblEnd, notOp2AndRes, zero, 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.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.Copy(res, maxL); + context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); + context.Branch(lblEnd); + + context.MarkLabel(lblEnd); + + return res; + } + + // ulong BinaryUnsignedSatQAcc(long op1, ulong op2); + private static Operand EmitBinaryUnsignedSatQAcc(ArmEmitterContext context, Operand op1, Operand op2) + { + Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64); + + Operand lbl1 = Label(); + Operand lblEnd = Label(); + + Operand maxUL = Const(ulong.MaxValue); + Operand maxL = Const(long.MaxValue); + Operand zero = Const(0L); + + Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2)); + + context.BranchIf(lbl1, op1, zero, Comparison.Less); + context.BranchIf(lblEnd, res, 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.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); + context.Branch(lblEnd); + + context.MarkLabel(lblEnd); + + return res; } public static Operand EmitFloatAbs(ArmEmitterContext context, Operand value, bool single, bool vector) diff --git a/ARMeilleure/Instructions/InstEmitSimdShift.cs b/ARMeilleure/Instructions/InstEmitSimdShift.cs index 0ee50f30..1a95200d 100644 --- a/ARMeilleure/Instructions/InstEmitSimdShift.cs +++ b/ARMeilleure/Instructions/InstEmitSimdShift.cs @@ -1004,7 +1004,7 @@ namespace ARMeilleure.Instructions e = EmitShrImm64(context, e, signedSrc, roundConst, shift); // shift <= 32 } - e = EmitSatQ(context, e, op.Size, signedSrc, signedDst); + e = signedSrc ? EmitSignedSrcSatQ(context, e, op.Size, signedDst) : EmitUnsignedSrcSatQ(context, e, op.Size, signedDst); res = EmitVectorInsert(context, res, e, part + index, op.Size); } diff --git a/ARMeilleure/Instructions/SoftFallback.cs b/ARMeilleure/Instructions/SoftFallback.cs index f83afc16..829dd37a 100644 --- a/ARMeilleure/Instructions/SoftFallback.cs +++ b/ARMeilleure/Instructions/SoftFallback.cs @@ -91,7 +91,7 @@ namespace ARMeilleure.Instructions } else /* if (eSize != 64) */ { - return SignedSrcSignedDstSatQ(value << shiftLsB, size); + return SignedSrcSignedDstSatQ(value << shiftLsB, size); // InstEmitSimdHelper.EmitSignedSrcSatQ(signedDst: true). } } else /* if (shiftLsB == 0) */ @@ -135,7 +135,7 @@ namespace ARMeilleure.Instructions } else /* if (eSize != 64) */ { - return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size); + return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size); // InstEmitSimdHelper.EmitUnsignedSrcSatQ(signedDst: false). } } else /* if (shiftLsB == 0) */ @@ -509,7 +509,7 @@ namespace ARMeilleure.Instructions #endregion #region "Saturating" - public static long SignedSrcSignedDstSatQ(long op, int size) + private static long SignedSrcSignedDstSatQ(long op, int size) { ExecutionContext context = NativeInterface.GetContext(); @@ -536,54 +536,7 @@ namespace ARMeilleure.Instructions } } - public static ulong SignedSrcUnsignedDstSatQ(long op, int size) - { - ExecutionContext context = NativeInterface.GetContext(); - - int eSize = 8 << size; - - ulong tMaxValue = (1UL << eSize) - 1UL; - ulong tMinValue = 0UL; - - if (op > (long)tMaxValue) - { - context.Fpsr |= FPSR.Qc; - - return tMaxValue; - } - else if (op < (long)tMinValue) - { - context.Fpsr |= FPSR.Qc; - - return tMinValue; - } - else - { - return (ulong)op; - } - } - - public static long UnsignedSrcSignedDstSatQ(ulong op, int size) - { - ExecutionContext context = NativeInterface.GetContext(); - - int eSize = 8 << size; - - long tMaxValue = (1L << (eSize - 1)) - 1L; - - if (op > (ulong)tMaxValue) - { - context.Fpsr |= FPSR.Qc; - - return tMaxValue; - } - else - { - return (long)op; - } - } - - public static ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size) + private static ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size) { ExecutionContext context = NativeInterface.GetContext(); @@ -602,208 +555,6 @@ namespace ARMeilleure.Instructions return op; } } - - public static long UnarySignedSatQAbsOrNeg(long op) - { - ExecutionContext context = NativeInterface.GetContext(); - - if (op == long.MinValue) - { - context.Fpsr |= FPSR.Qc; - - return long.MaxValue; - } - else - { - return op; - } - } - - public static long BinarySignedSatQAdd(long op1, long op2) - { - ExecutionContext context = NativeInterface.GetContext(); - - long add = op1 + op2; - - if ((~(op1 ^ op2) & (op1 ^ add)) < 0L) - { - context.Fpsr |= FPSR.Qc; - - if (op1 < 0L) - { - return long.MinValue; - } - else - { - return long.MaxValue; - } - } - else - { - return add; - } - } - - public static ulong BinaryUnsignedSatQAdd(ulong op1, ulong op2) - { - ExecutionContext context = NativeInterface.GetContext(); - - ulong add = op1 + op2; - - if ((add < op1) && (add < op2)) - { - context.Fpsr |= FPSR.Qc; - - return ulong.MaxValue; - } - else - { - return add; - } - } - - public static long BinarySignedSatQSub(long op1, long op2) - { - ExecutionContext context = NativeInterface.GetContext(); - - long sub = op1 - op2; - - if (((op1 ^ op2) & (op1 ^ sub)) < 0L) - { - context.Fpsr |= FPSR.Qc; - - if (op1 < 0L) - { - return long.MinValue; - } - else - { - return long.MaxValue; - } - } - else - { - return sub; - } - } - - public static ulong BinaryUnsignedSatQSub(ulong op1, ulong op2) - { - ExecutionContext context = NativeInterface.GetContext(); - - ulong sub = op1 - op2; - - if (op1 < op2) - { - context.Fpsr |= FPSR.Qc; - - return ulong.MinValue; - } - else - { - return sub; - } - } - - public static long BinarySignedSatQAcc(ulong op1, long op2) - { - ExecutionContext context = NativeInterface.GetContext(); - - if (op1 <= (ulong)long.MaxValue) - { - // op1 from ulong.MinValue to (ulong)long.MaxValue - // op2 from long.MinValue to long.MaxValue - - long add = (long)op1 + op2; - - if ((~op2 & add) < 0L) - { - context.Fpsr |= FPSR.Qc; - - return long.MaxValue; - } - else - { - return add; - } - } - else if (op2 >= 0L) - { - // op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue - // op2 from (long)ulong.MinValue to long.MaxValue - - context.Fpsr |= FPSR.Qc; - - return long.MaxValue; - } - else - { - // op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue - // op2 from long.MinValue to (long)ulong.MinValue - 1L - - ulong add = op1 + (ulong)op2; - - if (add > (ulong)long.MaxValue) - { - context.Fpsr |= FPSR.Qc; - - return long.MaxValue; - } - else - { - return (long)add; - } - } - } - - public static ulong BinaryUnsignedSatQAcc(long op1, ulong op2) - { - ExecutionContext context = NativeInterface.GetContext(); - - if (op1 >= 0L) - { - // op1 from (long)ulong.MinValue to long.MaxValue - // op2 from ulong.MinValue to ulong.MaxValue - - ulong add = (ulong)op1 + op2; - - if ((add < (ulong)op1) && (add < op2)) - { - context.Fpsr |= FPSR.Qc; - - return ulong.MaxValue; - } - else - { - return add; - } - } - else if (op2 > (ulong)long.MaxValue) - { - // op1 from long.MinValue to (long)ulong.MinValue - 1L - // op2 from (ulong)long.MaxValue + 1UL to ulong.MaxValue - - return (ulong)op1 + op2; - } - else - { - // op1 from long.MinValue to (long)ulong.MinValue - 1L - // op2 from ulong.MinValue to (ulong)long.MaxValue - - long add = op1 + (long)op2; - - if (add < (long)ulong.MinValue) - { - context.Fpsr |= FPSR.Qc; - - return ulong.MinValue; - } - else - { - return (ulong)add; - } - } - } #endregion #region "Count" |