mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Merge pull request #1166 from TomHarte/6502Exhaustive
This commit is contained in:
commit
211a6e5114
@ -236,7 +236,7 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
|
||||
case Instruction::Relative: {
|
||||
std::size_t operand_address = address_mapper(address);
|
||||
if(operand_address >= memory.size()) return;
|
||||
address++;
|
||||
++address;
|
||||
|
||||
instruction.operand = memory[operand_address];
|
||||
}
|
||||
@ -291,20 +291,34 @@ static void AddToDisassembly(PartialDisassembly &disassembly, const std::vector<
|
||||
}
|
||||
|
||||
// Decide on overall flow control.
|
||||
if(instruction.operation == Instruction::RTS || instruction.operation == Instruction::RTI) return;
|
||||
if(instruction.operation == Instruction::BRK) return; // TODO: check whether IRQ vector is within memory range
|
||||
if(instruction.operation == Instruction::JSR) {
|
||||
disassembly.remaining_entry_points.push_back(instruction.operand);
|
||||
}
|
||||
if(instruction.operation == Instruction::JMP) {
|
||||
if(instruction.addressing_mode == Instruction::Absolute)
|
||||
disassembly.remaining_entry_points.push_back(instruction.operand);
|
||||
return;
|
||||
}
|
||||
|
||||
// All relative instructions are flow control.
|
||||
if(instruction.addressing_mode == Instruction::Relative) {
|
||||
uint16_t destination = uint16_t(address + int8_t(instruction.operand));
|
||||
disassembly.remaining_entry_points.push_back(destination);
|
||||
}
|
||||
|
||||
switch(instruction.operation) {
|
||||
default: break;
|
||||
|
||||
case Instruction::KIL:
|
||||
case Instruction::RTS:
|
||||
case Instruction::RTI:
|
||||
case Instruction::BRK: // TODO: check whether IRQ vector is within memory range.
|
||||
disassembly.implicit_entry_points.push_back(address);
|
||||
return;
|
||||
|
||||
case Instruction::JMP:
|
||||
// Adding a new entry point for relative jumps was handled above.
|
||||
if(instruction.addressing_mode == Instruction::Absolute) {
|
||||
disassembly.remaining_entry_points.push_back(instruction.operand);
|
||||
}
|
||||
return;
|
||||
|
||||
case Instruction::JSR:
|
||||
disassembly.remaining_entry_points.push_back(instruction.operand);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace Analyser::Static::Disassembly {
|
||||
template <typename D, typename S> struct PartialDisassembly {
|
||||
D disassembly;
|
||||
std::vector<S> remaining_entry_points;
|
||||
std::map<S, S> touched; // Maps from start of range to end.
|
||||
std::vector<S> implicit_entry_points;
|
||||
};
|
||||
|
||||
template <typename D, typename S, typename Disassembler> D Disassemble(
|
||||
@ -50,18 +50,15 @@ template <typename D, typename S, typename Disassembler> D Disassemble(
|
||||
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;
|
||||
}
|
||||
}
|
||||
// Otherwise, copy in the new 'implicit entry points' (i.e. all locations that are one after
|
||||
// a disassembled region). There's a test above that'll ignore any which have already been
|
||||
// disassembled from.
|
||||
std::move(
|
||||
partial_disassembly.implicit_entry_points.begin(),
|
||||
partial_disassembly.implicit_entry_points.end(),
|
||||
std::back_inserter(partial_disassembly.remaining_entry_points)
|
||||
);
|
||||
partial_disassembly.implicit_entry_points.clear();
|
||||
}
|
||||
|
||||
return partial_disassembly.disassembly;
|
||||
|
@ -546,9 +546,6 @@ 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();
|
||||
@ -561,9 +558,6 @@ struct Z80Disassembler {
|
||||
// Store the instruction away.
|
||||
disassembly.disassembly.instructions_by_address[instruction.address] = instruction;
|
||||
|
||||
// Apply all touches.
|
||||
touched = accessor.address();
|
||||
|
||||
// Update access tables.
|
||||
int access_type =
|
||||
((instruction.source == Instruction::Location::Operand_Indirect) ? 1 : 0) |
|
||||
@ -595,7 +589,7 @@ struct Z80Disassembler {
|
||||
break;
|
||||
}
|
||||
|
||||
// Add any (potentially) newly discovered entry point.
|
||||
// Add any (potentially) newly-discovered entry point.
|
||||
if( instruction.operation == Instruction::Operation::JP ||
|
||||
instruction.operation == Instruction::Operation::JR ||
|
||||
instruction.operation == Instruction::Operation::CALL ||
|
||||
@ -604,13 +598,19 @@ struct Z80Disassembler {
|
||||
}
|
||||
|
||||
// This is it if: an unconditional RET, RETI, RETN, JP or JR is found.
|
||||
if(instruction.condition != Instruction::Condition::None) continue;
|
||||
switch(instruction.operation) {
|
||||
default: break;
|
||||
|
||||
if(instruction.operation == Instruction::Operation::RET) return;
|
||||
if(instruction.operation == Instruction::Operation::RETI) return;
|
||||
if(instruction.operation == Instruction::Operation::RETN) return;
|
||||
if(instruction.operation == Instruction::Operation::JP) return;
|
||||
if(instruction.operation == Instruction::Operation::JR) return;
|
||||
case Instruction::Operation::RET:
|
||||
case Instruction::Operation::RETI:
|
||||
case Instruction::Operation::RETN:
|
||||
case Instruction::Operation::JP:
|
||||
case Instruction::Operation::JR:
|
||||
if(instruction.condition == Instruction::Condition::None) {
|
||||
disassembly.implicit_entry_points.push_back(accessor.address());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -115,7 +115,7 @@ static Analyser::Static::TargetList CartridgeTargetsFrom(
|
||||
// be at play; disassemble to try to figure it out.
|
||||
std::vector<uint8_t> first_8k;
|
||||
first_8k.insert(first_8k.begin(), segment.data.begin(), segment.data.begin() + 8192);
|
||||
Analyser::Static::Z80::Disassembly disassembly =
|
||||
const Analyser::Static::Z80::Disassembly disassembly =
|
||||
Analyser::Static::Z80::Disassemble(
|
||||
first_8k,
|
||||
Analyser::Static::Disassembler::OffsetMapper(start_address),
|
||||
|
Loading…
Reference in New Issue
Block a user