2021-05-07 05:11:12 +00:00
|
|
|
#ifndef INC_6502_CPP_6502_HPP
|
|
|
|
#define INC_6502_CPP_6502_HPP
|
|
|
|
|
|
|
|
#include "assembly.hpp"
|
|
|
|
|
|
|
|
struct mos6502 : ASMLine
|
|
|
|
{
|
|
|
|
enum class OpCode {
|
|
|
|
unknown,
|
|
|
|
|
|
|
|
adc,
|
|
|
|
AND,
|
|
|
|
asl,
|
|
|
|
|
|
|
|
bcc,
|
|
|
|
bcs,
|
|
|
|
beq,
|
|
|
|
bit,
|
|
|
|
bmi,
|
|
|
|
bne,
|
|
|
|
bpl,
|
|
|
|
|
|
|
|
cpy,
|
|
|
|
cmp,
|
|
|
|
clc,
|
|
|
|
|
|
|
|
dec,
|
|
|
|
|
|
|
|
eor,
|
|
|
|
|
|
|
|
inc,
|
|
|
|
|
|
|
|
jmp,
|
|
|
|
jsr,
|
|
|
|
|
|
|
|
lda,
|
2021-05-09 04:58:55 +00:00
|
|
|
ldx,
|
2021-05-07 05:11:12 +00:00
|
|
|
ldy,
|
|
|
|
lsr,
|
|
|
|
|
|
|
|
ORA,
|
|
|
|
|
|
|
|
pha,
|
|
|
|
php,
|
|
|
|
pla,
|
|
|
|
plp,
|
|
|
|
|
|
|
|
rol,
|
|
|
|
ror,
|
|
|
|
rts,
|
|
|
|
|
|
|
|
sbc,
|
|
|
|
sec,
|
|
|
|
sta,
|
2021-05-09 04:58:55 +00:00
|
|
|
stx,
|
2021-05-07 05:11:12 +00:00
|
|
|
sty,
|
|
|
|
|
|
|
|
tax,
|
|
|
|
tay,
|
2021-05-09 04:58:55 +00:00
|
|
|
tsx,
|
2021-05-07 05:11:12 +00:00
|
|
|
txa,
|
2021-05-09 04:58:55 +00:00
|
|
|
txs,
|
2021-05-07 05:11:12 +00:00
|
|
|
tya,
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool get_is_branch(const OpCode o)
|
|
|
|
{
|
|
|
|
switch (o) {
|
|
|
|
case OpCode::beq:
|
|
|
|
case OpCode::bne:
|
|
|
|
case OpCode::bmi:
|
|
|
|
case OpCode::bpl:
|
|
|
|
case OpCode::bcc:
|
|
|
|
case OpCode::bcs:
|
|
|
|
return true;
|
|
|
|
case OpCode::adc:
|
|
|
|
case OpCode::AND:
|
|
|
|
case OpCode::asl:
|
|
|
|
case OpCode::bit:
|
|
|
|
case OpCode::cpy:
|
|
|
|
case OpCode::cmp:
|
|
|
|
case OpCode::clc:
|
|
|
|
case OpCode::dec:
|
|
|
|
case OpCode::eor:
|
|
|
|
case OpCode::inc:
|
|
|
|
case OpCode::jmp:
|
|
|
|
case OpCode::jsr:
|
|
|
|
case OpCode::lda:
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::ldx:
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::ldy:
|
|
|
|
case OpCode::lsr:
|
|
|
|
case OpCode::ORA:
|
|
|
|
case OpCode::pha:
|
|
|
|
case OpCode::php:
|
|
|
|
case OpCode::pla:
|
|
|
|
case OpCode::plp:
|
|
|
|
case OpCode::rol:
|
|
|
|
case OpCode::ror:
|
|
|
|
case OpCode::rts:
|
|
|
|
case OpCode::sbc:
|
|
|
|
case OpCode::sec:
|
|
|
|
case OpCode::sta:
|
|
|
|
case OpCode::sty:
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::stx:
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::tax:
|
|
|
|
case OpCode::tay:
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::tsx:
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::txa:
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::txs:
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::tya:
|
|
|
|
|
|
|
|
case OpCode::unknown:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool get_is_comparison(const OpCode o)
|
|
|
|
{
|
|
|
|
switch (o) {
|
|
|
|
case OpCode::bit:
|
|
|
|
case OpCode::cmp:
|
|
|
|
case OpCode::cpy:
|
|
|
|
return true;
|
|
|
|
case OpCode::adc:
|
|
|
|
case OpCode::AND:
|
|
|
|
case OpCode::asl:
|
|
|
|
case OpCode::beq:
|
|
|
|
case OpCode::bne:
|
|
|
|
case OpCode::bmi:
|
|
|
|
case OpCode::bpl:
|
|
|
|
case OpCode::bcc:
|
|
|
|
case OpCode::bcs:
|
|
|
|
case OpCode::clc:
|
|
|
|
case OpCode::dec:
|
|
|
|
case OpCode::eor:
|
|
|
|
case OpCode::inc:
|
|
|
|
case OpCode::jmp:
|
|
|
|
case OpCode::jsr:
|
|
|
|
case OpCode::lda:
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::ldx:
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::ldy:
|
|
|
|
case OpCode::lsr:
|
|
|
|
case OpCode::ORA:
|
|
|
|
case OpCode::pha:
|
|
|
|
case OpCode::php:
|
|
|
|
case OpCode::pla:
|
|
|
|
case OpCode::plp:
|
|
|
|
case OpCode::rol:
|
|
|
|
case OpCode::ror:
|
|
|
|
case OpCode::rts:
|
|
|
|
case OpCode::sbc:
|
|
|
|
case OpCode::sec:
|
|
|
|
case OpCode::sta:
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::stx:
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::sty:
|
|
|
|
case OpCode::tax:
|
|
|
|
case OpCode::tay:
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::tsx:
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::txa:
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::txs:
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::tya:
|
|
|
|
case OpCode::unknown:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
explicit mos6502(const OpCode o)
|
|
|
|
: ASMLine(Type::Instruction, std::string{ to_string(o) }), opcode(o), is_branch(get_is_branch(o)), is_comparison(get_is_comparison(o))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
mos6502(const Type t, std::string s)
|
|
|
|
: ASMLine(t, std::move(s))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
mos6502(const OpCode o, Operand t_o)
|
|
|
|
: ASMLine(Type::Instruction, std::string{ to_string(o) }), opcode(o), op(std::move(t_o)), is_branch(get_is_branch(o)), is_comparison(get_is_comparison(o))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
constexpr static std::string_view to_string(const OpCode o)
|
|
|
|
{
|
|
|
|
switch (o) {
|
|
|
|
case OpCode::lda: return "lda";
|
|
|
|
case OpCode::asl: return "asl";
|
|
|
|
case OpCode::rol: return "rol";
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::ldx: return "ldx";
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::ldy: return "ldy";
|
|
|
|
case OpCode::tay: return "tay";
|
|
|
|
case OpCode::tya: return "tya";
|
|
|
|
case OpCode::tax: return "tax";
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::tsx: return "tsx";
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::txa: return "txa";
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::txs: return "txs";
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::cpy: return "cpy";
|
|
|
|
case OpCode::eor: return "eor";
|
|
|
|
case OpCode::sta: return "sta";
|
|
|
|
case OpCode::sty: return "sty";
|
2021-05-09 04:58:55 +00:00
|
|
|
case OpCode::stx: return "stx";
|
2021-05-07 05:11:12 +00:00
|
|
|
case OpCode::pha: return "pha";
|
|
|
|
case OpCode::pla: return "pla";
|
|
|
|
case OpCode::php: return "php";
|
|
|
|
case OpCode::plp: return "plp";
|
|
|
|
case OpCode::lsr: return "lsr";
|
|
|
|
case OpCode::ror: return "ror";
|
|
|
|
case OpCode::AND: return "and";
|
|
|
|
case OpCode::inc: return "inc";
|
|
|
|
case OpCode::dec: return "dec";
|
|
|
|
case OpCode::ORA: return "ora";
|
|
|
|
case OpCode::cmp: return "cmp";
|
|
|
|
case OpCode::bne: return "bne";
|
|
|
|
case OpCode::bmi: return "bmi";
|
|
|
|
case OpCode::beq: return "beq";
|
|
|
|
case OpCode::jmp: return "jmp";
|
|
|
|
case OpCode::adc: return "adc";
|
|
|
|
case OpCode::sbc: return "sbc";
|
|
|
|
case OpCode::rts: return "rts";
|
|
|
|
case OpCode::clc: return "clc";
|
|
|
|
case OpCode::sec: return "sec";
|
|
|
|
case OpCode::bit: return "bit";
|
|
|
|
case OpCode::jsr: return "jsr";
|
|
|
|
case OpCode::bpl: return "bpl";
|
|
|
|
case OpCode::bcc: return "bcc";
|
|
|
|
case OpCode::bcs: return "bcs";
|
|
|
|
case OpCode::unknown: return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] std::string to_string() const
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case ASMLine::Type::Label:
|
|
|
|
return text;// + ':';
|
|
|
|
case ASMLine::Type::Directive:
|
|
|
|
case ASMLine::Type::Instruction: {
|
|
|
|
return fmt::format("\t{} {:15}; {}", text, op.value, comment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw std::runtime_error("Unable to render: " + text);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
OpCode opcode = OpCode::unknown;
|
|
|
|
Operand op;
|
|
|
|
std::string comment;
|
|
|
|
bool is_branch = false;
|
|
|
|
bool is_comparison = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif//INC_6502_CPP_6502_HPP
|