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); CpuThreadState.GPR[1] = 1; CpuThreadState.GPR[2] = 2; CpuThreadState.GPR[3] = 3; MipsEmiter.OP_3REG_Unsigned(1, 2, 2, OpCodes.Add); MipsEmiter.OP_3REG_Unsigned(0, 2, 2, OpCodes.Add); MipsEmiter.OP_2REG_IMM_Signed(10, 0, 1000, OpCodes.Add); 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(""); } } }); }