Esempio n. 1
0
        public static void Vmin_I(ArmEmitterContext context)
        {
            OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

            if (op.U)
            {
                if (Optimizations.UseSse2)
                {
                    EmitVectorBinaryOpSimd32(context, (op1, op2) => context.AddIntrinsic(X86PminuInstruction[op.Size], op1, op2));
                }
                else
                {
                    EmitVectorBinaryOpZx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareLessUI(op1, op2), op1, op2));
                }
            }
            else
            {
                if (Optimizations.UseSse2)
                {
                    EmitVectorBinaryOpSimd32(context, (op1, op2) => context.AddIntrinsic(X86PminsInstruction[op.Size], op1, op2));
                }
                else
                {
                    EmitVectorBinaryOpSx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareLess(op1, op2), op1, op2));
                }
            }
        }
        public static void Vmin_I(ArmEmitterContext context)
        {
            OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

            if (op.U)
            {
                EmitVectorBinaryOpZx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareLessUI(op1, op2), op1, op2));
            }
            else
            {
                EmitVectorBinaryOpSx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareLess(op1, op2), op1, op2));
            }
        }
Esempio n. 3
0
        private static void EmitCsel(ArmEmitterContext context, CselOperation cselOp)
        {
            OpCodeCsel op = (OpCodeCsel)context.CurrOp;

            Operand n = GetIntOrZR(context, op.Rn);
            Operand m = GetIntOrZR(context, op.Rm);

            if (cselOp == CselOperation.Increment)
            {
                m = context.Add(m, Const(m.Type, 1));
            }
            else if (cselOp == CselOperation.Invert)
            {
                m = context.BitwiseNot(m);
            }
            else if (cselOp == CselOperation.Negate)
            {
                m = context.Negate(m);
            }

            Operand condTrue = GetCondTrue(context, op.Cond);

            Operand d = context.ConditionalSelect(condTrue, n, m);

            SetIntOrZR(context, op.Rd, d);
        }
Esempio n. 4
0
        private static void EmitCmtstOp(ArmEmitterContext context, bool scalar)
        {
            OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;

            Operand res = context.VectorZero();

            int elems = !scalar?op.GetBytesCount() >> op.Size : 1;

            ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size));

            for (int index = 0; index < elems; index++)
            {
                Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
                Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);

                Operand test = context.BitwiseAnd(ne, me);

                Operand isTrue = context.ICompareNotEqual(test, Const(0L));

                Operand mask = context.ConditionalSelect(isTrue, Const(szMask), Const(0L));

                res = EmitVectorInsert(context, res, mask, index, op.Size);
            }

            context.Copy(GetVec(op.Rd), res);
        }
Esempio n. 5
0
        private static void EmitCmpOp(ArmEmitterContext context, Func2I emitCmp, bool scalar)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            Operand res = context.VectorZero();

            int elems = !scalar?op.GetBytesCount() >> op.Size : 1;

            ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size));

            for (int index = 0; index < elems; index++)
            {
                Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
                Operand me;

                if (op is OpCodeSimdReg binOp)
                {
                    me = EmitVectorExtractSx(context, binOp.Rm, index, op.Size);
                }
                else
                {
                    me = Const(0L);
                }

                Operand isTrue = emitCmp(ne, me);

                Operand mask = context.ConditionalSelect(isTrue, Const(szMask), Const(0L));

                res = EmitVectorInsert(context, res, mask, index, op.Size);
            }

            context.Copy(GetVec(op.Rd), res);
        }
