예제 #1
0
        public static void EmitGenericAluStoreA32(ArmEmitterContext context, int rd, bool setFlags, Operand value)
        {
            Debug.Assert(value.Type == OperandType.I32);

            if (rd == RegisterAlias.Aarch32Pc && setFlags)
            {
                if (setFlags)
                {
                    // TODO: Load SPSR etc.
                    Operand isThumb = GetFlag(PState.TFlag);

                    Operand lblThumb = Label();

                    context.BranchIfTrue(lblThumb, isThumb);

                    // Make this count as a call, the translator will ignore the low bit for the address.
                    context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseOr(context.BitwiseAnd(value, Const(~3)), Const(1))));

                    context.MarkLabel(lblThumb);

                    context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseOr(value, Const(1))));
                }
                else
                {
                    EmitAluWritePc(context, value);
                }
            }
            else
            {
                SetIntA32(context, rd, value);
            }
        }
예제 #2
0
        private static Operand EmitReverseBits8Op(ArmEmitterContext context, Operand op)
        {
            Debug.Assert(op.Type == OperandType.I64);

            Operand val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xaaul)), Const(1)),
                                            context.ShiftLeft(context.BitwiseAnd(op, Const(0x55ul)), Const(1)));

            val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xccul)), Const(2)),
                                    context.ShiftLeft(context.BitwiseAnd(val, Const(0x33ul)), Const(2)));

            return(context.BitwiseOr(context.ShiftRightUI(val, Const(4)),
                                     context.ShiftLeft(context.BitwiseAnd(val, Const(0x0ful)), Const(4))));
        }
예제 #3
0
        private static void EmitGetNzcv(ArmEmitterContext context)
        {
            OpCodeSystem op = (OpCodeSystem)context.CurrOp;

            Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
            Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
            Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
            Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));

            Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));

            SetIntOrZR(context, op.Rt, nzcvSh);
        }
        public static void Vrev(ArmEmitterContext context)
        {
            OpCode32Simd op = (OpCode32Simd)context.CurrOp;

            EmitVectorUnaryOpZx32(context, (op1) =>
            {
                switch (op.Opc)
                {
                case 0:
                    switch (op.Size)     // Swap bytes.
                    {
                    default:
                        return(op1);

                    case 1:
                        return(InstEmitAluHelper.EmitReverseBytes16_32Op(context, op1));

                    case 2:
                    case 3:
                        return(context.ByteSwap(op1));
                    }

                case 1:
                    switch (op.Size)
                    {
                    default:
                        return(op1);

                    case 2:
                        return(context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op1, Const(0xffff0000)), Const(16)),
                                                 context.ShiftLeft(context.BitwiseAnd(op1, Const(0x0000ffff)), Const(16))));

                    case 3:
                        return(context.BitwiseOr(
                                   context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op1, Const(0xffff000000000000ul)), Const(48)),
                                                     context.ShiftLeft(context.BitwiseAnd(op1, Const(0x000000000000fffful)), Const(48))),
                                   context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op1, Const(0x0000ffff00000000ul)), Const(16)),
                                                     context.ShiftLeft(context.BitwiseAnd(op1, Const(0x00000000ffff0000ul)), Const(16)))));
                    }

                case 2:
                    // Swap upper and lower halves.
                    return(context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op1, Const(0xffffffff00000000ul)), Const(32)),
                                             context.ShiftLeft(context.BitwiseAnd(op1, Const(0x00000000fffffffful)), Const(32))));
                }

                return(op1);
            });
        }
예제 #5
0
        private static void EmitGetFpscr(ArmEmitterContext context)
        {
            OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;

            Operand vSh = context.ShiftLeft(GetFpFlag(FPState.VFlag), Const((int)FPState.VFlag));
            Operand cSh = context.ShiftLeft(GetFpFlag(FPState.CFlag), Const((int)FPState.CFlag));
            Operand zSh = context.ShiftLeft(GetFpFlag(FPState.ZFlag), Const((int)FPState.ZFlag));
            Operand nSh = context.ShiftLeft(GetFpFlag(FPState.NFlag), Const((int)FPState.NFlag));

            Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));

            Operand fpscr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr)));

            SetIntA32(context, op.Rt, context.BitwiseOr(nzcvSh, fpscr));
        }
