1
0
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:
Thomas Harte 2023-09-10 17:02:20 -04:00 committed by GitHub
commit 211a6e5114
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 38 deletions

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;
}
}
}
}
};

View File

@ -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),