Esempio n. 6
0
        public static Operand EmitAsrC(ArmEmitterContext context, Operand m, bool setCarry, Operand shift, Operand shiftIsZero)
        {
            Debug.Assert(m.Type == OperandType.I32 && shift.Type == OperandType.I32 && shiftIsZero.Type == OperandType.I32);

            Operand l32Result;
            Operand ge32Result;

            Operand less32 = context.ICompareLess(shift, Const(32));

            ge32Result = context.ShiftRightSI(m, Const(31));

            if (setCarry)
            {
                EmitIfHelper(context, context.BitwiseOr(less32, shiftIsZero), () =>
                {
                    SetCarryMLsb(context, ge32Result);
                }, false);
            }

            l32Result = context.ShiftRightSI(m, shift);
            if (setCarry)
            {
                EmitIfHelper(context, context.BitwiseAnd(less32, context.BitwiseNot(shiftIsZero)), () =>
                {
                    Operand cOut = context.ShiftRightUI(m, context.Subtract(shift, Const(1)));

                    cOut = context.BitwiseAnd(cOut, Const(1));

                    SetFlag(context, PState.CFlag, cOut);
                });
            }

            return(context.ConditionalSelect(less32, l32Result, ge32Result));
        }
        public static void Vsel(ArmEmitterContext context)
        {
            OpCode32SimdSel op = (OpCode32SimdSel)context.CurrOp;

            Operand condition = null;

            switch (op.Cc)
            {
            case OpCode32SimdSelMode.Eq:
                condition = GetCondTrue(context, Condition.Eq);
                break;

            case OpCode32SimdSelMode.Ge:
                condition = GetCondTrue(context, Condition.Ge);
                break;

            case OpCode32SimdSelMode.Gt:
                condition = GetCondTrue(context, Condition.Gt);
                break;

            case OpCode32SimdSelMode.Vs:
                condition = GetCondTrue(context, Condition.Vs);
                break;
            }

            EmitScalarBinaryOpI32(context, (op1, op2) =>
            {
                return(context.ConditionalSelect(condition, op1, op2));
            });
        }
Esempio n. 8
0
 public static void Vtst(ArmEmitterContext context)
 {
     EmitVectorBinaryOpZx32(context, (op1, op2) =>
     {
         Operand isZero = context.ICompareEqual(context.BitwiseAnd(op1, op2), Const(0));
         return(context.ConditionalSelect(isZero, Const(0), Const(-1)));
     });
 }
Esempio n. 9
0
        public static void EmitBxWritePc(ArmEmitterContext context, Operand pc, int sourceRegister = 0)
        {
            bool    isReturn = sourceRegister == RegisterAlias.Aarch32Lr || IsA32Return(context);
            Operand mode     = context.BitwiseAnd(pc, Const(1));

            SetFlag(context, PState.TFlag, mode);

            Operand addr = context.ConditionalSelect(mode, context.BitwiseAnd(pc, Const(~1)), context.BitwiseAnd(pc, Const(~3)));

            InstEmitFlowHelper.EmitVirtualJump(context, addr, isReturn);
        }
Esempio n. 10
0
        private static Operand EmitUnsignedShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size)
        {
            Debug.Assert(op.Type == OperandType.I64);
            Debug.Assert(shiftLsB.Type == OperandType.I32);
            Debug.Assert((uint)size < 4u);

            Operand negShiftLsB = context.Negate(shiftLsB);

            Operand isPositive = context.ICompareGreaterOrEqual(shiftLsB, Const(0));

            Operand shl = context.ShiftLeft(op, shiftLsB);
            Operand shr = context.ShiftRightUI(op, negShiftLsB);

            Operand res = context.ConditionalSelect(isPositive, shl, shr);

            Operand isOutOfRange = context.BitwiseOr(
                context.ICompareGreaterOrEqual(shiftLsB, Const(8 << size)),
                context.ICompareGreaterOrEqual(negShiftLsB, Const(8 << size)));

            return(context.ConditionalSelect(isOutOfRange, Const(0UL), res));
        }
