public static void EmitAddsVCheck(AILEmitterCtx Context) { //V = (Rd ^ Rn) & (Rd ^ Rm) & ~(Rn ^ Rm) < 0 Context.EmitSttmp(); Context.EmitLdtmp(); Context.EmitLdtmp(); EmitDataLoadRn(Context); Context.Emit(OpCodes.Xor); Context.EmitLdtmp(); EmitDataLoadOper2(Context); Context.Emit(OpCodes.Xor); Context.Emit(OpCodes.And); EmitDataLoadOpers(Context); Context.Emit(OpCodes.Xor); Context.Emit(OpCodes.Not); Context.Emit(OpCodes.And); Context.EmitLdc_I(0); Context.Emit(OpCodes.Clt); Context.EmitStflg((int)APState.VBit); }
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); }); }
private static void EmitVectorBsl(AILEmitterCtx Context) { EmitVectorTernaryZx(Context, () => { Context.EmitSttmp(); Context.EmitLdtmp(); Context.Emit(OpCodes.Xor); Context.Emit(OpCodes.And); Context.EmitLdtmp(); Context.Emit(OpCodes.Xor); }); }
public static void Bsl_V(AILEmitterCtx Context) { if (AOptimizations.UseSse2) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; Type[] Types = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] }; EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size); EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size); Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types)); EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size); Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), Types)); EmitLdvecWithUnsignedCast(Context, Op.Rm, Op.Size); Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types)); EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size); if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } } else { EmitVectorTernaryOpZx(Context, () => { Context.EmitSttmp(); Context.EmitLdtmp(); Context.Emit(OpCodes.Xor); Context.Emit(OpCodes.And); Context.EmitLdtmp(); Context.Emit(OpCodes.Xor); }); } }
public static void EmitVectorOpByElem(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary, bool Signed) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; int Bytes = Op.GetBitsCount() >> 3; int Elems = Bytes >> Op.Size; EmitVectorExtract(Context, Op.Rm, Elem, Op.Size, Signed); Context.EmitSttmp(); for (int Index = 0; Index < Elems; Index++) { if (Ternary) { EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed); } EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed); Context.EmitLdtmp(); Emit(); EmitVectorInsertTmp(Context, Index, Op.Size); } Context.EmitLdvectmp(); Context.EmitStvec(Op.Rd); if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } }
private static void EmitLoad(AILEmitterCtx Context, AccessType AccType, bool Pair) { AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp; bool Ordered = (AccType & AccessType.Ordered) != 0; bool Exclusive = (AccType & AccessType.Exclusive) != 0; if (Ordered) { EmitBarrier(Context); } if (Exclusive) { EmitMemoryCall(Context, nameof(AMemory.SetExclusive), Op.Rn); } Context.EmitLdint(Op.Rn); Context.EmitSttmp(); Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); Context.EmitLdtmp(); EmitReadZxCall(Context, Op.Size); Context.EmitStintzr(Op.Rt); if (Pair) { Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); Context.EmitLdtmp(); Context.EmitLdc_I8(1 << Op.Size); Context.Emit(OpCodes.Add); EmitReadZxCall(Context, Op.Size); Context.EmitStintzr(Op.Rt2); } }
public static void EmitAdcsCCheck(AILEmitterCtx Context) { //C = (Rd == Rn && CIn) || Rd < Rn Context.EmitSttmp(); Context.EmitLdtmp(); Context.EmitLdtmp(); EmitDataLoadRn(Context); Context.Emit(OpCodes.Ceq); Context.EmitLdflg((int)APState.CBit); Context.Emit(OpCodes.And); Context.EmitLdtmp(); EmitDataLoadRn(Context); Context.Emit(OpCodes.Clt_Un); Context.Emit(OpCodes.Or); Context.EmitStflg((int)APState.CBit); }
private static void EmitWBackIfNeeded(AILEmitterCtx Context) { //Check whenever the current OpCode has post-indexed write back, if so write it. //Note: AOpCodeMemPair inherits from AOpCodeMemImm, so this works for both. if (Context.CurrOp is AOpCodeMemImm Op && Op.WBack) { Context.EmitLdtmp(); if (Op.PostIdx) { Context.EmitLdc_I(Op.Imm); Context.Emit(OpCodes.Add); } Context.EmitStint(Op.Rn); } }
public static void Ldp(AILEmitterCtx Context) { AOpCodeMemPair Op = (AOpCodeMemPair)Context.CurrOp; void EmitReadAndStore(int Rt) { if (Op.Extend64) { EmitReadSx64Call(Context, Op.Size); } else { EmitReadZxCall(Context, Op.Size); } if (Op is IAOpCodeSimd) { Context.EmitStvec(Rt); } else { Context.EmitStintzr(Rt); } } Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); EmitLoadAddress(Context); EmitReadAndStore(Op.Rt); Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); Context.EmitLdtmp(); Context.EmitLdc_I8(1 << Op.Size); Context.Emit(OpCodes.Add); EmitReadAndStore(Op.Rt2); EmitWBackIfNeeded(Context); }
public static void Stp(AILEmitterCtx Context) { AOpCodeMemPair Op = (AOpCodeMemPair)Context.CurrOp; Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); EmitLoadAddress(Context); if (Op is IAOpCodeSimd) { Context.EmitLdvec(Op.Rt); } else { Context.EmitLdintzr(Op.Rt); } EmitWriteCall(Context, Op.Size); Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); Context.EmitLdtmp(); Context.EmitLdc_I8(1 << Op.Size); Context.Emit(OpCodes.Add); if (Op is IAOpCodeSimd) { Context.EmitLdvec(Op.Rt2); } else { Context.EmitLdintzr(Op.Rt2); } EmitWriteCall(Context, Op.Size); EmitWBackIfNeeded(Context); }
private static void EmitQxtn(AILEmitterCtx Context, bool Signed, bool Scalar) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int Elems = (!Scalar ? 8 >> Op.Size : 1); int ESize = 8 << Op.Size; int TMaxValue = (Signed ? (1 << (ESize - 1)) - 1 : (int)((1L << ESize) - 1L)); int TMinValue = (Signed ? -((1 << (ESize - 1))) : 0); int Part = (!Scalar & (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0); Context.EmitLdc_I8(0L); Context.EmitSttmp(); for (int Index = 0; Index < Elems; Index++) { AILLabel LblLe = new AILLabel(); AILLabel LblGeEnd = new AILLabel(); EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, Signed); Context.Emit(OpCodes.Dup); Context.EmitLdc_I4(TMaxValue); Context.Emit(OpCodes.Conv_U8); Context.Emit(Signed ? OpCodes.Ble_S : OpCodes.Ble_Un_S, LblLe); Context.Emit(OpCodes.Pop); Context.EmitLdc_I4(TMaxValue); Context.EmitLdc_I8(0x8000000L); Context.EmitSttmp(); Context.Emit(OpCodes.Br_S, LblGeEnd); Context.MarkLabel(LblLe); Context.Emit(OpCodes.Dup); Context.EmitLdc_I4(TMinValue); Context.Emit(OpCodes.Conv_I8); Context.Emit(Signed ? OpCodes.Bge_S : OpCodes.Bge_Un_S, LblGeEnd); Context.Emit(OpCodes.Pop); Context.EmitLdc_I4(TMinValue); Context.EmitLdc_I8(0x8000000L); Context.EmitSttmp(); Context.MarkLabel(LblGeEnd); if (Scalar) { EmitVectorZeroLower(Context, Op.Rd); } EmitVectorInsert(Context, Op.Rd, Part + Index, Op.Size); } if (Part == 0) { EmitVectorZeroUpper(Context, Op.Rd); } Context.EmitLdarg(ATranslatedSub.StateArgIdx); Context.EmitLdarg(ATranslatedSub.StateArgIdx); Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpsr)); Context.EmitLdtmp(); Context.Emit(OpCodes.Conv_I4); Context.Emit(OpCodes.Or); Context.EmitCallPropSet(typeof(AThreadState), nameof(AThreadState.Fpsr)); }
public static void EmitSaturatingNarrowOp( AILEmitterCtx Context, Action Emit, bool SignedSrc, bool SignedDst, bool Scalar) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int Elems = !Scalar ? 8 >> Op.Size : 1; int ESize = 8 << Op.Size; int Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0; long TMaxValue = SignedDst ? (1 << (ESize - 1)) - 1 : (1L << ESize) - 1L; long TMinValue = SignedDst ? -((1 << (ESize - 1))) : 0; Context.EmitLdc_I8(0L); Context.EmitSttmp(); if (Part != 0) { Context.EmitLdvec(Op.Rd); Context.EmitStvectmp(); } for (int Index = 0; Index < Elems; Index++) { AILLabel LblLe = new AILLabel(); AILLabel LblGeEnd = new AILLabel(); EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc); Emit(); Context.Emit(OpCodes.Dup); Context.EmitLdc_I8(TMaxValue); Context.Emit(SignedSrc ? OpCodes.Ble_S : OpCodes.Ble_Un_S, LblLe); Context.Emit(OpCodes.Pop); Context.EmitLdc_I8(TMaxValue); Context.EmitLdc_I8(0x8000000L); Context.EmitSttmp(); Context.Emit(OpCodes.Br_S, LblGeEnd); Context.MarkLabel(LblLe); Context.Emit(OpCodes.Dup); Context.EmitLdc_I8(TMinValue); Context.Emit(SignedSrc ? OpCodes.Bge_S : OpCodes.Bge_Un_S, LblGeEnd); Context.Emit(OpCodes.Pop); Context.EmitLdc_I8(TMinValue); Context.EmitLdc_I8(0x8000000L); Context.EmitSttmp(); Context.MarkLabel(LblGeEnd); if (Scalar) { EmitVectorZeroLower(Context, Op.Rd); } EmitVectorInsertTmp(Context, Part + Index, Op.Size); } Context.EmitLdvectmp(); Context.EmitStvec(Op.Rd); if (Part == 0) { EmitVectorZeroUpper(Context, Op.Rd); } Context.EmitLdarg(ATranslatedSub.StateArgIdx); Context.EmitLdarg(ATranslatedSub.StateArgIdx); Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpsr)); Context.EmitLdtmp(); Context.Emit(OpCodes.Conv_I4); Context.Emit(OpCodes.Or); Context.EmitCallPropSet(typeof(AThreadState), nameof(AThreadState.Fpsr)); }