示例#1
0
        /*
         * registers[instruction.RT] = (
         *     (registers[instruction.RT] & 0x_0000_FFFF) |
         *     ((memory.tread!(ushort)(registers[instruction.RS] + instruction.IMM - 1) << 16) & 0x_FFFF_0000)
         * );
         */
        public void lwl()
        {
            MipsMethodEmiter.SaveGPR(RT, () =>
            {
                // registers[instruction.RT] & 0x_0000_FFFF
                MipsMethodEmiter.LoadGPR_Unsigned(RT);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, 0x0000FFFF);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.And);

                // ((memory.tread!(ushort)(registers[instruction.RS] + instruction.IMM - 1) << 16) & 0x_FFFF_0000)
                _save_pc();
                MipsMethodEmiter._getmemptr(() =>
                {
                    MipsMethodEmiter.LoadGPR_Unsigned(RS);
                    MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, IMM - 1);
                    MipsMethodEmiter.ILGenerator.Emit(OpCodes.Add);
                });
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldind_I2);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, 16);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Shl);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, 0xFFFF0000);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.And);

                // OR
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Or);
            });
        }
示例#2
0
        private void lv_sv_l_r_q(bool left, bool save)
        {
            var vt  = Instruction.VT5 | (Instruction.VT1 << 5);
            var m   = (vt >> 2) & 7;
            var i   = (vt >> 0) & 3;
            var dir = (vt & 32) != 0;

            {
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldarg_0);                 // CpuThreadState
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, m);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, i);
                MipsMethodEmiter.LoadGPR_Unsigned(RS);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, Instruction.IMM14 * 4);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Add);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, dir ? 1 : 0);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, save ? 1 : 0);
            }

            if (left)
            {
                MipsMethodEmiter.CallMethod(this.GetType(), "_lvl_svl_q");
            }
            else
            {
                MipsMethodEmiter.CallMethod(this.GetType(), "_lvr_svr_q");
            }
        }
示例#3
0
 public void divu()
 {
     MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldarg_0);
     MipsMethodEmiter.LoadGPR_Unsigned(RS);
     MipsMethodEmiter.LoadGPR_Unsigned(RT);
     MipsMethodEmiter.ILGenerator.Emit(OpCodes.Call, typeof(CpuEmiter).GetMethod("_divu_impl"));
 }
示例#4
0
 private void _save_i(OpCode OpCode)
 {
     _save_common(() =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RT);
         MipsMethodEmiter.ILGenerator.Emit(OpCode);
     });
 }
示例#5
0
 public void mtic()
 {
     //throw (new NotImplementedException());
     MipsMethodEmiter.SaveFieldI4(typeof(CpuThreadState).GetField("IC"), () =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RT);
     });
 }
示例#6
0
 public void wsbw()
 {
     MipsMethodEmiter.SaveGPR(RD, () =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RT);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Call, typeof(CpuEmiter).GetMethod("_wsbw_impl"));
     });
 }
示例#7
0
 private void _load_memory_imm14_index(uint Index)
 {
     MipsMethodEmiter._getmemptr(() =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RS);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, Instruction.IMM14 * 4 + Index * 4);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Add);
     });
 }
示例#8
0
 /////////////////////////////////////////////////////////////////////////////////////////////////
 // BIT REVerse.
 /////////////////////////////////////////////////////////////////////////////////////////////////
 public void bitrev()
 {
     MipsMethodEmiter.SaveGPR(RD, () =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RT);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Call, typeof(CpuEmiter).GetMethod("bitrev_impl"));
     });
     //throw (new NotImplementedException());
 }
示例#9
0
 public void rotrv()
 {
     MipsMethodEmiter.SaveGPR(RD, () =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RT);
         MipsMethodEmiter.LoadGPR_Unsigned(RS);
         MipsMethodEmiter.CallMethod(this.GetType(), "_rotr");
     });
 }
示例#10
0
 public void seh()
 {
     MipsMethodEmiter.SaveGPR(RD, () =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RT);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Conv_I2);
         //MipsMethodEmiter.ILGenerator.Emit(OpCodes.Conv_I4);
     });
 }
示例#11
0
 public void ext()
 {
     MipsMethodEmiter.SaveGPR(RT, () =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RS);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, Instruction.POS);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, Instruction.SIZE_E);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Call, typeof(CpuEmiter).GetMethod("_ext_impl"));
     });
 }
示例#12
0
        /////////////////////////////////////////////////////////////////////////////////////////////////
        // Move if Zero/Non zero.
        /////////////////////////////////////////////////////////////////////////////////////////////////
        private void _movzn(OpCode OpCode)
        {
            var SkipMoveLabel = MipsMethodEmiter.ILGenerator.DefineLabel();

            MipsMethodEmiter.LoadGPR_Unsigned(RT);
            MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4_0);
            MipsMethodEmiter.ILGenerator.Emit(OpCode, SkipMoveLabel);
            MipsMethodEmiter.SET_REG(RD, RS);
            MipsMethodEmiter.ILGenerator.MarkLabel(SkipMoveLabel);
        }
示例#13
0
 public void rotr()
 {
     MipsMethodEmiter.SaveGPR(RD, () =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RT);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, Instruction.POS);
         MipsMethodEmiter.CallMethod(this.GetType(), "_rotr");
     });
     //$rd = ROTR($rt, $ps);
 }
示例#14
0
 private void _save_common(Action Action)
 {
     _save_pc();
     MipsMethodEmiter._getmemptr(() =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RS);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, IMM);
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Add);
     });
     Action();
 }
示例#15
0
        public void jr()
        {
            // RETURN
            if (RS == 31)
            {
            }

            MipsMethodEmiter.SavePC(() =>
            {
                MipsMethodEmiter.LoadGPR_Unsigned(RS);
            });
            MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ret);
        }
示例#16
0
 // Load Word to Cop1 floating point.
 // Store Word from Cop1 floating point.
 public void lwc1()
 {
     MipsMethodEmiter.SaveFPR_I(FT, () =>
     {
         _save_pc();
         MipsMethodEmiter._getmemptr(() =>
         {
             MipsMethodEmiter.LoadGPR_Unsigned(RS);
             MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, IMM);
             MipsMethodEmiter.ILGenerator.Emit(OpCodes.Add);
         });
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldind_U4);
     });
 }
示例#17
0
        public void swr()
        {
            _save_pc();
            MipsMethodEmiter._getmemptr(() =>
            {
                MipsMethodEmiter.LoadGPR_Unsigned(RS);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, IMM - 0);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Add);
            });

            MipsMethodEmiter.LoadGPR_Unsigned(RT);
            MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, 0);
            MipsMethodEmiter.ILGenerator.Emit(OpCodes.Shr);
            MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_I4, 0x0000FFFF);
            MipsMethodEmiter.ILGenerator.Emit(OpCodes.And);
            MipsMethodEmiter.ILGenerator.Emit(OpCodes.Stind_I2);
        }
示例#18
0
 public void mtlo()
 {
     MipsMethodEmiter.SaveLO(() => { MipsMethodEmiter.LoadGPR_Unsigned(RS); });
 }
示例#19
0
 public void mthi()
 {
     MipsMethodEmiter.SaveHI(() => { MipsMethodEmiter.LoadGPR_Unsigned(RS); });
 }
示例#20
0
        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("");
                    }
                }
            };
        }
示例#21
0
        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("");
                    }
                }
            };
        }