Exemplo n.º 1
0
        protected virtual AstNode _Optimize(AstNodeStmContainer Container)
        {
            if (Container.Nodes.Count == 1) return Container.Nodes[0];

            var NewContainer = new AstNodeStmContainer(Container.Inline);

            foreach (var Node in Container.Nodes)
            {
                if (Node == null) continue;

                if (Node is AstNodeStmContainer)
                {
                    foreach (var Node2 in (Node as AstNodeStmContainer).Nodes)
                    {
                        if (!(Node2 is AstNodeStmEmpty))
                        {
                            NewContainer.AddStatement(Node2);
                        }
                    }
                }
                else
                {
                    if (!(Node is AstNodeStmEmpty))
                    {
                        NewContainer.AddStatement(Node);
                    }
                }
            }

            bool Rebuild = false;
            for (int n = 0; n < NewContainer.Nodes.Count - 1; n++)
            {
                var CurrentNode = NewContainer.Nodes[n];
                var NextNode = NewContainer.Nodes[n + 1];
                if ((CurrentNode is AstNodeStmGotoAlways) && (NextNode is AstNodeStmLabel))
                {
                    if ((CurrentNode as AstNodeStmGotoAlways).AstLabel == (NextNode as AstNodeStmLabel).AstLabel)
                    {
                        NewContainer.Nodes[n] = null;
                        //NewContainer.Nodes[n + 1] = null;
                        Rebuild = true;
                    }
                }
            }

            if (Rebuild)
            {
                return new AstNodeStmContainer(Container.Inline, NewContainer.Nodes.Where(Node => Node != null).ToArray());
            }
            else
            {
                return NewContainer;
            }
        }
