void DisassemblyFunction::load() { generateBranchLines(); // gather all branch targets std::set<u32> branchTargets; for (size_t i = 0; i < lines.size(); i++) { switch (lines[i].type) { case LINE_DOWN: branchTargets.insert(lines[i].second); break; case LINE_UP: branchTargets.insert(lines[i].first); break; default: break; } } DebugInterface* cpu = DisassemblyManager::getCpu(); u32 funcPos = address; u32 funcEnd = address+size; u32 nextData = symbolMap.GetNextSymbolAddress(funcPos-1,ST_DATA); u32 opcodeSequenceStart = funcPos; while (funcPos < funcEnd) { if (funcPos == nextData) { if (opcodeSequenceStart != funcPos) addOpcodeSequence(opcodeSequenceStart,funcPos); DisassemblyData* data = new DisassemblyData(funcPos,symbolMap.GetDataSize(funcPos),symbolMap.GetDataType(funcPos)); entries[funcPos] = data; lineAddresses.push_back(funcPos); funcPos += data->getTotalSize(); nextData = symbolMap.GetNextSymbolAddress(funcPos-1,ST_DATA); opcodeSequenceStart = funcPos; continue; } // force align if (funcPos % 4) { u32 nextPos = (funcPos+3) & ~3; DisassemblyComment* comment = new DisassemblyComment(funcPos,nextPos-funcPos,".align","4"); entries[funcPos] = comment; lineAddresses.push_back(funcPos); funcPos = nextPos; opcodeSequenceStart = funcPos; continue; } MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(cpu,funcPos); u32 opAddress = funcPos; funcPos += 4; // skip branches and their delay slots if (opInfo.isBranch) { funcPos += 4; continue; } // lui if (MIPS_GET_OP(opInfo.encodedOpcode) == 0x0F && funcPos < funcEnd && funcPos != nextData) { MIPSOpcode next = Memory::Read_Instruction(funcPos); MIPSInfo nextInfo = MIPSGetInfo(next); u32 immediate = ((opInfo.encodedOpcode & 0xFFFF) << 16) + (s16)(next.encoding & 0xFFFF); int rt = MIPS_GET_RT(opInfo.encodedOpcode); int nextRs = MIPS_GET_RS(next.encoding); int nextRt = MIPS_GET_RT(next.encoding); // both rs and rt of the second op have to match rt of the first, // otherwise there may be hidden consequences if the macro is displayed. // also, don't create a macro if something branches into the middle of it if (nextRs == rt && nextRt == rt && branchTargets.find(funcPos) == branchTargets.end()) { DisassemblyMacro* macro = NULL; switch (MIPS_GET_OP(next.encoding)) { case 0x09: // addiu macro = new DisassemblyMacro(opAddress); macro->setMacroLi(immediate,rt); funcPos += 4; break; case 0x20: // lb case 0x21: // lh case 0x23: // lw case 0x24: // lbu case 0x25: // lhu case 0x28: // sb case 0x29: // sh case 0x2B: // sw macro = new DisassemblyMacro(opAddress); int dataSize; switch (nextInfo & MEMTYPE_MASK) { case MEMTYPE_BYTE: dataSize = 1; break; case MEMTYPE_HWORD: dataSize = 2; break; case MEMTYPE_WORD: case MEMTYPE_FLOAT: dataSize = 4; break; case MEMTYPE_VQUAD: dataSize = 16; break; default: return; } macro->setMacroMemory(MIPSGetName(next),immediate,rt,dataSize); funcPos += 4; break; } if (macro != NULL) { if (opcodeSequenceStart != opAddress) addOpcodeSequence(opcodeSequenceStart,opAddress); entries[opAddress] = macro; for (int i = 0; i < macro->getNumLines(); i++) { lineAddresses.push_back(macro->getLineAddress(i)); } opcodeSequenceStart = funcPos; continue; } } } // just a normal opcode } if (opcodeSequenceStart != funcPos) addOpcodeSequence(opcodeSequenceStart,funcPos); }
void DisassemblyFunction::load() { generateBranchLines(); // gather all branch targets std::set<u32> branchTargets; for (size_t i = 0; i < lines.size(); i++) { switch (lines[i].type) { case LINE_DOWN: branchTargets.insert(lines[i].second); break; case LINE_UP: branchTargets.insert(lines[i].first); break; } } u32 funcPos = address; u32 funcEnd = address+size; u32 nextData = symbolMap.GetNextSymbolAddress(funcPos-1,ST_DATA); u32 opcodeSequenceStart = funcPos; while (funcPos < funcEnd) { if (funcPos == nextData) { if (opcodeSequenceStart != funcPos) addOpcodeSequence(opcodeSequenceStart,funcPos); DisassemblyData* data = new DisassemblyData(cpu,funcPos,symbolMap.GetDataSize(funcPos),symbolMap.GetDataType(funcPos)); entries[funcPos] = data; lineAddresses.push_back(funcPos); funcPos += data->getTotalSize(); nextData = symbolMap.GetNextSymbolAddress(funcPos-1,ST_DATA); opcodeSequenceStart = funcPos; continue; } // force align if (funcPos % 4) { u32 nextPos = (funcPos+3) & ~3; DisassemblyComment* comment = new DisassemblyComment(cpu,funcPos,nextPos-funcPos,".align","4"); entries[funcPos] = comment; lineAddresses.push_back(funcPos); funcPos = nextPos; opcodeSequenceStart = funcPos; continue; } MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(cpu,funcPos); u32 opAddress = funcPos; funcPos += 4; // skip branches and their delay slots if (opInfo.isBranch) { funcPos += 4; continue; } // lui if (MIPS_GET_OP(opInfo.encodedOpcode) == 0x0F && funcPos < funcEnd && funcPos != nextData) { u32 next = cpu->read32(funcPos); u32 immediate = ((opInfo.encodedOpcode & 0xFFFF) << 16) + (s16)(next & 0xFFFF); u32 immediateOr = ((opInfo.encodedOpcode & 0xFFFF) << 16) | (u16)(next & 0xFFFF); int rt = MIPS_GET_RT(opInfo.encodedOpcode); int nextRs = MIPS_GET_RS(next); int nextRt = MIPS_GET_RT(next); // both rs and rt of the second op have to match rt of the first, // otherwise there may be hidden consequences if the macro is displayed. // also, don't create a macro if something branches into the middle of it if (nextRs == rt && nextRt == rt && branchTargets.find(funcPos) == branchTargets.end()) { DisassemblyMacro* macro = NULL; switch (MIPS_GET_OP(next)) { case 0x09: // addiu macro = new DisassemblyMacro(cpu,opAddress); macro->setMacroLi(immediate,rt); funcPos += 4; break; case 0x0D: // ori macro = new DisassemblyMacro(cpu,opAddress); macro->setMacroLi(immediateOr,rt); funcPos += 4; break; case 0x20: // lb macro = new DisassemblyMacro(cpu,opAddress); macro->setMacroMemory("lb",immediate,rt,1); funcPos += 4; break; case 0x21: // lh macro = new DisassemblyMacro(cpu,opAddress); macro->setMacroMemory("lh",immediate,rt,2); funcPos += 4; break; case 0x23: // lw macro = new DisassemblyMacro(cpu,opAddress); macro->setMacroMemory("lw",immediate,rt,4); funcPos += 4; break; case 0x24: // lbu macro = new DisassemblyMacro(cpu,opAddress); macro->setMacroMemory("lbu",immediate,rt,1); funcPos += 4; break; case 0x25: // lhu macro = new DisassemblyMacro(cpu,opAddress); macro->setMacroMemory("lhu",immediate,rt,2); funcPos += 4; break; case 0x28: // sb macro = new DisassemblyMacro(cpu,opAddress); macro->setMacroMemory("sb",immediate,rt,1); funcPos += 4; break; case 0x29: // sh macro = new DisassemblyMacro(cpu,opAddress); macro->setMacroMemory("sh",immediate,rt,2); funcPos += 4; case 0x2B: // sw macro = new DisassemblyMacro(cpu,opAddress); macro->setMacroMemory("sw",immediate,rt,4); funcPos += 4; break; } if (macro != NULL) { if (opcodeSequenceStart != opAddress) addOpcodeSequence(opcodeSequenceStart,opAddress); entries[opAddress] = macro; for (int i = 0; i < macro->getNumLines(); i++) { lineAddresses.push_back(macro->getLineAddress(i)); } opcodeSequenceStart = funcPos; continue; } } } // just a normal opcode } if (opcodeSequenceStart != funcPos) addOpcodeSequence(opcodeSequenceStart,funcPos); }