public void SetInstructionAddressStall(uint value)
 {
     InstructionAddressStall = value & PspMemory.MemoryMask;
     if (InstructionAddressStall != 0 && !PspMemory.IsAddressValid(InstructionAddressStall))
     {
         throw new InvalidOperationException($"Invalid StallAddress! 0x{InstructionAddressStall}");
     }
     if (Debug)
     {
         Console.WriteLine("GpuDisplayList.SetInstructionAddressStall:{0:X8}", value);
     }
     StallAddressUpdated.Set();
 }
Exemple #2
0
            internal InternalFunctionCompiler(InjectContext injectContext, MipsMethodEmitter mipsMethodEmitter,
                                              DynarecFunctionCompiler dynarecFunctionCompiler, IInstructionReader instructionReader,
                                              Action <uint> exploreNewPcCallback, uint entryPc, bool doLog, bool checkValidAddress = true)
            {
                injectContext.InjectDependencesTo(this);
                _exploreNewPcCallback   = exploreNewPcCallback;
                _mipsMethodEmitter      = mipsMethodEmitter;
                _cpuEmitter             = new CpuEmitter(injectContext, mipsMethodEmitter, instructionReader);
                _globalInstructionStats = _cpuProcessor.GlobalInstructionStats;
                //this.InstructionStats = MipsMethodEmitter.InstructionStats;
                _instructionStats = new Dictionary <string, uint>();
                _newInstruction   = new Dictionary <string, bool>();
                _doLog            = doLog;

                _dynarecFunctionCompiler = dynarecFunctionCompiler;
                _instructionReader       = instructionReader;
                _entryPc = entryPc;

                if (checkValidAddress && !PspMemory.IsAddressValid(entryPc))
                {
                    throw new InvalidOperationException($"Trying to get invalid function 0x{entryPc:X8}");
                }
            }
Exemple #3
0
        private DynarecFunction _GenerateForPC(uint pc)
        {
            var memory = _cpuProcessor.Memory;

            if (DynarecConfig.DebugFunctionCreation)
            {
                Console.Write("PC=0x{0:X8}...", pc);
            }
            //var Stopwatch = new Logger.Stopwatch();
            var time0 = DateTime.UtcNow;

            var dynarecFunction =
                _cpuProcessor.DynarecFunctionCompiler.CreateFunction(
                    new InstructionStreamReader(new PspMemoryStream(memory)), pc);

            if (dynarecFunction.EntryPc != pc)
            {
                throw (new Exception("Unexpected error"));
            }

            if (DynarecConfig.AllowCreatingUsedFunctionsInBackground)
            {
                foreach (var callingPc in dynarecFunction.CallingPCs)
                {
                    if (PspMemory.IsAddressValid(callingPc))
                    {
                        AddPcLater(callingPc);
                    }
                }
            }

            var time1 = DateTime.UtcNow;

            if (DynarecConfig.ImmediateLinking)
            {
                try
                {
                    if (Platform.IsMono)
                    {
                        Marshal.Prelink(dynarecFunction.Delegate.Method);
                    }
                    dynarecFunction.Delegate(null);
                }
                catch (InvalidProgramException)
                {
                    Console.Error.WriteLine("Invalid delegate:");
                    Console.Error.WriteLine(dynarecFunction.AstNode.ToCSharpString());
                    Console.Error.WriteLine(dynarecFunction.AstNode.ToIlString <Action <CpuThreadState> >());
                    throw;
                }
            }

            var time2 = DateTime.UtcNow;

            dynarecFunction.TimeLinking = time2 - time1;
            var timeAstGeneration = time1 - time0;

            if (DynarecConfig.DebugFunctionCreation)
            {
                ConsoleUtils.SaveRestoreConsoleColor(
                    (timeAstGeneration + dynarecFunction.TimeLinking).TotalMilliseconds > 10
                        ? ConsoleColor.Red
                        : ConsoleColor.Gray, () =>
                {
                    Console.WriteLine(
                        "({0}): (analyze: {1}, generateAST: {2}, optimize: {3}, generateIL: {4}, createDelegate: {5}, link: {6}): ({1}, {2}, {3}, {4}, {5}, {6}) : {7} ms",
                        (dynarecFunction.MaxPc - dynarecFunction.MinPc) / 4,
                        (int)dynarecFunction.TimeAnalyzeBranches.TotalMilliseconds,
                        (int)dynarecFunction.TimeGenerateAst.TotalMilliseconds,
                        (int)dynarecFunction.TimeOptimize.TotalMilliseconds,
                        (int)dynarecFunction.TimeGenerateIl.TotalMilliseconds,
                        (int)dynarecFunction.TimeCreateDelegate.TotalMilliseconds,
                        (int)dynarecFunction.TimeLinking.TotalMilliseconds,
                        (int)(timeAstGeneration + dynarecFunction.TimeLinking).TotalMilliseconds
                        );
                });
            }

            //DynarecFunction.AstNode = DynarecFunction.AstNode.Optimize(CpuProcessor);

#if DEBUG_FUNCTION_CREATION
            CpuProcessor.DebugFunctionCreation = true;
#endif

            //if (CpuProcessor.DebugFunctionCreation)
            //{
            //	Console.WriteLine("-------------------------------------");
            //	Console.WriteLine("Created function for PC=0x{0:X8}", PC);
            //	Console.WriteLine("-------------------------------------");
            //	CpuThreadState.DumpRegistersCpu(Console.Out);
            //	Console.WriteLine("-------------------------------------");
            //	Console.WriteLine(DynarecFunction.AstNode.ToCSharpString());
            //	Console.WriteLine("-------------------------------------");
            //}

            return(dynarecFunction);
        }
Exemple #4
0
            /// <summary>
            /// PASS 1: Analyze Branches
            /// </summary>
            private void AnalyzeBranches()
            {
                _skipPc     = new HashSet <uint>();
                _analyzedPc = new HashSet <uint>();
                var branchesToAnalyze = new Queue <uint>();

                _labels[_entryPc] = AstLabel.CreateLabel("EntryPoint");

                var endPc = _instructionReader.EndPc;

                _pc    = _entryPc;
                _minPc = uint.MaxValue;
                _maxPc = uint.MinValue;

                branchesToAnalyze.Enqueue(_entryPc);

                while (true)
                {
HandleNewBranch:
                    var 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(
                                      $"Code sequence too long: >= {MaxNumberOfInstructions} at 0x{_entryPc:X8}");
                        }

                        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($"Jump_0x{jumpAddress:X8}");
                                            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($"Label_0x{branchAddress:X8}");
                                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);
                    }
                }

                _cpuEmitter.BranchCount = _labels.Count;
            }
 public bool IsAddressValid(uint address) => PspMemory.IsAddressValid(address);
Exemple #6
0
 public bool IsAddressValid(uint Address)
 {
     return(PspMemory.IsAddressValid(Address));
 }