コード例 #1
0
ファイル: Translator.cs プロジェクト: zhubaojian/Ryujinx
        private TranslatedSub TranslateTier0(CpuThreadState state, MemoryManager memory, long position)
        {
            Block block = Decoder.DecodeBasicBlock(state, memory, position);

            Block[] graph = new Block[] { block };

            string subName = GetSubroutineName(position);

            ILEmitterCtx context = new ILEmitterCtx(_cache, graph, block, subName);

            do
            {
                context.EmitOpCode();
            }while (context.AdvanceOpCode());

            TranslatedSub subroutine = context.GetSubroutine();

            subroutine.SetType(TranslatedSubType.SubTier0);

            _cache.AddOrUpdate(position, subroutine, block.OpCodes.Count);

            OpCode64 lastOp = block.GetLastOp();

            return(subroutine);
        }
コード例 #2
0
        public static void Blx(CpuThreadState state, MemoryManager memory, OpCode64 opCode, bool x)
        {
            A32OpCodeBImmAl op = (A32OpCodeBImmAl)opCode;

            if (IsConditionTrue(state, op.Cond))
            {
                uint pc = GetPc(state);

                if (state.Thumb)
                {
                    state.R14 = pc | 1;
                }
                else
                {
                    state.R14 = pc - 4U;
                }

                if (x)
                {
                    state.Thumb = !state.Thumb;
                }

                if (!state.Thumb)
                {
                    pc &= ~3U;
                }

                BranchWritePc(state, pc + (uint)op.Imm);
            }
        }
コード例 #3
0
        private static BasicBlock[] EmitAndGetBlocks(ILEmitterCtx context, Block[] blocks)
        {
            for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
            {
                Block block = blocks[blkIndex];

                context.CurrBlock = block;

                context.MarkLabel(context.GetLabel((long)block.Address));

                for (int opcIndex = 0; opcIndex < block.OpCodes.Count; opcIndex++)
                {
                    OpCode64 opCode = block.OpCodes[opcIndex];

                    context.CurrOp = opCode;

                    bool isLastOp = opcIndex == block.OpCodes.Count - 1;

                    if (isLastOp && block.Branch != null && block.Branch.Address <= block.Address)
                    {
                        context.EmitSynchronization();
                    }

                    ILLabel lblPredicateSkip = null;

                    if (opCode is OpCode32 op && op.Cond < Condition.Al)
                    {
                        lblPredicateSkip = new ILLabel();

                        context.EmitCondBranch(lblPredicateSkip, op.Cond.Invert());
                    }

                    opCode.Emitter(context);

                    if (lblPredicateSkip != null)
                    {
                        context.MarkLabel(lblPredicateSkip);

                        context.ResetBlockStateForPredicatedOp();

                        // If this is the last op on the block, and there's no "next" block
                        // after this one, then we have to return right now, with the address
                        // of the next instruction to be executed (in the case that the condition
                        // is false, and the branch was not taken, as all basic blocks should end
                        // with some kind of branch).
                        if (isLastOp && block.Next == null)
                        {
                            context.EmitStoreContext();
                            context.EmitLdc_I8(opCode.Position + opCode.OpCodeSizeInBytes);

                            context.Emit(OpCodes.Ret);
                        }
                    }
                }
            }

            return(context.GetBlocks());
        }
コード例 #4
0
        public void TryOptMarkCondWithoutCmp()
        {
            _optOpLastCompare = CurrOp;

            InstEmitAluHelper.EmitAluLoadOpers(this);

            Stloc(CmpOptTmp2Index, VarType.Int);
            Stloc(CmpOptTmp1Index, VarType.Int);
        }
コード例 #5
0
        public void TryOptMarkCondWithoutCmp()
        {
            _optOpLastCompare = CurrOp;

            InstEmitAluHelper.EmitDataLoadOpers(this);

            Stloc(Tmp4Index, IoType.Int);
            Stloc(Tmp3Index, IoType.Int);
        }
コード例 #6
0
ファイル: Translator.cs プロジェクト: zhubaojian/Ryujinx
        private void ExecuteSubroutineA32(CpuThreadState state, MemoryManager memory)
        {
            do
            {
                OpCode64 opCode = Decoder.DecodeOpCode(state, memory, state.R15);

                opCode.Interpreter(state, memory, opCode);
            }while (state.R15 != 0 && state.Running);
        }
コード例 #7
0
        public static void B(CpuThreadState state, MemoryManager memory, OpCode64 opCode)
        {
            A32OpCodeBImmAl op = (A32OpCodeBImmAl)opCode;

            if (IsConditionTrue(state, op.Cond))
            {
                BranchWritePc(state, GetPc(state) + (uint)op.Imm);
            }
        }
コード例 #8
0
        public void EmitStflg(int index)
        {
            //Set this only if any of the NZCV flag bits were modified.
            //This is used to ensure that, when emiting a direct IL branch
            //instruction for compare + branch sequences, we're not expecting
            //to use comparison values from an old instruction, when in fact
            //the flags were already overwritten by another instruction further along.
            if (index >= (int)PState.VBit)
            {
                _optOpLastFlagSet = CurrOp;
            }

            Stloc(index, VarType.Flag);
        }
コード例 #9
0
        private void ResetBlockState()
        {
            _ilBlock = _visitedBlocks[_currBlock];

            _ilBlocks.Add(_ilBlock);

            _ilBlock.Next   = GetOrCreateILBlock(_currBlock.Next);
            _ilBlock.Branch = GetOrCreateILBlock(_currBlock.Branch);

            _opcIndex = -1;

            _optOpLastFlagSet = null;
            _optOpLastCompare = null;
        }
コード例 #10
0
        public bool AdvanceOpCode()
        {
            if (_opcIndex + 1 == CurrBlock.OpCodes.Count &&
                _blkIndex + 1 == _graph.Length)
            {
                return(false);
            }

            while (++_opcIndex >= (CurrBlock?.OpCodes.Count ?? 0))
            {
                _blkIndex++;
                _opcIndex = -1;

                _optOpLastFlagSet = null;
                _optOpLastCompare = null;

                _ilBlock = _emitter.GetIlBlock(_blkIndex);
            }

            return(true);
        }
コード例 #11
0
        public static void Und(ILEmitterCtx context)
        {
            OpCode64 op = context.CurrOp;

            context.EmitStoreState();

            context.EmitLdarg(TranslatedSub.StateArgIdx);

            context.EmitLdc_I8(op.Position);
            context.EmitLdc_I4(op.RawOpCode);

            context.EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.OnUndefined));

            if (context.CurrBlock.Next != null)
            {
                context.EmitLoadState(context.CurrBlock.Next);
            }
            else
            {
                context.EmitLdc_I8(op.Position + 4);

                context.Emit(OpCodes.Ret);
            }
        }
コード例 #12
0
        public void EmitStflg(int index)
        {
            _optOpLastFlagSet = CurrOp;

            Stloc(index, IoType.Flag);
        }
コード例 #13
0
 private void ResetBlockState()
 {
     _optOpLastFlagSet = null;
     _optOpLastCompare = null;
 }
コード例 #14
0
 public static bool IsThumb(OpCode64 op)
 {
     return(op is OpCodeT16);
 }
コード例 #15
0
 public static void Blx(CpuThreadState state, MemoryManager memory, OpCode64 opCode)
 {
     Blx(state, memory, opCode, true);
 }