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; } }
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; }
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; }