コード例 #1
0
ファイル: InstEmitAlu32.cs プロジェクト: lalalaring/Ryujinx
        private static void EmitHsub8(ArmEmitterContext context, bool unsigned)
        {
            OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;

            Operand m = GetIntA32(context, op.Rm);
            Operand n = GetIntA32(context, op.Rn);
            Operand left, right, carry, res;

            // This relies on the equality x-y == (x^y) - (((x^y)&y) << 1).
            // Note that x^y always contains the LSB of the result.
            // Since we want to calculate (x+y)/2, we can instead calculate ((x^y)>>1) - ((x^y)&y).

            carry = context.BitwiseExclusiveOr(m, n);
            left  = context.ShiftRightUI(carry, Const(1));
            right = context.BitwiseAnd(carry, m);

            // We must now perform a partitioned subtraction.
            // We can do this because minuend contains 7 bit fields.
            // We use the extra bit in minuend as a bit to borrow from; we set this bit.
            // We invert this bit at the end as this tells us if that bit was borrowed from.

            res = context.BitwiseOr(left, Const(0x80808080));
            res = context.Subtract(res, right);
            res = context.BitwiseExclusiveOr(res, Const(0x80808080));

            if (!unsigned)
            {
                // We then sign extend the result into this bit.
                carry = context.BitwiseAnd(carry, Const(0x80808080));
                res   = context.BitwiseExclusiveOr(res, carry);
            }

            SetIntA32(context, op.Rd, res);
        }
コード例 #2
0
        public static void Bsl_V(ArmEmitterContext context)
        {
            if (Optimizations.UseSse2)
            {
                OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;

                Operand d = GetVec(op.Rd);
                Operand n = GetVec(op.Rn);
                Operand m = GetVec(op.Rm);

                Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, m);

                res = context.AddIntrinsic(Intrinsic.X86Pand, res, d);
                res = context.AddIntrinsic(Intrinsic.X86Pxor, res, m);

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

                context.Copy(GetVec(op.Rd), res);
            }
            else
            {
                EmitVectorTernaryOpZx(context, (op1, op2, op3) =>
                {
                    return(context.BitwiseExclusiveOr(
                               context.BitwiseAnd(op1,
                                                  context.BitwiseExclusiveOr(op2, op3)), op3));
                });
            }
        }
コード例 #3
0
        private static void EmitHadd8(ArmEmitterContext context, bool unsigned)
        {
            OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;

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

            Operand xor, res, carry;

            // This relies on the equality x+y == ((x&y) << 1) + (x^y).
            // Note that x^y always contains the LSB of the result.
            // Since we want to calculate (x+y)/2, we can instead calculate (x&y) + ((x^y)>>1).
            // We mask by 0x7F to remove the LSB so that it doesn't leak into the field below.

            res   = context.BitwiseAnd(m, n);
            carry = context.BitwiseExclusiveOr(m, n);
            xor   = context.ShiftRightUI(carry, Const(1));
            xor   = context.BitwiseAnd(xor, Const(0x7F7F7F7Fu));
            res   = context.Add(res, xor);

            if (!unsigned)
            {
                // Propagates the sign bit from (x^y)>>1 upwards by one.
                carry = context.BitwiseAnd(carry, Const(0x80808080u));
                res   = context.BitwiseExclusiveOr(res, carry);
            }

            SetIntA32(context, op.Rd, res);
        }
コード例 #4
0
        private static void EmitBifBit(ArmEmitterContext context, bool notRm)
        {
            OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

            if (Optimizations.UseSse2)
            {
                EmitVectorTernaryOpSimd32(context, (d, n, m) =>
                {
                    Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, d);
                    res         = context.AddIntrinsic((notRm) ? Intrinsic.X86Pandn : Intrinsic.X86Pand, m, res);
                    return(context.AddIntrinsic(Intrinsic.X86Pxor, d, res));
                });
            }
            else
            {
                EmitVectorTernaryOpZx32(context, (d, n, m) =>
                {
                    if (notRm)
                    {
                        m = context.BitwiseNot(m);
                    }
                    return(context.BitwiseExclusiveOr(
                               context.BitwiseAnd(m,
                                                  context.BitwiseExclusiveOr(d, n)), d));
                });
            }
        }
