コード例 #1
0
ファイル: AILEmitter.cs プロジェクト: zamil2200/Ryujinx
        public AILEmitter(ABlock[] Graph, ABlock Root, string SubName)
        {
            this.SubName = SubName;

            Locals = new Dictionary <ARegister, int>();

            ILBlocks = new AILBlock[Graph.Length];

            AILBlock GetBlock(int Index)
            {
                if (Index < 0 || Index >= ILBlocks.Length)
                {
                    return(null);
                }

                if (ILBlocks[Index] == null)
                {
                    ILBlocks[Index] = new AILBlock();
                }

                return(ILBlocks[Index]);
            }

            for (int Index = 0; Index < ILBlocks.Length; Index++)
            {
                AILBlock Block = GetBlock(Index);

                Block.Next   = GetBlock(Array.IndexOf(Graph, Graph[Index].Next));
                Block.Branch = GetBlock(Array.IndexOf(Graph, Graph[Index].Branch));
            }

            this.Root = ILBlocks[Array.IndexOf(Graph, Root)];
        }
コード例 #2
0
            public long GetInputs(AILBlock Root)
            {
                if (AllInputs.TryGetValue(Root, out long Inputs))
                {
                    return(Inputs | (AllOutputs & ~CmnOutputs[Root]));
                }

                return(0);
            }
コード例 #3
0
        private long GetInputsImpl(AILBlock Root, IEnumerable <PathIo> Values)
        {
            long Inputs = 0;

            foreach (PathIo Path in Values)
            {
                Inputs |= Path.GetInputs(Root);
            }

            return(Inputs);
        }
コード例 #4
0
        public ALocalAlloc(AILBlock[] Graph, AILBlock Root)
        {
            IntPaths = new Dictionary <AILBlock, PathIo>();
            VecPaths = new Dictionary <AILBlock, PathIo>();

            if (Graph.Length < MaxOptGraphLength)
            {
                InitializeOptimal(Graph, Root);
            }
            else
            {
                InitializeFast(Graph);
            }
        }
コード例 #5
0
            public void Set(AILBlock Root, long Inputs, long Outputs)
            {
                if (!AllInputs.TryAdd(Root, Inputs))
                {
                    AllInputs[Root] |= Inputs;
                }

                if (!CmnOutputs.TryAdd(Root, Outputs))
                {
                    CmnOutputs[Root] &= Outputs;
                }

                AllOutputs |= Outputs;
            }
コード例 #6
0
        public bool AdvanceOpCode()
        {
            while (++OpcIndex >= (CurrBlock?.OpCodes.Count ?? 0))
            {
                if (BlkIndex + 1 >= Graph.Length)
                {
                    return(false);
                }

                BlkIndex++;
                OpcIndex = -1;

                ILBlock = Emitter.GetILBlock(BlkIndex);
            }

            return(true);
        }
コード例 #7
0
ファイル: AILEmitterCtx.cs プロジェクト: andrewphb/Ryujinx
        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);
        }
コード例 #8
0
        public AILEmitterCtx(ATranslator Translator, ABlock[] Graph, ABlock Root)
        {
            this.Translator = Translator;
            this.Graph      = Graph;
            this.Root       = Root;

            string SubName = $"Sub{Root.Position:X16}";

            Labels = new Dictionary <long, AILLabel>();

            Emitter = new AILEmitter(Graph, Root, SubName);

            ILBlock = Emitter.GetILBlock(0);

            OpcIndex = -1;

            if (!AdvanceOpCode())
            {
                throw new ArgumentException(nameof(Graph));
            }
        }
コード例 #9
0
ファイル: AILEmitterCtx.cs プロジェクト: ckarcz/Ryujinx
        public AILEmitterCtx(
            ATranslator Translator,
            ABlock[]    Graph,
            ABlock Root,
            string SubName)
        {
            if (Translator == null)
            {
                throw new ArgumentNullException(nameof(Translator));
            }

            if (Graph == null)
            {
                throw new ArgumentNullException(nameof(Graph));
            }

            if (Root == null)
            {
                throw new ArgumentNullException(nameof(Root));
            }

            this.Translator = Translator;
            this.Graph      = Graph;
            this.Root       = Root;

            Callees = new HashSet <long>();

            Labels = new Dictionary <long, AILLabel>();

            Emitter = new AILEmitter(Graph, Root, SubName);

            ILBlock = Emitter.GetILBlock(0);

            OpcIndex = -1;

            if (Graph.Length == 0 || !AdvanceOpCode())
            {
                throw new ArgumentException(nameof(Graph));
            }
        }
