Пример #1
0
        public static void EmitSubsVCheck(ArmEmitterContext context, Operand n, Operand m, Operand d)
        {
            // V = (Rd ^ Rn) & (Rn ^ Rm) < 0
            Operand vOut = context.BitwiseExclusiveOr(d, n);

            vOut = context.BitwiseAnd(vOut, context.BitwiseExclusiveOr(n, m));

            vOut = context.ICompareLess(vOut, Const(vOut.Type, 0));

            SetFlag(context, PState.VFlag, vOut);
        }
Пример #2
0
        private static void EmitSat16(ArmEmitterContext context, int intMin, int intMax)
        {
            OpCode32Sat16 op = (OpCode32Sat16)context.CurrOp;

            void SetD(int part, Operand value)
            {
                if (part == 0)
                {
                    SetIntA32(context, op.Rd, context.ZeroExtend16(OperandType.I32, value));
                }
                else
                {
                    SetIntA32(context, op.Rd, context.BitwiseOr(GetIntA32(context, op.Rd), context.ShiftLeft(value, Const(16))));
                }
            }

            Operand n = GetIntA32(context, op.Rn);

            Operand nLow  = context.SignExtend16(OperandType.I32, n);
            Operand nHigh = context.ShiftRightSI(n, Const(16));

            for (int part = 0; part < 2; part++)
            {
                Operand nPart = part == 0 ? nLow : nHigh;

                Operand lblCheckLtIntMin = Label();
                Operand lblNoSat         = Label();
                Operand lblEnd           = Label();

                context.BranchIfFalse(lblCheckLtIntMin, context.ICompareGreater(nPart, Const(intMax)));

                SetFlag(context, PState.QFlag, Const(1));
                SetD(part, Const(intMax));
                context.Branch(lblEnd);

                context.MarkLabel(lblCheckLtIntMin);
                context.BranchIfFalse(lblNoSat, context.ICompareLess(nPart, Const(intMin)));

                SetFlag(context, PState.QFlag, Const(1));
                SetD(part, Const(intMin));
                context.Branch(lblEnd);

                context.MarkLabel(lblNoSat);

                SetD(part, nPart);

                context.MarkLabel(lblEnd);
            }
        }
Пример #3
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)));
            }
        }
Пример #4
0
        private static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblSlowPath)
        {
            int ptLevelBits = context.Memory.AddressSpaceBits - 12; // 12 = Number of page bits.
            int ptLevelSize = 1 << ptLevelBits;
            int ptLevelMask = ptLevelSize - 1;

            Operand pte = Ptc.State == PtcState.Disabled
                ? Const(context.Memory.PageTablePointer.ToInt64())
                : Const(context.Memory.PageTablePointer.ToInt64(), true, Ptc.PageTablePointerIndex);

            int bit = PageBits;

            do
            {
                Operand addrPart = context.ShiftRightUI(address, Const(bit));

                bit += ptLevelBits;

                if (bit < context.Memory.AddressSpaceBits)
                {
                    addrPart = context.BitwiseAnd(addrPart, Const(addrPart.Type, ptLevelMask));
                }

                Operand pteOffset = context.ShiftLeft(addrPart, Const(3));

                if (pteOffset.Type == OperandType.I32)
                {
                    pteOffset = context.ZeroExtend32(OperandType.I64, pteOffset);
                }

                Operand pteAddress = context.Add(pte, pteOffset);

                pte = context.Load(OperandType.I64, pteAddress);
            }while (bit < context.Memory.AddressSpaceBits);

            context.BranchIfTrue(lblSlowPath, context.ICompareLess(pte, Const(0L)));

            Operand pageOffset = context.BitwiseAnd(address, Const(address.Type, PageMask));

            if (pageOffset.Type == OperandType.I32)
            {
                pageOffset = context.ZeroExtend32(OperandType.I64, pageOffset);
            }

            return(context.Add(pte, pageOffset));
        }
Пример #5
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);
            }
        }
Пример #6
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);
        }
Пример #7
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));

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

            context.MarkLabel(lblNoSat);

            return(value);
        }
Пример #8
0
        public static void Cmlt_V(ArmEmitterContext context)
        {
            if (Optimizations.UseSse42)
            {
                OpCodeSimd op = (OpCodeSimd)context.CurrOp;

                Operand n = GetVec(op.Rn);

                Intrinsic cmpInst = X86PcmpgtInstruction[op.Size];

                Operand res = context.AddIntrinsic(cmpInst, context.VectorZero(), n);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    res = context.VectorZeroUpper64(res);
                }

                context.Copy(GetVec(op.Rd), res);
            }
            else
            {
                EmitCmpOp(context, (op1, op2) => context.ICompareLess(op1, op2), scalar: false);
            }
        }
Пример #9
0
 public static void EmitNZFlagsCheck(ArmEmitterContext context, Operand d)
 {
     SetFlag(context, PState.NFlag, context.ICompareLess(d, Const(d.Type, 0)));
     SetFlag(context, PState.ZFlag, context.ICompareEqual(d, Const(d.Type, 0)));
 }
Пример #10
0
 public static void Cmlt_S(ArmEmitterContext context)
 {
     EmitCmpOp(context, (op1, op2) => context.ICompareLess(op1, op2), scalar: true);
 }
Пример #11
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));
            }
        }