diff --git a/AOpCodeTable.cs b/AOpCodeTable.cs index 0e979aa..c69de38 100644 --- a/AOpCodeTable.cs +++ b/AOpCodeTable.cs @@ -387,6 +387,7 @@ namespace ChocolArm64 SetA64("0100111101xxxxxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm)); SetA64("0x00111100>>>xxx000101xxxxxxxxxx", AInstEmit.Ssra_V, typeof(AOpCodeSimdShImm)); SetA64("0100111101xxxxxx000101xxxxxxxxxx", AInstEmit.Ssra_V, typeof(AOpCodeSimdShImm)); + SetA64("0x001110<<1xxxxx001100xxxxxxxxxx", AInstEmit.Ssubw_V, typeof(AOpCodeSimdReg)); SetA64("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs)); SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs)); SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", AInstEmit.St__Vss, typeof(AOpCodeSimdMemSs)); @@ -430,6 +431,7 @@ namespace ChocolArm64 SetA64("0110111101xxxxxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm)); SetA64("0x10111100>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm)); SetA64("0110111101xxxxxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm)); + SetA64("0x101110<<1xxxxx001100xxxxxxxxxx", AInstEmit.Usubw_V, typeof(AOpCodeSimdReg)); SetA64("0>001110<<0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg)); SetA64("0>001110<<0xxxxx010110xxxxxxxxxx", AInstEmit.Uzp2_V, typeof(AOpCodeSimdReg)); SetA64("0x001110<<100001001010xxxxxxxxxx", AInstEmit.Xtn_V, typeof(AOpCodeSimd)); diff --git a/Instruction/AInstEmitSimdArithmetic.cs b/Instruction/AInstEmitSimdArithmetic.cs index 36bb1cb..8e74186 100644 --- a/Instruction/AInstEmitSimdArithmetic.cs +++ b/Instruction/AInstEmitSimdArithmetic.cs @@ -1072,6 +1072,11 @@ namespace ChocolArm64.Instruction EmitVectorSaturatingNarrowOpSxZx(Context, () => { }); } + public static void Ssubw_V(AILEmitterCtx Context) + { + EmitVectorWidenRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Sub)); + } + public static void Sub_S(AILEmitterCtx Context) { EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub)); @@ -1225,5 +1230,10 @@ namespace ChocolArm64.Instruction { EmitVectorSaturatingNarrowOpZxZx(Context, () => { }); } + + public static void Usubw_V(AILEmitterCtx Context) + { + EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub)); + } } } diff --git a/Instruction/AInstEmitSimdCmp.cs b/Instruction/AInstEmitSimdCmp.cs index 773d989..c2d4774 100644 --- a/Instruction/AInstEmitSimdCmp.cs +++ b/Instruction/AInstEmitSimdCmp.cs @@ -364,7 +364,7 @@ namespace ChocolArm64.Instruction AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int Bytes = Op.GetBitsCount() >> 3; - int Elems = (!Scalar ? Bytes >> Op.Size : 1); + int Elems = !Scalar ? Bytes >> Op.Size : 1; ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size)); @@ -408,7 +408,7 @@ namespace ChocolArm64.Instruction AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; int Bytes = Op.GetBitsCount() >> 3; - int Elems = (!Scalar ? Bytes >> Op.Size : 1); + int Elems = !Scalar ? Bytes >> Op.Size : 1; ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size)); @@ -522,4 +522,4 @@ namespace ChocolArm64.Instruction Context.MarkLabel(LblEnd); } } -} \ No newline at end of file +} diff --git a/Instruction/AInstEmitSimdHelper.cs b/Instruction/AInstEmitSimdHelper.cs index 7716e29..0bd1a62 100644 --- a/Instruction/AInstEmitSimdHelper.cs +++ b/Instruction/AInstEmitSimdHelper.cs @@ -419,20 +419,25 @@ namespace ChocolArm64.Instruction int SizeF = Op.Size & 1; int Bytes = Op.GetBitsCount() >> 3; + int Elems = Bytes >> SizeF + 2; - for (int Index = 0; Index < (Bytes >> SizeF + 2); Index++) + bool Rd = (Opers & OperFlags.Rd) != 0; + bool Rn = (Opers & OperFlags.Rn) != 0; + bool Rm = (Opers & OperFlags.Rm) != 0; + + for (int Index = 0; Index < Elems; Index++) { - if (Opers.HasFlag(OperFlags.Rd)) + if (Rd) { EmitVectorExtractF(Context, Op.Rd, Index, SizeF); } - if (Opers.HasFlag(OperFlags.Rn)) + if (Rn) { EmitVectorExtractF(Context, Op.Rn, Index, SizeF); } - if (Opers.HasFlag(OperFlags.Rm)) + if (Rm) { EmitVectorExtractF(Context, ((AOpCodeSimdReg)Op).Rm, Index, SizeF); } @@ -469,8 +474,9 @@ namespace ChocolArm64.Instruction int SizeF = Op.Size & 1; int Bytes = Op.GetBitsCount() >> 3; + int Elems = Bytes >> SizeF + 2; - for (int Index = 0; Index < (Bytes >> SizeF + 2); Index++) + for (int Index = 0; Index < Elems; Index++) { if (Ternary) { @@ -531,19 +537,23 @@ namespace ChocolArm64.Instruction int Bytes = Op.GetBitsCount() >> 3; int Elems = Bytes >> Op.Size; + bool Rd = (Opers & OperFlags.Rd) != 0; + bool Rn = (Opers & OperFlags.Rn) != 0; + bool Rm = (Opers & OperFlags.Rm) != 0; + for (int Index = 0; Index < Elems; Index++) { - if (Opers.HasFlag(OperFlags.Rd)) + if (Rd) { EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed); } - if (Opers.HasFlag(OperFlags.Rn)) + if (Rn) { EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed); } - if (Opers.HasFlag(OperFlags.Rm)) + if (Rm) { EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed); } @@ -662,9 +672,6 @@ namespace ChocolArm64.Instruction { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; - Context.EmitLdvec(Op.Rd); - Context.EmitStvectmp(); - int Elems = 8 >> Op.Size; int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0; @@ -707,9 +714,6 @@ namespace ChocolArm64.Instruction { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; - Context.EmitLdvec(Op.Rd); - Context.EmitStvectmp(); - int Elems = 8 >> Op.Size; int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0; @@ -747,21 +751,25 @@ namespace ChocolArm64.Instruction { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; - int Bytes = Op.GetBitsCount() >> 3; + int Words = Op.GetBitsCount() >> 4; + int Pairs = Words >> Op.Size; - int Elems = Bytes >> Op.Size; - int Half = Elems >> 1; - - for (int Index = 0; Index < Elems; Index++) + for (int Index = 0; Index < Pairs; Index++) { - int Elem = (Index & (Half - 1)) << 1; + int Idx = Index << 1; - EmitVectorExtract(Context, Index < Half ? Op.Rn : Op.Rm, Elem + 0, Op.Size, Signed); - EmitVectorExtract(Context, Index < Half ? Op.Rn : Op.Rm, Elem + 1, Op.Size, Signed); + EmitVectorExtract(Context, Op.Rn, Idx, Op.Size, Signed); + EmitVectorExtract(Context, Op.Rn, Idx + 1, Op.Size, Signed); Emit(); - EmitVectorInsertTmp(Context, Index, Op.Size); + EmitVectorExtract(Context, Op.Rm, Idx, Op.Size, Signed); + EmitVectorExtract(Context, Op.Rm, Idx + 1, Op.Size, Signed); + + Emit(); + + EmitVectorInsertTmp(Context, Pairs + Index, Op.Size); + EmitVectorInsertTmp(Context, Index, Op.Size); } Context.EmitLdvectmp(); @@ -818,7 +826,7 @@ namespace ChocolArm64.Instruction int Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0; - long TMaxValue = SignedDst ? (1 << (ESize - 1)) - 1 : (1L << ESize) - 1L; + long TMaxValue = SignedDst ? (1 << (ESize - 1)) - 1 : (long)(~0UL >> (64 - ESize)); long TMinValue = SignedDst ? -((1 << (ESize - 1))) : 0; Context.EmitLdc_I8(0L); @@ -871,7 +879,7 @@ namespace ChocolArm64.Instruction if (Scalar) { - EmitVectorZeroLower(Context, Op.Rd); + EmitVectorZeroLowerTmp(Context); } EmitVectorInsertTmp(Context, Part + Index, Op.Size); @@ -963,6 +971,11 @@ namespace ChocolArm64.Instruction EmitVectorInsert(Context, Rd, 0, 3, 0); } + public static void EmitVectorZeroLowerTmp(AILEmitterCtx Context) + { + EmitVectorInsertTmp(Context, 0, 3, 0); + } + public static void EmitVectorZeroUpper(AILEmitterCtx Context, int Rd) { EmitVectorInsert(Context, Rd, 1, 3, 0); @@ -1008,6 +1021,20 @@ namespace ChocolArm64.Instruction Context.EmitStvec(Reg); } + public static void EmitVectorInsertTmp(AILEmitterCtx Context, int Index, int Size, long Value) + { + ThrowIfInvalid(Index, Size); + + Context.EmitLdc_I8(Value); + Context.EmitLdvectmp(); + Context.EmitLdc_I4(Index); + Context.EmitLdc_I4(Size); + + AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt)); + + Context.EmitStvectmp(); + } + public static void EmitVectorInsertF(AILEmitterCtx Context, int Reg, int Index, int Size) { ThrowIfInvalidF(Index, Size); diff --git a/Instruction/AInstEmitSimdMove.cs b/Instruction/AInstEmitSimdMove.cs index 592cab7..3bf1e46 100644 --- a/Instruction/AInstEmitSimdMove.cs +++ b/Instruction/AInstEmitSimdMove.cs @@ -295,13 +295,22 @@ namespace ChocolArm64.Instruction int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0; + if (Part != 0) + { + Context.EmitLdvec(Op.Rd); + Context.EmitStvectmp(); + } + for (int Index = 0; Index < Elems; Index++) { EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size + 1); - EmitVectorInsert(Context, Op.Rd, Part + Index, Op.Size); + EmitVectorInsertTmp(Context, Part + Index, Op.Size); } + Context.EmitLdvectmp(); + Context.EmitStvec(Op.Rd); + if (Part == 0) { EmitVectorZeroUpper(Context, Op.Rd); @@ -342,7 +351,7 @@ namespace ChocolArm64.Instruction EmitVectorExtractZx(Context, Op.Rm, Idx + Part, Op.Size); EmitVectorInsertTmp(Context, Idx + 1, Op.Size); - EmitVectorInsertTmp(Context, Idx , Op.Size); + EmitVectorInsertTmp(Context, Idx, Op.Size); } Context.EmitLdvectmp(); @@ -398,7 +407,7 @@ namespace ChocolArm64.Instruction EmitVectorExtractZx(Context, Op.Rm, Base + Index, Op.Size); EmitVectorInsertTmp(Context, Idx + 1, Op.Size); - EmitVectorInsertTmp(Context, Idx , Op.Size); + EmitVectorInsertTmp(Context, Idx, Op.Size); } Context.EmitLdvectmp();