コード例 #5
0
        private static void EmitBifBit(ArmEmitterContext context, bool notRm)
        {
            OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;

            if (Optimizations.UseSse2)
            {
                Operand d = GetVec(op.Rd);
                Operand n = GetVec(op.Rn);
                Operand m = GetVec(op.Rm);

                Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, d);

                if (notRm)
                {
                    res = context.AddIntrinsic(Intrinsic.X86Pandn, m, res);
                }
                else
                {
                    res = context.AddIntrinsic(Intrinsic.X86Pand, m, res);
                }

                res = context.AddIntrinsic(Intrinsic.X86Pxor, d, res);

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

                context.Copy(GetVec(op.Rd), res);
            }
            else
            {
                Operand res = context.VectorZero();

                int elems = op.RegisterSize == RegisterSize.Simd128 ? 2 : 1;

                for (int index = 0; index < elems; index++)
                {
                    Operand d = EmitVectorExtractZx(context, op.Rd, index, 3);
                    Operand n = EmitVectorExtractZx(context, op.Rn, index, 3);
                    Operand m = EmitVectorExtractZx(context, op.Rm, index, 3);

                    if (notRm)
                    {
                        m = context.BitwiseNot(m);
                    }

                    Operand e = context.BitwiseExclusiveOr(d, n);

                    e = context.BitwiseAnd(e, m);
                    e = context.BitwiseExclusiveOr(e, d);

                    res = EmitVectorInsert(context, res, e, index, 3);
                }

                context.Copy(GetVec(op.Rd), res);
            }
        }
コード例 #6
0
 public static void Vbsl(ArmEmitterContext context)
 {
     EmitVectorTernaryOpZx32(context, (op1, op2, op3) =>
     {
         return(context.BitwiseExclusiveOr(
                    context.BitwiseAnd(op1,
                                       context.BitwiseExclusiveOr(op2, op3)), op3));
     });
 }
コード例 #7
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);
        }
コード例 #8
0
        private static void EmitBifBit(ArmEmitterContext context, bool notRm)
        {
            OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

            EmitVectorTernaryOpZx32(context, (d, n, m) =>
            {
                if (notRm)
                {
                    m = context.BitwiseNot(m);
                }
                return(context.BitwiseExclusiveOr(
                           context.BitwiseAnd(m,
                                              context.BitwiseExclusiveOr(d, n)), d));
            });
        }
コード例 #9
0
        private static void EmitSbc(ArmEmitterContext context, bool setFlags)
        {
            Operand n = GetAluN(context);
            Operand m = GetAluM(context);

            Operand d = context.Subtract(n, m);

            Operand borrow = context.BitwiseExclusiveOr(GetFlag(PState.CFlag), Const(1));

            if (context.CurrOp.RegisterSize == RegisterSize.Int64)
            {
                borrow = context.ZeroExtend32(OperandType.I64, borrow);
            }

            d = context.Subtract(d, borrow);

            if (setFlags)
            {
                EmitNZFlagsCheck(context, d);

                EmitSbcsCCheck(context, n, m);
                EmitSubsVCheck(context, n, m, d);
            }

            SetAluDOrZR(context, d);
        }
コード例 #10
0
        public static void Eon(ArmEmitterContext context)
        {
            Operand n = GetAluN(context);
            Operand m = GetAluM(context);

            Operand d = context.BitwiseExclusiveOr(n, context.BitwiseNot(m));

            SetAluD(context, d);
        }
コード例 #11
0
        public static void Teq(ArmEmitterContext context)
        {
            Operand n = GetAluN(context);
            Operand m = GetAluM(context);

            Operand res = context.BitwiseExclusiveOr(n, m);

            EmitNZFlagsCheck(context, res);
        }
コード例 #12
0
 public static void Veor_I(ArmEmitterContext context)
 {
     if (Optimizations.UseSse2)
     {
         EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.X86Pxor, n, m));
     }
     else
     {
         EmitVectorBinaryOpZx32(context, (op1, op2) => context.BitwiseExclusiveOr(op1, op2));
     }
 }
コード例 #13
0
 public static void Vbsl(ArmEmitterContext context)
 {
     if (Optimizations.UseSse2)
     {
         EmitVectorTernaryOpSimd32(context, (d, n, m) =>
         {
             Operand res = context.AddIntrinsic(Intrinsic.X86Pxor, n, m);
             res         = context.AddIntrinsic(Intrinsic.X86Pand, res, d);
             return(context.AddIntrinsic(Intrinsic.X86Pxor, res, m));
         });
     }
     else
     {
         EmitVectorTernaryOpZx32(context, (op1, op2, op3) =>
         {
             return(context.BitwiseExclusiveOr(
                        context.BitwiseAnd(op1,
                                           context.BitwiseExclusiveOr(op2, op3)), op3));
         });
     }
 }
コード例 #14
0
        public static void Eor(ArmEmitterContext context)
        {
            IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;

            Operand n = GetAluN(context);
            Operand m = GetAluM(context);

            Operand res = context.BitwiseExclusiveOr(n, m);

            if (op.SetFlags)
            {
                EmitNZFlagsCheck(context, res);
            }

            EmitAluStore(context, res);
        }