Esempio n. 11
0
        private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool unsigned)
        {
            if (shiftLsB.Type == OperandType.I64)
            {
                shiftLsB = context.ConvertI64ToI32(shiftLsB);
            }

            shiftLsB = context.SignExtend8(OperandType.I32, shiftLsB);
            Debug.Assert((uint)size < 4u);

            Operand negShiftLsB = context.Negate(shiftLsB);

            Operand isPositive = context.ICompareGreaterOrEqual(shiftLsB, Const(0));

            Operand shl = context.ShiftLeft(op, shiftLsB);
            Operand shr = unsigned ? context.ShiftRightUI(op, negShiftLsB) : context.ShiftRightSI(op, negShiftLsB);

            Operand res = context.ConditionalSelect(isPositive, shl, shr);

            if (unsigned)
            {
                Operand isOutOfRange = context.BitwiseOr(
                    context.ICompareGreaterOrEqual(shiftLsB, Const(8 << size)),
                    context.ICompareGreaterOrEqual(negShiftLsB, Const(8 << size)));

                return(context.ConditionalSelect(isOutOfRange, Const(op.Type, 0), res));
            }
            else
            {
                Operand isOutOfRange0 = context.ICompareGreaterOrEqual(shiftLsB, Const(8 << size));
                Operand isOutOfRangeN = context.ICompareGreaterOrEqual(negShiftLsB, Const(8 << size));

                // Also zero if shift is too negative, but value was positive.
                isOutOfRange0 = context.BitwiseOr(isOutOfRange0, context.BitwiseAnd(isOutOfRangeN, context.ICompareGreaterOrEqual(op, Const(op.Type, 0))));

                Operand min = (op.Type == OperandType.I64) ? Const(-1L) : Const(-1);

                return(context.ConditionalSelect(isOutOfRange0, Const(op.Type, 0), context.ConditionalSelect(isOutOfRangeN, min, res)));
            }
        }
Esempio n. 12
0
        public static Operand EmitLsrC(ArmEmitterContext context, Operand m, bool setCarry, Operand shift, Operand shiftIsZero)
        {
            Debug.Assert(m.Type == OperandType.I32 && shift.Type == OperandType.I32 && shiftIsZero.Type == OperandType.I32);

            Operand shiftLarge = context.ICompareGreaterOrEqual(shift, Const(32));
            Operand result     = context.ShiftRightUI(m, shift);

            if (setCarry)
            {
                EmitIfHelper(context, shiftIsZero, () =>
                {
                    Operand cOut = context.ShiftRightUI(m, context.Subtract(shift, Const(1)));

                    cOut = context.BitwiseAnd(cOut, Const(1));
                    cOut = context.ConditionalSelect(context.ICompareGreater(shift, Const(32)), Const(0), cOut);

                    SetFlag(context, PState.CFlag, cOut);
                }, false);
            }

            return(context.ConditionalSelect(shiftLarge, Const(0), result));
        }
Esempio n. 13
0
        private static Operand EmitSatQ(ArmEmitterContext context, Operand value, int eSize, bool signed)
        {
            Debug.Assert(eSize <= 32);

            long intMin = signed ? -(1L << (eSize - 1)) : 0;
            long intMax = signed ? (1L << (eSize - 1)) - 1 : (1L << eSize) - 1;

            Operand gt = context.ICompareGreater(value, Const(value.Type, intMax));
            Operand lt = context.ICompareLess(value, Const(value.Type, intMin));

            value = context.ConditionalSelect(gt, Const(value.Type, intMax), value);
            value = context.ConditionalSelect(lt, Const(value.Type, intMin), value);

            Operand lblNoSat = Label();

            context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt));

            context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));

            context.MarkLabel(lblNoSat);

            return(value);
        }
        private static Operand EmitSatQ(ArmEmitterContext context, Operand value, int eSize, bool signed)
        {
            Debug.Assert(eSize <= 32);

            long intMin = signed ? -(1L << (eSize - 1)) : 0;
            long intMax = signed ? (1L << (eSize - 1)) - 1 : (1L << eSize) - 1;

            Operand gt = context.ICompareGreater(value, Const(value.Type, intMax));
            Operand lt = context.ICompareLess(value, Const(value.Type, intMin));

            value = context.ConditionalSelect(gt, Const(value.Type, intMax), value);
            value = context.ConditionalSelect(lt, Const(value.Type, intMin), value);

            Operand lblNoSat = Label();

            context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt));

            // TODO: Set QC (to 1) on FPSCR here.

            context.MarkLabel(lblNoSat);

            return(value);
        }
