EightBit/M6502/src/Disassembly.cpp

232 lines
8.4 KiB
C++

#include "stdafx.h"
#include "Disassembly.h"
#include <sstream>
#include <iomanip>
#include <functional>
using namespace std::placeholders;
Disassembly::Disassembly(MOS6502& targetProcessor, const Symbols& targetSymbols)
: processor(targetProcessor),
symbols(targetSymbols)
{
dumpers = {
{ AddressingMode::Illegal, { std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1), std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1) } },
{ AddressingMode::Implied, { std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1), std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1) } },
{ AddressingMode::Accumulator, { std::bind(&Disassembly::Dump_Nothing, this, std::placeholders::_1), std::bind(&Disassembly::Dump_A, this, std::placeholders::_1) } },
{ AddressingMode::Immediate, { std::bind(&Disassembly::Dump_Byte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_imm, this, std::placeholders::_1) } },
{ AddressingMode::Relative, { std::bind(&Disassembly::Dump_Byte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_rel, this, std::placeholders::_1) } },
{ AddressingMode::XIndexed, { std::bind(&Disassembly::Dump_Byte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_xind, this, std::placeholders::_1) } },
{ AddressingMode::IndexedY, { std::bind(&Disassembly::Dump_Byte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_indy, this, std::placeholders::_1) } },
{ AddressingMode::ZeroPageIndirect, { std::bind(&Disassembly::Dump_Byte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_zpind, this, std::placeholders::_1) } },
{ AddressingMode::ZeroPage, { std::bind(&Disassembly::Dump_Byte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_zp, this, std::placeholders::_1) } },
{ AddressingMode::ZeroPageX, { std::bind(&Disassembly::Dump_Byte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_zpx, this, std::placeholders::_1) } },
{ AddressingMode::ZeroPageY, { std::bind(&Disassembly::Dump_Byte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_zpy, this, std::placeholders::_1) } },
{ AddressingMode::Absolute, { std::bind(&Disassembly::Dump_DByte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_abs, this, std::placeholders::_1) } },
{ AddressingMode::AbsoluteX, { std::bind(&Disassembly::Dump_DByte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_absx, this, std::placeholders::_1) } },
{ AddressingMode::AbsoluteY, { std::bind(&Disassembly::Dump_DByte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_absy, this, std::placeholders::_1) } },
{ AddressingMode::AbsoluteXIndirect, { std::bind(&Disassembly::Dump_DByte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_absxind, this, std::placeholders::_1) } },
{ AddressingMode::Indirect, { std::bind(&Disassembly::Dump_DByte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_ind, this, std::placeholders::_1) } },
{ AddressingMode::ZeroPageRelative, { std::bind(&Disassembly::Dump_DByte, this, std::placeholders::_1), std::bind(&Disassembly::Dump_zprel, this, std::placeholders::_1) } },
};
}
std::string Disassembly::Dump_ByteValue(uint8_t value) const {
std::ostringstream output;
output << std::hex << std::setw(2) << std::setfill('0') << (int)value;
return output.str();
}
std::string Disassembly::Dump_WordValue(uint16_t value) const {
std::ostringstream output;
output << std::hex << std::setw(4) << std::setfill('0') << (int)value;
return output.str();
}
std::string Disassembly::DumpBytes(AddressingMode mode, uint16_t current) const {
return getDumper(mode).byteDumper(current);
}
std::string Disassembly::Disassemble(uint16_t current) const {
std::ostringstream output;
auto content = processor.GetByte(current);
const auto& instruction = processor.getInstruction(content);
auto mode = instruction.mode;
auto mnemomic = instruction.display;
auto operand = DumpOperand(mode, current + 1);
auto label = symbols.getLabels().find(current);
if (label != symbols.getLabels().end())
output << label->second << ": ";
output << mnemomic << " " << operand;
return output.str();
}
std::string Disassembly::DumpOperand(AddressingMode mode, uint16_t current) const {
return getDumper(mode).disassemblyDumper(current);
}
////
uint8_t Disassembly::GetByte(uint16_t address) const {
return processor.GetByte(address);
}
uint16_t Disassembly::GetWord(uint16_t address) const {
return processor.GetWord(address);
}
////
std::string Disassembly::Dump_Nothing(uint16_t) const {
return "";
}
std::string Disassembly::Dump_Byte(uint16_t address) const {
return Dump_ByteValue(GetByte(address));
}
std::string Disassembly::Dump_DByte(uint16_t address) const {
return Dump_Byte(address) + Dump_Byte(address + 1);
}
////
std::string Disassembly::ConvertAddress(uint16_t address) const {
auto label = symbols.getLabels().find(address);
if (label != symbols.getLabels().end())
return label->second;
std::ostringstream output;
output << "$" << Dump_WordValue(address);
return output.str();
}
std::string Disassembly::ConvertAddress(uint8_t address) const {
auto label = symbols.getLabels().find(address);
if (label != symbols.getLabels().end())
return label->second;
std::ostringstream output;
output << "$" << Dump_ByteValue(address);
return output.str();
}
std::string Disassembly::ConvertConstant(uint16_t constant) const {
auto label = symbols.getConstants().find(constant);
if (label != symbols.getConstants().end())
return label->second;
return Dump_DByte(constant);
}
std::string Disassembly::ConvertConstant(uint8_t constant) const {
auto label = symbols.getConstants().find(constant);
if (label != symbols.getConstants().end())
return label->second;
return Dump_ByteValue(constant);
}
////
std::string Disassembly::Dump_A(uint16_t) const {
return "A";
}
std::string Disassembly::Dump_imm(uint16_t current) const {
std::ostringstream output;
auto immediate = GetByte(current);
output << "#" << ConvertConstant(immediate);
return output.str();
}
std::string Disassembly::Dump_abs(uint16_t current) const {
auto address = GetWord(current);
return ConvertAddress(address);
}
std::string Disassembly::Dump_zp(uint16_t current) const {
auto zp = GetByte(current);
return ConvertAddress(zp);
}
std::string Disassembly::Dump_zpx(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << ConvertAddress(zp) << ",X";
return output.str();
}
std::string Disassembly::Dump_zpy(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << ConvertAddress(zp) << ",Y";
return output.str();
}
std::string Disassembly::Dump_absx(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << ConvertAddress(address) << ",X";
return output.str();
}
std::string Disassembly::Dump_absy(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << ConvertAddress(address) << ",Y";
return output.str();
}
std::string Disassembly::Dump_absxind(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << "(" << ConvertAddress(address) << ",X)";
return output.str();
}
std::string Disassembly::Dump_xind(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << "(" << ConvertAddress(zp) << ",X)";
return output.str();
}
std::string Disassembly::Dump_indy(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << "(" << ConvertAddress(zp) << "),Y";
return output.str();
}
std::string Disassembly::Dump_ind(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << "(" << ConvertAddress(address) << ")";
return output.str();
}
std::string Disassembly::Dump_zpind(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << "(" << ConvertAddress(zp) << ")";
return output.str();
}
std::string Disassembly::Dump_rel(uint16_t current) const {
uint16_t relative = 1 + current + (int8_t)GetByte(current);
return ConvertAddress(relative);
}
std::string Disassembly::Dump_zprel(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
int8_t displacement = GetByte(current + 1);
uint16_t address = 1 + current + displacement;
output << ConvertAddress(zp) << "," << ConvertAddress(address);
return output.str();
}