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("");
                    }
                }
            });
        }
        public Result CreateDelegate(AstNodeStm astNodeStm, int totalInstructions)
        {
            var time0 = DateTime.UtcNow;

            astNodeStm = AstOptimizerPsp.GlobalOptimize(_processor, Ast.Statements(astNodeStm, Ast.Return()));

            var time1 = DateTime.UtcNow;

#if DEBUG_GENERATE_IL
            Console.WriteLine("{0}", GeneratorIL.GenerateToString <GeneratorILPsp>(DynamicMethod, AstNodeStm));
#endif
#if DEBUG_GENERATE_IL_CSHARP
            Console.WriteLine("{0}", AstNodeExtensions.ToCSharpString(AstNodeStm).Replace("CpuThreadState.", ""));
#endif

            Action <CpuThreadState> Delegate;
            var time2 = time1;

            var disableOptimizations = DynarecConfig.DisableDotNetJitOptimizations;
            if (totalInstructions >= DynarecConfig.InstructionCountToDisableOptimizations)
            {
                disableOptimizations = true;
            }

            if (Platform.IsMono)
            {
                disableOptimizations = false;
            }
            if (DynarecConfig.ForceJitOptimizationsOnEvenLargeFunctions)
            {
                disableOptimizations = false;
            }

            try
            {
                Delegate = MethodCreator.CreateDynamicMethod <Action <CpuThreadState> >(
                    //Delegate = MethodCreator.CreateMethodInClass<Action<CpuThreadState>>(
                    Assembly.GetExecutingAssembly().ManifestModule,
                    $"DynamicMethod_0x{this._pc:X}",
                    disableOptimizations,
                    dynamicMethod =>
                {
                    astNodeStm.GenerateIl(dynamicMethod);
                    time2 = DateTime.UtcNow;
                }
                    );
            }
            catch (InvalidProgramException)
            {
                Console.Error.WriteLine("Invalid Delegate:");
#if LOG_TRACE
                Console.WriteLine("Invalid Delegate:");
                foreach (var Line in SafeILGenerator.GetEmittedInstructions())
                {
                    if (Line.Substr(0, 1) == ":")
                    {
                        Console.WriteLine("{0}", Line);
                    }
                    else
                    {
                        Console.WriteLine("    {0}", Line);
                    }
                }
#endif
                throw;
            }

            var time3 = DateTime.UtcNow;

            return(new Result
            {
                Delegate = Delegate,
                DisableOptimizations = disableOptimizations,
                TimeOptimize = time1 - time0,
                TimeGenerateIl = time2 - time1,
                TimeCreateDelegate = time3 - time2,
            });
        }