示例#1
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");
            }
        }
示例#2
0
        /*
         * if (enabled && prefix.enabled) {
         *      foreach (i, value; src) {
         *              if (prefix.mask(i)) continue;
         *
         *              switch (prefix.saturation(i)) {
         *                      case 1: value = clamp!(float)(value,  0.0, 1.0); break;
         *                      case 3: value = clamp!(float)(value, -1.0, 1.0); break;
         *                      default: break;
         *              }
         *
         * dst[i] = value;
         *      }
         *      prefix.enabled = false;
         * } else {
         *      foreach (i, value; src) *dst[i] = value;
         * }
         */

        private void VfpuSave_Register(uint Register, int Index, uint VectorSize, VfpuPrefix Prefix, Action Action, bool Debug = false)
        {
            CheckPrefixUsage(ref Prefix);
            _VfpuLoadVectorWithIndexPointer(Register, (uint)Index, VectorSize, Debug);
            {
                Action();
                if (Prefix.Enabled)
                {
                    if (!Prefix.DestinationMask(Index))
                    {
                        float Min = 0, Max = 0;
                        bool  DoClamp = false;
                        switch (Prefix.DestinationSaturation(Index))
                        {
                        case 1: DoClamp = true; Min = 0.0f; Max = 1.0f; break;

                        case 3: DoClamp = true; Min = -1.0f; Max = 1.0f; break;

                        default: break;
                        }
                        if (DoClamp)
                        {
                            MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_R4, Min);
                            MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_R4, Max);
                            MipsMethodEmiter.CallMethod(typeof(MathFloat), "Clamp");
                        }
                    }
                }
            }
            MipsMethodEmiter.ILGenerator.Emit(OpCodes.Stind_R4);
        }
示例#3
0
 public void ceil_w_s()
 {
     MipsMethodEmiter.SaveFPR_I(FD, () =>
     {
         MipsMethodEmiter.LoadFPR(FS);
         MipsMethodEmiter.CallMethod(typeof(MathFloat), "Ceil");
     });
 }
示例#4
0
 public void rotrv()
 {
     MipsMethodEmiter.SaveGPR(RD, () =>
     {
         MipsMethodEmiter.LoadGPR_Unsigned(RT);
         MipsMethodEmiter.LoadGPR_Unsigned(RS);
         MipsMethodEmiter.CallMethod(this.GetType(), "_rotr");
     });
 }
示例#5
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);
 }
示例#6
0
 // OP_V_INTERNAL_IN_N!(1, "1.0f / sqrt(v)");
 public void vrsq()
 {
     VectorOperationSaveVd((Index, Load) =>
     {
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_R4, 1.0f);
         Load(1);
         MipsMethodEmiter.CallMethod(typeof(MathFloat), "Sqrt");
         MipsMethodEmiter.ILGenerator.Emit(OpCodes.Div);
     });
 }
示例#7
0
        /*
         * if (enabled && prefix.enabled) {
         *      foreach (i, ref value; dst) {
         *              // Constant.
         *              if (prefix.constant(i)) {
         *                      final switch (prefix.index(i)) {
         *                              case 0: value = prefix.absolute(i) ? (3.0f       ) : (0.0f); break;
         *                              case 1: value = prefix.absolute(i) ? (1.0f / 3.0f) : (1.0f); break;
         *                              case 2: value = prefix.absolute(i) ? (1.0f / 4.0f) : (2.0f); break;
         *                              case 3: value = prefix.absolute(i) ? (1.0f / 6.0f) : (0.5f); break;
         *                      }
         *              }
         *              // Value
         *              else {
         *                      value = *src[prefix.index(i)];
         *              }
         *
         *              if (prefix.absolute(i)) value = abs(value);
         *              if (prefix.negate  (i)) value = -value;
         *      }
         *      prefix.enabled = false;
         * } else {
         *      foreach (n, ref value; dst) value = *src[n];
         * }
         */

        private void VfpuLoad_Register(uint Register, int Index, uint VectorSize, ref VfpuPrefix Prefix, bool Debug = false)
        {
            //Console.Error.WriteLine("{0:X}", PC);
            CheckPrefixUsage(ref Prefix);
            //Console.Error.WriteLine("PREFIX [1]!" + Index);

            if (Prefix.Enabled)
            {
                //Console.Error.WriteLine("PREFIX [2]!" + Index);
                Prefix.UsedPC = PC;
                Prefix.UsedCount++;

                // Constant.
                if (Prefix.SourceConstant(Index))
                {
                    float Value = 0.0f;
                    switch (Prefix.SourceIndex(Index))
                    {
                    case 0: Value = Prefix.SourceAbsolute(Index) ? (3.0f) : (0.0f); break;

                    case 1: Value = Prefix.SourceAbsolute(Index) ? (1.0f / 3.0f) : (1.0f); break;

                    case 2: Value = Prefix.SourceAbsolute(Index) ? (1.0f / 4.0f) : (2.0f); break;

                    case 3: Value = Prefix.SourceAbsolute(Index) ? (1.0f / 6.0f) : (0.5f); break;

                    default: throw(new InvalidOperationException());
                    }
                    //Console.Error.WriteLine("VALUE:: " + Value);
                    MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_R4, Value);
                }
                // Value.
                else
                {
                    _VfpuLoadVectorWithIndexPointer(Register, (uint)Prefix.SourceIndex(Index), VectorSize, Debug);
                    MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldind_R4);
                }

                if (Prefix.SourceAbsolute(Index))
                {
                    //MipsMethodEmiter.ILGenerator.Emit(OpCodes);
                    MipsMethodEmiter.CallMethod(typeof(MathFloat), "Abs");
                }
                if (Prefix.SourceNegate(Index))
                {
                    MipsMethodEmiter.ILGenerator.Emit(OpCodes.Neg);
                }
            }
            else
            {
                _VfpuLoadVectorWithIndexPointer(Register, (uint)Index, VectorSize, Debug);
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldind_R4);
            }
        }