예제 #6
0
        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);
        }
예제 #7
0
        public static void Orr_Vi(ArmEmitterContext context)
        {
            if (Optimizations.UseSse2)
            {
                OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;

                int eSize = 8 << op.Size;

                Operand d   = GetVec(op.Rd);
                Operand imm = eSize switch {
                    16 => X86GetAllElements(context, (short)op.Immediate),
                    32 => X86GetAllElements(context, (int)op.Immediate),
                    _ => throw new InvalidOperationException($"Invalid element size {eSize}.")
                };

                Operand res = context.AddIntrinsic(Intrinsic.X86Por, d, imm);

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

                context.Copy(GetVec(op.Rd), res);
            }
            else
            {
                EmitVectorImmBinaryOp(context, (op1, op2) => context.BitwiseOr(op1, op2));
            }
        }
예제 #8
0
        public static void EmitTailContinue(ArmEmitterContext context, Operand address, bool allowRejit = false)
        {
            // Left option here as it may be useful if we need to return to managed rather than tail call in future.
            // (eg. for debug)
            bool useTailContinue = true;

            if (useTailContinue)
            {
                if (context.HighCq)
                {
                    // If we're doing a tail continue in HighCq, reserve a space in the jump table to avoid calling back
                    // to the translator. This will always try to get a HighCq version of our continue target as well.
                    EmitJumpTableBranch(context, address, true);
                }
                else
                {
                    if (allowRejit)
                    {
                        address = context.BitwiseOr(address, Const(CallFlag));
                    }

                    Operand fallbackAddr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), address);

                    EmitNativeCall(context, fallbackAddr, true);
                }
            }
            else
            {
                context.Return(address);
            }
        }
예제 #9
0
        public static void Extr(ArmEmitterContext context)
        {
            OpCodeAluRs op = (OpCodeAluRs)context.CurrOp;

            Operand res = GetIntOrZR(context, op.Rm);

            if (op.Shift != 0)
            {
                if (op.Rn == op.Rm)
                {
                    res = context.RotateRight(res, Const(op.Shift));
                }
                else
                {
                    res = context.ShiftRightUI(res, Const(op.Shift));

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

                    int invShift = op.GetBitsCount() - op.Shift;

                    res = context.BitwiseOr(res, context.ShiftLeft(n, Const(invShift)));
                }
            }

            SetAluDOrZR(context, res);
        }
예제 #10
0
        private static void EmitBranchFallback(ArmEmitterContext context, Operand address, bool isJump)
        {
            address = context.BitwiseOr(address, Const(address.Type, (long)CallFlag)); // Set call flag.
            Operand fallbackAddr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), address);

            EmitNativeCall(context, fallbackAddr, isJump);
        }
예제 #11
0
        public static Operand EmitReverseBits32Op(ArmEmitterContext context, Operand op)
        {
            Debug.Assert(op.Type == OperandType.I32);

            Operand val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xaaaaaaaau)), Const(1)),
                                            context.ShiftLeft(context.BitwiseAnd(op, Const(0x55555555u)), Const(1)));

            val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xccccccccu)), Const(2)),
                                    context.ShiftLeft(context.BitwiseAnd(val, Const(0x33333333u)), Const(2)));
            val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xf0f0f0f0u)), Const(4)),
                                    context.ShiftLeft(context.BitwiseAnd(val, Const(0x0f0f0f0fu)), Const(4)));
            val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xff00ff00u)), Const(8)),
                                    context.ShiftLeft(context.BitwiseAnd(val, Const(0x00ff00ffu)), Const(8)));

            return(context.BitwiseOr(context.ShiftRightUI(val, Const(16)), context.ShiftLeft(val, Const(16))));
        }
예제 #12
0
        public static void Sli_V(ArmEmitterContext context)
        {
            OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;

            Operand res = context.VectorZero();

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

            int shift = GetImmShl(op);

            ulong mask = shift != 0 ? ulong.MaxValue >> (64 - shift) : 0;

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

                Operand neShifted = context.ShiftLeft(ne, Const(shift));

                Operand de = EmitVectorExtractZx(context, op.Rd, index, op.Size);

                Operand deMasked = context.BitwiseAnd(de, Const(mask));

                Operand e = context.BitwiseOr(neShifted, deMasked);

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

            context.Copy(GetVec(op.Rd), res);
        }
