コード例 #1
0
        public static bool isEndBlockInsn(int pc, int opcode, Common.Instruction insn)
        {
            if (insn.hasFlags(Common.Instruction.FLAG_ENDS_BLOCK))
            {
                if (insn.hasFlags(Common.Instruction.FLAG_IS_CONDITIONAL | Common.Instruction.FLAG_IS_BRANCHING))
                {
                    // Detect the conditional
                    //    "BEQ $xx, $xx, target"
                    // which is equivalent to the unconditional
                    //    "B target"
                    if (insn == Instructions.BEQ)
                    {
                        int rt = (opcode >> 16) & 0x1F;
                        int rs = (opcode >> 21) & 0x1F;
                        if (rs == rt)
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        Console.WriteLine(string.Format("Unknown conditional instruction ending a block: {0}", insn.disasm(pc, opcode)));
                    }
                }
                else
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #2
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private IExecutable analyse(CompilerContext context, int startAddress, bool recursive, int instanceIndex) throws ClassFormatError
        private IExecutable analyse(CompilerContext context, int startAddress, bool recursive, int instanceIndex)
        {
            if (log.TraceEnabled)
            {
                log.trace(string.Format("Compiler.analyse Block 0x{0:X8}", startAddress));
            }
            int            maxBranchInstructions = int.MaxValue;  // 5 for FRONTIER_1337 homebrew
            MemorySections memorySections        = MemorySections.Instance;
            CodeBlock      codeBlock             = new CodeBlock(startAddress, instanceIndex);
            Stack <int>    pendingBlockAddresses = new Stack <int>();

            pendingBlockAddresses.Clear();
            pendingBlockAddresses.Push(startAddress);
            ISet <int> branchingToAddresses = new HashSet <int>();

            while (pendingBlockAddresses.Count > 0)
            {
                int pc = pendingBlockAddresses.Pop();
                if (!isAddressGood(pc))
                {
                    if (IgnoreInvalidMemory)
                    {
                        Console.WriteLine(string.Format("IGNORING: Trying to compile an invalid address 0x{0:X8} while compiling from 0x{1:X8}", pc, startAddress));
                    }
                    else
                    {
                        Console.WriteLine(string.Format("Trying to compile an invalid address 0x{0:X8} while compiling from 0x{1:X8}", pc, startAddress));
                    }
                    return(null);
                }
                bool isBranchTarget = true;
                int  endPc          = MemoryMap.END_RAM;

                // Handle branching to a delayed instruction.
                // The delayed instruction has already been analysed, but the next
                // address maybe not.
                if (context.analysedAddresses.Contains(pc) && !context.analysedAddresses.Contains(pc + 4))
                {
                    pc += 4;
                }

                if (context.analysedAddresses.Contains(pc) && isBranchTarget)
                {
                    codeBlock.IsBranchTarget = pc;
                }
                else
                {
                    IMemoryReader memoryReader = MemoryReader.getMemoryReader(pc, 4);
                    while (!context.analysedAddresses.Contains(pc) && pc <= endPc)
                    {
                        int opcode = memoryReader.readNext();

                        Common.Instruction insn = Decoder.instruction(opcode);

                        context.analysedAddresses.Add(pc);
                        int npc = pc + 4;

                        int  branchingTo           = 0;
                        bool isBranching           = false;
                        bool checkDynamicBranching = false;
                        if (insn.hasFlags(Common.Instruction.FLAG_IS_BRANCHING))
                        {
                            branchingTo = branchTarget(npc, opcode);
                            isBranching = true;
                        }
                        else if (insn.hasFlags(Common.Instruction.FLAG_IS_JUMPING))
                        {
                            branchingTo           = jumpTarget(npc, opcode);
                            isBranching           = true;
                            checkDynamicBranching = true;
                        }

                        if (isEndBlockInsn(pc, opcode, insn))
                        {
                            endPc = npc;
                        }
                        else if (pc < endPc && insn.hasFlags(Common.Instruction.FLAG_SYSCALL))
                        {
                            endPc = pc;
                        }

                        if (insn.hasFlags(Common.Instruction.FLAG_STARTS_NEW_BLOCK))
                        {
                            if (recursive)
                            {
                                context.blocksToBeAnalysed.Push(branchingTo);
                            }
                        }
                        else if (isBranching)
                        {
                            if (branchingTo != 0)
                            {                             // Ignore "J 0x00000000" instruction
                                bool analyseBranch = true;
                                if (maxBranchInstructions < 0)
                                {
                                    analyseBranch = false;
                                }
                                else
                                {
                                    maxBranchInstructions--;

                                    // Analyse only the jump instructions that are jumping to
                                    // non-writable memory sections. A jump to a writable memory
                                    // section has to be interpreted at runtime to check if the
                                    // reached code has not been changed (i.e. invalidated).
                                    if (checkDynamicBranching && memorySections.canWrite(branchingTo, false))
                                    {
                                        analyseBranch = false;
                                    }
                                }

                                if (analyseBranch)
                                {
                                    pendingBlockAddresses.Push(branchingTo);
                                }
                                else
                                {
                                    branchingToAddresses.Add(branchingTo);
                                }
                            }
                        }

                        bool useMMIO = useMMIOAddresses.Contains(pc & Memory.addressMask);

                        codeBlock.addInstruction(pc, opcode, insn, isBranchTarget, isBranching, branchingTo, useMMIO);
                        pc = npc;

                        isBranchTarget = false;
                    }
                }

                foreach (int branchingTo in branchingToAddresses)
                {
                    codeBlock.IsBranchTarget = branchingTo;
                }
            }

            codeBlock.addCodeBlock();

            IExecutable executable;

            if (RuntimeContext.CompilerEnabled || codeBlock.hasFlags(FLAG_SYSCALL))
            {
                executable = codeBlock.getExecutable(context);
            }
            else
            {
                executable = null;
            }
            if (log.TraceEnabled)
            {
                log.trace("Executable: " + executable);
            }

            return(executable);
        }