Example #1
0
        public virtual bool checkSimpleInterpretedCodeBlock(CodeBlock codeBlock)
        {
            bool isSimple  = true;
            int  insnCount = 0;

            Common.Instruction[] insns = new Common.Instruction[100];
            int[] opcodes    = new int[100];
            int   opcodeJrRa = AllegrexOpcodes.JR | (Common._ra << 21);           // jr $ra

            IMemoryReader memoryReader   = MemoryReader.getMemoryReader(codeBlock.StartAddress, 4);
            int           notSimpleFlags = FLAG_IS_BRANCHING | FLAG_IS_JUMPING | FLAG_STARTS_NEW_BLOCK | FLAG_ENDS_BLOCK;

            while (true)
            {
                if (insnCount >= insns.Length)
                {
                    // Extend insns array
                    Common.Instruction[] newInsns = new Common.Instruction[insnCount + 100];
                    Array.Copy(insns, 0, newInsns, 0, insnCount);
                    insns = newInsns;
                    // Extend opcodes array
                    int[] newOpcodes = new int[newInsns.Length];
                    Array.Copy(opcodes, 0, newOpcodes, 0, insnCount);
                    opcodes = newOpcodes;
                }

                int opcode = memoryReader.readNext();

                if (opcode == opcodeJrRa)
                {
                    int delaySlotOpcode = memoryReader.readNext();
                    Common.Instruction delaySlotInsn = Decoder.instruction(delaySlotOpcode);
                    insns[insnCount]   = delaySlotInsn;
                    opcodes[insnCount] = delaySlotOpcode;
                    insnCount++;
                    break;
                }

                Common.Instruction insn = Decoder.instruction(opcode);
                if ((insn.Flags & notSimpleFlags) != 0)
                {
                    isSimple = false;
                    break;
                }

                insns[insnCount]   = insn;
                opcodes[insnCount] = opcode;
                insnCount++;
            }

            if (isSimple)
            {
                if (insnCount < insns.Length)
                {
                    // Compact insns array
                    Common.Instruction[] newInsns = new Common.Instruction[insnCount];
                    Array.Copy(insns, 0, newInsns, 0, insnCount);
                    insns = newInsns;
                    // Compact opcodes array
                    int[] newOpcodes = new int[insnCount];
                    Array.Copy(opcodes, 0, newOpcodes, 0, insnCount);
                    opcodes = newOpcodes;
                }
                codeBlock.InterpretedInstructions = insns;
                codeBlock.InterpretedOpcodes      = opcodes;
            }
            else
            {
                codeBlock.InterpretedInstructions = null;
                codeBlock.InterpretedOpcodes      = null;
            }

            return(isSimple);
        }
Example #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);
        }
Example #3
0
 public InterpretExecutable(CodeBlock codeBlock)
 {
     this.codeBlock = codeBlock;
 }