예제 #13
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));
        }
예제 #14
0
        public static void Vmov_GD(ArmEmitterContext context)
        {
            OpCode32SimdMovGpDouble op = (OpCode32SimdMovGpDouble)context.CurrOp;

            Operand vec = GetVecA32(op.Vm >> 1);

            if (op.Op == 1)
            {
                // To general purpose.
                Operand value = context.VectorExtract(OperandType.I64, vec, op.Vm & 1);
                SetIntA32(context, op.Rt, context.ConvertI64ToI32(value));
                SetIntA32(context, op.Rt2, context.ConvertI64ToI32(context.ShiftRightUI(value, Const(32))));
            }
            else
            {
                // From general purpose.
                Operand lowValue  = GetIntA32(context, op.Rt);
                Operand highValue = GetIntA32(context, op.Rt2);

                Operand value = context.BitwiseOr(
                    context.ZeroExtend32(OperandType.I64, lowValue),
                    context.ShiftLeft(context.ZeroExtend32(OperandType.I64, highValue), Const(32)));

                context.Copy(vec, context.VectorInsert(vec, value, op.Vm & 1));
            }
        }
예제 #15
0
        public static Operand EmitReverseBytes16_64Op(ArmEmitterContext context, Operand op)
        {
            Debug.Assert(op.Type == OperandType.I64);

            return(context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xff00ff00ff00ff00ul)), Const(8)),
                                     context.ShiftLeft(context.BitwiseAnd(op, Const(0x00ff00ff00ff00fful)), Const(8))));
        }
예제 #16
0
        public static void Orn_V(ArmEmitterContext context)
        {
            if (Optimizations.UseSse2)
            {
                OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;

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

                Operand mask = X86GetAllElements(context, -1L);

                Operand res = context.AddIntrinsic(Intrinsic.X86Pandn, m, mask);

                res = context.AddIntrinsic(Intrinsic.X86Por, res, n);

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

                context.Copy(GetVec(op.Rd), res);
            }
            else
            {
                EmitVectorBinaryOpZx(context, (op1, op2) =>
                {
                    return(context.BitwiseOr(op1, context.BitwiseNot(op2)));
                });
            }
        }
예제 #17
0
        public static void EmitBxWritePc(ArmEmitterContext context, Operand pc)
        {
            Operand mode = context.BitwiseAnd(pc, Const(1));

            SetFlag(context, PState.TFlag, mode);

            Operand lblArmMode = Label();

            context.BranchIfTrue(lblArmMode, mode);

            // Make this count as a call, the translator will ignore the low bit for the address.
            context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseOr(pc, Const((int)InstEmitFlowHelper.CallFlag))));

            context.MarkLabel(lblArmMode);

            context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseOr(context.BitwiseAnd(pc, Const(~3)), Const((int)InstEmitFlowHelper.CallFlag))));
        }
예제 #18
0
        public static void EmitDynamicTableCall(ArmEmitterContext context, Operand tableAddress, Operand address, bool isJump)
        {
            // Loop over elements of the dynamic table. Unrolled loop.

            Operand endLabel      = Label();
            Operand fallbackLabel = Label();

            void EmitTableEntry(Operand entrySkipLabel)
            {
                // Try to take this entry in the table if its guest address equals 0.
                Operand gotResult = context.CompareAndSwap(tableAddress, Const(0L), address);

                // Is the address ours? (either taken via CompareAndSwap (0), or what was already here)
                context.BranchIfFalse(entrySkipLabel,
                                      context.BitwiseOr(
                                          context.ICompareEqual(gotResult, address),
                                          context.ICompareEqual(gotResult, Const(0L)))
                                      );

                // It's ours, so what function is it pointing to?
                Operand targetFunctionPtr = context.Add(tableAddress, Const(8L));
                Operand targetFunction    = context.Load(OperandType.I64, targetFunctionPtr);

                // Call the function.
                // We pass in the entry address as the guest address, as the entry may need to be updated by the
                // indirect call stub.
                EmitNativeCallWithGuestAddress(context, targetFunction, tableAddress, isJump);

                context.Branch(endLabel);
            }

            // Currently this uses a size of 1, as higher values inflate code size for no real benefit.
            for (int i = 0; i < JumpTable.DynamicTableElems; i++)
            {
                if (i == JumpTable.DynamicTableElems - 1)
                {
                    // If this is the last entry, avoid emitting the additional label and add.
                    EmitTableEntry(fallbackLabel);
                }
                else
                {
                    Operand nextLabel = Label();

                    EmitTableEntry(nextLabel);

                    context.MarkLabel(nextLabel);

                    // Move to the next table entry.
                    tableAddress = context.Add(tableAddress, Const((long)JumpTable.JumpTableStride));
                }
            }

            context.MarkLabel(fallbackLabel);

            EmitBranchFallback(context, address, isJump);

            context.MarkLabel(endLabel);
        }
