New improved disassembler for 6502: much smaller than before.

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian.Conlon 2017-07-14 17:22:28 +01:00
parent 7ff7ee040f
commit 3084d2341c
10 changed files with 630 additions and 1696 deletions

View File

@ -1,23 +0,0 @@
#pragma once
namespace EightBit {
enum AddressingMode {
Illegal,
Implied,
Accumulator,
Immediate,
Relative,
XIndexed,
IndexedY,
ZeroPage,
ZeroPageX,
ZeroPageY,
Absolute,
AbsoluteX,
AbsoluteY,
AbsoluteXIndirect,
Indirect,
ZeroPageIndirect,
ZeroPageRelative
};
}

View File

@ -1,14 +0,0 @@
#pragma once
#include <cstdint>
#include <functional>
namespace EightBit {
typedef std::function<std::string(uint16_t current)> dumper_t;
struct AddressingModeDumper {
dumper_t byteDumper;
dumper_t disassemblyDumper;
};
}

View File

@ -4,34 +4,319 @@
#include <cstdint>
#include "mos6502.h"
#include "AddressingMode.h"
#include "Symbols.h"
#include "AddressingModeDumper.h"
namespace EightBit {
class Disassembly {
public:
MOS6502& processor;
const Symbols& symbols;
std::map<AddressingMode, AddressingModeDumper> dumpers;
Disassembly(MOS6502& processor, const Symbols& symbols);
std::string Dump_Flags(uint8_t value) const;
std::string Dump_ByteValue(uint8_t value) const;
std::string Dump_WordValue(uint16_t value) const;
std::string DumpBytes(AddressingMode mode, uint16_t current) const;
std::string Disassemble(uint16_t current) const;
std::string DumpOperand(AddressingMode mode, uint16_t current) const;
private:
uint8_t GetByte(uint16_t address) const;
uint16_t GetWord(uint16_t address) const;
MOS6502& processor;
const Symbols& symbols;
mutable uint16_t m_address;
std::string disassemble_Implied(const std::string& instruction) const {
return "\t" + instruction;
}
std::string disassemble_Absolute(const std::string& instruction) const {
return AM_Absolute_dump() + "\t" + instruction + " " + AM_Absolute();
}
std::string disassemble_Indirect(const std::string& instruction) const {
return AM_Absolute_dump() + "\t" + instruction + " (" + AM_Absolute() + ")";
}
std::string disassemble_Relative(const std::string& instruction, uint16_t address) const {
return AM_Immediate_dump() + "\t" + instruction + " $" + Dump_WordValue(address);
}
std::string disassemble_AM_00(int bbb, const std::string& instruction) const {
return AM_00_dump(bbb) + "\t" + instruction + " " + AM_00(bbb);
}
std::string disassemble_AM_01(int bbb, const std::string& instruction) const {
return AM_01_dump(bbb) + "\t" + instruction + " " + AM_01(bbb);
}
std::string disassemble_AM_10(int bbb, const std::string& instruction) const {
return AM_10_dump(bbb) + "\t" + instruction + " " + AM_10(bbb);
}
std::string disassemble_AM_10_x(int bbb, const std::string& instruction) const {
return AM_10_x_dump(bbb) + "\t" + instruction + " " + AM_10_x(bbb);
}
#pragma region 6502 addressing modes
#pragma region References
std::string AM_Immediate_dump() const {
return Dump_Byte(m_address + 1);
}
std::string AM_Immediate() const {
return "#" + AM_Immediate_dump();
}
std::string AM_Absolute_dump() const {
return Dump_DByte(m_address + 1);
}
std::string AM_Absolute() const {
return "$" + Dump_WordValue(processor.getMemory().peekWord(m_address + 1));
}
std::string AM_ZeroPage_dump() const {
return Dump_Byte(m_address + 1);
}
std::string AM_ZeroPage() const {
return "$" + Dump_Byte(m_address + 1);
}
std::string AM_ZeroPageX_dump() const {
return AM_ZeroPage_dump();
}
std::string AM_ZeroPageX() const {
return AM_ZeroPage() + ",X";
}
std::string AM_ZeroPageY_dump() const {
return AM_ZeroPage_dump();
}
std::string AM_ZeroPageY() const {
return AM_ZeroPage() + ",Y";
}
std::string AM_AbsoluteX_dump() const {
return AM_Absolute_dump();
}
std::string AM_AbsoluteX() const {
return AM_Absolute() + ",X";
}
std::string AM_AbsoluteY_dump() const {
return AM_Absolute_dump();
}
std::string AM_AbsoluteY() const {
return AM_Absolute() + ",Y";
}
std::string AM_IndexedIndirectX_dump() const {
return AM_ZeroPage_dump();
}
std::string AM_IndexedIndirectX() const {
return "($" + Dump_Byte(m_address + 1) + ",X)";
}
std::string AM_IndirectIndexedY_dump() const {
return AM_ZeroPage_dump();
}
std::string AM_IndirectIndexedY() const {
return "($" + Dump_Byte(m_address + 1) + "),Y";
}
#pragma endregion References
#pragma region 6502 addressing mode switching
std::string AM_00_dump(int bbb) const {
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:
__assume(0);
}
}
std::string AM_00(int bbb) const {
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:
__assume(0);
}
}
std::string AM_01_dump(int bbb) const {
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:
__assume(0);
}
}
std::string AM_01(int bbb) const {
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:
__assume(0);
}
}
std::string AM_10_dump(int bbb) const {
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:
__assume(0);
}
}
std::string AM_10(int bbb) const {
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:
__assume(0);
}
}
std::string AM_10_x_dump(int bbb) const {
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:
__assume(0);
}
}
std::string AM_10_x(int bbb) const {
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:
__assume(0);
}
}
#pragma endregion 6502 addressing mode switching
#pragma endregion 6502 addressing modes
uint8_t GetByte(uint16_t address) const;
std::string Dump_Nothing(uint16_t unused) const;
std::string Dump_Byte(uint16_t address) const;
std::string Dump_DByte(uint16_t address) const;
@ -39,28 +324,5 @@ namespace EightBit {
std::string ConvertAddress(uint8_t address) const;
std::string ConvertConstant(uint16_t constant) const;
std::string ConvertConstant(uint8_t constant) const;
std::string Dump_A(uint16_t unused) const;
std::string Dump_imm(uint16_t current) const;
std::string Dump_abs(uint16_t current) const;
std::string Dump_zp(uint16_t current) const;
std::string Dump_zpx(uint16_t current) const;
std::string Dump_zpy(uint16_t current) const;
std::string Dump_absx(uint16_t current) const;
std::string Dump_absy(uint16_t current) const;
std::string Dump_absxind(uint16_t current) const;
std::string Dump_xind(uint16_t current) const;
std::string Dump_indy(uint16_t current) const;
std::string Dump_ind(uint16_t current) const;
std::string Dump_zpind(uint16_t current) const;
std::string Dump_rel(uint16_t current) const;
std::string Dump_zprel(uint16_t current) const;
const AddressingModeDumper& getDumper(AddressingMode mode) const {
auto dumper = dumpers.find(mode);
if (dumper == dumpers.end())
throw std::invalid_argument("Illegal addressing mode");
return dumper->second;
}
};
}

