private static void EmitShrImmSaturatingNarrowOp(ArmEmitterContext context, ShrImmSaturatingNarrowFlags flags) { OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp; bool scalar = (flags & ShrImmSaturatingNarrowFlags.Scalar) != 0; bool signedSrc = (flags & ShrImmSaturatingNarrowFlags.SignedSrc) != 0; bool signedDst = (flags & ShrImmSaturatingNarrowFlags.SignedDst) != 0; bool round = (flags & ShrImmSaturatingNarrowFlags.Round) != 0; int shift = GetImmShr(op); long roundConst = 1L << (shift - 1); int elems = !scalar ? 8 >> op.Size : 1; int part = !scalar && (op.RegisterSize == RegisterSize.Simd128) ? elems : 0; Operand res = part == 0 ? context.VectorZero() : context.Copy(GetVec(op.Rd)); for (int index = 0; index < elems; index++) { Operand e = EmitVectorExtract(context, op.Rn, index, op.Size + 1, signedSrc); if (op.Size <= 1 || !round) { if (round) { e = context.Add(e, Const(roundConst)); } e = signedSrc ? context.ShiftRightSI(e, Const(shift)) : context.ShiftRightUI(e, Const(shift)); } else /* if (op.Size == 2 && round) */ { e = EmitShrImm64(context, e, signedSrc, roundConst, shift); // shift <= 32 } e = EmitSatQ(context, e, op.Size, signedSrc, signedDst); res = EmitVectorInsert(context, res, e, part + index, op.Size); } context.Copy(GetVec(op.Rd), res); }
private static void EmitShrImmSaturatingNarrowOp(ArmEmitterContext context, ShrImmSaturatingNarrowFlags flags) { OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp; bool scalar = (flags & ShrImmSaturatingNarrowFlags.Scalar) != 0; bool signedSrc = (flags & ShrImmSaturatingNarrowFlags.SignedSrc) != 0; bool signedDst = (flags & ShrImmSaturatingNarrowFlags.SignedDst) != 0; bool round = (flags & ShrImmSaturatingNarrowFlags.Round) != 0; if (scalar) { // TODO: Support scalar operation. throw new NotImplementedException(); } int shift = GetImmShr(op); long roundConst = 1L << (shift - 1); EmitVectorUnaryNarrowOp32(context, (op1) => { if (op.Size <= 1 || !round) { if (round) { op1 = context.Add(op1, Const(op1.Type, roundConst)); } op1 = signedSrc ? context.ShiftRightSI(op1, Const(shift)) : context.ShiftRightUI(op1, Const(shift)); } else /* if (op.Size == 2 && round) */ { op1 = EmitShrImm64(context, op1, signedSrc, roundConst, shift); // shift <= 32 } return(EmitSatQ(context, op1, 8 << op.Size, signedDst)); }, signedSrc); }
private static void EmitShrImmSaturatingNarrowOp(AILEmitterCtx Context, ShrImmSaturatingNarrowFlags Flags) { AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp; bool Scalar = (Flags & ShrImmSaturatingNarrowFlags.Scalar) != 0; bool SignedSrc = (Flags & ShrImmSaturatingNarrowFlags.SignedSrc) != 0; bool SignedDst = (Flags & ShrImmSaturatingNarrowFlags.SignedDst) != 0; bool Round = (Flags & ShrImmSaturatingNarrowFlags.Round) != 0; int Shift = GetImmShr(Op); long RoundConst = 1L << (Shift - 1); int Elems = !Scalar ? 8 >> Op.Size : 1; int Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0; if (Scalar) { EmitVectorZeroLowerTmp(Context); } if (Part != 0) { Context.EmitLdvec(Op.Rd); Context.EmitStvectmp(); } for (int Index = 0; Index < Elems; Index++) { EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc); if (Op.Size <= 1 || !Round) { if (Round) { Context.EmitLdc_I8(RoundConst); Context.Emit(OpCodes.Add); } Context.EmitLdc_I4(Shift); Context.Emit(SignedSrc ? OpCodes.Shr : OpCodes.Shr_Un); } else /* if (Op.Size == 2 && Round) */ { EmitShrImm_64(Context, SignedSrc, RoundConst, Shift); // Shift <= 32 } EmitSatQ(Context, Op.Size, SignedSrc, SignedDst); EmitVectorInsertTmp(Context, Part + Index, Op.Size); } Context.EmitLdvectmp(); Context.EmitStvec(Op.Rd); if (Part == 0) { EmitVectorZeroUpper(Context, Op.Rd); } }
private static void EmitRoundShrImmSaturatingNarrowOp(AILEmitterCtx Context, ShrImmSaturatingNarrowFlags Flags) { EmitShrImmSaturatingNarrowOp(Context, ShrImmSaturatingNarrowFlags.Round | Flags); }
private static void EmitRoundShrImmSaturatingNarrowOp(ArmEmitterContext context, ShrImmSaturatingNarrowFlags flags) { EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.Round | flags); }
private static void EmitShrImmSaturatingNarrowOp(ILEmitterCtx context, ShrImmSaturatingNarrowFlags flags) { OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp; bool scalar = (flags & ShrImmSaturatingNarrowFlags.Scalar) != 0; bool signedSrc = (flags & ShrImmSaturatingNarrowFlags.SignedSrc) != 0; bool signedDst = (flags & ShrImmSaturatingNarrowFlags.SignedDst) != 0; bool round = (flags & ShrImmSaturatingNarrowFlags.Round) != 0; int shift = GetImmShr(op); long roundConst = 1L << (shift - 1); int elems = !scalar ? 8 >> op.Size : 1; int part = !scalar && (op.RegisterSize == RegisterSize.Simd128) ? elems : 0; if (scalar) { EmitVectorZeroLowerTmp(context); } if (part != 0) { context.EmitLdvec(op.Rd); context.EmitStvectmp(); } for (int index = 0; index < elems; index++) { EmitVectorExtract(context, op.Rn, index, op.Size + 1, signedSrc); if (op.Size <= 1 || !round) { if (round) { context.EmitLdc_I8(roundConst); context.Emit(OpCodes.Add); } context.EmitLdc_I4(shift); context.Emit(signedSrc ? OpCodes.Shr : OpCodes.Shr_Un); } else /* if (op.Size == 2 && round) */ { EmitShrImm64(context, signedSrc, roundConst, shift); // shift <= 32 } EmitSatQ(context, op.Size, signedSrc, signedDst); EmitVectorInsertTmp(context, part + index, op.Size); } context.EmitLdvectmp(); context.EmitStvec(op.Rd); if (part == 0) { EmitVectorZeroUpper(context, op.Rd); } }