コード例 #15
0
ファイル: InstEmitAlu32.cs プロジェクト: rubikex/Ryujinx
        public static void Uhadd8(ArmEmitterContext context)
        {
            OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;

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

            Operand xor, res;

            res = context.BitwiseAnd(m, n);
            xor = context.BitwiseExclusiveOr(m, n);
            xor = context.ShiftRightUI(xor, Const(1));
            xor = context.BitwiseAnd(xor, Const(0x7F7F7F7Fu));
            res = context.Add(res, xor);

            SetIntA32(context, op.Rd, res);
        }
コード例 #16
0
        public static void Cls(ArmEmitterContext context)
        {
            OpCodeAlu op = (OpCodeAlu)context.CurrOp;

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

            Operand nHigh = context.ShiftRightUI(n, Const(1));

            bool is32Bits = op.RegisterSize == RegisterSize.Int32;

            Operand mask = is32Bits ? Const(int.MaxValue) : Const(long.MaxValue);

            Operand nLow = context.BitwiseAnd(n, mask);

            Operand res = context.CountLeadingZeros(context.BitwiseExclusiveOr(nHigh, nLow));

            res = context.Subtract(res, Const(res.Type, 1));

            SetAluDOrZR(context, res);
        }
コード例 #17
0
        public static Operand EmitPolynomialMultiply(ArmEmitterContext context, Operand op1, Operand op2, int eSize)
        {
            Debug.Assert(eSize <= 32);

            Operand result = eSize == 32 ? Const(0L) : Const(0);

            if (eSize == 32)
            {
                op1 = context.ZeroExtend32(OperandType.I64, op1);
                op2 = context.ZeroExtend32(OperandType.I64, op2);
            }

            for (int i = 0; i < eSize; i++)
            {
                Operand mask = context.BitwiseAnd(op1, Const(op1.Type, 1L << i));

                result = context.BitwiseExclusiveOr(result, context.Multiply(op2, mask));
            }

            return(result);
        }
コード例 #18
0
        public static void Sbc(ArmEmitterContext context)
        {
            IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;

            Operand n = GetAluN(context);
            Operand m = GetAluM(context, setCarry: false);

            Operand res = context.Subtract(n, m);

            Operand borrow = context.BitwiseExclusiveOr(GetFlag(PState.CFlag), Const(1));

            res = context.Subtract(res, borrow);

            if (op.SetFlags)
            {
                EmitNZFlagsCheck(context, res);

                EmitSbcsCCheck(context, n, m);
                EmitSubsVCheck(context, n, m, res);
            }

            EmitAluStore(context, res);
        }
コード例 #19
0
        private static void EmitSse41ConvertInt32(ArmEmitterContext context, FPRoundingMode roundMode, bool signed)
        {
            // A port of the similar round function in InstEmitSimdCvt.
            OpCode32SimdCvtFI op = (OpCode32SimdCvtFI)context.CurrOp;

            bool    doubleSize = (op.Size & 1) != 0;
            int     shift      = doubleSize ? 1 : 2;
            Operand n          = GetVecA32(op.Vm >> shift);

            n = EmitSwapScalar(context, n, op.Vm, doubleSize);

            if (!doubleSize)
            {
                Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpss, n, n, Const((int)CmpCondition.OrderedQ));
                nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);

                nRes = context.AddIntrinsic(Intrinsic.X86Roundss, nRes, Const(X86GetRoundControl(roundMode)));

                Operand zero = context.VectorZero();

                Operand nCmp;
                Operand nIntOrLong2 = default;

                if (!signed)
                {
                    nCmp = context.AddIntrinsic(Intrinsic.X86Cmpss, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
                    nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
                }

                int fpMaxVal = 0x4F000000; // 2.14748365E9f (2147483648)

                Operand fpMaxValMask = X86GetScalar(context, fpMaxVal);

                Operand nIntOrLong = context.AddIntrinsicInt(Intrinsic.X86Cvtss2si, nRes);

                if (!signed)
                {
                    nRes = context.AddIntrinsic(Intrinsic.X86Subss, nRes, fpMaxValMask);

                    nCmp = context.AddIntrinsic(Intrinsic.X86Cmpss, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
                    nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);

                    nIntOrLong2 = context.AddIntrinsicInt(Intrinsic.X86Cvtss2si, nRes);
                }

                nRes = context.AddIntrinsic(Intrinsic.X86Cmpss, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));

                Operand nInt = context.AddIntrinsicInt(Intrinsic.X86Cvtsi2si, nRes);

                Operand dRes;
                if (signed)
                {
                    dRes = context.BitwiseExclusiveOr(nIntOrLong, nInt);
                }
                else
                {
                    dRes = context.BitwiseExclusiveOr(nIntOrLong2, nInt);
                    dRes = context.Add(dRes, nIntOrLong);
                }

                InsertScalar(context, op.Vd, dRes);
            }
            else
            {
                Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpsd, n, n, Const((int)CmpCondition.OrderedQ));
                nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);

                nRes = context.AddIntrinsic(Intrinsic.X86Roundsd, nRes, Const(X86GetRoundControl(roundMode)));

                Operand zero = context.VectorZero();

                Operand nCmp;
                Operand nIntOrLong2 = default;

                if (!signed)
                {
                    nCmp = context.AddIntrinsic(Intrinsic.X86Cmpsd, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
                    nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
                }

                long fpMaxVal = 0x41E0000000000000L; // 2147483648.0000000d (2147483648)

                Operand fpMaxValMask = X86GetScalar(context, fpMaxVal);

                Operand nIntOrLong = context.AddIntrinsicInt(Intrinsic.X86Cvtsd2si, nRes);

                if (!signed)
                {
                    nRes = context.AddIntrinsic(Intrinsic.X86Subsd, nRes, fpMaxValMask);

                    nCmp = context.AddIntrinsic(Intrinsic.X86Cmpsd, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
                    nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);

                    nIntOrLong2 = context.AddIntrinsicInt(Intrinsic.X86Cvtsd2si, nRes);
                }

                nRes = context.AddIntrinsic(Intrinsic.X86Cmpsd, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));

                Operand nLong = context.AddIntrinsicLong(Intrinsic.X86Cvtsi2si, nRes);
                nLong = context.ConvertI64ToI32(nLong);

                Operand dRes;
                if (signed)
                {
                    dRes = context.BitwiseExclusiveOr(nIntOrLong, nLong);
                }
                else
                {
                    dRes = context.BitwiseExclusiveOr(nIntOrLong2, nLong);
                    dRes = context.Add(dRes, nIntOrLong);
                }

                InsertScalar(context, op.Vd, dRes);
            }
        }
