Files
EightBit/M6502/src/Disassembly.cpp
Adrian.Conlon 13725b7a3c Tidy method casing a little.
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
2017-07-17 15:35:24 +01:00

371 lines
8.7 KiB
C++

#include "stdafx.h"
#include "Disassembly.h"
#include <sstream>
#include <iomanip>
#include <functional>
using namespace std::placeholders;
EightBit::Disassembly::Disassembly(MOS6502& targetProcessor, const Symbols& targetSymbols)
: processor(targetProcessor),
symbols(targetSymbols) {
}
std::string EightBit::Disassembly::dump_Flags(uint8_t value) const {
std::string returned;
returned += (value & MOS6502::NF) ? "N" : "-";
returned += (value & MOS6502::VF) ? "O" : "-";
returned += (value & MOS6502::RF) ? "R" : "-";
returned += (value & MOS6502::BF) ? "B" : "-";
returned += (value & MOS6502::DF) ? "D" : "-";
returned += (value & MOS6502::IF) ? "I" : "-";
returned += (value & MOS6502::ZF) ? "Z" : "-";
returned += (value & MOS6502::CF) ? "C" : "-";
return returned;
}
std::string EightBit::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 EightBit::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 EightBit::Disassembly::disassemble(uint16_t current) const {
m_address = current;
std::ostringstream output;
auto memory = processor.getMemory();
auto cell = memory.peek(current);
output << dump_ByteValue(cell);
auto byte = memory.peek(current + 1);
uint16_t relative = processor.PC().word + 2 + (int8_t)byte;
auto aaa = (cell & 0b11100000) >> 5;
auto bbb = (cell & 0b00011100) >> 2;
auto cc = (cell & 0b00000011);
switch (cc) {
case 0b00:
switch (aaa) {
case 0b000:
switch (bbb) {
case 0b000: // BRK
output << disassemble_Implied("BRK");
break;
case 0b010: // PHP
output << disassemble_Implied("PHP");
break;
case 0b100: // BPL
output << disassemble_Relative("BPL", relative);
break;
case 0b110: // CLC
output << disassemble_Implied("CLC");
break;
default:
throw std::domain_error("Illegal instruction");
}
break;
case 0b001:
switch (bbb) {
case 0b000: // JSR
output << disassemble_Absolute("JSR");
break;
case 0b010: // PLP
output << disassemble_Implied("PLP");
break;
case 0b100: // BMI
output << disassemble_Relative("BMI", relative);
break;
case 0b110: // SEC
output << disassemble_Implied("SEC");
break;
default: // BIT
output << disassemble_AM_00(bbb, "BIT");
break;
}
break;
case 0b010:
switch (bbb) {
case 0b000: // RTI
output << disassemble_Implied("RTI");
break;
case 0b010: // PHA
output << disassemble_Implied("PHA");
break;
case 0b011: // JMP
output << disassemble_Absolute("JMP");
break;
case 0b100: // BVC
output << disassemble_Relative("BVC", relative);
break;
case 0b110: // CLI
output << disassemble_Implied("CLI");
break;
default:
throw std::domain_error("Illegal addressing mode");
}
break;
case 0b011:
switch (bbb) {
case 0b000: // RTS
output << disassemble_Implied("RTS");
break;
case 0b010: // PLA
output << disassemble_Implied("PLA");
break;
case 0b011: // JMP (abs)
output << disassemble_Indirect("JMP");
break;
case 0b100: // BVS
output << disassemble_Relative("BVS", relative);
break;
case 0b110: // SEI
output << disassemble_Implied("SEI");
break;
default:
throw std::domain_error("Illegal addressing mode");
}
break;
case 0b100:
switch (bbb) {
case 0b010: // DEY
output << disassemble_Implied("DEY");
break;
case 0b100: // BCC
output << disassemble_Relative("BCC", relative);
break;
case 0b110: // TYA
output << disassemble_Implied("TYA");
break;
default: // STY
output << disassemble_AM_00(bbb, "STY");
break;
}
break;
case 0b101:
switch (bbb) {
case 0b010: // TAY
output << disassemble_Implied("TAY");
break;
case 0b100: // BCS
output << disassemble_Relative("BCS", relative);
break;
case 0b110: // CLV
output << disassemble_Implied("CLV");
break;
default: // LDY
output << disassemble_AM_00(bbb, "LDY");
break;
}
break;
case 0b110:
switch (bbb) {
case 0b010: // INY
output << disassemble_Implied("INY");
break;
case 0b100: // BNE
output << disassemble_Relative("BNE", relative);
break;
case 0b110: // CLD
output << disassemble_Implied("CLD");
break;
default: // CPY
output << disassemble_AM_00(bbb, "CPY");
break;
}
break;
case 0b111:
switch (bbb) {
case 0b010: // INX
output << disassemble_Implied("INX");
break;
case 0b100: // BEQ
output << disassemble_Relative("BEQ", relative);
break;
case 0b110: // SED
output << disassemble_Implied("SED");
break;
default: // CPX
output << disassemble_AM_00(bbb, "CPX");
break;
}
break;
}
break;
case 0b01:
switch (aaa) {
case 0b000: // ORA
output << disassemble_AM_01(bbb, "ORA");
break;
case 0b001: // AND
output << disassemble_AM_01(bbb, "AND");
break;
case 0b010: // EOR
output << disassemble_AM_01(bbb, "EOR");
break;
case 0b011: // ADC
output << disassemble_AM_01(bbb, "ADC");
break;
case 0b100: // STA
output << disassemble_AM_01(bbb, "STA");
break;
case 0b101: // LDA
output << disassemble_AM_01(bbb, "LDA");
break;
case 0b110: // CMP
output << disassemble_AM_01(bbb, "CMP");
break;
case 0b111: // SBC
output << disassemble_AM_01(bbb, "SBC");
break;
default:
__assume(0);
}
break;
case 0b10:
switch (aaa) {
case 0b000: // ASL
output << disassemble_AM_10(bbb, "ASL");
break;
case 0b001: // ROL
output << disassemble_AM_10(bbb, "ROL");
break;
case 0b010: // LSR
output << disassemble_AM_10(bbb, "LSR");
break;
case 0b011: // ROR
output << disassemble_AM_10(bbb, "ROR");
break;
case 0b100:
switch (bbb) {
case 0b010: // TXA
output << disassemble_Implied("TXA");
break;
case 0b110: // TXS
output << disassemble_Implied("TXS");
break;
default: // STX
output << disassemble_AM_10_x(bbb, "STX");
break;
}
break;
case 0b101:
switch (bbb) {
case 0b010: // TAX
output << disassemble_Implied("TAX");
break;
case 0b110: // TSX
output << disassemble_Implied("TSX");
break;
default: // LDX
output << disassemble_AM_10_x(bbb, "LDX");
break;
}
break;
case 0b110:
switch (bbb) {
case 0b010: // DEX
output << disassemble_Implied("DEX");
break;
default: // DEC
output << disassemble_AM_10(bbb, "DEC");
break;
}
break;
case 0b111:
switch (bbb) {
case 0b010: // NOP
output << disassemble_Implied("NOP");
break;
default: // INC
output << disassemble_AM_10(bbb, "INC");
break;
}
break;
default:
__assume(0);
}
break;
case 0b11:
throw std::domain_error("Illegal instruction group");
default:
__assume(0);
}
//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();
}
////
uint8_t EightBit::Disassembly::getByte(uint16_t address) const {
return processor.getMemory().peek(address);
}
////
std::string EightBit::Disassembly::dump_Byte(uint16_t address) const {
return dump_ByteValue(getByte(address));
}
std::string EightBit::Disassembly::dump_DByte(uint16_t address) const {
return dump_Byte(address) + dump_Byte(address + 1);
}
////
std::string EightBit::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 EightBit::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 EightBit::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 EightBit::Disassembly::convertConstant(uint8_t constant) const {
auto label = symbols.getConstants().find(constant);
if (label != symbols.getConstants().end())
return label->second;
return dump_ByteValue(constant);
}