CSPspEmu.Core.Cpu.Dynarec.DynarecFunctionCompiler.InternalFunctionCompiler.AnalyzeBranches C# (CSharp) Method

AnalyzeBranches() private method

PASS 1: Analyze Branches
private AnalyzeBranches ( ) : void
return void
            private void AnalyzeBranches()
            {
                SkipPC = new HashSet<uint>();
                AnalyzedPC = new HashSet<uint>();
                var BranchesToAnalyze = new Queue<uint>();

                Labels[EntryPC] = AstLabel.CreateLabel("EntryPoint");

                uint EndPC = (uint)InstructionReader.EndPC;
                PC = EntryPC;
                MinPC = uint.MaxValue;
                MaxPC = uint.MinValue;

                BranchesToAnalyze.Enqueue(EntryPC);

                while (true)
                {
                HandleNewBranch: ;
                    bool EndOfBranchFound = false;

                    if (BranchesToAnalyze.Count == 0) break;

                    for (PC = BranchesToAnalyze.Dequeue(); PC <= EndPC; PC += 4)
                    {
                        // If already analyzed, stop scanning this branch.
                        if (AnalyzedPC.Contains(PC)) break;
                        AnalyzedPC.Add(PC);
                        //Console.WriteLine("%08X".Sprintf(PC));

                        if (AnalyzedPC.Count > MaxNumberOfInstructions)
                        {
                            throw (new InvalidDataException(String.Format("Code sequence too long: >= {0} at 0x{1:X8}", MaxNumberOfInstructions, EntryPC)));
                        }

                        UpdateMinMax(PC);

                        //Console.WriteLine("    PC:{0:X}", PC);

                        var Instruction = InstructionReader[PC];

                        var BranchInfo = DynarecBranchAnalyzer.GetBranchInfo(Instruction);
                        var DisassemblerInfo = MipsDisassembler.Disassemble(PC, Instruction);

                        LogInstruction(PC, Instruction);

                        // Break
                        if (DisassemblerInfo.InstructionInfo.Name == "break")
                        {
                            break;
                        }
                        // Branch instruction.
                        //else if (BranchInfo.HasFlag(DynarecBranchAnalyzer.JumpFlags.JumpAlways))
                        else if (BranchInfo.HasFlag(DynarecBranchAnalyzer.JumpFlags.JumpInstruction))
                        {
                            //Console.WriteLine("Instruction");

                            var JumpAddress = Instruction.GetJumpAddress(Memory, PC);

                            // Located a jump-always instruction with a delayed slot. Process next instruction too.
                            if (BranchInfo.HasFlag(DynarecBranchAnalyzer.JumpFlags.AndLink))
                            {
                                // Just a function call. Continue analyzing.
                            }
                            else
                            {
                                if (PspMemory.IsAddressValid(JumpAddress))
                                {
                                    if (!LabelsJump.ContainsKey(JumpAddress))
                                    {
                                        if (AddressInsideFunction(JumpAddress))
                                        {
                                            //Console.WriteLine("JumpAddress: {0:X8}", JumpAddress);
                                            LabelsJump[JumpAddress] = AstLabel.CreateLabel(String.Format("Jump_0x{0:X8}", JumpAddress));
                                            BranchesToAnalyze.Enqueue(JumpAddress);
                                        }
                                    }
                                }

                                EndOfBranchFound = true;
                                continue;
                            }
                        }
                        else if (BranchInfo.HasFlag(DynarecBranchAnalyzer.JumpFlags.BranchOrJumpInstruction))
                        {
                            var BranchAddress = Instruction.GetBranchAddress(PC);
                            if (!Labels.ContainsKey(BranchAddress))
                            {
                                //Console.WriteLine("BranchAddress: {0:X8}", BranchAddress);
                                UpdateMinMax(BranchAddress);
                                Labels[BranchAddress] = AstLabel.CreateLabel(String.Format("Label_0x{0:X8}", BranchAddress));
                                BranchesToAnalyze.Enqueue(BranchAddress);
                            }
                        }
                        else if (BranchInfo.HasFlag(DynarecBranchAnalyzer.JumpFlags.SyscallInstruction))
                        {
                            // On this special Syscall
                            if (Instruction.CODE == SyscallInfo.NativeCallSyscallCode)
                            {
                                //PC += 4;
                                goto HandleNewBranch;
                            }
                        }

                        // Jump-Always found. And we have also processed the delayed branch slot. End the branch.
                        if (EndOfBranchFound)
                        {
                            EndOfBranchFound = false;
                            goto HandleNewBranch;
                        }
                    }
                }

                //Console.WriteLine("FunctionSegment({0:X8}-{1:X8})", MinPC, MaxPC);

                foreach (var LabelAddress in LabelsJump.Keys.ToArray())
                {
                    if (!AddressInsideFunction(LabelAddress))
                    {
                        LabelsJump.Remove(LabelAddress);
                    }
                }

                this.CpuEmitter.BranchCount = Labels.Count;
            }