コード例 #20
0
ファイル: InstEmitFlowHelper.cs プロジェクト: venhow/Ryujinx
        public static Operand GetCondTrue(ArmEmitterContext context, Condition condition)
        {
            Operand cmpResult = context.TryGetComparisonResult(condition);

            if (cmpResult != null)
            {
                return(cmpResult);
            }

            Operand value = Const(1);

            Operand Inverse(Operand val)
            {
                return(context.BitwiseExclusiveOr(val, Const(1)));
            }

            switch (condition)
            {
            case Condition.Eq:
                value = GetFlag(PState.ZFlag);
                break;

            case Condition.Ne:
                value = Inverse(GetFlag(PState.ZFlag));
                break;

            case Condition.GeUn:
                value = GetFlag(PState.CFlag);
                break;

            case Condition.LtUn:
                value = Inverse(GetFlag(PState.CFlag));
                break;

            case Condition.Mi:
                value = GetFlag(PState.NFlag);
                break;

            case Condition.Pl:
                value = Inverse(GetFlag(PState.NFlag));
                break;

            case Condition.Vs:
                value = GetFlag(PState.VFlag);
                break;

            case Condition.Vc:
                value = Inverse(GetFlag(PState.VFlag));
                break;

            case Condition.GtUn:
            {
                Operand c = GetFlag(PState.CFlag);
                Operand z = GetFlag(PState.ZFlag);

                value = context.BitwiseAnd(c, Inverse(z));

                break;
            }

            case Condition.LeUn:
            {
                Operand c = GetFlag(PState.CFlag);
                Operand z = GetFlag(PState.ZFlag);

                value = context.BitwiseOr(Inverse(c), z);

                break;
            }

            case Condition.Ge:
            {
                Operand n = GetFlag(PState.NFlag);
                Operand v = GetFlag(PState.VFlag);

                value = context.ICompareEqual(n, v);

                break;
            }

            case Condition.Lt:
            {
                Operand n = GetFlag(PState.NFlag);
                Operand v = GetFlag(PState.VFlag);

                value = context.ICompareNotEqual(n, v);

                break;
            }

            case Condition.Gt:
            {
                Operand n = GetFlag(PState.NFlag);
                Operand z = GetFlag(PState.ZFlag);
                Operand v = GetFlag(PState.VFlag);

                value = context.BitwiseAnd(Inverse(z), context.ICompareEqual(n, v));

                break;
            }

            case Condition.Le:
            {
                Operand n = GetFlag(PState.NFlag);
                Operand z = GetFlag(PState.ZFlag);
                Operand v = GetFlag(PState.VFlag);

                value = context.BitwiseOr(z, context.ICompareNotEqual(n, v));

                break;
            }
            }

            return(value);
        }
コード例 #21
0
 public static void Vmvn_I(ArmEmitterContext context)
 {
     EmitVectorImmUnaryOp32(context, (op1) => context.BitwiseExclusiveOr(op1, op1));
 }
コード例 #22
0
 public static void Eor(ArmEmitterContext context)
 {
     SetAluD(context, context.BitwiseExclusiveOr(GetAluN(context), GetAluM(context)));
 }