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:
parent
408bd63b08
commit
7baa08dcb4
@ -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)
|
||||||
}
|
{
|
||||||
else /* if (sub) */
|
de = signed ? EmitBinarySignedSatQAdd(context, ne, me) : EmitBinaryUnsignedSatQAdd(context, ne, me);
|
||||||
{
|
}
|
||||||
de = EmitBinarySatQSub(context, ne, me, signed);
|
else /* if (sub) */
|
||||||
|
{
|
||||||
|
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo info;
|
Operand lbl1 = Label();
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
if (signedSrc)
|
int eSize = 8 << sizeDst;
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
return context.Call(info, op, Const(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TSrc (64bit) == TDst (64bit); signed.
|
// TSrc (16bit, 32bit, 64bit; unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned).
|
||||||
public static Operand EmitUnarySignedSatQAbsOrNeg(ArmEmitterContext context, Operand op)
|
// 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);
|
||||||
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnarySignedSatQAbsOrNeg)), op);
|
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);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
|
// long UnarySignedSatQAbsOrNeg(long op);
|
||||||
public static Operand EmitBinarySatQAdd(ArmEmitterContext context, Operand op1, Operand op2, bool signed)
|
private static Operand EmitUnarySignedSatQAbsOrNeg(ArmEmitterContext context, Operand op)
|
||||||
{
|
{
|
||||||
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size.");
|
Debug.Assert(op.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 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
|
// long BinarySignedSatQAdd(long op1, long op2);
|
||||||
public static Operand EmitBinarySatQSub(ArmEmitterContext context, Operand op1, Operand op2, bool signed)
|
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);
|
||||||
|
|
||||||
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.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 EmitBinarySatQAccumulate(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.BinarySignedSatQAcc))
|
|
||||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAcc));
|
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
public static Operand EmitFloatAbs(ArmEmitterContext context, Operand value, bool single, bool vector)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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)));
|
||||||
|
@ -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";
|
||||||
|
Loading…
Reference in New Issue
Block a user