示例#8
0
        /// <summary>
        /// ID("mtv",         VM("010010:00:111:rt:0:0000000:0:vd"), "%t, %zs", ADDR_TYPE_NONE, INSTR_TYPE_PSP),
        /// </summary>
        public void mtv()
        {
            /*
             * Console.Error.WriteLine("MTV:{0}", Instruction.VD);
             * _VfpuLoadVectorWithIndexPointer(Instruction.VD, 0, 1);
             * MipsMethodEmiter.LoadGPR_Signed(Instruction.RT);
             * MipsMethodEmiter.CallMethod(typeof(MathFloat), "ReinterpretIntAsFloat");
             * MipsMethodEmiter.ILGenerator.Emit(OpCodes.Stind_R4);
             */

            VectorOperationSaveVd(1, (Index, Load) =>
            {
                MipsMethodEmiter.LoadGPR_Signed(RT);
                MipsMethodEmiter.CallMethod(typeof(MathFloat), "ReinterpretIntAsFloat");
            });
        }
示例#9
0
        // ROTate
        public void vrot()
        {
            var  VectorSize = Instruction.ONE_TWO;
            uint imm5       = Instruction.IMM5;

            if (VectorSize == 1)
            {
                throw(new NotImplementedException());
            }

            //uint imm5 = instruction.IMM5;
            int  SinIndex  = (int)((imm5 >> 2) & 3);
            int  CosIndex  = (int)((imm5 >> 0) & 3);
            bool NegateSin = ((imm5 & 16) != 0);

            foreach (var Index in XRange(VectorSize))
            {
                Save_VD(Index, VectorSize, () =>
                {
                    if (SinIndex == CosIndex)
                    {
                        // Angle [-1, +1]
                        Load_VS(0, 1);                         // Angle
                        MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_R4, (float)(Math.PI / 2.0f));
                        MipsMethodEmiter.ILGenerator.Emit(OpCodes.Mul);
                        MipsMethodEmiter.CallMethod(typeof(MathFloat), "Sin");
                        if (NegateSin)
                        {
                            MipsMethodEmiter.ILGenerator.Emit(OpCodes.Neg);
                        }
                    }
                    else
                    {
                        MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_R4, (float)(0.0f));
                    }
                });
            }

            if (SinIndex != CosIndex)
            {
                Save_VD(SinIndex, VectorSize, () =>
                {
                    // Angle [-1, +1]
                    Load_VS(0, 1);                     // Angle
                    MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_R4, (float)(Math.PI / 2.0f));
                    MipsMethodEmiter.ILGenerator.Emit(OpCodes.Mul);
                    MipsMethodEmiter.CallMethod(typeof(MathFloat), "Sin");
                    if (NegateSin)
                    {
                        MipsMethodEmiter.ILGenerator.Emit(OpCodes.Neg);
                    }
                });
            }

            Save_VD(CosIndex, VectorSize, () =>
            {
                // Angle [-1, +1]
                Load_VS(0, 1);                 // Angle
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Ldc_R4, (float)(Math.PI / 2.0f));
                MipsMethodEmiter.ILGenerator.Emit(OpCodes.Mul);
                MipsMethodEmiter.CallMethod(typeof(MathFloat), "Cos");
            });
        }
示例#10
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("");
                    }
                }
            };
        }