예제 #19
0
        private static Operand EmitReverseBytes32_64Op(ArmEmitterContext context, Operand op)
        {
            Debug.Assert(op.Type == OperandType.I64);

            Operand val = EmitReverseBytes16_64Op(context, op);

            return(context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xffff0000ffff0000ul)), Const(16)),
                                     context.ShiftLeft(context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16))));
        }
예제 #20
0
        public static void Orn(ArmEmitterContext context)
        {
            Operand n = GetAluN(context);
            Operand m = GetAluM(context);

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

            SetAluD(context, d);
        }
예제 #21
0
        private static void EmitExtend16(ArmEmitterContext context, bool signed)
        {
            IOpCode32AluUx op = (IOpCode32AluUx)context.CurrOp;

            Operand m = GetAluM(context);
            Operand res;

            if (op.RotateBits == 0)
            {
                res = m;
            }
            else
            {
                Operand rotate = Const(op.RotateBits);
                res = context.RotateRight(m, rotate);
            }

            Operand low16, high16;

            if (signed)
            {
                low16  = context.SignExtend8(OperandType.I32, res);
                high16 = context.SignExtend8(OperandType.I32, context.ShiftRightUI(res, Const(16)));
            }
            else
            {
                low16  = context.ZeroExtend8(OperandType.I32, res);
                high16 = context.ZeroExtend8(OperandType.I32, context.ShiftRightUI(res, Const(16)));
            }

            if (op.Add)
            {
                Operand n = GetAluN(context);
                Operand lowAdd, highAdd;
                if (signed)
                {
                    lowAdd  = context.SignExtend16(OperandType.I32, n);
                    highAdd = context.SignExtend16(OperandType.I32, context.ShiftRightUI(n, Const(16)));
                }
                else
                {
                    lowAdd  = context.ZeroExtend16(OperandType.I32, n);
                    highAdd = context.ZeroExtend16(OperandType.I32, context.ShiftRightUI(n, Const(16)));
                }

                low16  = context.Add(low16, lowAdd);
                high16 = context.Add(high16, highAdd);
            }

            res = context.BitwiseOr(
                context.ZeroExtend16(OperandType.I32, low16),
                context.ShiftLeft(context.ZeroExtend16(OperandType.I32, high16), Const(16)));

            EmitAluStore(context, res);
        }
예제 #22
0
        private static void EmitSri(ArmEmitterContext context, bool scalar)
        {
            OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;

            int shift = GetImmShr(op);
            int eSize = 8 << op.Size;

            ulong mask = (ulong.MaxValue << (eSize - shift)) & (ulong.MaxValue >> (64 - eSize));

            if (Optimizations.UseSse2 && op.Size > 0)
            {
                Operand d = GetVec(op.Rd);
                Operand n = GetVec(op.Rn);

                Intrinsic srlInst = X86PsrlInstruction[op.Size];

                Operand nShifted = context.AddIntrinsic(srlInst, n, Const(shift));

                Operand dMask = X86GetAllElements(context, (long)mask * _masks_SliSri[op.Size]);

                Operand dMasked = context.AddIntrinsic(Intrinsic.X86Pand, d, dMask);

                Operand res = context.AddIntrinsic(Intrinsic.X86Por, nShifted, dMasked);

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

                context.Copy(d, res);
            }
            else
            {
                Operand res = context.VectorZero();

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

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

                    Operand neShifted = shift != 64 ? context.ShiftRightUI(ne, Const(shift)) : Const(0UL);

                    Operand de = EmitVectorExtractZx(context, op.Rd, index, op.Size);

                    Operand deMasked = context.BitwiseAnd(de, Const(mask));

                    Operand e = context.BitwiseOr(neShifted, deMasked);

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

                context.Copy(GetVec(op.Rd), res);
            }
        }
