mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-26 08:29:33 +00:00
Improves M50470 entry-point detection, adds test output.
This commit is contained in:
parent
56111c75ae
commit
dcc2fe0990
@ -31,7 +31,6 @@ template <
|
||||
> class Disassembler {
|
||||
public:
|
||||
using ProgramCounterType = typename MinIntTypeValue<max_address>::type;
|
||||
static_assert(!std::is_same_v<ProgramCounterType, void>);
|
||||
|
||||
/*!
|
||||
Adds the result of disassembling @c memory which is @c length @c MemoryWords long from @c start_address
|
||||
@ -48,9 +47,19 @@ template <
|
||||
const auto next_entry_point = pending_entry_points_.front();
|
||||
pending_entry_points_.pop_front();
|
||||
|
||||
parser.parse(*this, memory - location, next_entry_point, length + location);
|
||||
if(next_entry_point >= location) {
|
||||
parser.parse(*this, memory - location, next_entry_point % max_address, length + location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::map<ProgramCounterType, InstructionType> &instructions() const {
|
||||
return instructions_;
|
||||
}
|
||||
|
||||
const std::set<ProgramCounterType> &entry_points() const {
|
||||
return entry_points_;
|
||||
}
|
||||
|
||||
void announce_overflow(ProgramCounterType) {}
|
||||
void announce_instruction(ProgramCounterType address, InstructionType instruction) {
|
||||
|
@ -169,31 +169,37 @@ inline constexpr const char *addressing_mode_name(AddressingMode addressing_mode
|
||||
would appear in an assembler. E.g. '$5a' for that zero page address, or '$5a, x' for zero-page indexed from $5a. This function
|
||||
may access up to three bytes from @c operation onwards.
|
||||
*/
|
||||
inline std::string address(AddressingMode addressing_mode, const uint8_t *operation) {
|
||||
inline std::string address(AddressingMode addressing_mode, const uint8_t *operation, uint16_t program_counter) {
|
||||
std::stringstream output;
|
||||
output << std::hex << std::setfill('0') << std::setw(2);
|
||||
output << std::hex;
|
||||
|
||||
#define NUM(x) std::setfill('0') << std::setw(2) << int(x)
|
||||
#define NUM4(x) std::setfill('0') << std::setw(4) << int(x)
|
||||
switch(addressing_mode) {
|
||||
default: return "???";
|
||||
case AddressingMode::Implied: return "";
|
||||
case AddressingMode::Accumulator: return "A ";
|
||||
case AddressingMode::Immediate: output << "#$" << int(operation[1]); break;
|
||||
case AddressingMode::Absolute: output << "$" << int(operation[2]) << int(operation[1]); break;
|
||||
case AddressingMode::AbsoluteX: output << "$" << int(operation[2]) << int(operation[1]) << ", x"; break;
|
||||
case AddressingMode::AbsoluteY: output << "$" << int(operation[2]) << int(operation[1]) << ", y"; break;
|
||||
case AddressingMode::ZeroPage: output << "$" << int(operation[1]); break;
|
||||
case AddressingMode::ZeroPageX: output << "$" << int(operation[1]) << ", x"; break;
|
||||
case AddressingMode::ZeroPageY: output << "$" << int(operation[1]) << ", y"; break;
|
||||
case AddressingMode::XIndirect: output << "(($" << int(operation[1]) << ", x))"; break;
|
||||
case AddressingMode::IndirectY: output << "(($" << int(operation[1]) << "), y)"; break;
|
||||
case AddressingMode::Relative: output << "+#$" << int(int8_t(operation[1])); break;
|
||||
case AddressingMode::AbsoluteIndirect: output << "($" << int(operation[2]) << int(operation[1]) << ")"; break;
|
||||
case AddressingMode::ZeroPageIndirect: output << "($" << int(operation[1]) << ")"; break;
|
||||
case AddressingMode::SpecialPage: output << "$1f" << int(operation[1]); break;
|
||||
case AddressingMode::ImmediateZeroPage: output << "#$" << int(operation[1]) << ", $" << int(int8_t(operation[2])); break;
|
||||
case AddressingMode::AccumulatorRelative: output << "A, +#$" << int(int8_t(operation[1])); break;
|
||||
case AddressingMode::ZeroPageRelative: output << "$" << int(operation[1]) << ", +#$" << int(int8_t(operation[2])); break;
|
||||
case AddressingMode::Immediate: output << "#$" << NUM(operation[1]); break;
|
||||
case AddressingMode::Absolute: output << "$" << NUM(operation[2]) << NUM(operation[1]); break;
|
||||
case AddressingMode::AbsoluteX: output << "$" << NUM(operation[2]) << NUM(operation[1]) << ", x"; break;
|
||||
case AddressingMode::AbsoluteY: output << "$" << NUM(operation[2]) << NUM(operation[1]) << ", y"; break;
|
||||
case AddressingMode::ZeroPage: output << "$" << NUM(operation[1]); break;
|
||||
case AddressingMode::ZeroPageX: output << "$" << NUM(operation[1]) << ", x"; break;
|
||||
case AddressingMode::ZeroPageY: output << "$" << NUM(operation[1]) << ", y"; break;
|
||||
case AddressingMode::XIndirect: output << "(($" << NUM(operation[1]) << ", x))"; break;
|
||||
case AddressingMode::IndirectY: output << "(($" << NUM(operation[1]) << "), y)"; break;
|
||||
case AddressingMode::Relative: output << "#$" << NUM4(2 + program_counter + int8_t(operation[1])); break;
|
||||
case AddressingMode::AbsoluteIndirect: output << "($" << NUM(operation[2]) << NUM(operation[1]) << ") "; break;
|
||||
case AddressingMode::ZeroPageIndirect: output << "($" << NUM(operation[1]) << ")"; break;
|
||||
case AddressingMode::SpecialPage: output << "$1f" << NUM(operation[1]); break;
|
||||
case AddressingMode::ImmediateZeroPage: output << "#$" << NUM(operation[1]) << ", $" << NUM(operation[2]); break;
|
||||
case AddressingMode::AccumulatorRelative: output << "A, $" << NUM4(2 + program_counter + int8_t(operation[1])); break;
|
||||
case AddressingMode::ZeroPageRelative:
|
||||
output << "$" << NUM(operation[1]) << ", $" << NUM4(2 + program_counter + int8_t(operation[2]));
|
||||
break;
|
||||
}
|
||||
#undef NUM4
|
||||
#undef NUM
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
@ -48,35 +48,50 @@ template<typename Target, bool include_entries_and_accesses> struct Parser {
|
||||
case Operation::RTS: case Operation::RTI: case Operation::BRK:
|
||||
return;
|
||||
|
||||
// Terminating operations with implied additional entry point.
|
||||
// Terminating operations, possibly with implied additional entry point.
|
||||
case Operation::JMP:
|
||||
target.add_entry(storage[start + 1] | (storage[start + 2] << 8));
|
||||
if(next.second.addressing_mode == AddressingMode::Absolute) {
|
||||
target.add_entry(uint16_t(storage[start + 1] | (storage[start + 2] << 8)));
|
||||
}
|
||||
return;
|
||||
case Operation::BRA:
|
||||
target.add_entry(start + 2 + int8_t(storage[start + 1]));
|
||||
target.add_entry(uint16_t(start + 2 + int8_t(storage[start + 1])));
|
||||
return;
|
||||
|
||||
// Instructions that suggest another entry point but don't terminate parsing.
|
||||
// case Operation::BBS: case Operation::BBC: // TODO: BBS, BBC
|
||||
case Operation::BCC: case Operation::BCS:
|
||||
case Operation::BVC: case Operation::BVS:
|
||||
case Operation::BMI: case Operation::BPL:
|
||||
case Operation::BNE: case Operation::BEQ:
|
||||
target.add_entry(start + 2 + int8_t(storage[start + 1]));
|
||||
target.add_entry(uint16_t(start + 2 + int8_t(storage[start + 1])));
|
||||
break;
|
||||
case Operation::JSR:
|
||||
target.add_entry(storage[start + 1] | (storage[start + 2] << 8));
|
||||
switch(next.second.addressing_mode) {
|
||||
default: break;
|
||||
case AddressingMode::Absolute:
|
||||
target.add_entry(uint16_t(storage[start + 1] | (storage[start + 2] << 8)));
|
||||
break;
|
||||
case AddressingMode::SpecialPage:
|
||||
target.add_entry(uint16_t(storage[start + 1] | 0x1f00));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// // TODO: addressing like the below for the relevant BBC and BBS.
|
||||
// case AddressingMode::Bit0AccumulatorRelative:
|
||||
// target.add_access(start + 2 + int8_t(storage[start + 1]), access_type(next.second.operation));
|
||||
// break;
|
||||
case Operation::BBS0: case Operation::BBS1: case Operation::BBS2: case Operation::BBS3:
|
||||
case Operation::BBS4: case Operation::BBS5: case Operation::BBS6: case Operation::BBS7:
|
||||
case Operation::BBC0: case Operation::BBC1: case Operation::BBC2: case Operation::BBC3:
|
||||
case Operation::BBC4: case Operation::BBC5: case Operation::BBC6: case Operation::BBC7:
|
||||
switch(next.second.addressing_mode) {
|
||||
default: break;
|
||||
case AddressingMode::AccumulatorRelative:
|
||||
target.add_entry(uint16_t(start + 2 + int8_t(storage[start + 1])));
|
||||
break;
|
||||
case AddressingMode::ZeroPageRelative:
|
||||
target.add_entry(uint16_t(start + 3 + int8_t(storage[start + 2])));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// // TODO: this is a potential addressing mode for JSR.
|
||||
// case AddressingMode::SpecialPage:
|
||||
// target.add_access(storage[start + 1] | 0x1f00, access_type(next.second.operation));
|
||||
// break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
@ -84,9 +99,9 @@ template<typename Target, bool include_entries_and_accesses> struct Parser {
|
||||
// Provide any fixed address accesses.
|
||||
switch(next.second.addressing_mode) {
|
||||
case AddressingMode::Absolute:
|
||||
target.add_access(storage[start + 1] | (storage[start + 2] << 8), access_type(next.second.operation));
|
||||
target.add_access(uint16_t(storage[start + 1] | (storage[start + 2] << 8)), access_type(next.second.operation));
|
||||
break;
|
||||
case AddressingMode::ZeroPage:
|
||||
case AddressingMode::ZeroPage: case AddressingMode::ZeroPageRelative:
|
||||
target.add_access(storage[start + 1], access_type(next.second.operation));
|
||||
break;
|
||||
case AddressingMode::ImmediateZeroPage:
|
||||
|
@ -222,8 +222,24 @@ uint8_t GLU::read_microcontroller_address(uint16_t address) {
|
||||
void GLU::set_microcontroller_rom(const std::vector<uint8_t> &rom) {
|
||||
executor_.set_rom(rom);
|
||||
|
||||
// TEST invocation.
|
||||
InstructionSet::Disassembler<InstructionSet::M50740::Parser, 0x1fff, InstructionSet::M50740::Instruction, uint8_t, uint16_t> disassembler;
|
||||
disassembler.disassemble(rom.data(), 0x1000, uint16_t(rom.size()), 0x1000);
|
||||
|
||||
const auto instructions = disassembler.instructions();
|
||||
const auto entry_points = disassembler.entry_points();
|
||||
for(const auto &pair : instructions) {
|
||||
std::cout << std::hex << pair.first << "\t\t";
|
||||
if(entry_points.find(pair.first) != entry_points.end()) {
|
||||
std::cout << "L" << pair.first << "\t";
|
||||
} else {
|
||||
std::cout << "\t\t";
|
||||
}
|
||||
std::cout << operation_name(pair.second.operation) << " ";
|
||||
std::cout << address(pair.second.addressing_mode, &rom[pair.first - 0x1000], pair.first);
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void GLU::run_for(Cycles cycles) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user