private AstNodeStmContainer CreateDelegateForMethodInfoPriv(MethodInfo MethodInfo, HlePspFunctionAttribute HlePspFunctionAttribute, out List <ParamInfo> OutParamInfoList) { var RegisterReader = new AstRegisterReader(MethodInfo, Memory); OutParamInfoList = RegisterReader.ParamInfoList; //var SafeILGenerator = MipsMethodEmiter.SafeILGenerator; var AstNodes = new AstNodeStmContainer(); AstNodes.AddStatement(ast.Comment("HleModuleHost.CreateDelegateForMethodInfo(" + MethodInfo + ", " + HlePspFunctionAttribute + ")")); AstNodeExprCall AstMethodCall; { //var ModuleObject = this.Cast(this.GetType(), this.FieldAccess(this.Argument<CpuThreadState>(0, "CpuThreadState"), "ModuleObject")); //SafeILGenerator.LoadArgument0CpuThreadState(); //SafeILGenerator.LoadField(typeof(CpuThreadState).GetField("ModuleObject")); //SafeILGenerator.CastClass(this.GetType()); var AstParameters = new List <AstNodeExpr>(); foreach (var ParameterInfo in MethodInfo.GetParameters()) { var ParameterType = ParameterInfo.ParameterType; var HleInvalidAsNullAttribute = ParameterInfo.GetCustomAttribute <HleInvalidAsNullAttribute>(); var HleInvalidAsInvalidPointerAttribute = ParameterInfo.GetCustomAttribute <HleInvalidAsInvalidPointerAttribute>(); InvalidAddressAsEnum InvalidAddressAsEnum = InvalidAddressAsEnum.Exception; if (HleInvalidAsNullAttribute != null) { InvalidAddressAsEnum = InvalidAddressAsEnum.Null; } if (HleInvalidAsInvalidPointerAttribute != null) { InvalidAddressAsEnum = InvalidAddressAsEnum.InvalidAddress; } // The CpuThreadState if (ParameterType == typeof(CpuThreadState)) { AstParameters.Add(ast.CpuThreadStateExpr); } // A stringz else if (ParameterType == typeof(string)) { AstParameters.Add( ast.CallStatic( (Func <CpuThreadState, uint, string>)HleModuleHost.StringFromAddress, ast.CpuThreadStateExpr, RegisterReader.Read <uint>(ParameterInfo) ) ); } // A pointer or ref/out else if (ParameterType.IsPointer || ParameterType.IsByRef) { AstParameters.Add( ast.Cast( ParameterType, ast.MemoryGetPointer( CpuProcessor.Memory, RegisterReader.Read <uint>(ParameterInfo), safe: true, errorDescription: "Invalid Pointer for Argument '" + ParameterType.Name + " " + ParameterInfo.Name + "'", invalidAddress: InvalidAddressAsEnum ) ) ); } // A long type else if (ParameterType == typeof(long) || ParameterType == typeof(ulong)) { AstParameters.Add(RegisterReader.Read(ParameterInfo)); } // A float register. else if (ParameterType == typeof(float)) { AstParameters.Add(RegisterReader.Read(ParameterInfo)); } // PspPointer else if (ParameterType == typeof(PspPointer)) { AstParameters.Add(ast.CallStatic( typeof(PspPointer).GetMethod("op_Implicit", new[] { typeof(uint) }), RegisterReader.Read <uint>(ParameterInfo) )); } // A class else if (ParameterType.IsClass) { if (!ParameterType.Implements(typeof(IHleUidPoolClass))) { throw (new InvalidCastException( $"Can't use a class '{ParameterType}' not implementing IHleUidPoolClass as parameter")); } AstParameters.Add(ast.Cast(ParameterType, ast.CallStatic( (Func <CpuThreadState, Type, int, bool, object>)GetObjectFromPoolHelper, ast.CpuThreadStateExpr, ast.Immediate(ParameterType), RegisterReader.Read <int>(ParameterInfo), (InvalidAddressAsEnum == InvalidAddressAsEnum.Null) ))); } // An integer register else { AstParameters.Add(ast.Cast(ParameterType, RegisterReader.Read((ParameterType == typeof(uint)) ? typeof(uint) : typeof(int), ParameterInfo))); } } AstMethodCall = ast.CallInstance( ThisILInstanceHolder.GetAstFieldAccess(), MethodInfo, AstParameters.ToArray() ); } if (AstMethodCall.Type == typeof(void)) { AstNodes.AddStatement(ast.Statement(AstMethodCall)); } else if (AstMethodCall.Type == typeof(long)) { AstNodes.AddStatement(ast.Assign(ast.GPR_l(2), ast.Cast <long>(AstMethodCall))); } else if (AstMethodCall.Type == typeof(float)) { AstNodes.AddStatement(ast.Assign(ast.Fpr(0), ast.Cast <float>(AstMethodCall))); } else if (AstMethodCall.Type.IsClass) { if (!AstMethodCall.Type.Implements(typeof(IHleUidPoolClass))) { throw (new InvalidCastException( $"Can't use a class '{AstMethodCall.Type}' not implementing IHleUidPoolClass as return value")); } AstNodes.AddStatement(ast.Assign( ast.Gpr(2), ast.CallStatic( (Func <CpuThreadState, Type, IHleUidPoolClass, uint>)GetOrAllocIndexFromPoolHelper, ast.CpuThreadStateExpr, ast.Immediate(AstMethodCall.Type), ast.Cast <IHleUidPoolClass>(AstMethodCall) ) )); } else { AstNodes.AddStatement(ast.Assign(ast.Gpr(2), ast.Cast <uint>(AstMethodCall))); } return(AstNodes); }
private Action <CpuThreadState> CreateDelegateForMethodInfo(MethodInfo MethodInfo, HlePspFunctionAttribute HlePspFunctionAttribute) { if (!MethodInfo.DeclaringType.IsAssignableFrom(this.GetType())) { throw (new Exception($"Invalid {MethodInfo.DeclaringType} != {this.GetType()}")); } bool SkipLog = HlePspFunctionAttribute.SkipLog; var NotImplementedAttribute = (HlePspNotImplementedAttribute)MethodInfo .GetCustomAttributes(typeof(HlePspNotImplementedAttribute), true).FirstOrDefault(); bool NotImplementedFunc = (NotImplementedAttribute != null) && NotImplementedAttribute.Notice; List <ParamInfo> ParamInfoList; var AstNodes = AstOptimizerPsp.GlobalOptimize( CpuProcessor, ast.Statements( // Do stuff before CreateDelegateForMethodInfoPriv(MethodInfo, HlePspFunctionAttribute, out ParamInfoList) // Do stuff after ) ); var Delegate = AstNodeExtensions.GeneratorIlPsp.GenerateDelegate <Action <CpuThreadState> >( $"Proxy_{this.GetType().Name}_{MethodInfo.Name}", AstNodes ); //return Delegate; return((CpuThreadState) => { bool Trace = (!SkipLog && CpuThreadState.CpuProcessor.CpuConfig.DebugSyscalls); bool NotImplemented = NotImplementedFunc && HleConfig.DebugNotImplemented; if (Trace && (MethodInfo.DeclaringType.Name == "Kernel_Library")) { Trace = false; } //Console.WriteLine("aaaaaaaaaaaaa"); 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; var NormalRegisterReader = new NormalRegisterReader(CpuThreadState); foreach (var ParamInfo in ParamInfoList) { if (Count > 0) { Out.Write(", "); } Out.Write("{0}:", ParamInfo.ParameterInfo.Name); switch (ParamInfo.RegisterType) { case HleModuleHost.ParamInfo.RegisterTypeEnum.Fpr: case HleModuleHost.ParamInfo.RegisterTypeEnum.Gpr: var Object = NormalRegisterReader.Read <uint>(ParamInfo.ParameterInfo); Out.Write("{0}", ToNormalizedTypeString(ParamInfo.ParameterInfo.ParameterType, CpuThreadState, Object)); break; default: throw (new NotImplementedException()); } Count++; } Out.Write(")"); //Console.WriteLine(""); } try { CpuThreadState.Pc = CpuThreadState.Ra; Delegate(CpuThreadState); } catch (InvalidProgramException) { Console.WriteLine("CALLING: {0}", MethodInfo); Console.WriteLine("{0}", (new GeneratorCSharp()).GenerateRoot(AstNodes).ToString()); foreach (var Line in AstNodeExtensions.GeneratorIlPsp.GenerateToStringList(MethodInfo, AstNodes)) { Console.WriteLine(Line); } throw; } catch (MemoryPartitionNoMemoryException) { CpuThreadState.Gpr[2] = (int)SceKernelErrors.ERROR_ERRNO_NO_MEMORY; } catch (SceKernelException SceKernelException) { CpuThreadState.Gpr[2] = (int)SceKernelException.SceKernelError; } catch (SceKernelSelfStopUnloadModuleException) { throw; } #if !DO_NOT_PROPAGATE_EXCEPTIONS catch (Exception Exception) { throw (new Exception( $"ERROR calling {MethodInfo.DeclaringType.Name}.{MethodInfo.Name}!", Exception )); } #endif finally { if (Trace) { Out.WriteLine(" : {0}", ToNormalizedTypeString(MethodInfo.ReturnType, CpuThreadState, ((MethodInfo.ReturnType == typeof(float)) ? (object)CpuThreadState.Fpr[0] : (object)CpuThreadState.Gpr[2]))); Out.WriteLine(""); } } }); }
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(""); } } }); }
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(""); } } }; }
private AstNodeStmContainer CreateDelegateForMethodInfoPriv(MethodInfo MethodInfo, HlePspFunctionAttribute HlePspFunctionAttribute, out List<ParamInfo> ParamInfoList) { int GprIndex = 4; int FprIndex = 0; //var SafeILGenerator = MipsMethodEmiter.SafeILGenerator; var AstNodes = new AstNodeStmContainer(); AstNodes.AddStatement(ast.Comment("HleModuleHost.CreateDelegateForMethodInfo(" + MethodInfo + ", " + HlePspFunctionAttribute + ")")); ParamInfoList = new List<ParamInfo>(); AstNodeExprCall AstMethodCall; { //var ModuleObject = this.Cast(this.GetType(), this.FieldAccess(this.Argument<CpuThreadState>(0, "CpuThreadState"), "ModuleObject")); //SafeILGenerator.LoadArgument0CpuThreadState(); //SafeILGenerator.LoadField(typeof(CpuThreadState).GetField("ModuleObject")); //SafeILGenerator.CastClass(this.GetType()); var AstParameters = new List<AstNodeExpr>(); foreach (var ParameterInfo in MethodInfo.GetParameters()) { var ParameterType = ParameterInfo.ParameterType; // The CpuThreadState if (ParameterType == typeof(CpuThreadState)) { AstParameters.Add(MipsMethodEmitter.CpuThreadStateArgument()); } // A stringz else if (ParameterType == typeof(string)) { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = ParameterType, }); AstParameters.Add( ast.CallStatic( (Func<CpuThreadState, uint, string>)HleModuleHost.StringFromAddress, MipsMethodEmitter.CpuThreadStateArgument(), MipsMethodEmitter.GPR_u(GprIndex) ) ); 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), }); AstParameters.Add( ast.Cast( ParameterType, MipsMethodEmitter.AstMemoryGetPointer( MipsMethodEmitter.GPR_u(GprIndex), Safe: true, ErrorDescription: "Invalid Pointer for Argument '" + ParameterType.Name + " " + ParameterInfo.Name + "'" ) ) ); 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, }); if (ParameterType == typeof(ulong)) { AstParameters.Add(MipsMethodEmitter.GPR_ul(GprIndex + 0)); } else { AstParameters.Add(MipsMethodEmitter.GPR_sl(GprIndex + 0)); } 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, }); AstParameters.Add(MipsMethodEmitter.FPR(FprIndex)); FprIndex++; } // Test else if (ParameterType == typeof(PspPointer)) { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = ParameterType, }); AstParameters.Add(ast.CallStatic( typeof(PspPointer).GetMethod("op_Implicit", new[] { typeof(uint) }), MipsMethodEmitter.GPR_u(GprIndex) )); GprIndex++; } // An integer register else { ParamInfoList.Add(new ParamInfo() { ParameterName = ParameterInfo.Name, RegisterType = ParamInfo.RegisterTypeEnum.Gpr, RegisterIndex = GprIndex, ParameterType = ParameterType, }); if (ParameterType == typeof(uint)) { AstParameters.Add(ast.Cast(ParameterType, MipsMethodEmitter.GPR_u(GprIndex))); } else { AstParameters.Add(ast.Cast(ParameterType, MipsMethodEmitter.GPR_s(GprIndex))); } GprIndex++; } } AstMethodCall = ast.CallInstance( ThisILInstanceHolder.GetAstFieldAccess(), MethodInfo, AstParameters.ToArray() ); } if (AstMethodCall.Type == typeof(void)) AstNodes.AddStatement(ast.Statement(AstMethodCall)); else if (AstMethodCall.Type == typeof(long)) AstNodes.AddStatement(ast.Assign(MipsMethodEmitter.GPR_l(2), ast.Cast<long>(AstMethodCall))); else if (AstMethodCall.Type == typeof(float)) AstNodes.AddStatement(ast.Assign(MipsMethodEmitter.FPR(0), ast.Cast<float>(AstMethodCall))); else AstNodes.AddStatement(ast.Assign(MipsMethodEmitter.GPR(2), ast.Cast<uint>(AstMethodCall))); return AstNodes; }
private Action<CpuThreadState> CreateDelegateForMethodInfo(MethodInfo MethodInfo, HlePspFunctionAttribute HlePspFunctionAttribute) { if (MethodInfo.DeclaringType != this.GetType()) throw (new Exception("Invalid")); bool SkipLog = HlePspFunctionAttribute.SkipLog; var NotImplementedAttribute = (HlePspNotImplementedAttribute)MethodInfo.GetCustomAttributes(typeof(HlePspNotImplementedAttribute), true).FirstOrDefault(); bool NotImplementedFunc = (NotImplementedAttribute != null) && NotImplementedAttribute.Notice; List<ParamInfo> ParamInfoList; var AstNodes = AstOptimizerPsp.GlobalOptimize( CpuProcessor, ast.Statements( // Do stuff before CreateDelegateForMethodInfoPriv(MethodInfo, HlePspFunctionAttribute, out ParamInfoList) // Do stuff after ) ); var Delegate = GeneratorIL.GenerateDelegate<GeneratorILPsp, Action<CpuThreadState>>( String.Format("Proxy_{0}_{1}", this.GetType().Name, MethodInfo.Name), AstNodes ); //return Delegate; 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; //Console.WriteLine("aaaaaaaaaaaaa"); 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(""); } try { Delegate(CpuThreadState); } catch (InvalidProgramException) { Console.WriteLine("CALLING: {0}", MethodInfo); Console.WriteLine("{0}", (new GeneratorCSharp()).GenerateRoot(AstNodes).ToString()); foreach (var Line in GeneratorIL.GenerateToStringList<GeneratorILPsp>(MethodInfo, AstNodes)) { Console.WriteLine(Line); } throw; } catch (MemoryPartitionNoMemoryException) { CpuThreadState.GPR[2] = (int)SceKernelErrors.ERROR_ERRNO_NO_MEMORY; } catch (SceKernelException SceKernelException) { CpuThreadState.GPR[2] = (int)SceKernelException.SceKernelError; } catch (SceKernelSelfStopUnloadModuleException) { throw; } #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(""); } } }; }
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(""); } } }; }