ChocolArm64: More accurate implementation of Frecpe & Frecps (#228)
* ChocolArm64: More accurate implementation of Frecpe * ChocolArm64: Handle infinities and zeros in Frecps
This commit is contained in:
parent
6479c3e484
commit
0f8f40486d
4 changed files with 170 additions and 109 deletions
|
@ -641,106 +641,34 @@ namespace ChocolArm64.Instruction
|
|||
|
||||
public static void Frecpe_S(AILEmitterCtx Context)
|
||||
{
|
||||
EmitFrecpe(Context, 0, Scalar: true);
|
||||
EmitScalarUnaryOpF(Context, () =>
|
||||
{
|
||||
EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.RecipEstimate));
|
||||
});
|
||||
}
|
||||
|
||||
public static void Frecpe_V(AILEmitterCtx Context)
|
||||
{
|
||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
||||
|
||||
for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
|
||||
EmitVectorUnaryOpF(Context, () =>
|
||||
{
|
||||
EmitFrecpe(Context, Index, Scalar: false);
|
||||
}
|
||||
|
||||
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
||||
{
|
||||
EmitVectorZeroUpper(Context, Op.Rd);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitFrecpe(AILEmitterCtx Context, int Index, bool Scalar)
|
||||
{
|
||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
if (SizeF == 0)
|
||||
{
|
||||
Context.EmitLdc_R4(1);
|
||||
}
|
||||
else /* if (SizeF == 1) */
|
||||
{
|
||||
Context.EmitLdc_R8(1);
|
||||
}
|
||||
|
||||
EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
|
||||
|
||||
Context.Emit(OpCodes.Div);
|
||||
|
||||
if (Scalar)
|
||||
{
|
||||
EmitVectorZeroAll(Context, Op.Rd);
|
||||
}
|
||||
|
||||
EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
|
||||
EmitUnarySoftFloatCall(Context, nameof(ASoftFloat.RecipEstimate));
|
||||
});
|
||||
}
|
||||
|
||||
public static void Frecps_S(AILEmitterCtx Context)
|
||||
{
|
||||
EmitFrecps(Context, 0, Scalar: true);
|
||||
EmitScalarBinaryOpF(Context, () =>
|
||||
{
|
||||
EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.RecipStep));
|
||||
});
|
||||
}
|
||||
|
||||
public static void Frecps_V(AILEmitterCtx Context)
|
||||
{
|
||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
||||
|
||||
for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
|
||||
EmitVectorBinaryOpF(Context, () =>
|
||||
{
|
||||
EmitFrecps(Context, Index, Scalar: false);
|
||||
}
|
||||
|
||||
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
||||
{
|
||||
EmitVectorZeroUpper(Context, Op.Rd);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitFrecps(AILEmitterCtx Context, int Index, bool Scalar)
|
||||
{
|
||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
if (SizeF == 0)
|
||||
{
|
||||
Context.EmitLdc_R4(2);
|
||||
}
|
||||
else /* if (SizeF == 1) */
|
||||
{
|
||||
Context.EmitLdc_R8(2);
|
||||
}
|
||||
|
||||
EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
|
||||
EmitVectorExtractF(Context, Op.Rm, Index, SizeF);
|
||||
|
||||
Context.Emit(OpCodes.Mul);
|
||||
Context.Emit(OpCodes.Sub);
|
||||
|
||||
if (Scalar)
|
||||
{
|
||||
EmitVectorZeroAll(Context, Op.Rd);
|
||||
}
|
||||
|
||||
EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
|
||||
EmitBinarySoftFloatCall(Context, nameof(ASoftFloat.RecipStep));
|
||||
});
|
||||
}
|
||||
|
||||
public static void Frinta_S(AILEmitterCtx Context)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue