public static void Fccmp_S(AILEmitterCtx Context) { AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp; AILLabel LblTrue = new AILLabel(); AILLabel LblEnd = new AILLabel(); Context.EmitCondBranch(LblTrue, Op.Cond); //TODO: Share this logic with Ccmp. Context.EmitLdc_I4((Op.NZCV >> 0) & 1); Context.EmitStflg((int)APState.VBit); Context.EmitLdc_I4((Op.NZCV >> 1) & 1); Context.EmitStflg((int)APState.CBit); Context.EmitLdc_I4((Op.NZCV >> 2) & 1); Context.EmitStflg((int)APState.ZBit); Context.EmitLdc_I4((Op.NZCV >> 3) & 1); Context.EmitStflg((int)APState.NBit); Context.Emit(OpCodes.Br_S, LblEnd); Context.MarkLabel(LblTrue); Fcmp_S(Context); Context.MarkLabel(LblEnd); }
private static void EmitCcmp(AILEmitterCtx Context, CcmpOp CmpOp) { AOpCodeCcmp Op = (AOpCodeCcmp)Context.CurrOp; AILLabel LblTrue = new AILLabel(); AILLabel LblEnd = new AILLabel(); Context.EmitCondBranch(LblTrue, Op.Cond); Context.EmitLdc_I4((Op.NZCV >> 0) & 1); Context.EmitStflg((int)APState.VBit); Context.EmitLdc_I4((Op.NZCV >> 1) & 1); Context.EmitStflg((int)APState.CBit); Context.EmitLdc_I4((Op.NZCV >> 2) & 1); Context.EmitStflg((int)APState.ZBit); Context.EmitLdc_I4((Op.NZCV >> 3) & 1); Context.EmitStflg((int)APState.NBit); Context.Emit(OpCodes.Br_S, LblEnd); Context.MarkLabel(LblTrue); EmitDataLoadOpers(Context); if (CmpOp == CcmpOp.Cmp) { Context.Emit(OpCodes.Sub); Context.EmitZNFlagCheck(); EmitSubsCCheck(Context); EmitSubsVCheck(Context); } else if (CmpOp == CcmpOp.Cmn) { Context.Emit(OpCodes.Add); Context.EmitZNFlagCheck(); EmitAddsCCheck(Context); EmitAddsVCheck(Context); } else { throw new ArgumentException(nameof(CmpOp)); } Context.Emit(OpCodes.Pop); Context.MarkLabel(LblEnd); }
private static void EmitZeroCVFlags(AILEmitterCtx Context) { Context.EmitLdc_I4(0); Context.EmitStflg((int)APState.VBit); Context.EmitLdc_I4(0); Context.EmitStflg((int)APState.CBit); }
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 EmitSetNZCV(AILEmitterCtx Context, int NZCV) { Context.EmitLdc_I4((NZCV >> 0) & 1); Context.EmitStflg((int)APState.VBit); Context.EmitLdc_I4((NZCV >> 1) & 1); Context.EmitStflg((int)APState.CBit); Context.EmitLdc_I4((NZCV >> 2) & 1); Context.EmitStflg((int)APState.ZBit); Context.EmitLdc_I4((NZCV >> 3) & 1); Context.EmitStflg((int)APState.NBit); }
public static void EmitAddsCCheck(AILEmitterCtx Context) { //C = Rd < Rn Context.Emit(OpCodes.Dup); EmitDataLoadRn(Context); Context.Emit(OpCodes.Clt_Un); Context.EmitStflg((int)APState.CBit); }
public static void EmitSubsCCheck(AILEmitterCtx Context) { //C = Rn == Rm || Rn > Rm = !(Rn < Rm) EmitDataLoadOpers(Context); Context.Emit(OpCodes.Clt_Un); Context.EmitLdc_I4(1); Context.Emit(OpCodes.Xor); Context.EmitStflg((int)APState.CBit); }
public static void EmitSubsCCheck(AILEmitterCtx Context) { //C = Rn == Rm || Rn > Rm EmitDataLoadOpers(Context); Context.Emit(OpCodes.Ceq); EmitDataLoadOpers(Context); Context.Emit(OpCodes.Cgt_Un); Context.Emit(OpCodes.Or); Context.EmitStflg((int)APState.CBit); }
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); }
public static void Fcmp_S(AILEmitterCtx Context) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false; //Handle NaN case. //If any number is NaN, then NZCV = 0011. if (CmpWithZero) { EmitNaNCheck(Context, Op.Rn); } else { EmitNaNCheck(Context, Op.Rn); EmitNaNCheck(Context, Op.Rm); Context.Emit(OpCodes.Or); } AILLabel LblNaN = new AILLabel(); AILLabel LblEnd = new AILLabel(); Context.Emit(OpCodes.Brtrue_S, LblNaN); void EmitLoadOpers() { EmitVectorExtractF(Context, Op.Rn, 0, Op.Size); if (CmpWithZero) { if (Op.Size == 0) { Context.EmitLdc_R4(0); } else /* if (SizeF == 1) */ { Context.EmitLdc_R8(0); } } else { EmitVectorExtractF(Context, Op.Rm, 0, Op.Size); } } //Z = Rn == Rm EmitLoadOpers(); Context.Emit(OpCodes.Ceq); Context.Emit(OpCodes.Dup); Context.EmitStflg((int)APState.ZBit); //C = Rn >= Rm EmitLoadOpers(); Context.Emit(OpCodes.Cgt); Context.Emit(OpCodes.Or); Context.EmitStflg((int)APState.CBit); //N = Rn < Rm EmitLoadOpers(); Context.Emit(OpCodes.Clt); Context.EmitStflg((int)APState.NBit); //V = 0 Context.EmitLdc_I4(0); Context.EmitStflg((int)APState.VBit); Context.Emit(OpCodes.Br_S, LblEnd); Context.MarkLabel(LblNaN); EmitSetNZCV(Context, 0b0011); Context.MarkLabel(LblEnd); }
public static void Fcmp_S(AILEmitterCtx Context) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false; //todo //Context.TryMarkCondWithoutCmp(); void EmitLoadOpers() { Context.EmitLdvecsf(Op.Rn); if (CmpWithZero) { EmitLdcImmF(Context, 0, Op.Size); } else { Context.EmitLdvecsf(Op.Rm); } } //Z = Rn == Rm EmitLoadOpers(); Context.Emit(OpCodes.Ceq); Context.Emit(OpCodes.Dup); Context.EmitStflg((int)APState.ZBit); //C = Rn >= Rm EmitLoadOpers(); Context.Emit(OpCodes.Cgt); Context.Emit(OpCodes.Or); Context.EmitStflg((int)APState.CBit); //N = Rn < Rm EmitLoadOpers(); Context.Emit(OpCodes.Clt); Context.EmitStflg((int)APState.NBit); //Handle NaN case. If any number is NaN, then NZCV = 0011. AILLabel LblNotNaN = new AILLabel(); if (CmpWithZero) { EmitNaNCheck(Context, Op.Rn); } else { EmitNaNCheck(Context, Op.Rn); EmitNaNCheck(Context, Op.Rm); Context.Emit(OpCodes.Or); } Context.Emit(OpCodes.Brfalse_S, LblNotNaN); Context.EmitLdc_I4(1); Context.EmitLdc_I4(1); Context.EmitStflg((int)APState.CBit); Context.EmitStflg((int)APState.VBit); Context.MarkLabel(LblNotNaN); }