Exemplo n.º 2
0
		protected override AstNode _Optimize(AstNodeStmContainer _Container)
		{
			var Node = base._Optimize(_Container);
			if (Node is AstNodeStmContainer)
			{
				var Container = Node as AstNodeStmContainer;
#if ENABLE_OPTIMIZE_LWL_LWR
				Container.Nodes = OptimizeLwlLwr(Container.Nodes);
#endif
				//foreach (var _Node in Container.Nodes)
				//{
				//	if (_Node is AstNodeStmPspInstruction)
				//	{
				//		var PspNode = (_Node as AstNodeStmPspInstruction);
				//		if (PspNode.DisassembledResult.InstructionInfo.InstructionType == InstructionType.Psp)
				//		{
				//
				//			Console.WriteLine(PspNode.DisassembledResult);
				//		}
				//	}
				//}
				return base._Optimize(Container);
			}
			return Node;
		}
 private void TryPutLabelAT(uint PC, AstNodeStmContainer Nodes)
 {
     if (Labels.ContainsKey(PC))
     {
         Nodes.AddStatement(EmitInstructionCountIncrement(false));
         Nodes.AddStatement(ast.Label(Labels[PC]));
     }
     if (LabelsJump.ContainsKey(PC)) Nodes.AddStatement(ast.Label(LabelsJump[PC]));
 }
            //static int DummyTempCounter = 0;
            /// <summary>
            /// PASS 2: Generate code and put labels;
            /// </summary>
            private AstNodeStmContainer GenerateCode()
            {
                foreach (var Label in Labels.ToArray())
                {
                    if (!(Label.Key >= MinPC && Label.Key <= MaxPC))
                    {
                        Labels.Remove(Label.Key);
                    }
                }
                //AnalyzedPC

                InstructionsEmitedSinceLastWaypoint = 0;

                //Debug.WriteLine("PASS2: MinPC:{0:X}, MaxPC:{1:X}", MinPC, MaxPC);

                // Jumps to the entry point.
                var Nodes = new AstNodeStmContainer();

                Nodes.AddStatement(ast.GotoAlways(Labels[EntryPC]));

                for (PC = MinPC; PC <= MaxPC; )
                {
                    if (!AnalyzedPC.Contains(PC))
                    {
                        PC += 4;
                        continue;
                    }
                    uint CurrentInstructionPC = PC;
                    Instruction CurrentInstruction = InstructionReader[PC];
                    InstructionsProcessed++;

                    var BranchInfo = DynarecBranchAnalyzer.GetBranchInfo(CurrentInstruction.Value);

                    // Delayed branch instruction.
                    if ((BranchInfo & DynarecBranchAnalyzer.JumpFlags.BranchOrJumpInstruction) != 0)
                    {
                        InstructionsEmitedSinceLastWaypoint += 2;
                        Nodes.AddStatement(EmitInstructionCountIncrement(true));

                        var BranchAddress = CurrentInstruction.GetBranchAddress(PC);

                        if (BranchInfo.HasFlag(DynarecBranchAnalyzer.JumpFlags.JumpInstruction))
                        {
                            TryPutLabelAT(PC, Nodes);

                            var DelayedBranchInstruction = _GetAstCpuInstructionAT(PC + 4); // Delayed
                            var JumpInstruction = _GetAstCpuInstructionAT(PC + 0); // Jump

                #if !DISABLE_JUMP_GOTO
                            var JumpInstruction2 = CpuEmitter.LoadAT(PC + 0);
                            var JumpDisasm = MipsDisassembler.Disassemble(PC + 0, JumpInstruction2);
                            var JumpJumpPC = JumpDisasm.Instruction.GetJumpAddress(Memory, JumpDisasm.InstructionPC);

                            // An internal jump.
                            if (
                                (JumpDisasm.InstructionInfo.Name == "j")
                                && (LabelsJump.ContainsKey(JumpJumpPC))
                            )
                            {
                                JumpInstruction = new AstNodeStmPspInstruction(JumpDisasm, ast.GotoAlways(LabelsJump[JumpJumpPC]));

                                //Console.WriteLine(
                                //	"{0}: {1} : Function({2:X8}-{3:X8})",
                                //	DummyTempCounter,
                                //	GeneratorCSharpPsp.GenerateString<GeneratorCSharpPsp>(AstOptimizerPsp.GlobalOptimize(CpuProcessor, JumpInstruction)),
                                //	MinPC, MaxPC
                                //);

                                //DummyTempCounter++;
                            }
                            else if (JumpDisasm.InstructionInfo.Name == "j" || JumpDisasm.InstructionInfo.Name == "jal")
                            {
                                CallingPCs.Add(JumpJumpPC);
                            }
                #endif

                            // Put delayed instruction first.
                            Nodes.AddStatement(DelayedBranchInstruction);
                            // A jump outside the current function.
                            Nodes.AddStatement(JumpInstruction);

                            PC += 8;
                        }
                        else
                        {
                            // Branch instruction.
                            Nodes.AddStatement(EmitCpuInstruction());

                            //if ((BranchInfo & CpuBranchAnalyzer.Flags.Likely) != 0)
                            if (BranchInfo.HasFlag(DynarecBranchAnalyzer.JumpFlags.Likely))
                            {
                                //Console.WriteLine("Likely");
                                // Delayed instruction.
                                Nodes.AddStatement(CpuEmitter._branch_likely(EmitCpuInstruction()));
                            }
                            else
                            {
                                //Console.WriteLine("Not Likely");
                                // Delayed instruction.
                                Nodes.AddStatement(EmitCpuInstruction());
                            }

                            if (CurrentInstructionPC + 4 != BranchAddress)
                            {
                                if (Labels.ContainsKey(BranchAddress))
                                {
                                    Nodes.AddStatement(CpuEmitter._branch_post(Labels[BranchAddress], BranchAddress));
                                }
                                // Code not reached.
                                else
                                {
                                    throw (new InvalidOperationException("!Labels.ContainsKey(BranchAddress)"));
                                }
                            }
                            else
                            {
                                throw (new InvalidOperationException("Invalid branch!"));
                            }
                        }
                    }
                    // Normal instruction.
                    else
                    {
                        // Syscall instruction.
                        if ((BranchInfo & DynarecBranchAnalyzer.JumpFlags.SyscallInstruction) != 0)
                        {
                            Nodes.AddStatement(StorePC());
                        }
                        Nodes.AddStatement(EmitCpuInstruction());
                        if ((BranchInfo & DynarecBranchAnalyzer.JumpFlags.SyscallInstruction) != 0)
                        {
                            // On this special Syscall
                            if (CurrentInstruction.CODE == SyscallInfo.NativeCallSyscallCode)
                            {
                                //PC += 4;
                                break;
                            }
                        }
                    }
                }

                //MipsMethodEmiter.GenerateIL(Nodes);
                ShowInstructionStats();

                //if (BreakPoint) IsDebuggerPresentDebugBreak();

                return Nodes;
            }
