diff --git a/AOpCodeTable.cs b/AOpCodeTable.cs index 5db495a..6b250b4 100644 --- a/AOpCodeTable.cs +++ b/AOpCodeTable.cs @@ -183,7 +183,7 @@ namespace ChocolArm64 Set("000111100x1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg)); Set("000111100x1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg)); Set("0>0011100<1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg)); - Set("0x0011111<1011100<1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg)); - Set("0x0011111<> 11) & 1; - } - else - { - Index = (OpCode >> 21) & 1 | - (OpCode >> 10) & 2; + case 1: + Index = (OpCode >> 21) & 1 | + (OpCode >> 10) & 2 | + (OpCode >> 18) & 4; + + Rm &= 0xf; + + break; + + case 2: + Index = (OpCode >> 21) & 1 | + (OpCode >> 10) & 2; + + break; + + default: Emitter = AInstEmit.Und; return; } + + } } } \ No newline at end of file diff --git a/Decoder/AOpCodeSimdRegElemF.cs b/Decoder/AOpCodeSimdRegElemF.cs new file mode 100644 index 0000000..e61d709 --- /dev/null +++ b/Decoder/AOpCodeSimdRegElemF.cs @@ -0,0 +1,22 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdRegElemF : AOpCodeSimdReg + { + public int Index { get; private set; } + + public AOpCodeSimdRegElemF(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + if ((Size & 1) != 0) + { + Index = (OpCode >> 11) & 1; + } + else + { + Index = (OpCode >> 21) & 1 | + (OpCode >> 10) & 2; + } + } + } +} \ No newline at end of file diff --git a/Instruction/AInstEmitSimdArithmetic.cs b/Instruction/AInstEmitSimdArithmetic.cs index 9c1bc28..9f5cc64 100644 --- a/Instruction/AInstEmitSimdArithmetic.cs +++ b/Instruction/AInstEmitSimdArithmetic.cs @@ -341,6 +341,11 @@ namespace ChocolArm64.Instruction EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul)); } + public static void Mul_Ve(AILEmitterCtx Context) + { + EmitVectorBinaryOpByElemZx(Context, () => Context.Emit(OpCodes.Mul)); + } + public static void Neg_V(AILEmitterCtx Context) { EmitVectorUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg)); diff --git a/Instruction/AInstEmitSimdCvt.cs b/Instruction/AInstEmitSimdCvt.cs index e970277..b9944e5 100644 --- a/Instruction/AInstEmitSimdCvt.cs +++ b/Instruction/AInstEmitSimdCvt.cs @@ -99,6 +99,11 @@ namespace ChocolArm64.Instruction EmitVectorInsertF(Context, Op.Rd, Part + Index, 0); } } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } } public static void Fcvtps_Gp(AILEmitterCtx Context) diff --git a/Instruction/AInstEmitSimdHelper.cs b/Instruction/AInstEmitSimdHelper.cs index 68ee3d3..33e4d54 100644 --- a/Instruction/AInstEmitSimdHelper.cs +++ b/Instruction/AInstEmitSimdHelper.cs @@ -200,20 +200,6 @@ namespace ChocolArm64.Instruction EmitVectorOpF(Context, Emit, OperFlags.RdRnRm); } - public static void EmitVectorBinaryOpByElemF(AILEmitterCtx Context, Action Emit) - { - AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; - - EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: false); - } - - public static void EmitVectorTernaryOpByElemF(AILEmitterCtx Context, Action Emit) - { - AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; - - EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: true); - } - public static void EmitVectorOpF(AILEmitterCtx Context, Action Emit, OperFlags Opers) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; @@ -250,6 +236,20 @@ namespace ChocolArm64.Instruction } } + public static void EmitVectorBinaryOpByElemF(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp; + + EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: false); + } + + public static void EmitVectorTernaryOpByElemF(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdRegElemF Op = (AOpCodeSimdRegElemF)Context.CurrOp; + + EmitVectorOpByElemF(Context, Emit, Op.Index, Ternary: true); + } + public static void EmitVectorOpByElemF(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; @@ -341,6 +341,54 @@ namespace ChocolArm64.Instruction } } + public static void EmitVectorBinaryOpByElemSx(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; + + EmitVectorOpByElem(Context, Emit, Op.Index, false, true); + } + + public static void EmitVectorBinaryOpByElemZx(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; + + EmitVectorOpByElem(Context, Emit, Op.Index, false, false); + } + + public static void EmitVectorTernaryOpByElemZx(AILEmitterCtx Context, Action Emit) + { + AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp; + + EmitVectorOpByElem(Context, Emit, Op.Index, true, false); + } + + public static void EmitVectorOpByElem(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary, bool Signed) + { + AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; + + int Bytes = Context.CurrOp.GetBitsCount() >> 3; + + for (int Index = 0; Index < (Bytes >> Op.Size); Index++) + { + if (Ternary) + { + EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed); + } + + EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed); + EmitVectorExtract(Context, Op.Rm, Index, Op.Size, Signed); + + Emit(); + + EmitVectorInsert(Context, Op.Rd, Index, Op.Size); + } + + if (Op.RegisterSize == ARegisterSize.SIMD64) + { + EmitVectorZeroUpper(Context, Op.Rd); + } + } + public static void EmitVectorImmUnaryOp(AILEmitterCtx Context, Action Emit) { EmitVectorImmOp(Context, Emit, false);