2017-06-04 20:38:34 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstdint>
|
2018-08-18 22:56:16 +00:00
|
|
|
#include <string>
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2018-10-31 23:29:13 +00:00
|
|
|
#include <EightBitCompilerDefinitions.h>
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
namespace EightBit {
|
2018-10-31 23:29:13 +00:00
|
|
|
|
|
|
|
class Bus;
|
|
|
|
class MOS6502;
|
|
|
|
class Symbols;
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
class Disassembly {
|
|
|
|
public:
|
2018-10-20 19:52:41 +00:00
|
|
|
Disassembly(Bus& bus, MOS6502& processor, const Symbols& symbols);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble(uint16_t current);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2018-01-27 10:13:17 +00:00
|
|
|
static std::string dump_Flags(uint8_t value);
|
|
|
|
static std::string dump_ByteValue(uint8_t value);
|
|
|
|
static std::string dump_WordValue(uint16_t value);
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
private:
|
2018-10-20 19:52:41 +00:00
|
|
|
Bus& m_bus;
|
2017-07-14 16:22:28 +00:00
|
|
|
MOS6502& processor;
|
|
|
|
const Symbols& symbols;
|
|
|
|
|
2018-08-11 20:19:19 +00:00
|
|
|
mutable uint16_t m_address = 0xffff;
|
2017-07-14 16:22:28 +00:00
|
|
|
|
|
|
|
std::string disassemble_Implied(const std::string& instruction) const {
|
|
|
|
return "\t" + instruction;
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble_Absolute(const std::string& instruction) {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_Absolute_dump() + "\t" + instruction + " " + AM_Absolute();
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble_Indirect(const std::string& instruction) {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_Absolute_dump() + "\t" + instruction + " (" + AM_Absolute() + ")";
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble_Relative(const std::string& instruction, uint16_t address) {
|
2017-07-17 14:35:24 +00:00
|
|
|
return AM_Immediate_dump() + "\t" + instruction + " $" + dump_WordValue(address);
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble_Immediate(const std::string& instruction) {
|
2018-01-21 10:45:25 +00:00
|
|
|
return AM_Immediate_dump() + "\t" + instruction + " " + AM_Immediate();
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble_AM_00(int bbb, const std::string& instruction) {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_00_dump(bbb) + "\t" + instruction + " " + AM_00(bbb);
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble_AM_01(int bbb, const std::string& instruction) {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_01_dump(bbb) + "\t" + instruction + " " + AM_01(bbb);
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble_AM_10(int bbb, const std::string& instruction) {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_10_dump(bbb) + "\t" + instruction + " " + AM_10(bbb);
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble_AM_10_x(int bbb, const std::string& instruction) {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_10_x_dump(bbb) + "\t" + instruction + " " + AM_10_x(bbb);
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble_AM_11(int bbb, const std::string& instruction) {
|
2018-01-01 12:28:00 +00:00
|
|
|
return AM_11_dump(bbb) + "\t" + instruction + " " + AM_11(bbb);
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string disassemble_AM_11_x(int bbb, const std::string& instruction) {
|
2018-01-01 21:05:42 +00:00
|
|
|
return AM_11_x_dump(bbb) + "\t" + instruction + " " + AM_11_x(bbb);
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_Immediate_dump() {
|
2017-07-17 14:35:24 +00:00
|
|
|
return dump_Byte(m_address + 1);
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_Immediate() {
|
2017-12-28 14:18:17 +00:00
|
|
|
return "#$" + AM_Immediate_dump();
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_Absolute_dump() {
|
2017-07-17 14:35:24 +00:00
|
|
|
return dump_DByte(m_address + 1);
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_Absolute() {
|
2018-01-01 21:05:42 +00:00
|
|
|
return "$" + dump_Word(m_address + 1);
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_ZeroPage_dump() {
|
2017-07-17 14:35:24 +00:00
|
|
|
return dump_Byte(m_address + 1);
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_ZeroPage() {
|
2017-07-17 14:35:24 +00:00
|
|
|
return "$" + dump_Byte(m_address + 1);
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_ZeroPageX_dump() {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_ZeroPage_dump();
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_ZeroPageX() {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_ZeroPage() + ",X";
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_ZeroPageY_dump() {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_ZeroPage_dump();
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_ZeroPageY() {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_ZeroPage() + ",Y";
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_AbsoluteX_dump() {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_Absolute_dump();
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_AbsoluteX() {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_Absolute() + ",X";
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_AbsoluteY_dump() {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_Absolute_dump();
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_AbsoluteY() {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_Absolute() + ",Y";
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_IndexedIndirectX_dump() {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_ZeroPage_dump();
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_IndexedIndirectX() {
|
2017-07-17 14:35:24 +00:00
|
|
|
return "($" + dump_Byte(m_address + 1) + ",X)";
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_IndirectIndexedY_dump() {
|
2017-07-14 16:22:28 +00:00
|
|
|
return AM_ZeroPage_dump();
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_IndirectIndexedY() {
|
2017-07-17 14:35:24 +00:00
|
|
|
return "($" + dump_Byte(m_address + 1) + "),Y";
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_00_dump(int bbb) {
|
2017-07-14 16:22:28 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_Immediate_dump();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage_dump();
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute_dump();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageX_dump();
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteX_dump();
|
|
|
|
case 0b010:
|
|
|
|
case 0b100:
|
|
|
|
case 0b110:
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
default:
|
2018-01-01 01:16:22 +00:00
|
|
|
UNREACHABLE;
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_00(int bbb) {
|
2017-07-14 16:22:28 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_Immediate();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage();
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageX();
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteX();
|
|
|
|
case 0b010:
|
|
|
|
case 0b100:
|
|
|
|
case 0b110:
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
default:
|
2018-01-01 01:16:22 +00:00
|
|
|
UNREACHABLE;
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_01_dump(int bbb) {
|
2017-07-14 16:22:28 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_IndexedIndirectX_dump();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage_dump();
|
|
|
|
case 0b010:
|
|
|
|
return AM_Immediate_dump();
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute_dump();
|
|
|
|
case 0b100:
|
|
|
|
return AM_IndirectIndexedY_dump();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageX_dump();
|
|
|
|
case 0b110:
|
|
|
|
return AM_AbsoluteY_dump();
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteX_dump();
|
|
|
|
default:
|
2018-01-01 01:16:22 +00:00
|
|
|
UNREACHABLE;
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_01(int bbb) {
|
2017-07-14 16:22:28 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_IndexedIndirectX();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage();
|
|
|
|
case 0b010:
|
|
|
|
return AM_Immediate();
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute();
|
|
|
|
case 0b100:
|
|
|
|
return AM_IndirectIndexedY();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageX();
|
|
|
|
case 0b110:
|
|
|
|
return AM_AbsoluteY();
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteX();
|
|
|
|
default:
|
2018-01-01 01:16:22 +00:00
|
|
|
UNREACHABLE;
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_10_dump(int bbb) {
|
2017-07-14 16:22:28 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_Immediate_dump();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage_dump();
|
|
|
|
case 0b010:
|
|
|
|
return "";
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute_dump();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageX_dump();
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteX_dump();
|
|
|
|
case 0b100:
|
|
|
|
case 0b110:
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
default:
|
2018-01-01 01:16:22 +00:00
|
|
|
UNREACHABLE;
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_10(int bbb) {
|
2017-07-14 16:22:28 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_Immediate();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage();
|
|
|
|
case 0b010:
|
|
|
|
return "A";
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageX();
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteX();
|
|
|
|
case 0b100:
|
|
|
|
case 0b110:
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
default:
|
2018-01-01 01:16:22 +00:00
|
|
|
UNREACHABLE;
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_10_x_dump(int bbb) {
|
2017-07-14 16:22:28 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_Immediate_dump();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage_dump();
|
|
|
|
case 0b010:
|
|
|
|
return "";
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute_dump();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageY_dump();
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteY_dump();
|
|
|
|
case 0b100:
|
|
|
|
case 0b110:
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
default:
|
2018-01-01 01:16:22 +00:00
|
|
|
UNREACHABLE;
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_10_x(int bbb) {
|
2017-07-14 16:22:28 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_Immediate();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage();
|
|
|
|
case 0b010:
|
|
|
|
return "A";
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageY();
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteY();
|
|
|
|
case 0b100:
|
|
|
|
case 0b110:
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
default:
|
2018-01-01 01:16:22 +00:00
|
|
|
UNREACHABLE;
|
2017-07-14 16:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_11_dump(int bbb) {
|
2018-01-01 12:28:00 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_IndexedIndirectX_dump();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage_dump();
|
|
|
|
case 0b010:
|
|
|
|
return AM_Immediate_dump();
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute_dump();
|
|
|
|
case 0b100:
|
|
|
|
return AM_IndirectIndexedY_dump();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageY_dump();
|
|
|
|
case 0b110:
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteY_dump();
|
|
|
|
default:
|
|
|
|
UNREACHABLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_11_x_dump(int bbb) {
|
2018-01-01 21:05:42 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_IndexedIndirectX_dump();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage_dump();
|
|
|
|
case 0b010:
|
|
|
|
return AM_Immediate_dump();
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute_dump();
|
|
|
|
case 0b100:
|
|
|
|
return AM_IndirectIndexedY_dump();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageX_dump();
|
|
|
|
case 0b110:
|
|
|
|
return AM_AbsoluteY_dump();
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteX_dump();
|
|
|
|
default:
|
|
|
|
UNREACHABLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_11(int bbb) {
|
2018-01-01 12:28:00 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_IndexedIndirectX();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage();
|
|
|
|
case 0b010:
|
|
|
|
return AM_Immediate();
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute();
|
|
|
|
case 0b100:
|
|
|
|
return AM_IndirectIndexedY();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageY();
|
|
|
|
case 0b110:
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteY();
|
|
|
|
default:
|
|
|
|
UNREACHABLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string AM_11_x(int bbb) {
|
2018-01-01 21:05:42 +00:00
|
|
|
switch (bbb) {
|
|
|
|
case 0b000:
|
|
|
|
return AM_IndexedIndirectX();
|
|
|
|
case 0b001:
|
|
|
|
return AM_ZeroPage();
|
|
|
|
case 0b010:
|
|
|
|
return AM_Immediate();
|
|
|
|
case 0b011:
|
|
|
|
return AM_Absolute();
|
|
|
|
case 0b100:
|
|
|
|
return AM_IndirectIndexedY();
|
|
|
|
case 0b101:
|
|
|
|
return AM_ZeroPageX();
|
|
|
|
case 0b110:
|
|
|
|
return AM_AbsoluteY();
|
|
|
|
case 0b111:
|
|
|
|
return AM_AbsoluteX();
|
|
|
|
default:
|
|
|
|
UNREACHABLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-28 14:18:17 +00:00
|
|
|
static void dump(std::ostream& out, int value, int width);
|
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
uint8_t getByte(uint16_t address);
|
|
|
|
uint16_t getWord(uint16_t address);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string dump_Byte(uint16_t address);
|
|
|
|
std::string dump_DByte(uint16_t address);
|
|
|
|
std::string dump_Word(uint16_t address);
|
2017-06-04 20:38:34 +00:00
|
|
|
|
2017-07-17 14:35:24 +00:00
|
|
|
std::string convertAddress(uint16_t address) const;
|
|
|
|
std::string convertAddress(uint8_t address) const;
|
2018-10-20 19:52:41 +00:00
|
|
|
std::string convertConstant(uint16_t constant);
|
2017-07-17 14:35:24 +00:00
|
|
|
std::string convertConstant(uint8_t constant) const;
|
2018-10-20 19:52:41 +00:00
|
|
|
|
|
|
|
Bus& BUS() { return m_bus; }
|
2017-07-02 21:03:33 +00:00
|
|
|
};
|
|
|
|
}
|