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(); }
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}"); } }
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); }
/// <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);
public bool IsAddressValid(uint Address) { return(PspMemory.IsAddressValid(Address)); }