예제 #1
0
        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);
                }
            }
        }
예제 #2
0
        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);
                }
            }
        }
예제 #3
0
        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();
                            }
                        }
                    }
                }
            }
        }