public void CreateDelegateTest() { var PspConfig = new PspConfig(); var PspEmulatorContext = new PspEmulatorContext(PspConfig); PspEmulatorContext.SetInstanceType<PspMemory, LazyPspMemory>(); var Memory = PspEmulatorContext.GetInstance<PspMemory>(); var Processor = PspEmulatorContext.GetInstance<CpuProcessor>(); var CpuThreadState = new CpuThreadState(Processor); var MipsEmiter = new MipsMethodEmiter(new MipsEmiter(), Processor, 0); CpuThreadState.GPR[1] = 1; CpuThreadState.GPR[2] = 2; CpuThreadState.GPR[3] = 3; MipsEmiter.OP_3REG_Unsigned(1, 2, 2, () => { MipsEmiter.SafeILGenerator.BinaryOperation(SafeBinaryOperator.AdditionSigned); }); MipsEmiter.OP_3REG_Unsigned(0, 2, 2, () => { MipsEmiter.SafeILGenerator.BinaryOperation(SafeBinaryOperator.AdditionSigned); }); MipsEmiter.OP_2REG_IMM_Signed(10, 0, 1000, () => { MipsEmiter.SafeILGenerator.BinaryOperation(SafeBinaryOperator.AdditionSigned); }); MipsEmiter.CreateDelegate()(CpuThreadState); Assert.AreEqual(4, CpuThreadState.GPR[1]); Assert.AreEqual(0, CpuThreadState.GPR[0]); Assert.AreEqual(1000, CpuThreadState.GPR[10]); }
private Action<CpuThreadState> CreateDelegateForMethodInfo(MethodInfo MethodInfo, HlePspFunctionAttribute HlePspFunctionAttribute) { var MipsMethodEmiter = new MipsMethodEmiter(HleState.MipsEmiter, HleState.CpuProcessor); int GprIndex = 4; int FprIndex = 0; var NotImplementedAttribute = (HlePspNotImplementedAttribute)MethodInfo.GetCustomAttributes(typeof(HlePspNotImplementedAttribute), true).FirstOrDefault(); bool NotImplemented = (NotImplementedAttribute != null) ? NotImplementedAttribute.Notice : false; bool SkipLog = HlePspFunctionAttribute.SkipLog; var ParamInfoList = new List<ParamInfo>(); Action CallAction = () => { MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldarg_0); MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldfld, typeof(CpuThreadState).GetField("ModuleObject")); MipsMethodEmiter.ILGenerator.Emit(OpCodes.Castclass, this.GetType()); foreach (var ParameterInfo in MethodInfo.GetParameters()) { var ParameterType = ParameterInfo.ParameterType; // The CpuThreadState if (ParameterType == typeof(CpuThreadState)) { MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldarg_0); } // A stringz else if (ParameterType == typeof(string)) { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = ParameterType, }); MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldarg_0); MipsMethodEmiter.LoadGPR_Unsigned(GprIndex); MipsMethodEmiter.ILGenerator.Emit(OpCodes.Call, typeof(HleModuleHost).GetMethod("StringFromAddress")); GprIndex++; } // A pointer else if (ParameterType.IsPointer) { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = typeof(uint), }); MipsMethodEmiter._getmemptr(() => { MipsMethodEmiter.LoadGPR_Unsigned(GprIndex); }, Safe: true); GprIndex++; } // A long type else if (ParameterType == typeof(long) || ParameterType == typeof(ulong)) { while (GprIndex % 2 != 0) GprIndex++; ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = ParameterType, }); MipsMethodEmiter.LoadGPRLong_Signed(GprIndex + 0); /* MipsMethodEmiter.LoadGPR_Unsigned(GprIndex + 0); MipsMethodEmiter.LoadGPR_Unsigned(GprIndex + 1); MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, 32); MipsMethodEmiter.ILGenerator.Emit(OpCodes.Shl); MipsMethodEmiter.ILGenerator.Emit(OpCodes.Or); */ GprIndex += 2; } // A float register. else if (ParameterType == typeof(float)) { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Fpr, RegisterIndex = FprIndex, ParameterType = ParameterType, }); MipsMethodEmiter.LoadFPR(FprIndex); FprIndex++; } // An integer register else { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = ParameterType, }); MipsMethodEmiter.LoadGPR_Unsigned(GprIndex); GprIndex++; } //MipsMethodEmiter.ILGenerator.Emit(OpCodes.ld } MipsMethodEmiter.ILGenerator.Emit(OpCodes.Call, MethodInfo); }; if (MethodInfo.ReturnType == typeof(void)) { CallAction(); } else if (MethodInfo.ReturnType == typeof(long)) { MipsMethodEmiter.SaveGPRLong(2, CallAction); } else { MipsMethodEmiter.SaveGPR(2, CallAction); } var Delegate = MipsMethodEmiter.CreateDelegate(); return (CpuThreadState) => { bool Trace = (!SkipLog && CpuThreadState.CpuProcessor.PspConfig.DebugSyscalls); if (NotImplemented) { Trace = true; ConsoleUtils.SaveRestoreConsoleState(() => { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine( "Not implemented {0}.{1}", MethodInfo.DeclaringType.Name, MethodInfo.Name ); }); } var Out = Console.Out; if (NotImplemented) { Out = Console.Error; } if (Trace) { if (HleState.ThreadManager.Current != null) { Out.Write( "Thread({0}:'{1}') : RA(0x{2:X})", HleState.ThreadManager.Current.Id, HleState.ThreadManager.Current.Name, HleState.ThreadManager.Current.CpuThreadState.RA ); } else { Out.Write("NoThread:"); } Out.Write(" : {0}.{1}", MethodInfo.DeclaringType.Name, MethodInfo.Name); Out.Write("("); int Count = 0; foreach (var ParamInfo in ParamInfoList) { if (Count > 0) Out.Write(", "); Out.Write("{0}:", ParamInfo.ParameterName); switch (ParamInfo.RegisterType) { case HleModuleHost.ParamInfo.RegisterTypeEnum.Fpr: case HleModuleHost.ParamInfo.RegisterTypeEnum.Gpr: uint Int4 = (uint)CpuThreadState.GPR[ParamInfo.RegisterIndex]; uint Float4 = (uint)CpuThreadState.FPR[ParamInfo.RegisterIndex]; Out.Write("{0}", ToNormalizedTypeString(ParamInfo.ParameterType, CpuThreadState, Int4, Float4)); break; default: throw(new NotImplementedException()); } Count++; } Out.Write(")"); //Console.WriteLine(""); } CpuThreadState.ModuleObject = this; try { Delegate(CpuThreadState); } catch (SceKernelException SceKernelException) { CpuThreadState.GPR[2] = (int)SceKernelException.SceKernelError; } catch (SceKernelSelfStopUnloadModuleException SceKernelSelfStopUnloadModuleException) { throw (SceKernelSelfStopUnloadModuleException); } catch (Exception Exception) { throw (new Exception( String.Format("ERROR calling {0}.{1}!", MethodInfo.DeclaringType.Name, MethodInfo.Name), Exception )); } finally { if (Trace) { Out.WriteLine(" : {0}", ToNormalizedTypeString(MethodInfo.ReturnType, CpuThreadState, (uint)CpuThreadState.GPR[2], (float)CpuThreadState.FPR[0])); Out.WriteLine(""); } } }; }
static private Action <CpuThreadState> _CreateDelegateForPC(CpuProcessor CpuProcessor, Stream MemoryStream, uint EntryPC, out int InstructionsProcessed) { InstructionsProcessed = 0; if (EntryPC == 0) { if (MemoryStream is PspMemoryStream) { throw (new InvalidOperationException("EntryPC can't be NULL")); } } if (CpuProcessor.PspConfig.TraceJIT) { Console.WriteLine("Emiting EntryPC=0x{0:X}", EntryPC); } MemoryStream.Position = EntryPC; if ((MemoryStream.Length >= 8) && new BinaryReader(MemoryStream).ReadUInt64() == 0x0000000003E00008) { Console.WriteLine("NullSub detected at 0x{0:X}!", EntryPC); } var InstructionReader = new InstructionReader(MemoryStream); var MipsMethodEmiter = new MipsMethodEmiter(MipsEmiter, CpuProcessor); var ILGenerator = MipsMethodEmiter.ILGenerator; var CpuEmiter = new CpuEmiter(MipsMethodEmiter, InstructionReader, MemoryStream, CpuProcessor); uint PC; uint EndPC = (uint)MemoryStream.Length; uint MinPC = uint.MaxValue, MaxPC = uint.MinValue; var Labels = new SortedDictionary <uint, Label>(); var BranchesToAnalyze = new Queue <uint>(); var AnalyzedPC = new HashSet <uint>(); Labels[EntryPC] = ILGenerator.DefineLabel(); BranchesToAnalyze.Enqueue(EntryPC); // PASS1: Analyze and find labels. PC = EntryPC; //Debug.WriteLine("PASS1: (PC={0:X}, EndPC={1:X})", PC, EndPC); var GlobalInstructionStats = CpuProcessor.GlobalInstructionStats; var InstructionStats = new Dictionary <string, uint>(); var NewInstruction = new Dictionary <string, bool>(); int MaxNumberOfInstructions = 8 * 1024; //int MaxNumberOfInstructions = 60; while (BranchesToAnalyze.Count > 0) { bool EndOfBranchFound = false; 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 + "")); } MinPC = Math.Min(MinPC, PC); MaxPC = Math.Max(MaxPC, PC); //Console.WriteLine(" PC:{0:X}", PC); CpuEmiter.LoadAT(PC); var BranchInfo = GetBranchInfo(CpuEmiter.Instruction.Value); if (CpuProcessor.PspConfig.LogInstructionStats) { var InstructionName = GetInstructionName(CpuEmiter.Instruction.Value, null); if (!InstructionStats.ContainsKey(InstructionName)) { InstructionStats[InstructionName] = 0; } InstructionStats[InstructionName]++; if (!GlobalInstructionStats.ContainsKey(InstructionName)) { NewInstruction[InstructionName] = true; GlobalInstructionStats[InstructionName] = 0; } GlobalInstructionStats[InstructionName]++; //var GlobalInstructionStats = CpuProcessor.GlobalInstructionStats; //var InstructionStats = new Dictionary<string, uint>(); //var NewInstruction = new Dictionary<string, bool>(); } // Branch instruction. if ((BranchInfo & CpuBranchAnalyzer.Flags.JumpInstruction) != 0) { //Console.WriteLine("Instruction"); EndOfBranchFound = true; continue; } else if ((BranchInfo & CpuBranchAnalyzer.Flags.BranchOrJumpInstruction) != 0) { var BranchAddress = CpuEmiter.Instruction.GetBranchAddress(PC); Labels[BranchAddress] = ILGenerator.DefineLabel(); BranchesToAnalyze.Enqueue(BranchAddress); // Jump Always performed. /* * if ((BranchInfo & CpuBranchAnalyzer.Flags.JumpAlways) != 0) * { * EndOfBranchFound = true; * continue; * } */ } else if ((BranchInfo & CpuBranchAnalyzer.Flags.SyscallInstruction) != 0) { // On this special Syscall if (CpuEmiter.Instruction.CODE == FunctionGenerator.NativeCallSyscallCode) { //PC += 4; break; } } // A Jump Always found. And we have also processed the delayed branch slot. End the branch. if (EndOfBranchFound) { EndOfBranchFound = false; break; } } } // PASS2: Generate code and put labels; Action <uint> _EmitCpuInstructionAT = (_PC) => { if (CpuProcessor.PspConfig.TraceJIT) { ILGenerator.Emit(OpCodes.Ldarg_0); ILGenerator.Emit(OpCodes.Ldc_I4, _PC); ILGenerator.Emit(OpCodes.Call, typeof(CpuThreadState).GetMethod("Trace")); Console.WriteLine(" PC=0x{0:X}", _PC); } CpuEmiter.LoadAT(_PC); CpuEmiterInstruction(CpuEmiter.Instruction.Value, CpuEmiter); }; uint InstructionsEmitedSinceLastWaypoint = 0; Action StorePC = () => { MipsMethodEmiter.SavePC(PC); }; Action <bool> EmitInstructionCountIncrement = (bool CheckForYield) => { if (!CpuProcessor.PspConfig.CountInstructionsAndYield) { return; } //Console.WriteLine("EmiteInstructionCountIncrement: {0},{1}", InstructionsEmitedSinceLastWaypoint, CheckForYield); if (InstructionsEmitedSinceLastWaypoint > 0) { MipsMethodEmiter.SaveStepInstructionCount(() => { MipsMethodEmiter.LoadStepInstructionCount(); ILGenerator.Emit(OpCodes.Ldc_I4, InstructionsEmitedSinceLastWaypoint); //ILGenerator.Emit(OpCodes.Add); ILGenerator.Emit(OpCodes.Sub); }); //ILGenerator.Emit(OpCodes.Ldc_I4, 100); //ILGenerator.EmitCall(OpCodes.Call, typeof(Console).GetMethod("WriteLine"), new Type[] { typeof(int) }); InstructionsEmitedSinceLastWaypoint = 0; } if (CheckForYield) { if (!CpuProcessor.PspConfig.BreakInstructionThreadSwitchingForSpeed) { var NoYieldLabel = ILGenerator.DefineLabel(); MipsMethodEmiter.LoadStepInstructionCount(); ILGenerator.Emit(OpCodes.Ldc_I4_0); ILGenerator.Emit(OpCodes.Bgt, NoYieldLabel); //ILGenerator.Emit(OpCodes.Ldc_I4, 1000000); //ILGenerator.Emit(OpCodes.Blt, NoYieldLabel); MipsMethodEmiter.SaveStepInstructionCount(() => { ILGenerator.Emit(OpCodes.Ldc_I4_0); }); StorePC(); ILGenerator.Emit(OpCodes.Ldarg_0); ILGenerator.Emit(OpCodes.Call, typeof(CpuThreadState).GetMethod("Yield")); //ILGenerator.Emit(OpCodes.Call, typeof(GreenThread).GetMethod("Yield")); ILGenerator.MarkLabel(NoYieldLabel); } } }; Action EmitCpuInstruction = () => { if (CpuProcessor.NativeBreakpoints.Contains(PC)) { ILGenerator.Emit(OpCodes.Call, typeof(DebugUtils).GetMethod("IsDebuggerPresentDebugBreak")); } // Marks label. if (Labels.ContainsKey(PC)) { EmitInstructionCountIncrement(false); ILGenerator.MarkLabel(Labels[PC]); } _EmitCpuInstructionAT(PC); PC += 4; InstructionsEmitedSinceLastWaypoint++; }; //Debug.WriteLine("PASS2: MinPC:{0:X}, MaxPC:{1:X}", MinPC, MaxPC); // Jumps to the entry point. ILGenerator.Emit(OpCodes.Br, Labels[EntryPC]); for (PC = MinPC; PC <= MaxPC;) { uint CurrentInstructionPC = PC; Instruction CurrentInstruction = InstructionReader[PC]; InstructionsProcessed++; /* * if (!AnalyzedPC.Contains(CurrentInstructionPC)) * { * // Marks label. * if (Labels.ContainsKey(PC)) * { * ILGenerator.MarkLabel(Labels[PC]); * } * * * PC += 4; * continue; * } */ var BranchInfo = GetBranchInfo(CurrentInstruction.Value); // Delayed branch instruction. if ((BranchInfo & CpuBranchAnalyzer.Flags.BranchOrJumpInstruction) != 0) { InstructionsEmitedSinceLastWaypoint += 2; EmitInstructionCountIncrement(true); var BranchAddress = CurrentInstruction.GetBranchAddress(PC); if ((BranchInfo & CpuBranchAnalyzer.Flags.JumpInstruction) != 0) { // Marks label. if (Labels.ContainsKey(PC)) { ILGenerator.MarkLabel(Labels[PC]); } _EmitCpuInstructionAT(PC + 4); _EmitCpuInstructionAT(PC + 0); PC += 8; } else { // Branch instruction. EmitCpuInstruction(); //if ((BranchInfo & CpuBranchAnalyzer.Flags.Likely) != 0) if (BranchInfo.HasFlag(CpuBranchAnalyzer.Flags.Likely)) { //Console.WriteLine("Likely"); // Delayed instruction. CpuEmiter._branch_likely(() => { EmitCpuInstruction(); }); } else { //Console.WriteLine("Not Likely"); // Delayed instruction. EmitCpuInstruction(); } if (CurrentInstructionPC + 4 != BranchAddress) { if (Labels.ContainsKey(BranchAddress)) { CpuEmiter._branch_post(Labels[BranchAddress]); } // Code not reached. else { } } } } // Normal instruction. else { // Syscall instruction. if ((BranchInfo & CpuBranchAnalyzer.Flags.SyscallInstruction) != 0) { StorePC(); } EmitCpuInstruction(); if ((BranchInfo & CpuBranchAnalyzer.Flags.SyscallInstruction) != 0) { // On this special Syscall if (CurrentInstruction.CODE == FunctionGenerator.NativeCallSyscallCode) { //PC += 4; break; } } } } if (CpuProcessor.PspConfig.ShowInstructionStats) { Console.Error.WriteLine("-------------------------- {0:X}-{1:X} ", MinPC, MaxPC); foreach (var Pair in InstructionStats.OrderByDescending(Item => Item.Value)) { Console.Error.Write("{0} : {1}", Pair.Key, Pair.Value); if (NewInstruction.ContainsKey(Pair.Key)) { Console.Error.Write(" <-- NEW!"); } Console.Error.WriteLine(""); } } //if (BreakPoint) IsDebuggerPresentDebugBreak(); Action <CpuThreadState> Delegate = MipsMethodEmiter.CreateDelegate(); return(Delegate); }
private Action<CpuThreadState> CreateDelegateForMethodInfo(MethodInfo MethodInfo, HlePspFunctionAttribute HlePspFunctionAttribute) { var MipsMethodEmiter = new MipsMethodEmiter(CpuProcessor, 0); int GprIndex = 4; int FprIndex = 0; var NotImplementedAttribute = (HlePspNotImplementedAttribute)MethodInfo.GetCustomAttributes(typeof(HlePspNotImplementedAttribute), true).FirstOrDefault(); bool NotImplementedFunc = (NotImplementedAttribute != null) ? NotImplementedAttribute.Notice : false; bool SkipLog = HlePspFunctionAttribute.SkipLog; var SafeILGenerator = MipsMethodEmiter.SafeILGenerator; SafeILGenerator.Comment("HleModuleHost.CreateDelegateForMethodInfo(" + MethodInfo + ", " + HlePspFunctionAttribute + ")"); var ParamInfoList = new List<ParamInfo>(); Action CallAction = () => { SafeILGenerator.LoadArgument0CpuThreadState(); SafeILGenerator.LoadField(typeof(CpuThreadState).GetField("ModuleObject")); SafeILGenerator.CastClass(this.GetType()); foreach (var ParameterInfo in MethodInfo.GetParameters()) { var ParameterType = ParameterInfo.ParameterType; // The CpuThreadState if (ParameterType == typeof(CpuThreadState)) { SafeILGenerator.LoadArgument0CpuThreadState(); } // A stringz else if (ParameterType == typeof(string)) { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = ParameterType, }); SafeILGenerator.LoadArgument0CpuThreadState(); MipsMethodEmiter.LoadGPR_Unsigned(GprIndex); SafeILGenerator.Call(typeof(HleModuleHost).GetMethod("StringFromAddress")); GprIndex++; } // A pointer or ref/out else if (ParameterType.IsPointer || ParameterType.IsByRef) { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = typeof(uint), }); MipsMethodEmiter._getmemptr(() => { MipsMethodEmiter.LoadGPR_Unsigned(GprIndex); }, Safe: true, ErrorDescription: "Invalid Pointer for Argument '" + ParameterType.Name + " " + ParameterInfo.Name + "'"); GprIndex++; } /* // An array else if (ParameterType.IsArray) { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = typeof(uint), }); // Pointer MipsMethodEmiter._getmemptr(() => { MipsMethodEmiter.LoadGPR_Unsigned(GprIndex); }, Safe: true, ErrorDescription: "Invalid Pointer for Argument '" + ParameterType.Name + " " + ParameterInfo.Name + "'"); GprIndex++; // Array MipsMethodEmiter.LoadGPR_Unsigned(GprIndex); GprIndex++; MipsMethodEmiter.CallMethod(HleModuleHost.PointerLengthToArrat); } */ // A long type else if (ParameterType == typeof(long) || ParameterType == typeof(ulong)) { while (GprIndex % 2 != 0) GprIndex++; ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = ParameterType, }); MipsMethodEmiter.LoadGPRLong_Signed(GprIndex + 0); /* MipsMethodEmiter.LoadGPR_Unsigned(GprIndex + 0); MipsMethodEmiter.LoadGPR_Unsigned(GprIndex + 1); SafeILGenerator.Push((int)32); MipsMethodEmiter.ILGenerator.Emit(OpCodes.Shl); MipsMethodEmiter.ILGenerator.Emit(OpCodes.Or); */ GprIndex += 2; } // A float register. else if (ParameterType == typeof(float)) { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Fpr, RegisterIndex = FprIndex, ParameterType = ParameterType, }); MipsMethodEmiter.LoadFPR(FprIndex); FprIndex++; } // Test else if (ParameterType == typeof(PspPointer)) { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = ParameterType, }); MipsMethodEmiter.LoadGPR_Unsigned(GprIndex); MipsMethodEmiter.CallMethod(typeof(PspPointer).GetMethod("op_Implicit", new[] { typeof(uint) })); GprIndex++; } // An integer register else { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = ParameterType, }); MipsMethodEmiter.LoadGPR_Unsigned(GprIndex); GprIndex++; } //MipsMethodEmiter.ILGenerator.Emit(OpCodes.ld } SafeILGenerator.Call(MethodInfo); }; if (MethodInfo.ReturnType == typeof(void)) { CallAction(); } else if (MethodInfo.ReturnType == typeof(long)) { MipsMethodEmiter.SaveGPRLong(2, CallAction); } else if (MethodInfo.ReturnType == typeof(float)) { MipsMethodEmiter.SaveFPR(0, CallAction); } else { MipsMethodEmiter.SaveGPR(2, CallAction); } var Delegate = MipsMethodEmiter.CreateDelegate(); return (CpuThreadState) => { bool Trace = (!SkipLog && CpuThreadState.CpuProcessor.PspConfig.DebugSyscalls); bool NotImplemented = NotImplementedFunc && CpuThreadState.CpuProcessor.PspConfig.DebugNotImplemented; if (Trace && (MethodInfo.DeclaringType.Name == "Kernel_Library")) Trace = false; if (NotImplemented) { Trace = true; ConsoleUtils.SaveRestoreConsoleState(() => { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine( "Not implemented {0}.{1}", MethodInfo.DeclaringType.Name, MethodInfo.Name ); }); } var Out = Console.Out; if (NotImplemented) { Out = Console.Error; } if (Trace) { if (ThreadManager.Current != null) { Out.Write( "Thread({0}:'{1}') : RA(0x{2:X})", ThreadManager.Current.Id, ThreadManager.Current.Name, ThreadManager.Current.CpuThreadState.RA ); } else { Out.Write("NoThread:"); } Out.Write(" : {0}.{1}", MethodInfo.DeclaringType.Name, MethodInfo.Name); Out.Write("("); int Count = 0; foreach (var ParamInfo in ParamInfoList) { if (Count > 0) Out.Write(", "); Out.Write("{0}:", ParamInfo.ParameterName); switch (ParamInfo.RegisterType) { case HleModuleHost.ParamInfo.RegisterTypeEnum.Fpr: case HleModuleHost.ParamInfo.RegisterTypeEnum.Gpr: uint Int4 = (uint)CpuThreadState.GPR[ParamInfo.RegisterIndex]; uint Float4 = (uint)CpuThreadState.FPR[ParamInfo.RegisterIndex]; Out.Write("{0}", ToNormalizedTypeString(ParamInfo.ParameterType, CpuThreadState, Int4, Float4)); break; default: throw (new NotImplementedException()); } Count++; } Out.Write(")"); //Console.WriteLine(""); } CpuThreadState.ModuleObject = this; try { Delegate(CpuThreadState); } catch (MemoryPartitionNoMemoryException) { CpuThreadState.GPR[2] = (int)SceKernelErrors.ERROR_ERRNO_NO_MEMORY; } catch (SceKernelException SceKernelException) { CpuThreadState.GPR[2] = (int)SceKernelException.SceKernelError; } catch (SceKernelSelfStopUnloadModuleException SceKernelSelfStopUnloadModuleException) { throw (SceKernelSelfStopUnloadModuleException); } #if !DO_NOT_PROPAGATE_EXCEPTIONS catch (Exception Exception) { throw (new Exception( String.Format("ERROR calling {0}.{1}!", MethodInfo.DeclaringType.Name, MethodInfo.Name), Exception )); } #endif finally { if (Trace) { Out.WriteLine(" : {0}", ToNormalizedTypeString(MethodInfo.ReturnType, CpuThreadState, (uint)CpuThreadState.GPR[2], (float)CpuThreadState.FPR[0])); Out.WriteLine(""); } } }; }