Beispiel #1
0
        public static void Vshrn(ArmEmitterContext context)
        {
            OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
            int shift            = GetImmShr(op);

            EmitVectorUnaryNarrowOp32(context, (op1) => context.ShiftRightUI(op1, Const(shift)));
        }
Beispiel #2
0
        public static void Vshrn(ArmEmitterContext context)
        {
            OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
            int shift            = (8 << op.Size) - op.Shift; // Shr amount is flipped.

            EmitVectorUnaryNarrowOp32(context, (op1) => context.ShiftRightUI(op1, Const(shift)));
        }
Beispiel #3
0
        public static void Vrshr(ArmEmitterContext context)
        {
            OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
            int  shift           = GetImmShr(op);
            long roundConst      = 1L << (shift - 1);

            if (op.U)
            {
                if (op.Size < 2)
                {
                    EmitVectorUnaryOpZx32(context, (op1) =>
                    {
                        op1 = context.Add(op1, Const(op1.Type, roundConst));

                        return(context.ShiftRightUI(op1, Const(shift)));
                    });
                }
                else if (op.Size == 2)
                {
                    EmitVectorUnaryOpZx32(context, (op1) =>
                    {
                        op1 = context.ZeroExtend32(OperandType.I64, op1);
                        op1 = context.Add(op1, Const(op1.Type, roundConst));

                        return(context.ConvertI64ToI32(context.ShiftRightUI(op1, Const(shift))));
                    });
                }
                else /* if (op.Size == 3) */
                {
                    EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: false, roundConst, shift));
                }
            }
            else
            {
                if (op.Size < 2)
                {
                    EmitVectorUnaryOpSx32(context, (op1) =>
                    {
                        op1 = context.Add(op1, Const(op1.Type, roundConst));

                        return(context.ShiftRightSI(op1, Const(shift)));
                    });
                }
                else if (op.Size == 2)
                {
                    EmitVectorUnaryOpSx32(context, (op1) =>
                    {
                        op1 = context.SignExtend32(OperandType.I64, op1);
                        op1 = context.Add(op1, Const(op1.Type, roundConst));

                        return(context.ConvertI64ToI32(context.ShiftRightSI(op1, Const(shift))));
                    });
                }
                else /* if (op.Size == 3) */
                {
                    EmitVectorUnaryOpZx32(context, (op1) => EmitShrImm64(context, op1, signed: true, roundConst, shift));
                }
            }
        }
Beispiel #4
0
        public static void Vshr(ArmEmitterContext context)
        {
            OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
            int shift            = GetImmShr(op);
            int maxShift         = (8 << op.Size) - 1;

            if (op.U)
            {
                EmitVectorUnaryOpZx32(context, (op1) => (shift > maxShift) ? Const(op1.Type, 0) : context.ShiftRightUI(op1, Const(shift)));
            }
            else
            {
                EmitVectorUnaryOpSx32(context, (op1) => context.ShiftRightSI(op1, Const(Math.Min(maxShift, shift))));
            }
        }
        public static void EmitVectorImmBinaryQdQmOpI32(ArmEmitterContext context, Func2I emit, bool signed)
        {
            OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;

            Operand res = GetVecA32(op.Qd);

            int elems = op.GetBytesCount() >> op.Size;

            for (int index = 0; index < elems; index++)
            {
                Operand de = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size, signed);
                Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed);

                res = EmitVectorInsert(context, res, emit(de, me), op.Id + index, op.Size);
            }

            context.Copy(GetVecA32(op.Qd), res);
        }
Beispiel #6
0
        public static void Vsra(ArmEmitterContext context)
        {
            OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
            int shift            = GetImmShr(op);
            int maxShift         = (8 << op.Size) - 1;

            if (op.U)
            {
                EmitVectorImmBinaryQdQmOpZx32(context, (op1, op2) =>
                {
                    Operand shiftRes = shift > maxShift ? Const(op2.Type, 0) : context.ShiftRightUI(op2, Const(shift));

                    return(context.Add(op1, shiftRes));
                });
            }
            else
            {
                EmitVectorImmBinaryQdQmOpSx32(context, (op1, op2) => context.Add(op1, context.ShiftRightSI(op2, Const(Math.Min(maxShift, shift)))));
            }
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        public static void Vshl(ArmEmitterContext context)
        {
            OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;

            EmitVectorUnaryOpZx32(context, (op1) => context.ShiftLeft(op1, Const(op.Shift)));
        }
Beispiel #9
0
 private static int GetImmShr(OpCode32SimdShImm op)
 {
     return((8 << op.Size) - op.Shift); // Shr amount is flipped.
 }
Beispiel #10
0
        public static void Vqshrn(ArmEmitterContext context)
        {
            OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;

            EmitShrImmSaturatingNarrowOp(context, op.U ? ShrImmSaturatingNarrowFlags.VectorZxZx : ShrImmSaturatingNarrowFlags.VectorSxSx);
        }