Exemplo n.º 5
0
		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;
		}
			/// <summary>
			/// PASS 2: Generate code and put labels;
			/// </summary>
			private AstNodeStmContainer GenerateCode()
			{
				foreach (var Label in Labels.ToArray())
				{
					if (!(Label.Key >= MinPC && Label.Key <= MaxPC))
					{
						Labels.Remove(Label.Key);
					}
				}
				//AnalyzedPC

				InstructionsEmitedSinceLastWaypoint = 0;

				//Debug.WriteLine("PASS2: MinPC:{0:X}, MaxPC:{1:X}", MinPC, MaxPC);

				// Jumps to the entry point.
				var Nodes = new AstNodeStmContainer();

				Nodes.AddStatement(ast.GotoAlways(Labels[EntryPC]));

				for (PC = MinPC; PC <= MaxPC; )
				{
					uint CurrentInstructionPC = PC;
					Instruction CurrentInstruction = InstructionReader[PC];
					InstructionsProcessed++;

					var BranchInfo = DynarecBranchAnalyzer.GetBranchInfo(CurrentInstruction.Value);

					// Delayed branch instruction.
					if ((BranchInfo & DynarecBranchAnalyzer.JumpFlags.BranchOrJumpInstruction) != 0)
					{
						InstructionsEmitedSinceLastWaypoint += 2;
						Nodes.AddStatement(EmitInstructionCountIncrement(true));

						var BranchAddress = CurrentInstruction.GetBranchAddress(PC);

						if (BranchInfo.HasFlag(DynarecBranchAnalyzer.JumpFlags.JumpInstruction))
						{
							TryPutLabelAT(PC, Nodes);

							var DelayedBranchInstruction = _EmitCpuInstructionAT(PC + 4); // Delayed
							var JumpInstruction = _EmitCpuInstructionAT(PC + 0); // Jump

							// Put delayed instruction first.
							Nodes.AddStatement(DelayedBranchInstruction);

#if true
							var JumpDisasm = JumpInstruction.DisassembledResult;
							var JumpJumpPC = JumpDisasm.Instruction.GetJumpAddress(JumpDisasm.InstructionPC);
							// An internal jump.
							if (
								(JumpDisasm.InstructionInfo.Name == "j")
								&& (LabelsJump.ContainsKey(JumpJumpPC))
							)
							{
								Nodes.AddStatement(ast.Statements(
									ast.Comment(String.Format("{0:X8}: j 0x{1:X8}", JumpDisasm.InstructionPC, JumpJumpPC)),
									ast.GotoAlways(LabelsJump[JumpJumpPC])
								));
							}
							// A jump outside the current function.
							else
#endif
							{
								Nodes.AddStatement(JumpInstruction);
							}
							PC += 8;
						}
						else
						{
							// Branch instruction.
							Nodes.AddStatement(EmitCpuInstruction());

							//if ((BranchInfo & CpuBranchAnalyzer.Flags.Likely) != 0)
							if (BranchInfo.HasFlag(DynarecBranchAnalyzer.JumpFlags.Likely))
							{
								//Console.WriteLine("Likely");
								// Delayed instruction.
								Nodes.AddStatement(CpuEmitter._branch_likely(EmitCpuInstruction()));
							}
							else
							{
								//Console.WriteLine("Not Likely");
								// Delayed instruction.
								Nodes.AddStatement(EmitCpuInstruction());
							}

							if (CurrentInstructionPC + 4 != BranchAddress)
							{
								if (Labels.ContainsKey(BranchAddress))
								{
									Nodes.AddStatement(CpuEmitter._branch_post(Labels[BranchAddress], BranchAddress));
								}
								// Code not reached.
								else
								{
								}
							}
						}
					}
					// Normal instruction.
					else
					{
						// Syscall instruction.
						if ((BranchInfo & DynarecBranchAnalyzer.JumpFlags.SyscallInstruction) != 0)
						{
							Nodes.AddStatement(StorePC());
						}
						Nodes.AddStatement(EmitCpuInstruction());
						if ((BranchInfo & DynarecBranchAnalyzer.JumpFlags.SyscallInstruction) != 0)
						{
							// On this special Syscall
							if (CurrentInstruction.CODE == SyscallInfo.NativeCallSyscallCode)
							{
								//PC += 4;
								break;
							}
						}
					}
				}

				//MipsMethodEmiter.GenerateIL(Nodes);
				//ShowInstructionStats();

				//if (BreakPoint) IsDebuggerPresentDebugBreak();

				return Nodes;
			}