public virtual void make(CpuState cpu) { pc = cpu.pc; for (int i = 0; i < NUMBER_REGISTERS; i++) { gpr[i] = cpu.getRegister(i); } threadID = Modules.ThreadManForUserModule.CurrentThreadID; threadName = Modules.ThreadManForUserModule.getThreadName(threadID); Memory mem = MemoryViewer.Memory; if (MemoryViewer.isAddressGood(cpu.pc)) { opcode = mem.read32(cpu.pc); Common.Instruction insn = Decoder.instruction(opcode); asm = insn.disasm(cpu.pc, opcode); } else { opcode = 0; asm = "?"; } dirty = true; }
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); }
private void loadBeforeCodeInstructions(NativeCodeSequence nativeCodeSequence, string codeInstructions) { System.IO.StreamReader reader = new System.IO.StreamReader(new StringReader(codeInstructions)); if (reader == null) { return; } Pattern codeInstructionPattern = Pattern.compile("\\s*(\\w+\\s*:?\\s*)?\\[(\\p{XDigit}+)\\].*"); const int opcodeGroup = 2; const int address = 0; try { while (true) { string line = reader.ReadLine(); if (string.ReferenceEquals(line, null)) { break; } line = line.Trim(); if (line.Length > 0) { try { Matcher codeInstructionMatcher = codeInstructionPattern.matcher(line); int opcode = 0; if (codeInstructionMatcher.matches()) { opcode = Utilities.parseAddress(codeInstructionMatcher.group(opcodeGroup)); } else { opcode = Utilities.parseAddress(line.Trim()); } Common.Instruction insn = Decoder.instruction(opcode); CodeInstruction codeInstruction = new CodeInstruction(address, opcode, insn, false, false, 0); nativeCodeSequence.addBeforeCodeInstruction(codeInstruction); } catch (System.FormatException e) { Compiler.Console.WriteLine(e); } } } } catch (IOException e) { Compiler.Console.WriteLine(e); } }
//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); }
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); }