diff --git a/Analyser/Static/Disassembler/Kernel.hpp b/Analyser/Static/Disassembler/Kernel.hpp index 380b7198a..7b9ef0f8e 100644 --- a/Analyser/Static/Disassembler/Kernel.hpp +++ b/Analyser/Static/Disassembler/Kernel.hpp @@ -14,23 +14,23 @@ namespace Analyser::Static::Disassembly { template struct PartialDisassembly { D disassembly; std::vector remaining_entry_points; - std::vector touched; + std::map touched; // Maps from start of range to end. }; template D Disassemble( const std::vector &memory, const std::function &address_mapper, std::vector entry_points, - bool exhaustive) { + bool exhaustive) +{ PartialDisassembly partial_disassembly; partial_disassembly.remaining_entry_points = entry_points; - partial_disassembly.touched.resize(memory.size()); - while(true) { + while(!partial_disassembly.remaining_entry_points.empty()) { // Do a recursive-style disassembly for all current entry points. while(!partial_disassembly.remaining_entry_points.empty()) { // Pull the next entry point from the back of the vector. - S next_entry_point = partial_disassembly.remaining_entry_points.back(); + const S next_entry_point = partial_disassembly.remaining_entry_points.back(); partial_disassembly.remaining_entry_points.pop_back(); // If that address has already been visited, forget about it. @@ -50,14 +50,18 @@ template D Disassemble( break; } - // Otherwise, find the first address that isn't yet disassembled and chuck it onto the list. - auto first_untouched = std::find(partial_disassembly.touched.begin(), partial_disassembly.touched.end(), false); - if(first_untouched == partial_disassembly.touched.end()) { - break; + // Otherwise, find the first area between or just beyond a disassembled range + // that isn't yet disassembled and chuck it onto the list. + for(const auto &pair: partial_disassembly.touched) { + const auto end = pair.second; + if(partial_disassembly.touched.find(end) == partial_disassembly.touched.end()) { + if(address_mapper(end) < memory.size()) { + partial_disassembly.remaining_entry_points.push_back(end); + } + + break; + } } - partial_disassembly.remaining_entry_points.push_back( - static_cast(first_untouched - partial_disassembly.touched.begin()) - ); } return partial_disassembly.disassembly; diff --git a/Analyser/Static/Disassembler/Z80.cpp b/Analyser/Static/Disassembler/Z80.cpp index 20b4c8cab..92c6e53d0 100644 --- a/Analyser/Static/Disassembler/Z80.cpp +++ b/Analyser/Static/Disassembler/Z80.cpp @@ -546,6 +546,9 @@ struct Z80Disassembler { disassembly.disassembly.internal_calls.insert(entry_point); Accessor accessor(memory, address_mapper, entry_point); + auto &touched = disassembly.touched[entry_point]; + touched = entry_point; + while(!accessor.at_end()) { Instruction instruction; instruction.address = accessor.address(); @@ -559,10 +562,7 @@ struct Z80Disassembler { disassembly.disassembly.instructions_by_address[instruction.address] = instruction; // Apply all touches. - std::fill( - disassembly.touched.begin() + instruction.address, - disassembly.touched.begin() + accessor.address(), - true); + touched = accessor.address(); // Update access tables. int access_type =