0
0
Fork 0

Implemented in IR the managed methods of the Saturating region ... (#3665)

* 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.
This commit is contained in:
LDj3SNuD 2022-09-09 00:40:41 +02:00 committed by GitHub
parent 408bd63b08
commit 7baa08dcb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 243 additions and 324 deletions

View file

@ -1352,7 +1352,7 @@ namespace ARMeilleure.Instructions
if (op.Size <= 2) 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) */ else /* if (op.Size == 3) */
{ {
@ -1419,15 +1419,18 @@ namespace ARMeilleure.Instructions
{ {
Operand temp = add ? context.Add(ne, me) : context.Subtract(ne, me); 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) */ else /* if (op.Size == 3) */
{ {
de = EmitBinarySatQAdd(context, ne, me, signed); if (add)
{
de = signed ? EmitBinarySignedSatQAdd(context, ne, me) : EmitBinaryUnsignedSatQAdd(context, ne, me);
} }
else /* if (sub) */ else /* if (sub) */
{ {
de = EmitBinarySatQSub(context, ne, me, signed); de = signed ? EmitBinarySignedSatQSub(context, ne, me) : EmitBinaryUnsignedSatQSub(context, ne, me);
}
} }
res = EmitVectorInsert(context, res, de, index, op.Size); res = EmitVectorInsert(context, res, de, index, op.Size);
@ -1445,11 +1448,11 @@ namespace ARMeilleure.Instructions
{ {
Operand temp = context.Add(ne, me); 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) */ 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); 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); 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); 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 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); res = EmitVectorInsert(context, res, temp, part + index, op.Size);
} }
@ -1528,74 +1533,248 @@ namespace ARMeilleure.Instructions
context.Copy(d, res); context.Copy(d, res);
} }
// TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned). // TSrc (16bit, 32bit, 64bit; signed) > TDst (8bit, 16bit, 32bit; signed, unsigned).
public static Operand EmitSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedSrc, bool signedDst) // 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) Debug.Assert(op.Type == OperandType.I64 && (uint)sizeDst <= 2u);
{
throw new ArgumentOutOfRangeException(nameof(sizeDst)); 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 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;
} }
MethodInfo info; // 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(op.Type == OperandType.I64 && (uint)sizeDst <= 2u);
if (signedSrc) Operand lblEnd = Label();
{
info = signedDst int eSize = 8 << sizeDst;
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcSignedDstSatQ))
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcUnsignedDstSatQ)); Operand maxL = signedDst ? Const((1L << (eSize - 1)) - 1L) : Const((1UL << eSize) - 1UL);
}
else Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
{
info = signedDst context.BranchIf(lblEnd, res, maxL, Comparison.LessOrEqualUI);
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcSignedDstSatQ)) context.Copy(res, maxL);
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcUnsignedDstSatQ)); context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
} }
return context.Call(info, op, Const(sizeDst)); // long UnarySignedSatQAbsOrNeg(long op);
private static Operand EmitUnarySignedSatQAbsOrNeg(ArmEmitterContext context, Operand op)
{
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);
context.MarkLabel(lblEnd);
return res;
} }
// TSrc (64bit) == TDst (64bit); signed. // long BinarySignedSatQAdd(long op1, long op2);
public static Operand EmitUnarySignedSatQAbsOrNeg(ArmEmitterContext context, Operand op) 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);
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnarySignedSatQAbsOrNeg)), op); 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);
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;
} }
// TSrcs (64bit) == TDst (64bit); signed, unsigned. // ulong BinaryUnsignedSatQAdd(ulong op1, ulong op2);
public static Operand EmitBinarySatQAdd(ArmEmitterContext context, Operand op1, Operand op2, bool signed) 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);
MethodInfo info = signed Operand lblEnd = Label();
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAdd))
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAdd));
return context.Call(info, op1, op2); Operand maxUL = Const(ulong.MaxValue);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
context.BranchIf(lblEnd, res, op1, Comparison.GreaterOrEqualUI);
context.Copy(res, maxUL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lblEnd);
return res;
} }
// TSrcs (64bit) == TDst (64bit); signed, unsigned. // long BinarySignedSatQSub(long op1, long op2);
public static Operand EmitBinarySatQSub(ArmEmitterContext context, Operand op1, Operand op2, bool signed) private static Operand EmitBinarySignedSatQSub(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);
MethodInfo info = signed Operand lblEnd = Label();
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQSub))
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQSub));
return context.Call(info, op1, op2); 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;
} }
// TSrcs (64bit) == TDst (64bit); signed, unsigned. // ulong BinaryUnsignedSatQSub(ulong op1, ulong op2);
public static Operand EmitBinarySatQAccumulate(ArmEmitterContext context, Operand op1, Operand op2, bool signed) private static Operand EmitBinaryUnsignedSatQSub(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);
MethodInfo info = signed Operand lblEnd = Label();
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAcc))
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAcc));
return context.Call(info, op1, op2); 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) public static Operand EmitFloatAbs(ArmEmitterContext context, Operand value, bool single, bool vector)

View file

@ -1004,7 +1004,7 @@ namespace ARMeilleure.Instructions
e = EmitShrImm64(context, e, signedSrc, roundConst, shift); // shift <= 32 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); res = EmitVectorInsert(context, res, e, part + index, op.Size);
} }

View file

@ -91,7 +91,7 @@ namespace ARMeilleure.Instructions
} }
else /* if (eSize != 64) */ else /* if (eSize != 64) */
{ {
return SignedSrcSignedDstSatQ(value << shiftLsB, size); return SignedSrcSignedDstSatQ(value << shiftLsB, size); // InstEmitSimdHelper.EmitSignedSrcSatQ(signedDst: true).
} }
} }
else /* if (shiftLsB == 0) */ else /* if (shiftLsB == 0) */
@ -135,7 +135,7 @@ namespace ARMeilleure.Instructions
} }
else /* if (eSize != 64) */ else /* if (eSize != 64) */
{ {
return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size); return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size); // InstEmitSimdHelper.EmitUnsignedSrcSatQ(signedDst: false).
} }
} }
else /* if (shiftLsB == 0) */ else /* if (shiftLsB == 0) */
@ -509,7 +509,7 @@ namespace ARMeilleure.Instructions
#endregion #endregion
#region "Saturating" #region "Saturating"
public static long SignedSrcSignedDstSatQ(long op, int size) private static long SignedSrcSignedDstSatQ(long op, int size)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@ -536,54 +536,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static ulong SignedSrcUnsignedDstSatQ(long op, int size) private static ulong UnsignedSrcUnsignedDstSatQ(ulong 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)
{ {
ExecutionContext context = NativeInterface.GetContext(); ExecutionContext context = NativeInterface.GetContext();
@ -602,208 +555,6 @@ namespace ARMeilleure.Instructions
return op; 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 #endregion
#region "Count" #region "Count"

View file

@ -127,7 +127,7 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr))); // A32 only. SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); // A32 only. SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only. SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
@ -140,12 +140,6 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128))); SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAcc)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAdd)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQSub)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAcc)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAdd)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQSub)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingSigns))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingSigns)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32b))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32b)));
@ -188,8 +182,6 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcSignedDstSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcUnsignedDstSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3)));
@ -198,12 +190,9 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnarySignedSatQAbsOrNeg)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64))); SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcSignedDstSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcUnsignedDstSatQ)));
SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert))); SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert))); SetDelegateInfo(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)));

View file

@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 3585; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 3666; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";