Fix Fmin/max and add vector version, add and modifying fmin/max tests (#89)
This commit is contained in:
parent
5a383d86b1
commit
b0368079fb
3 changed files with 154 additions and 4 deletions
|
@ -211,8 +211,10 @@ namespace ChocolArm64
|
||||||
Set("0>1011100<1xxxxx111111xxxxxxxxxx", AInstEmit.Fdiv_V, typeof(AOpCodeSimdReg));
|
Set("0>1011100<1xxxxx111111xxxxxxxxxx", AInstEmit.Fdiv_V, typeof(AOpCodeSimdReg));
|
||||||
Set("000111110x0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg));
|
Set("000111110x0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg));
|
||||||
Set("000111100x1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg));
|
Set("000111100x1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg));
|
||||||
|
Set("0x0011100x1xxxxx111101xxxxxxxxxx", AInstEmit.Fmax_V, typeof(AOpCodeSimdReg));
|
||||||
Set("000111100x1xxxxx011010xxxxxxxxxx", AInstEmit.Fmaxnm_S, typeof(AOpCodeSimdReg));
|
Set("000111100x1xxxxx011010xxxxxxxxxx", AInstEmit.Fmaxnm_S, typeof(AOpCodeSimdReg));
|
||||||
Set("000111100x1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg));
|
Set("000111100x1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg));
|
||||||
|
Set("0x0011101x1xxxxx111101xxxxxxxxxx", AInstEmit.Fmin_V, typeof(AOpCodeSimdReg));
|
||||||
Set("000111100x1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg));
|
Set("000111100x1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg));
|
||||||
Set("0>0011100<1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg));
|
Set("0>0011100<1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg));
|
||||||
Set("0x0011111<<xxxxx0001x0xxxxxxxxxx", AInstEmit.Fmla_Ve, typeof(AOpCodeSimdRegElemF));
|
Set("0x0011111<<xxxxx0001x0xxxxxxxxxx", AInstEmit.Fmla_Ve, typeof(AOpCodeSimdRegElemF));
|
||||||
|
|
|
@ -211,17 +211,87 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
public static void Fmax_S(AILEmitterCtx Context)
|
public static void Fmax_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
EmitScalarBinaryOpF(Context, () =>
|
EmitScalarBinaryOpF(Context, () =>
|
||||||
{
|
{
|
||||||
EmitBinaryMathCall(Context, nameof(Math.Max));
|
if (Op.Size == 0)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.MaxF));
|
||||||
|
}
|
||||||
|
else if (Op.Size == 1)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Max));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Fmax_V(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
|
EmitVectorBinaryOpF(Context, () =>
|
||||||
|
{
|
||||||
|
if (Op.Size == 0)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.MaxF));
|
||||||
|
}
|
||||||
|
else if (Op.Size == 1)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Max));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Fmin_S(AILEmitterCtx Context)
|
public static void Fmin_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
EmitScalarBinaryOpF(Context, () =>
|
EmitScalarBinaryOpF(Context, () =>
|
||||||
{
|
{
|
||||||
EmitBinaryMathCall(Context, nameof(Math.Min));
|
if (Op.Size == 0)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.MinF));
|
||||||
|
}
|
||||||
|
else if (Op.Size == 1)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Min));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Fmin_V(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
|
int SizeF = Op.Size & 1;
|
||||||
|
|
||||||
|
EmitVectorBinaryOpF(Context, () =>
|
||||||
|
{
|
||||||
|
if (SizeF == 0)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.MinF));
|
||||||
|
}
|
||||||
|
else if (SizeF == 1)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Min));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,17 +580,19 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
|
int SizeF = Op.Size & 1;
|
||||||
|
|
||||||
EmitVectorUnaryOpF(Context, () =>
|
EmitVectorUnaryOpF(Context, () =>
|
||||||
{
|
{
|
||||||
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||||
|
|
||||||
Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
|
Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
|
||||||
|
|
||||||
if (Op.Size == 2)
|
if (SizeF == 0)
|
||||||
{
|
{
|
||||||
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
|
||||||
}
|
}
|
||||||
else if (Op.Size == 3)
|
else if (SizeF == 1)
|
||||||
{
|
{
|
||||||
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,6 +256,82 @@ namespace ChocolArm64.Instruction
|
||||||
((Value >> 6) & 1) + (Value >> 7);
|
((Value >> 6) & 1) + (Value >> 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float MaxF(float val1, float val2)
|
||||||
|
{
|
||||||
|
if (val1 == 0.0 && val2 == 0.0)
|
||||||
|
{
|
||||||
|
if (BitConverter.SingleToInt32Bits(val1) < 0 && BitConverter.SingleToInt32Bits(val2) < 0)
|
||||||
|
return -0.0f;
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val1 > val2)
|
||||||
|
return val1;
|
||||||
|
|
||||||
|
if (float.IsNaN(val1))
|
||||||
|
return val1;
|
||||||
|
|
||||||
|
return val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Max(double val1, double val2)
|
||||||
|
{
|
||||||
|
if (val1 == 0.0 && val2 == 0.0)
|
||||||
|
{
|
||||||
|
if (BitConverter.DoubleToInt64Bits(val1) < 0 && BitConverter.DoubleToInt64Bits(val2) < 0)
|
||||||
|
return -0.0;
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val1 > val2)
|
||||||
|
return val1;
|
||||||
|
|
||||||
|
if (double.IsNaN(val1))
|
||||||
|
return val1;
|
||||||
|
|
||||||
|
return val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float MinF(float val1, float val2)
|
||||||
|
{
|
||||||
|
if (val1 == 0.0 && val2 == 0.0)
|
||||||
|
{
|
||||||
|
if (BitConverter.SingleToInt32Bits(val1) < 0 || BitConverter.SingleToInt32Bits(val2) < 0)
|
||||||
|
return -0.0f;
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val1 < val2)
|
||||||
|
return val1;
|
||||||
|
|
||||||
|
if (float.IsNaN(val1))
|
||||||
|
return val1;
|
||||||
|
|
||||||
|
return val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Min(double val1, double val2)
|
||||||
|
{
|
||||||
|
if (val1 == 0.0 && val2 == 0.0)
|
||||||
|
{
|
||||||
|
if (BitConverter.DoubleToInt64Bits(val1) < 0 || BitConverter.DoubleToInt64Bits(val2) < 0)
|
||||||
|
return -0.0;
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val1 < val2)
|
||||||
|
return val1;
|
||||||
|
|
||||||
|
if (double.IsNaN(val1))
|
||||||
|
return val1;
|
||||||
|
|
||||||
|
return val2;
|
||||||
|
}
|
||||||
|
|
||||||
public static float RoundF(float Value, int Fpcr)
|
public static float RoundF(float Value, int Fpcr)
|
||||||
{
|
{
|
||||||
switch ((ARoundMode)((Fpcr >> 22) & 3))
|
switch ((ARoundMode)((Fpcr >> 22) & 3))
|
||||||
|
|
Loading…
Reference in a new issue