diff options
Diffstat (limited to 'ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs')
| -rw-r--r-- | ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs index 559811d9..02e903f6 100644 --- a/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs +++ b/ChocolArm64/Instruction/AInstEmitSimdArithmetic.cs @@ -158,6 +158,42 @@ namespace ChocolArm64.Instruction Context.MarkLabel(LblTrue); } + private static void EmitDoublingMultiplyHighHalf(AILEmitterCtx Context, bool Round) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int ESize = 8 << Op.Size; + + Context.Emit(OpCodes.Mul); + + if (!Round) + { + Context.EmitAsr(ESize - 1); + } + else + { + long RoundConst = 1L << (ESize - 1); + + AILLabel LblTrue = new AILLabel(); + + Context.EmitLsl(1); + + Context.EmitLdc_I8(RoundConst); + + Context.Emit(OpCodes.Add); + + Context.EmitAsr(ESize); + + Context.Emit(OpCodes.Dup); + Context.EmitLdc_I8((long)int.MinValue); + Context.Emit(OpCodes.Bne_Un_S, LblTrue); + + Context.Emit(OpCodes.Neg); + + Context.MarkLabel(LblTrue); + } + } + private static void EmitHighNarrow(AILEmitterCtx Context, Action Emit, bool Round) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; @@ -1040,6 +1076,16 @@ namespace ChocolArm64.Instruction EmitVectorSaturatingBinaryOpSx(Context, SaturatingFlags.Add); } + public static void Sqdmulh_S(AILEmitterCtx Context) + { + EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: false), SaturatingFlags.ScalarSx); + } + + public static void Sqdmulh_V(AILEmitterCtx Context) + { + EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: false), SaturatingFlags.VectorSx); + } + public static void Sqneg_S(AILEmitterCtx Context) { EmitScalarSaturatingUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg)); @@ -1050,6 +1096,16 @@ namespace ChocolArm64.Instruction EmitVectorSaturatingUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg)); } + public static void Sqrdmulh_S(AILEmitterCtx Context) + { + EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: true), SaturatingFlags.ScalarSx); + } + + public static void Sqrdmulh_V(AILEmitterCtx Context) + { + EmitSaturatingBinaryOp(Context, () => EmitDoublingMultiplyHighHalf(Context, Round: true), SaturatingFlags.VectorSx); + } + public static void Sqsub_S(AILEmitterCtx Context) { EmitScalarSaturatingBinaryOpSx(Context, SaturatingFlags.Sub); |
