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