From df3cbadcebe48d40a6b8a8e510d21d452d0e0ab3 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 6 Apr 2018 10:20:17 -0300 Subject: [PATCH] Fix FRSQRTS and FCM* (scalar) instructions --- .../Instruction/AInstEmitSimdArithmetic.cs | 41 +++++++++++++++---- ChocolArm64/Instruction/AInstEmitSimdCmp.cs | 32 ++++++++++----- 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index 772b7955..bf119a18 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -512,21 +512,33 @@ namespace ChocolArm64.Instruction public static void Frsqrts_S(AILEmitterCtx Context) { - EmitScalarBinaryOpF(Context, () => EmitFrsqrts(Context)); + EmitFrsqrts(Context, 0, Scalar: true); } public static void Frsqrts_V(AILEmitterCtx Context) { - EmitVectorBinaryOpF(Context, () => EmitFrsqrts(Context)); - } - - private static void EmitFrsqrts(AILEmitterCtx Context) - { - IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp; + AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int SizeF = Op.Size & 1; - Context.Emit(OpCodes.Mul); + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + for (int Index = 0; Index < Bytes >> SizeF + 2; Index++) + { + EmitFrsqrts(Context, Index, Scalar: false); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + + private static void EmitFrsqrts(AILEmitterCtx Context, int Index, bool Scalar) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int SizeF = Op.Size & 1; if (SizeF == 0) { @@ -537,7 +549,11 @@ namespace ChocolArm64.Instruction Context.EmitLdc_R8(3); } - Context.Emit(OpCodes.Add); + EmitVectorExtractF(Context, Op.Rn, Index, SizeF); + EmitVectorExtractF(Context, Op.Rm, Index, SizeF); + + Context.Emit(OpCodes.Mul); + Context.Emit(OpCodes.Sub); if (SizeF == 0) { @@ -549,6 +565,13 @@ namespace ChocolArm64.Instruction } Context.Emit(OpCodes.Mul); + + if (Scalar) + { + EmitVectorZeroAll(Context, Op.Rd); + } + + EmitVectorInsertF(Context, Op.Rd, Index, SizeF); } public static void Fsqrt_S(AILEmitterCtx Context) diff --git a/ChocolArm64/Instruction/AInstEmitSimdCmp.cs b/ChocolArm64/Instruction/AInstEmitSimdCmp.cs index a71b6d42..f155d7e8 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdCmp.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdCmp.cs @@ -313,13 +313,7 @@ namespace ChocolArm64.Instruction private static void EmitScalarFcmp(AILEmitterCtx Context, OpCode ILOp) { - AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; - - int SizeF = Op.Size & 1; - - EmitFcmp(Context, ILOp, 0); - - EmitScalarSetF(Context, Op.Rd, SizeF); + EmitFcmp(Context, ILOp, 0, Scalar: true); } private static void EmitVectorFcmp(AILEmitterCtx Context, OpCode ILOp) @@ -332,7 +326,7 @@ namespace ChocolArm64.Instruction for (int Index = 0; Index < Bytes >> SizeF + 2; Index++) { - EmitFcmp(Context, ILOp, Index); + EmitFcmp(Context, ILOp, Index, Scalar: false); } if (Op.RegisterSize == ARegisterSize.SIMD64) @@ -341,7 +335,7 @@ namespace ChocolArm64.Instruction } } - private static void EmitFcmp(AILEmitterCtx Context, OpCode ILOp, int Index) + private static void EmitFcmp(AILEmitterCtx Context, OpCode ILOp, int Index, bool Scalar) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; @@ -369,13 +363,29 @@ namespace ChocolArm64.Instruction Context.Emit(ILOp, LblTrue); - EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, 0); + if (Scalar) + { + EmitVectorZeroAll(Context, Op.Rd); + } + else + { + EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, 0); + } Context.Emit(OpCodes.Br_S, LblEnd); Context.MarkLabel(LblTrue); - EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, (long)SzMask); + if (Scalar) + { + EmitVectorInsert(Context, Op.Rd, Index, 3, (long)SzMask); + + EmitVectorZeroUpper(Context, Op.Rd); + } + else + { + EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, (long)SzMask); + } Context.MarkLabel(LblEnd); }