Esempio n. 15
0
        private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool signed)
        {
            Debug.Assert(op.Type == OperandType.I64);
            Debug.Assert(shiftLsB.Type == OperandType.I32);
            Debug.Assert((uint)size < 4u);

            Operand negShiftLsB = context.Negate(shiftLsB);

            Operand isInRange = context.BitwiseAnd(
                context.ICompareLess(shiftLsB, Const(8 << size)),
                context.ICompareLess(negShiftLsB, Const(8 << size)));

            Operand isPositive = context.ICompareGreaterOrEqual(shiftLsB, Const(0));

            Operand shl = context.ShiftLeft(op, shiftLsB);

            Operand sarOrShr = signed
                ? context.ShiftRightSI(op, negShiftLsB)
                : context.ShiftRightUI(op, negShiftLsB);

            Operand res = context.ConditionalSelect(isPositive, shl, sarOrShr);

            if (signed)
            {
                Operand isPositive2 = context.ICompareGreaterOrEqual(op, Const(0L));

                Operand res2 = context.ConditionalSelect(isPositive2, Const(0L), Const(-1L));
                res2 = context.ConditionalSelect(isPositive, Const(0L), res2);

                return(context.ConditionalSelect(isInRange, res, res2));
            }
            else
            {
                return(context.ConditionalSelect(isInRange, res, Const(0UL)));
            }
        }
Esempio n. 16
0
        public static void Vpmin_I(ArmEmitterContext context)
        {
            OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

            if (Optimizations.UseSsse3)
            {
                EmitSsse3VectorPairwiseOp32(context, op.U ? X86PminuInstruction : X86PminsInstruction);
            }
            else
            {
                EmitVectorPairwiseOpI32(context, (op1, op2) =>
                {
                    Operand greater = op.U ? context.ICompareLessUI(op1, op2) : context.ICompareLess(op1, op2);
                    return(context.ConditionalSelect(greater, op1, op2));
                }, !op.U);
            }
        }
Esempio n. 17
0
        public static Operand GetMShiftedByReg(ArmEmitterContext context, IOpCode32AluRsReg op, bool setCarry)
        {
            Operand m           = GetIntA32(context, op.Rm);
            Operand s           = context.ZeroExtend8(OperandType.I32, GetIntA32(context, op.Rs));
            Operand shiftIsZero = context.ICompareEqual(s, Const(0));

            Operand zeroResult  = m;
            Operand shiftResult = m;

            setCarry &= ShouldSetFlags(context);

            switch (op.ShiftType)
            {
            case ShiftType.Lsl: shiftResult = EmitLslC(context, m, setCarry, s, shiftIsZero); break;

            case ShiftType.Lsr: shiftResult = EmitLsrC(context, m, setCarry, s, shiftIsZero); break;

            case ShiftType.Asr: shiftResult = EmitAsrC(context, m, setCarry, s, shiftIsZero); break;

            case ShiftType.Ror: shiftResult = EmitRorC(context, m, setCarry, s, shiftIsZero); break;
            }

            return(context.ConditionalSelect(shiftIsZero, zeroResult, shiftResult));
        }
Esempio n. 18
0
        private static Operand ZerosOrOnes(ArmEmitterContext context, Operand fromBool, OperandType baseType)
        {
            var ones = (baseType == OperandType.I64) ? Const(-1L) : Const(-1);

            return(context.ConditionalSelect(fromBool, ones, Const(baseType, 0L)));
        }
Esempio n. 19
0
        private static Operand EmitAbs(ArmEmitterContext context, Operand value)
        {
            Operand isPositive = context.ICompareGreaterOrEqual(value, Const(value.Type, 0));

            return(context.ConditionalSelect(isPositive, value, context.Negate(value)));
        }