using ChocolArm64.Decoder; using ChocolArm64.State; using ChocolArm64.Translation; using System; using System.Reflection.Emit; using System.Runtime.Intrinsics.X86; using static ChocolArm64.Instruction.AInstEmitSimdHelper; namespace ChocolArm64.Instruction { static partial class AInstEmit { public static void And_V(AILEmitterCtx Context) { if (AOptimizations.UseSse2) { EmitSse2Call(Context, nameof(Sse2.And)); } else { EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.And)); } } public static void Bic_V(AILEmitterCtx Context) { EmitVectorBinaryOpZx(Context, () => { Context.Emit(OpCodes.Not); Context.Emit(OpCodes.And); }); } public static void Bic_Vi(AILEmitterCtx Context) { EmitVectorImmBinaryOp(Context, () => { Context.Emit(OpCodes.Not); Context.Emit(OpCodes.And); }); } public static void Bif_V(AILEmitterCtx Context) { EmitBitBif(Context, true); } public static void Bit_V(AILEmitterCtx Context) { EmitBitBif(Context, false); } private static void EmitBitBif(AILEmitterCtx Context, bool NotRm) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; int Bytes = Op.GetBitsCount() >> 3; int Elems = Bytes >> Op.Size; for (int Index = 0; Index < Elems; Index++) { EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size); EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size); Context.Emit(OpCodes.Xor); EmitVectorExtractZx(Context, Op.Rm, Index, Op.Size); if (NotRm) { Context.Emit(OpCodes.Not); } Context.Emit(OpCodes.And); EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size); Context.Emit(OpCodes.Xor); EmitVectorInsert(Context, Op.Rd, Index, Op.Size); } if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } } public static void Bsl_V(AILEmitterCtx Context) { EmitVectorTernaryOpZx(Context, () => { Context.EmitSttmp(); Context.EmitLdtmp(); Context.Emit(OpCodes.Xor); Context.Emit(OpCodes.And); Context.EmitLdtmp(); Context.Emit(OpCodes.Xor); }); } public static void Eor_V(AILEmitterCtx Context) { if (AOptimizations.UseSse2) { EmitSse2Call(Context, nameof(Sse2.Xor)); } else { EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Xor)); } } public static void Not_V(AILEmitterCtx Context) { EmitVectorUnaryOpZx(Context, () => Context.Emit(OpCodes.Not)); } public static void Orn_V(AILEmitterCtx Context) { EmitVectorBinaryOpZx(Context, () => { Context.Emit(OpCodes.Not); Context.Emit(OpCodes.Or); }); } public static void Orr_V(AILEmitterCtx Context) { if (AOptimizations.UseSse2) { EmitSse2Call(Context, nameof(Sse2.Or)); } else { EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Or)); } } public static void Orr_Vi(AILEmitterCtx Context) { EmitVectorImmBinaryOp(Context, () => Context.Emit(OpCodes.Or)); } public static void Rbit_V(AILEmitterCtx Context) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int Elems = Op.RegisterSize == ARegisterSize.SIMD128 ? 16 : 8; for (int Index = 0; Index < Elems; Index++) { EmitVectorExtractZx(Context, Op.Rn, Index, 0); Context.Emit(OpCodes.Conv_U4); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ReverseBits8)); Context.Emit(OpCodes.Conv_U8); EmitVectorInsert(Context, Op.Rd, Index, 0); } if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } } public static void Rev16_V(AILEmitterCtx Context) { EmitRev_V(Context, ContainerSize: 1); } public static void Rev32_V(AILEmitterCtx Context) { EmitRev_V(Context, ContainerSize: 2); } public static void Rev64_V(AILEmitterCtx Context) { EmitRev_V(Context, ContainerSize: 3); } private static void EmitRev_V(AILEmitterCtx Context, int ContainerSize) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; if (Op.Size >= ContainerSize) { throw new InvalidOperationException(); } int Bytes = Op.GetBitsCount() >> 3; int Elems = Bytes >> Op.Size; int ContainerMask = (1 << (ContainerSize - Op.Size)) - 1; for (int Index = 0; Index < Elems; Index++) { int RevIndex = Index ^ ContainerMask; EmitVectorExtractZx(Context, Op.Rn, RevIndex, Op.Size); EmitVectorInsertTmp(Context, Index, Op.Size); } Context.EmitLdvectmp(); Context.EmitStvec(Op.Rd); if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } } } }