parent
d562ba37a0
commit
8c85bdf2ed
16 changed files with 450 additions and 163 deletions
|
@ -268,7 +268,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (setCarry)
|
||||
{
|
||||
SetFlag(context, PState.CFlag, Const(0));;
|
||||
SetFlag(context, PState.CFlag, Const(0));
|
||||
}
|
||||
|
||||
return Const(0);
|
||||
|
|
|
@ -384,8 +384,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
OperandType type = sizeF != 0 ? OperandType.FP64
|
||||
: OperandType.FP32;
|
||||
OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;
|
||||
|
||||
Operand ne0 = context.VectorExtract(type, GetVec(op.Rn), 0);
|
||||
Operand ne1 = context.VectorExtract(type, GetVec(op.Rn), 1);
|
||||
|
@ -455,6 +454,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand a = GetVec(op.Ra);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
@ -462,18 +462,16 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Size == 0)
|
||||
{
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Mulss, n, m);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Addss, a, res);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Addss, a, res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorZeroUpper96(res));
|
||||
context.Copy(d, context.VectorZeroUpper96(res));
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Mulsd, n, m);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Addsd, a, res);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Addsd, a, res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorZeroUpper64(res));
|
||||
context.Copy(d, context.VectorZeroUpper64(res));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -517,18 +515,32 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Fmaxnm_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMaxNum, SoftFloat64.FPMaxNum, op1, op2);
|
||||
});
|
||||
EmitSse41MaxMinNumOpF(context, isMaxNum: true, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMaxNum, SoftFloat64.FPMaxNum, op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fmaxnm_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMaxNum, SoftFloat64.FPMaxNum, op1, op2);
|
||||
});
|
||||
EmitSse41MaxMinNumOpF(context, isMaxNum: true, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMaxNum, SoftFloat64.FPMaxNum, op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fmaxp_V(ArmEmitterContext context)
|
||||
|
@ -578,18 +590,32 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Fminnm_S(ArmEmitterContext context)
|
||||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMinNum, SoftFloat64.FPMinNum, op1, op2);
|
||||
});
|
||||
EmitSse41MaxMinNumOpF(context, isMaxNum: false, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMinNum, SoftFloat64.FPMinNum, op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fminnm_V(ArmEmitterContext context)
|
||||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
if (Optimizations.FastFP && Optimizations.UseSse41)
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMinNum, SoftFloat64.FPMinNum, op1, op2);
|
||||
});
|
||||
EmitSse41MaxMinNumOpF(context, isMaxNum: false, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMinNum, SoftFloat64.FPMinNum, op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fminp_V(ArmEmitterContext context)
|
||||
|
@ -813,6 +839,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand a = GetVec(op.Ra);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
@ -820,18 +847,16 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Size == 0)
|
||||
{
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Mulss, n, m);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Subss, a, res);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Subss, a, res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorZeroUpper96(res));
|
||||
context.Copy(d, context.VectorZeroUpper96(res));
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Mulsd, n, m);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Subsd, a, res);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Subsd, a, res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorZeroUpper64(res));
|
||||
context.Copy(d, context.VectorZeroUpper64(res));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1035,36 +1060,88 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Fnmadd_S(ArmEmitterContext context) // Fused.
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
int sizeF = op.Size & 1;
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand a = GetVec(op.Ra);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;
|
||||
if (op.Size == 0)
|
||||
{
|
||||
Operand mask = X86GetScalar(context, -0f);
|
||||
|
||||
Operand ne = context.VectorExtract(type, GetVec(op.Rn), 0);
|
||||
Operand me = context.VectorExtract(type, GetVec(op.Rm), 0);
|
||||
Operand ae = context.VectorExtract(type, GetVec(op.Ra), 0);
|
||||
Operand aNeg = context.AddIntrinsic(Intrinsic.X86Xorps, mask, a);
|
||||
|
||||
Operand res = context.Subtract(context.Multiply(context.Negate(ne), me), ae);
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Mulss, n, m);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Subss, aNeg, res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
context.Copy(d, context.VectorZeroUpper96(res));
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
Operand mask = X86GetScalar(context, -0d);
|
||||
|
||||
Operand aNeg = context.AddIntrinsic(Intrinsic.X86Xorpd, mask, a);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Mulsd, n, m);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Subsd, aNeg, res);
|
||||
|
||||
context.Copy(d, context.VectorZeroUpper64(res));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarTernaryRaOpF(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPNegMulAdd, SoftFloat64.FPNegMulAdd, op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fnmsub_S(ArmEmitterContext context) // Fused.
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
int sizeF = op.Size & 1;
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand a = GetVec(op.Ra);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;
|
||||
if (op.Size == 0)
|
||||
{
|
||||
Operand mask = X86GetScalar(context, -0f);
|
||||
|
||||
Operand ne = context.VectorExtract(type, GetVec(op.Rn), 0);
|
||||
Operand me = context.VectorExtract(type, GetVec(op.Rm), 0);
|
||||
Operand ae = context.VectorExtract(type, GetVec(op.Ra), 0);
|
||||
Operand aNeg = context.AddIntrinsic(Intrinsic.X86Xorps, mask, a);
|
||||
|
||||
Operand res = context.Subtract(context.Multiply(ne, me), ae);
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Mulss, n, m);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Addss, aNeg, res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
context.Copy(d, context.VectorZeroUpper96(res));
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
Operand mask = X86GetScalar(context, -0d);
|
||||
|
||||
Operand aNeg = context.AddIntrinsic(Intrinsic.X86Xorpd, mask, a);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Mulsd, n, m);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Addsd, aNeg, res);
|
||||
|
||||
context.Copy(d, context.VectorZeroUpper64(res));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarTernaryRaOpF(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPNegMulSub, SoftFloat64.FPNegMulSub, op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void Fnmul_S(ArmEmitterContext context)
|
||||
|
@ -2067,9 +2144,7 @@ namespace ARMeilleure.Instructions
|
|||
m = context.AddIntrinsic(Intrinsic.X86Psrldq, m, Const(8));
|
||||
}
|
||||
|
||||
Intrinsic movInst = op.Size == 0
|
||||
? Intrinsic.X86Pmovsxbw
|
||||
: Intrinsic.X86Pmovsxwd;
|
||||
Intrinsic movInst = op.Size == 0 ? Intrinsic.X86Pmovsxbw : Intrinsic.X86Pmovsxwd;
|
||||
|
||||
n = context.AddIntrinsic(movInst, n);
|
||||
m = context.AddIntrinsic(movInst, m);
|
||||
|
@ -2694,9 +2769,7 @@ namespace ARMeilleure.Instructions
|
|||
m = context.AddIntrinsic(Intrinsic.X86Psrldq, m, Const(8));
|
||||
}
|
||||
|
||||
Intrinsic movInst = op.Size == 0
|
||||
? Intrinsic.X86Pmovzxbw
|
||||
: Intrinsic.X86Pmovzxwd;
|
||||
Intrinsic movInst = op.Size == 0 ? Intrinsic.X86Pmovzxbw : Intrinsic.X86Pmovzxwd;
|
||||
|
||||
n = context.AddIntrinsic(movInst, n);
|
||||
m = context.AddIntrinsic(movInst, m);
|
||||
|
@ -3011,6 +3084,98 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
||||
private static Operand EmitSse2VectorIsQNaNOpF(ArmEmitterContext context, Operand opF)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
if ((op.Size & 1) == 0)
|
||||
{
|
||||
const int QBit = 22;
|
||||
|
||||
Operand qMask = X86GetAllElements(context, 1 << QBit);
|
||||
|
||||
Operand mask1 = context.AddIntrinsic(Intrinsic.X86Cmpps, opF, opF, Const((int)CmpCondition.UnorderedQ));
|
||||
|
||||
Operand mask2 = context.AddIntrinsic(Intrinsic.X86Pand, opF, qMask);
|
||||
mask2 = context.AddIntrinsic(Intrinsic.X86Cmpps, mask2, qMask, Const((int)CmpCondition.Equal));
|
||||
|
||||
return context.AddIntrinsic(Intrinsic.X86Andps, mask1, mask2);
|
||||
}
|
||||
else /* if ((op.Size & 1) == 1) */
|
||||
{
|
||||
const int QBit = 51;
|
||||
|
||||
Operand qMask = X86GetAllElements(context, 1L << QBit);
|
||||
|
||||
Operand mask1 = context.AddIntrinsic(Intrinsic.X86Cmppd, opF, opF, Const((int)CmpCondition.UnorderedQ));
|
||||
|
||||
Operand mask2 = context.AddIntrinsic(Intrinsic.X86Pand, opF, qMask);
|
||||
mask2 = context.AddIntrinsic(Intrinsic.X86Cmppd, mask2, qMask, Const((int)CmpCondition.Equal));
|
||||
|
||||
return context.AddIntrinsic(Intrinsic.X86Andpd, mask1, mask2);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitSse41MaxMinNumOpF(ArmEmitterContext context, bool isMaxNum, bool scalar)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand nQNaNMask = EmitSse2VectorIsQNaNOpF(context, n);
|
||||
Operand mQNaNMask = EmitSse2VectorIsQNaNOpF(context, m);
|
||||
|
||||
Operand nNum = context.Copy(n);
|
||||
Operand mNum = context.Copy(m);
|
||||
|
||||
int sizeF = op.Size & 1;
|
||||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
Operand negInfMask = X86GetAllElements(context, isMaxNum ? float.NegativeInfinity : float.PositiveInfinity);
|
||||
|
||||
Operand nMask = context.AddIntrinsic(Intrinsic.X86Andnps, mQNaNMask, nQNaNMask);
|
||||
Operand mMask = context.AddIntrinsic(Intrinsic.X86Andnps, nQNaNMask, mQNaNMask);
|
||||
|
||||
nNum = context.AddIntrinsic(Intrinsic.X86Blendvps, nNum, negInfMask, nMask);
|
||||
mNum = context.AddIntrinsic(Intrinsic.X86Blendvps, mNum, negInfMask, mMask);
|
||||
|
||||
Operand res = context.AddIntrinsic(isMaxNum ? Intrinsic.X86Maxps : Intrinsic.X86Minps, nNum, mNum);
|
||||
|
||||
if (scalar)
|
||||
{
|
||||
res = context.VectorZeroUpper96(res);
|
||||
}
|
||||
else if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
res = context.VectorZeroUpper64(res);
|
||||
}
|
||||
|
||||
context.Copy(d, res);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Operand negInfMask = X86GetAllElements(context, isMaxNum ? double.NegativeInfinity : double.PositiveInfinity);
|
||||
|
||||
Operand nMask = context.AddIntrinsic(Intrinsic.X86Andnpd, mQNaNMask, nQNaNMask);
|
||||
Operand mMask = context.AddIntrinsic(Intrinsic.X86Andnpd, nQNaNMask, mQNaNMask);
|
||||
|
||||
nNum = context.AddIntrinsic(Intrinsic.X86Blendvpd, nNum, negInfMask, nMask);
|
||||
mNum = context.AddIntrinsic(Intrinsic.X86Blendvpd, mNum, negInfMask, mMask);
|
||||
|
||||
Operand res = context.AddIntrinsic(isMaxNum ? Intrinsic.X86Maxpd : Intrinsic.X86Minpd, nNum, mNum);
|
||||
|
||||
if (scalar)
|
||||
{
|
||||
res = context.VectorZeroUpper64(res);
|
||||
}
|
||||
|
||||
context.Copy(d, res);
|
||||
}
|
||||
}
|
||||
|
||||
private enum AddSub
|
||||
{
|
||||
None,
|
||||
|
|
|
@ -300,7 +300,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitCmpSseOrSse2OpF(context, CmpCondition.Equal, scalar: true);
|
||||
EmitSse2CmpOpF(context, CmpCondition.Equal, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -312,7 +312,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitCmpSseOrSse2OpF(context, CmpCondition.Equal, scalar: false);
|
||||
EmitSse2CmpOpF(context, CmpCondition.Equal, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -324,7 +324,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitCmpSseOrSse2OpF(context, CmpCondition.GreaterThanOrEqual, scalar: true);
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -336,7 +336,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitCmpSseOrSse2OpF(context, CmpCondition.GreaterThanOrEqual, scalar: false);
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -348,7 +348,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitCmpSseOrSse2OpF(context, CmpCondition.GreaterThan, scalar: true);
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThan, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -360,7 +360,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitCmpSseOrSse2OpF(context, CmpCondition.GreaterThan, scalar: false);
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThan, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -372,7 +372,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitCmpSseOrSse2OpF(context, CmpCondition.LessThanOrEqual, scalar: true);
|
||||
EmitSse2CmpOpF(context, CmpCondition.LessThanOrEqual, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -384,7 +384,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitCmpSseOrSse2OpF(context, CmpCondition.LessThanOrEqual, scalar: false);
|
||||
EmitSse2CmpOpF(context, CmpCondition.LessThanOrEqual, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -396,7 +396,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitCmpSseOrSse2OpF(context, CmpCondition.LessThan, scalar: true);
|
||||
EmitSse2CmpOpF(context, CmpCondition.LessThan, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -408,7 +408,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitCmpSseOrSse2OpF(context, CmpCondition.LessThan, scalar: false);
|
||||
EmitSse2CmpOpF(context, CmpCondition.LessThan, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -673,7 +673,7 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
||||
private static void EmitCmpSseOrSse2OpF(ArmEmitterContext context, CmpCondition cond, bool scalar)
|
||||
private static void EmitSse2CmpOpF(ArmEmitterContext context, CmpCondition cond, bool scalar)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
|
|
|
@ -907,7 +907,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand res = context.VectorZero();
|
||||
|
||||
Operand me = EmitVectorExtract(context, op.Rm, op.Index, op.Size, signed);;
|
||||
Operand me = EmitVectorExtract(context, op.Rm, op.Index, op.Size, signed);
|
||||
|
||||
int elems = 8 >> op.Size;
|
||||
|
||||
|
@ -939,7 +939,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand res = context.VectorZero();
|
||||
|
||||
Operand me = EmitVectorExtract(context, op.Rm, op.Index, op.Size, signed);;
|
||||
Operand me = EmitVectorExtract(context, op.Rm, op.Index, op.Size, signed);
|
||||
|
||||
int elems = 8 >> op.Size;
|
||||
|
||||
|
@ -1114,6 +1114,7 @@ namespace ARMeilleure.Instructions
|
|||
Equal = 0, // Ordered, non-signaling.
|
||||
LessThan = 1, // Ordered, signaling.
|
||||
LessThanOrEqual = 2, // Ordered, signaling.
|
||||
UnorderedQ = 3, // Non-signaling.
|
||||
NotLessThan = 5, // Unordered, signaling.
|
||||
NotLessThanOrEqual = 6, // Unordered, signaling.
|
||||
OrderedQ = 7, // Non-signaling.
|
||||
|
|
|
@ -177,7 +177,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
nShifted = context.AddIntrinsic(Intrinsic.X86Movlhps, nShifted, context.VectorZero());
|
||||
nShifted = context.VectorZeroUpper64(nShifted);
|
||||
}
|
||||
|
||||
nShifted = context.AddIntrinsic(Intrinsic.X86Psrldq, nShifted, Const(op.Imm4));
|
||||
|
@ -188,7 +188,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
mShifted = context.AddIntrinsic(Intrinsic.X86Movlhps, mShifted, context.VectorZero());
|
||||
mShifted = context.VectorZeroUpper64(mShifted);
|
||||
}
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Por, nShifted, mShifted);
|
||||
|
@ -277,9 +277,10 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, GetVec(op.Rd), n, 1, 3));
|
||||
context.Copy(d, EmitVectorInsert(context, d, n, 1, 3));
|
||||
}
|
||||
|
||||
public static void Fmov_S(ArmEmitterContext context)
|
||||
|
@ -311,18 +312,32 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
|
||||
|
||||
Operand e = Const(op.Immediate);
|
||||
|
||||
Operand res = context.VectorZero();
|
||||
|
||||
int elems = op.RegisterSize == RegisterSize.Simd128 ? 4 : 2;
|
||||
|
||||
for (int index = 0; index < (elems >> op.Size); index++)
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size + 2);
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
context.Copy(GetVec(op.Rd), X86GetAllElements(context, op.Immediate));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Copy(GetVec(op.Rd), X86GetScalar(context, op.Immediate));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand e = Const(op.Immediate);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
Operand res = context.VectorZero();
|
||||
|
||||
int elems = op.RegisterSize == RegisterSize.Simd128 ? 2 : 1;
|
||||
|
||||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
res = EmitVectorInsert(context, res, e, index, 3);
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Ins_Gp(ArmEmitterContext context)
|
||||
|
@ -349,7 +364,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitMoviMvni(context, not: false);
|
||||
EmitSse2MoviMvni(context, not: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -361,7 +376,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitMoviMvni(context, not: true);
|
||||
EmitSse2MoviMvni(context, not: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -430,13 +445,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand d = GetVec(op.Rd);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Movlhps, d, context.VectorZero());
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand res = context.VectorZeroUpper64(d);
|
||||
|
||||
Operand mask = X86GetAllElements(context, _masksE0_TrnUzpXtn[op.Size]);
|
||||
|
||||
Operand res2 = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
|
||||
Operand res2 = context.AddIntrinsic(Intrinsic.X86Pshufb, GetVec(op.Rn), mask);
|
||||
|
||||
Intrinsic movInst = op.RegisterSize == RegisterSize.Simd128
|
||||
? Intrinsic.X86Movlhps
|
||||
|
@ -444,7 +457,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
res = context.AddIntrinsic(movInst, res, res2);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
context.Copy(d, res);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -452,7 +465,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;
|
||||
|
||||
Operand res = part == 0 ? context.VectorZero() : context.Copy(GetVec(op.Rd));
|
||||
Operand d = GetVec(op.Rd);
|
||||
|
||||
Operand res = part == 0 ? context.VectorZero() : context.Copy(d);
|
||||
|
||||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
|
@ -461,7 +476,7 @@ namespace ARMeilleure.Instructions
|
|||
res = EmitVectorInsert(context, res, ne, part + index, op.Size);
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
context.Copy(d, res);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,7 +490,7 @@ namespace ARMeilleure.Instructions
|
|||
EmitVectorZip(context, part: 1);
|
||||
}
|
||||
|
||||
private static void EmitMoviMvni(ArmEmitterContext context, bool not)
|
||||
private static void EmitSse2MoviMvni(ArmEmitterContext context, bool not)
|
||||
{
|
||||
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
|
||||
|
||||
|
|
|
@ -1089,8 +1089,6 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static float FPMulSub(float valueA, float value1, float value2)
|
||||
{
|
||||
ExecutionContext context = NativeInterface.GetContext();
|
||||
|
||||
value1 = value1.FPNeg();
|
||||
|
||||
return FPMulAdd(valueA, value1, value2);
|
||||
|
@ -1138,6 +1136,21 @@ namespace ARMeilleure.Instructions
|
|||
return result;
|
||||
}
|
||||
|
||||
public static float FPNegMulAdd(float valueA, float value1, float value2)
|
||||
{
|
||||
valueA = valueA.FPNeg();
|
||||
value1 = value1.FPNeg();
|
||||
|
||||
return FPMulAdd(valueA, value1, value2);
|
||||
}
|
||||
|
||||
public static float FPNegMulSub(float valueA, float value1, float value2)
|
||||
{
|
||||
valueA = valueA.FPNeg();
|
||||
|
||||
return FPMulAdd(valueA, value1, value2);
|
||||
}
|
||||
|
||||
public static float FPRecipEstimate(float value)
|
||||
{
|
||||
ExecutionContext context = NativeInterface.GetContext();
|
||||
|
@ -2196,6 +2209,21 @@ namespace ARMeilleure.Instructions
|
|||
return result;
|
||||
}
|
||||
|
||||
public static double FPNegMulAdd(double valueA, double value1, double value2)
|
||||
{
|
||||
valueA = valueA.FPNeg();
|
||||
value1 = value1.FPNeg();
|
||||
|
||||
return FPMulAdd(valueA, value1, value2);
|
||||
}
|
||||
|
||||
public static double FPNegMulSub(double valueA, double value1, double value2)
|
||||
{
|
||||
valueA = valueA.FPNeg();
|
||||
|
||||
return FPMulAdd(valueA, value1, value2);
|
||||
}
|
||||
|
||||
public static double FPRecipEstimate(double value)
|
||||
{
|
||||
ExecutionContext context = NativeInterface.GetContext();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue