private static void logCodeBlock(CodeBlock codeBlock, long allCycles, long instructionCount, long callCount, int count, IList <int> sortedBackBranches) { string name = codeBlock.ClassName; NativeCodeManager nativeCodeManager = Compiler.Instance.NativeCodeManager; NativeCodeSequence nativeCodeSequence = nativeCodeManager.getCompiledNativeCodeBlock(codeBlock.StartAddress); if (nativeCodeSequence != null) { name = string.Format("{0} ({1})", name, nativeCodeSequence.Name); } int lowestAddress = codeBlock.LowestAddress; int highestAddress = codeBlock.HighestAddress; int Length = (highestAddress - lowestAddress) / 4 + 1; double percentage = 0; if (allCycles != 0) { percentage = (instructionCount / (double)allCycles) * 100; } //JAVA TO C# CONVERTER TODO TASK: The following line has a Java format specifier which cannot be directly translated to .NET: //ORIGINAL LINE: Console.WriteLine(String.format("%s %,d instructions (%2.3f%%), %,d calls (%08X - %08X, Length %d)", name, instructionCount, percentage, callCount, lowestAddress, highestAddress, Length)); Console.WriteLine(string.Format("%s %,d instructions (%2.3f%%), %,d calls (%08X - %08X, Length %d)", name, instructionCount, percentage, callCount, lowestAddress, highestAddress, Length)); if (count < detailedCodeBlockLogThreshold && codeBlock.Length <= codeLogMaxLength) { logCode(codeBlock); } foreach (int address in sortedBackBranches) { if (address < lowestAddress || address > highestAddress) { continue; } CodeInstruction codeInstruction = codeBlock.getCodeInstruction(address); if (codeInstruction == null) { continue; } int branchingToAddress = codeInstruction.BranchingTo; // Add 2 for branch instruction itself and delay slot int backBranchLength = (address - branchingToAddress) / 4 + 2; //JAVA TO C# CONVERTER TODO TASK: The following line has a Java format specifier which cannot be directly translated to .NET: //ORIGINAL LINE: Console.WriteLine(String.format(" Back Branch %08X %,d times (Length %d)", address, backBranchCounts.get(address), backBranchLength)); Console.WriteLine(string.Format(" Back Branch %08X %,d times (Length %d)", address, backBranchCounts[address], backBranchLength)); if (count < detailedCodeBlockLogThreshold && backBranchLength <= backBranchMaxLength) { logCode(codeBlock, branchingToAddress, backBranchLength, backBranchContextBefore, backBranchContextAfter, address); } } }
private void compileBranch(CompilerContext context, MethodVisitor mv) { // Perform any required checkSync() before executing the delay slot instruction, // so that the emulation can be paused in a consistent state // before the branch and its delay slot. context.startJump(BranchingTo); int branchingOpcode = getBranchingOpcode(context, mv); if (branchingOpcode != Opcodes.NOP) { CodeInstruction branchingToCodeInstruction = context.CodeBlock.getCodeInstruction(BranchingTo); // Fallback when branching to the 2nd instruction of a native code sequence whose // 1st instruction is the delay slot instruction. // In such a case, assume a branch to the native code sequence. if (branchingToCodeInstruction == null) { CodeInstruction nativeCodeInstruction = context.getCodeInstruction(BranchingTo - 4); if (nativeCodeInstruction != null && nativeCodeInstruction is NativeCodeInstruction) { NativeCodeSequence nativeCodeSequence = ((NativeCodeInstruction)nativeCodeInstruction).NativeCodeSequence; if (getDelaySlotCodeInstruction(context).Opcode == nativeCodeSequence.FirstOpcode) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("0x{0:X8}: branching to the 2nd instruction of a native code sequence, assuming the 1st instruction", Address)); } branchingToCodeInstruction = nativeCodeInstruction; } } } if (branchingToCodeInstruction != null) { // Some applications do have branches to delay slot instructions // (probably from programmers that didn't know/care about delay slots). // // Handle a branch to a NOP in a delay slot: just skip the NOP and assume the branch // is to the instruction following the NOP. // E.g.: // 0x00000000 b 0x00000014 -> branching to a NOP in a delay slot, assume a branch to 0x00000018 // 0x00000004 nop // ... // 0x00000010 b 0x00000020 // 0x00000014 nop // 0x00000018 something // if (branchingToCodeInstruction.Insn == Instructions.NOP) { CodeInstruction beforeBranchingToCodeInstruction = context.CodeBlock.getCodeInstruction(BranchingTo - 4); if (beforeBranchingToCodeInstruction != null && beforeBranchingToCodeInstruction.hasFlags(Instruction.FLAG_HAS_DELAY_SLOT)) { //if (log.DebugEnabled) { Console.WriteLine(string.Format("0x{0:X8}: branching to a NOP in a delay slot, correcting to the next instruction", Address)); } branchingToCodeInstruction = context.CodeBlock.getCodeInstruction(BranchingTo + 4); } } context.visitJump(branchingOpcode, branchingToCodeInstruction); } else { context.visitJump(branchingOpcode, BranchingTo); } } }
private void scanNativeCodeSequences(CompilerContext context) { NativeCodeManager nativeCodeManager = context.NativeCodeManager; //JAVA TO C# CONVERTER WARNING: Unlike Java's ListIterator, enumerators in .NET do not allow altering the collection: for (IEnumerator <CodeInstruction> lit = codeInstructions.GetEnumerator(); lit.MoveNext();) { CodeInstruction codeInstruction = lit.Current; NativeCodeSequence nativeCodeSequence = nativeCodeManager.getNativeCodeSequence(codeInstruction, this); if (nativeCodeSequence != null) { if (nativeCodeSequence.Hook) { HookCodeInstruction hookCodeInstruction = new HookCodeInstruction(nativeCodeSequence, codeInstruction); // Replace the current code instruction by the hook code instruction //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: lit.remove(); lit.add(hookCodeInstruction); } else { NativeCodeInstruction nativeCodeInstruction = new NativeCodeInstruction(codeInstruction.Address, nativeCodeSequence); if (nativeCodeInstruction.Branching) { IsBranchTarget = nativeCodeInstruction.BranchingTo; } if (nativeCodeSequence.WholeCodeBlock) { codeInstructions.Clear(); codeInstructions.AddLast(nativeCodeInstruction); } else { // Remove the first opcode that started this native code sequence //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: lit.remove(); // Add any code instructions that need to be inserted before // the native code sequence IList <CodeInstruction> beforeCodeInstructions = nativeCodeSequence.BeforeCodeInstructions; if (beforeCodeInstructions != null) { foreach (CodeInstruction beforeCodeInstruction in beforeCodeInstructions) { CodeInstruction newCodeInstruction = new CodeInstruction(beforeCodeInstruction); newCodeInstruction.Address = codeInstruction.Address; lit.add(newCodeInstruction); } } // Add the native code sequence itself lit.add(nativeCodeInstruction); // Remove the further opcodes from the native code sequence //JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops: for (int i = nativeCodeSequence.NumOpcodes - 1; i > 0 && lit.hasNext(); i--) { lit.Current; //JAVA TO C# CONVERTER TODO TASK: .NET enumerators are read-only: lit.remove(); } } } } } }