private static void EmitFrecps(AILEmitterCtx Context, int Index, bool Scalar) { AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; int SizeF = Op.Size & 1; if (SizeF == 0) { Context.EmitLdc_R4(2); } else /* if (SizeF == 1) */ { Context.EmitLdc_R8(2); } EmitVectorExtractF(Context, Op.Rn, Index, SizeF); EmitVectorExtractF(Context, Op.Rm, Index, SizeF); Context.Emit(OpCodes.Mul); Context.Emit(OpCodes.Sub); if (Scalar) { EmitVectorZeroAll(Context, Op.Rd); } EmitVectorInsertF(Context, Op.Rd, Index, SizeF); }
private static void EmitFcmp(AILEmitterCtx Context, OpCode ILOp, int Index, bool Scalar) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; int SizeF = Op.Size & 1; ulong SzMask = ulong.MaxValue >> (64 - (32 << SizeF)); EmitVectorExtractF(Context, Op.Rn, Index, SizeF); if (Op is AOpCodeSimdReg BinOp) { EmitVectorExtractF(Context, BinOp.Rm, Index, SizeF); } else if (SizeF == 0) { Context.EmitLdc_R4(0); } else /* if (SizeF == 1) */ { Context.EmitLdc_R8(0); } AILLabel LblTrue = new AILLabel(); AILLabel LblEnd = new AILLabel(); Context.Emit(ILOp, LblTrue); if (Scalar) { EmitVectorZeroAll(Context, Op.Rd); } else { EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, 0); } Context.Emit(OpCodes.Br_S, LblEnd); Context.MarkLabel(LblTrue); if (Scalar) { EmitVectorInsert(Context, Op.Rd, Index, 3, (long)SzMask); EmitVectorZeroUpper(Context, Op.Rd); } else { EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, (long)SzMask); } Context.MarkLabel(LblEnd); }
private static void EmitLdcImmF(AILEmitterCtx Context, double ImmF, int Size) { if (Size == 0) { Context.EmitLdc_R4((float)ImmF); } else if (Size == 1) { Context.EmitLdc_R8(ImmF); } else { throw new ArgumentOutOfRangeException(nameof(Size)); } }
private static void EmitI2fFBitsMul(AILEmitterCtx Context, int Size, int FBits) { if (FBits != 0) { if (Size == 0) { Context.EmitLdc_R4(1f / MathF.Pow(2, FBits)); } else if (Size == 1) { Context.EmitLdc_R8(1 / Math.Pow(2, FBits)); } else { throw new ArgumentOutOfRangeException(nameof(Size)); } Context.Emit(OpCodes.Mul); } }
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); }