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