コード例 #10
0
ファイル: AILEmitterCtx.cs プロジェクト: andrewphb/Ryujinx
        public AILEmitterCtx(
            ATranslatorCache Cache,
            ABlock[]         Graph,
            ABlock Root,
            string SubName)
        {
            this.Cache = Cache ?? throw new ArgumentNullException(nameof(Cache));
            this.Graph = Graph ?? throw new ArgumentNullException(nameof(Graph));
            this.Root  = Root ?? throw new ArgumentNullException(nameof(Root));

            Labels = new Dictionary <long, AILLabel>();

            Emitter = new AILEmitter(Graph, Root, SubName);

            ILBlock = Emitter.GetILBlock(0);

            OpcIndex = -1;

            if (Graph.Length == 0 || !AdvanceOpCode())
            {
                throw new ArgumentException(nameof(Graph));
            }
        }
コード例 #11
0
        private void InitializeOptimal(AILBlock[] Graph, AILBlock Root)
        {
            //This will go through all possible paths on the graph,
            //and store all inputs/outputs for each block. A register
            //that was previously written to already is not considered an input.
            //When a block can be reached by more than one path, then the
            //output from all paths needs to be set for this block, and
            //only outputs present in all of the parent blocks can be considered
            //when doing input elimination. Each block chain have a root, that's where
            //the code starts executing. They are present on the subroutine start point,
            //and on call return points too (address written to X30 by BL).
            HashSet <BlockIo> Visited = new HashSet <BlockIo>();

            Queue <BlockIo> Unvisited = new Queue <BlockIo>();

            void Enqueue(BlockIo Block)
            {
                if (!Visited.Contains(Block))
                {
                    Unvisited.Enqueue(Block);

                    Visited.Add(Block);
                }
            }

            Enqueue(new BlockIo()
            {
                Block = Root,
                Entry = Root
            });

            while (Unvisited.Count > 0)
            {
                BlockIo Current = Unvisited.Dequeue();

                Current.IntInputs  |= Current.Block.IntInputs & ~Current.IntOutputs;
                Current.VecInputs  |= Current.Block.VecInputs & ~Current.VecOutputs;
                Current.IntOutputs |= Current.Block.IntOutputs;
                Current.VecOutputs |= Current.Block.VecOutputs;

                //Check if this is a exit block
                //(a block that returns or calls another sub).
                if ((Current.Block.Next == null &&
                     Current.Block.Branch == null) || Current.Block.HasStateStore)
                {
                    if (!IntPaths.TryGetValue(Current.Block, out PathIo IntPath))
                    {
                        IntPaths.Add(Current.Block, IntPath = new PathIo());
                    }

                    if (!VecPaths.TryGetValue(Current.Block, out PathIo VecPath))
                    {
                        VecPaths.Add(Current.Block, VecPath = new PathIo());
                    }

                    IntPath.Set(Current.Entry, Current.IntInputs, Current.IntOutputs);
                    VecPath.Set(Current.Entry, Current.VecInputs, Current.VecOutputs);
                }

                void EnqueueFromCurrent(AILBlock Block, bool RetTarget)
                {
                    BlockIo BlkIO = new BlockIo()
                    {
                        Block = Block
                    };

                    if (RetTarget)
                    {
                        BlkIO.Entry = Block;
                    }
                    else
                    {
                        BlkIO.Entry      = Current.Entry;
                        BlkIO.IntInputs  = Current.IntInputs;
                        BlkIO.VecInputs  = Current.VecInputs;
                        BlkIO.IntOutputs = Current.IntOutputs;
                        BlkIO.VecOutputs = Current.VecOutputs;
                    }

                    Enqueue(BlkIO);
                }

                if (Current.Block.Next != null)
                {
                    EnqueueFromCurrent(Current.Block.Next, Current.Block.HasStateStore);
                }

                if (Current.Block.Branch != null)
                {
                    EnqueueFromCurrent(Current.Block.Branch, false);
                }
            }
        }
コード例 #12
0
 public long GetVecOutputs(AILBlock Block) => VecPaths[Block].GetOutputs();
コード例 #13
0
 public long GetIntOutputs(AILBlock Block) => IntPaths[Block].GetOutputs();
コード例 #14
0
 public long GetVecInputs(AILBlock Root) => GetInputsImpl(Root, VecPaths.Values);
コード例 #15
0
 public long GetIntInputs(AILBlock Root) => GetInputsImpl(Root, IntPaths.Values);
コード例 #16
0
 public PathIo(AILBlock Root, long Inputs, long Outputs) : this()
 {
     Set(Root, Inputs, Outputs);
 }