View File

@ -1,9 +0,0 @@
#pragma once
namespace EightBit {
enum ProcessorType {
Cpu6502,
Cpu65SC02,
Cpu65C02
};
}

View File

@ -7,8 +7,6 @@
#include "Memory.h"
#include "Processor.h"
#include "ProcessorType.h"
#include "AddressingMode.h"
#include "Signal.h"
namespace EightBit {
@ -25,32 +23,17 @@ namespace EightBit {
CF = 0x01, // Carry
};
typedef std::function<void()> instruction_t;
struct Instruction {
instruction_t vector = nullptr;
int count = 0;
AddressingMode mode = AddressingMode::Illegal;
std::string display = "";
};
MOS6502(Memory& memory, ProcessorType level);
MOS6502(Memory& memory);
Signal<MOS6502> ExecutingInstruction;
Signal<MOS6502> ExecutedInstruction;
ProcessorType getLevel() const { return level; }
uint8_t& X() { return x; }
uint8_t& Y() { return y; }
uint8_t& A() { return a; }
uint8_t& S() { return s; }
uint8_t& P() { return p; }
const Instruction& getInstruction(uint8_t code) const {
return instructions[code];
}
virtual void initialise();
virtual int step();
@ -74,19 +57,7 @@ namespace EightBit {
virtual int Execute(uint8_t cell);
void ___();
private:
static Instruction INS(instruction_t method, int cycles, AddressingMode addressing, std::string display);
void Install6502Instructions();
void Install65sc02Instructions();
void Install65c02Instructions();
void InstallInstructionSet(const std::array<Instruction, 0x100>& basis);
void OverlayInstructionSet(const std::array<Instruction, 0x100>& overlay);
void OverlayInstructionSet(const std::array<Instruction, 0x100>& overlay, bool includeIllegal);
void UpdateZeroFlag(uint8_t datum) { clearFlag(P(), ZF, datum); }
void UpdateNegativeFlag(uint8_t datum) { setFlag(P(), NF, datum & NF); }
@ -169,18 +140,6 @@ namespace EightBit {
#pragma region References
uint8_t& AM_A() {
return A();
}
uint8_t& AM_X() {
return X();
}
uint8_t& AM_Y() {
return Y();
}
uint8_t& AM_Immediate() {
FetchByte();
return m_memory.reference();
@ -295,7 +254,7 @@ namespace EightBit {
case 0b001:
return AM_ZeroPage();
case 0b010:
return AM_A();
return A();
case 0b011:
return AM_Absolute();
case 0b101:
@ -310,14 +269,14 @@ namespace EightBit {
}
}
uint8_t& AM_10_x(int bbb, bool x = false) {
uint8_t& AM_10_x(int bbb) {
switch (bbb) {
case 0b000:
return AM_Immediate();
case 0b001:
return AM_ZeroPage();
case 0b010:
return AM_A();
return A();
case 0b011:
return AM_Absolute();
case 0b101:
@ -344,9 +303,6 @@ namespace EightBit {
void BIT(uint8_t data);
void TSB(uint8_t& output);
void TRB(uint8_t& output);
void INC(uint8_t& output);
void ROL(uint8_t& output);
@ -363,9 +319,6 @@ namespace EightBit {
void EOR(uint8_t data);
void CPX(uint8_t data);
void CPY(uint8_t data);
void CMP(uint8_t data);
void CMP(uint8_t first, uint8_t second);
void LDA(uint8_t data);
@ -376,265 +329,20 @@ namespace EightBit {
void ADC_b(uint8_t data);
void ADC_d(uint8_t data);
void RMB(uint8_t& output, uint8_t flag);
void SMB(uint8_t& output, uint8_t flag);
void Branch(int8_t displacement);
void Branch();
void Branch(bool flag);
void BitBranch_Clear(uint8_t check);
void BitBranch_Set(uint8_t check);
void NOP_imp();
void NOP2_imp();
void NOP3_imp();
void ORA_xind();
void ORA_zp();
void ORA_imm();
void ORA_abs();
void ORA_absx();
void ORA_absy();
void ORA_zpx();
void ORA_indy();
void ORA_zpind();
void AND_zpx();
void AND_indy();
void AND_zp();
void AND_absx();
void AND_absy();
void AND_imm();
void AND_xind();
void AND_abs();
void AND_zpind();
void EOR_absx();
void EOR_absy();
void EOR_zpx();
void EOR_indy();
void EOR_abs();
void EOR_imm();
void EOR_zp();
void EOR_xind();
void EOR_zpind();
void LDA_absx();
void LDA_absy();
void LDA_zpx();
void LDA_indy();
void LDA_abs();
void LDA_imm();
void LDA_zp();
void LDA_xind();
void LDA_zpind();
void LDX_imm();
void LDX_zp();
void LDX_abs();
void LDX_zpy();
void LDX_absy();
void LDY_imm();
void LDY_zp();
void LDY_abs();
void LDY_zpx();
void LDY_absx();
void CMP_absx();
void CMP_absy();
void CMP_zpx();
void CMP_indy();
void CMP_abs();
void CMP_imm();
void CMP_zp();
void CMP_xind();
void CMP_zpind();
void CPX_abs();
void CPX_zp();
void CPX_imm();
void CPY_imm();
void CPY_zp();
void CPY_abs();
void ADC_zp();
void ADC_xind();
void ADC_imm();
void ADC_abs();
void ADC_zpx();
void ADC_indy();
void ADC_absx();
void ADC_absy();
void ADC_zpind();
void SBC_xind();
void SBC_zp();
void SBC_imm();
void SBC_abs();
void SBC_zpx();
void SBC_indy();
void SBC_absx();
void SBC_absy();
void SBC_zpind();
void BIT_imm();
void BIT_zp();
void BIT_zpx();
void BIT_abs();
void BIT_absx();
void DEC_a();
void DEC_absx();
void DEC_zpx();
void DEC_abs();
void DEC_zp();
void DEX_imp();
void DEY_imp();
void INC_a();
void INC_zp();
void INC_absx();
void INC_zpx();
void INC_abs();
void INX_imp();
void INY_imp();
void STX_zpy();
void STX_abs();
void STX_zp();
void STY_zpx();
void STY_abs();
void STY_zp();
void STA_absx();
void STA_absy();
void STA_zpx();
void STA_indy();
void STA_abs();
void STA_zp();
void STA_xind();
void STA_zpind();
void STZ_zp();
void STZ_zpx();
void STZ_abs();
void STZ_absx();
void TSX_imp();
void TAX_imp();
void TAY_imp();
void TXS_imp();
void TYA_imp();
void TXA_imp();
void PHP_imp();
void PLP_imp();
void PLA_imp();
void PHA_imp();
void PHX_imp();
void PHY_imp();
void PLX_imp();
void PLY_imp();
void ASL_a();
void ASL_zp();
void ASL_abs();
void ASL_absx();
void ASL_zpx();
void LSR_absx();
void LSR_zpx();
void LSR_abs();
void LSR_a();
void LSR_zp();
void ROL_absx();
void ROL_zpx();
void ROL_abs();
void ROL_a();
void ROL_zp();
void ROR_absx();
void ROR_zpx();
void ROR_abs();
void ROR_a();
void ROR_zp();
void TSB_zp();
void TSB_abs();
void TRB_zp();
void TRB_abs();
void RMB0_zp();
void RMB1_zp();
void RMB2_zp();
void RMB3_zp();
void RMB4_zp();
void RMB5_zp();
void RMB6_zp();
void RMB7_zp();
void SMB0_zp();
void SMB1_zp();
void SMB2_zp();
void SMB3_zp();
void SMB4_zp();
void SMB5_zp();
void SMB6_zp();
void SMB7_zp();
void PHP();
void PLP();
void JSR_abs();
void RTI_imp();
void RTS_imp();
void RTI();
void RTS();
void JMP_abs();
void JMP_ind();
void JMP_absxind();
void BRK_imp();
void WAI_imp();
void STP_imp();
void SED_imp();
void CLD_imp();
void CLV_imp();
void SEI_imp();
void CLI_imp();
void CLC_imp();
void SEC_imp();
void BMI_rel();
void BPL_rel();
void BVC_rel();
void BVS_rel();
void BCC_rel();
void BCS_rel();
void BNE_rel();
void BEQ_rel();
void BRA_rel();
void BBR0_zprel();
void BBR1_zprel();
void BBR2_zprel();
void BBR3_zprel();
void BBR4_zprel();
void BBR5_zprel();
void BBR6_zprel();
void BBR7_zprel();
void BBS0_zprel();
void BBS1_zprel();
void BBS2_zprel();
void BBS3_zprel();
void BBS4_zprel();
void BBS5_zprel();
void BBS6_zprel();
void BBS7_zprel();
void BRK();
const uint16_t PageOne = 0x100;
const uint16_t IRQvector = 0xfffe;
@ -648,13 +356,5 @@ namespace EightBit {
uint8_t p; // processor status
register16_t m_memptr;
std::array<Instruction, 0x100> instructions;
ProcessorType level;
std::array<Instruction, 0x100> overlay6502;
std::array<Instruction, 0x100> overlay65sc02;
std::array<Instruction, 0x100> overlay65c02;
};
}

View File

@ -10,25 +10,6 @@ using namespace std::placeholders;
EightBit::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 EightBit::Disassembly::Dump_Flags(uint8_t value) const {
@ -56,52 +37,296 @@ std::string EightBit::Disassembly::Dump_WordValue(uint16_t value) const {
return output.str();
}
std::string EightBit::Disassembly::DumpBytes(AddressingMode mode, uint16_t current) const {
return getDumper(mode).byteDumper(current);
}
std::string EightBit::Disassembly::Disassemble(uint16_t current) const {
m_address = current;
std::ostringstream output;
auto content = processor.GetByte(current);
const auto& instruction = processor.getInstruction(content);
auto memory = processor.getMemory();
auto mode = instruction.mode;
auto mnemomic = instruction.display;
auto cell = memory.peek(current);
auto operand = DumpOperand(mode, current + 1);
output << Dump_ByteValue(cell);
auto label = symbols.getLabels().find(current);
if (label != symbols.getLabels().end())
output << label->second << ": ";
output << mnemomic << " " << operand;
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();
}
std::string EightBit::Disassembly::DumpOperand(AddressingMode mode, uint16_t current) const {
return getDumper(mode).disassemblyDumper(current);
}
////
uint8_t EightBit::Disassembly::GetByte(uint16_t address) const {
return processor.GetByte(address);
}
uint16_t EightBit::Disassembly::GetWord(uint16_t address) const {
register16_t returned;
processor.GetWord(address, returned);
return returned.word;
return processor.getMemory().peek(address);
}
////
std::string EightBit::Disassembly::Dump_Nothing(uint16_t) const {
return "";
}
std::string EightBit::Disassembly::Dump_Byte(uint16_t address) const {
return Dump_ByteValue(GetByte(address));
}
@ -143,104 +368,4 @@ std::string EightBit::Disassembly::ConvertConstant(uint8_t constant) const {
return label->second;
return Dump_ByteValue(constant);
}
////
std::string EightBit::Disassembly::Dump_A(uint16_t) const {
return "A";
}
std::string EightBit::Disassembly::Dump_imm(uint16_t current) const {
std::ostringstream output;
auto immediate = GetByte(current);
output << "#" << ConvertConstant(immediate);
return output.str();
}
std::string EightBit::Disassembly::Dump_abs(uint16_t current) const {
auto address = GetWord(current);
return ConvertAddress(address);
}
std::string EightBit::Disassembly::Dump_zp(uint16_t current) const {
auto zp = GetByte(current);
return ConvertAddress(zp);
}
std::string EightBit::Disassembly::Dump_zpx(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << ConvertAddress(zp) << ",X";
return output.str();
}
std::string EightBit::Disassembly::Dump_zpy(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << ConvertAddress(zp) << ",Y";
return output.str();
}
std::string EightBit::Disassembly::Dump_absx(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << ConvertAddress(address) << ",X";
return output.str();
}
std::string EightBit::Disassembly::Dump_absy(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << ConvertAddress(address) << ",Y";
return output.str();
}
std::string EightBit::Disassembly::Dump_absxind(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << "(" << ConvertAddress(address) << ",X)";
return output.str();
}
std::string EightBit::Disassembly::Dump_xind(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << "(" << ConvertAddress(zp) << ",X)";
return output.str();
}
std::string EightBit::Disassembly::Dump_indy(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << "(" << ConvertAddress(zp) << "),Y";
return output.str();
}
std::string EightBit::Disassembly::Dump_ind(uint16_t current) const {
std::ostringstream output;
auto address = GetWord(current);
output << "(" << ConvertAddress(address) << ")";
return output.str();
}
std::string EightBit::Disassembly::Dump_zpind(uint16_t current) const {
std::ostringstream output;
auto zp = GetByte(current);
output << "(" << ConvertAddress(zp) << ")";
return output.str();
}
std::string EightBit::Disassembly::Dump_rel(uint16_t current) const {
uint16_t relative = 1 + current + (int8_t)GetByte(current);
return ConvertAddress(relative);
}
std::string EightBit::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();
}

View File

@ -136,12 +136,9 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\inc\AddressingMode.h" />
<ClInclude Include="..\inc\AddressingModeDumper.h" />
<ClInclude Include="..\inc\Disassembly.h" />
<ClInclude Include="..\inc\DisassemblyEventArgs.h" />
<ClInclude Include="..\inc\mos6502.h" />
<ClInclude Include="..\inc\ProcessorType.h" />
<ClInclude Include="..\inc\ProfileEventArgs.h" />
<ClInclude Include="..\inc\ProfileLineEventArgs.h" />
<ClInclude Include="..\inc\Profiler.h" />

View File

@ -14,12 +14,6 @@
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\AddressingMode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\AddressingModeDumper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\Disassembly.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -29,9 +23,6 @@
<ClInclude Include="..\inc\mos6502.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\ProcessorType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\ProfileEventArgs.h">
<Filter>Header Files</Filter>
</ClInclude>

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,6 @@
#include "Board.h"
#include "Disassembly.h"
#include "ProcessorType.h"
#include <iostream>
#include <sstream>
#include <iomanip>
@ -12,7 +10,7 @@
Board::Board(const Configuration& configuration)
: m_configuration(configuration),
m_memory(0xffff),
m_cpu(EightBit::MOS6502(m_memory, EightBit::ProcessorType::Cpu6502)),
m_cpu(EightBit::MOS6502(m_memory)),
m_symbols(""),
m_disassembler(m_cpu, m_symbols),
m_profiler(m_cpu, m_disassembler, m_symbols),
@ -77,9 +75,6 @@ void Board::Cpu_ExecutingInstruction_Debug(const EightBit::MOS6502& cpu) {
auto address = m_cpu.PC().word;
auto cell = m_memory.peek(address);
const auto& instruction = m_cpu.getInstruction(cell);
auto mode = instruction.mode;
std::cout << std::hex;
std::cout << "PC=" << std::setw(4) << std::setfill('0') << address << ":";
std::cout << "P=" << m_disassembler.Dump_Flags(m_cpu.P()) << ", ";
@ -89,11 +84,6 @@ void Board::Cpu_ExecutingInstruction_Debug(const EightBit::MOS6502& cpu) {
std::cout << "Y=" << (int)m_cpu.Y() << ", ";
std::cout << "S=" << (int)m_cpu.S() << "\t";
std::cout << m_disassembler.Dump_ByteValue(cell);
std::cout << m_disassembler.DumpBytes(mode, address + 1);
std::cout << "\t ";
std::cout << m_disassembler.Disassemble(address);
std::cout << "\n";