예제 #23
0
        public static void EmitAdcsCCheck(ArmEmitterContext context, Operand n, Operand d)
        {
            // C = (Rd == Rn && CIn) || Rd < Rn
            Operand cIn = GetFlag(PState.CFlag);

            Operand cOut = context.BitwiseAnd(context.ICompareEqual(d, n), cIn);

            cOut = context.BitwiseOr(cOut, context.ICompareLessUI(d, n));

            SetFlag(context, PState.CFlag, cOut);
        }
예제 #24
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.BitwiseOr(pc, Const((int)InstEmitFlowHelper.CallFlag)), context.BitwiseAnd(pc, Const(~3)));

            InstEmitFlowHelper.EmitVirtualJump(context, addr, isReturn);
        }
예제 #25
0
        public static void EmitSbcsCCheck(ArmEmitterContext context, Operand n, Operand m)
        {
            // C = (Rn == Rm && CIn) || Rn > Rm
            Operand cIn = GetFlag(PState.CFlag);

            Operand cOut = context.BitwiseAnd(context.ICompareEqual(n, m), cIn);

            cOut = context.BitwiseOr(cOut, context.ICompareGreaterUI(n, m));

            SetFlag(context, PState.CFlag, cOut);
        }
예제 #26
0
 public static void Vorr_I(ArmEmitterContext context)
 {
     if (Optimizations.UseSse2)
     {
         EmitVectorBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(Intrinsic.X86Por, n, m));
     }
     else
     {
         EmitVectorBinaryOpZx32(context, (op1, op2) => context.BitwiseOr(op1, op2));
     }
 }
예제 #27
0
        public static void Movt(ArmEmitterContext context)
        {
            OpCode32AluImm16 op = (OpCode32AluImm16)context.CurrOp;

            Operand d   = GetIntA32(context, op.Rd);
            Operand imm = Const(op.Immediate << 16); // Immeditate value as top halfword.
            Operand res = context.BitwiseAnd(d, Const(0x0000ffff));

            res = context.BitwiseOr(res, imm);

            EmitAluStore(context, res);
        }
예제 #28
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)));
            }
        }
예제 #29
0
        public static void Pkh(ArmEmitterContext context)
        {
            OpCode32AluRsImm op = (OpCode32AluRsImm)context.CurrOp;

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

            Operand res;

            bool tbform = op.ShiftType == ShiftType.Asr;

            if (tbform)
            {
                res = context.BitwiseOr(context.BitwiseAnd(n, Const(0xFFFF0000)), context.BitwiseAnd(m, Const(0xFFFF)));
            }
            else
            {
                res = context.BitwiseOr(context.BitwiseAnd(m, Const(0xFFFF0000)), context.BitwiseAnd(n, Const(0xFFFF)));
            }

            EmitAluStore(context, res);
        }
예제 #30
0
        public static void Bfm(ArmEmitterContext context)
        {
            OpCodeBfm op = (OpCodeBfm)context.CurrOp;

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

            Operand res;

            if (op.Pos < op.Shift)
            {
                // BFI.
                int shift = op.GetBitsCount() - op.Shift;

                int width = op.Pos + 1;

                long mask = (long)(ulong.MaxValue >> (64 - width));

                res = context.ShiftLeft(context.BitwiseAnd(n, Const(n.Type, mask)), Const(shift));

                res = context.BitwiseOr(res, context.BitwiseAnd(d, Const(d.Type, ~(mask << shift))));
            }
            else
            {
                // BFXIL.
                int shift = op.Shift;

                int width = op.Pos - shift + 1;

                long mask = (long)(ulong.MaxValue >> (64 - width));

                res = context.BitwiseAnd(context.ShiftRightUI(n, Const(shift)), Const(n.Type, mask));

                res = context.BitwiseOr(res, context.BitwiseAnd(d, Const(d.Type, ~mask)));
            }

            SetIntOrZR(context, op.Rd, res);
        }