6502-emulator/src/opcode/handler/bitwise-opcode-handler-cont...

369 lines
15 KiB
C++

#include "bitwise-opcode-handler-container.h"
#include "../../utils.h"
namespace emu_6502 {
BitwiseOpcodeHandlerContainer::BitwiseOpcodeHandlerContainer() {
handlers.insert({Op::AND_IMM, [this](Machine& machine) { and_imm(machine); }});
handlers.insert({Op::AND_ZPG, [this](Machine& machine) { and_zpg(machine); }});
handlers.insert({Op::AND_ZPG_X, [this](Machine& machine) { and_zpg_x(machine); }});
handlers.insert({Op::AND_ABS, [this](Machine& machine) { and_abs(machine); }});
handlers.insert({Op::AND_ABS_X, [this](Machine& machine) { and_abs_x(machine); }});
handlers.insert({Op::AND_ABS_Y, [this](Machine& machine) { and_abs_y(machine); }});
handlers.insert({Op::AND_IND_X, [this](Machine& machine) { and_ind_x(machine); }});
handlers.insert({Op::AND_IND_Y, [this](Machine& machine) { and_ind_y(machine); }});
handlers.insert({Op::ORA_IMM, [this](Machine& machine) { or_imm(machine); }});
handlers.insert({Op::ORA_ZPG, [this](Machine& machine) { or_zpg(machine); }});
handlers.insert({Op::ORA_ZPG_X, [this](Machine& machine) { or_zpg_x(machine); }});
handlers.insert({Op::ORA_ABS, [this](Machine& machine) { or_abs(machine); }});
handlers.insert({Op::ORA_ABS_X, [this](Machine& machine) { or_abs_x(machine); }});
handlers.insert({Op::ORA_ABS_Y, [this](Machine& machine) { or_abs_y(machine); }});
handlers.insert({Op::ORA_IND_X, [this](Machine& machine) { or_ind_x(machine); }});
handlers.insert({Op::ORA_IND_Y, [this](Machine& machine) { or_ind_y(machine); }});
handlers.insert({Op::EOR_IMM, [this](Machine& machine) { xor_imm(machine); }});
handlers.insert({Op::EOR_ZPG, [this](Machine& machine) { xor_zpg(machine); }});
handlers.insert({Op::EOR_ZPG_X, [this](Machine& machine) { xor_zpg_x(machine); }});
handlers.insert({Op::EOR_ABS, [this](Machine& machine) { xor_abs(machine); }});
handlers.insert({Op::EOR_ABS_X, [this](Machine& machine) { xor_abs_x(machine); }});
handlers.insert({Op::EOR_ABS_Y, [this](Machine& machine) { xor_abs_y(machine); }});
handlers.insert({Op::EOR_IND_X, [this](Machine& machine) { xor_ind_x(machine); }});
handlers.insert({Op::EOR_IND_Y, [this](Machine& machine) { xor_ind_y(machine); }});
handlers.insert({Op::BIT_ZPG, [this](Machine& machine) { bit_zpg(machine); }});
handlers.insert({Op::BIT_ABS, [this](Machine& machine) { bit_abs(machine); }});
handlers.insert({Op::ASL_ACC, [this](Machine& machine) { asl_acc(machine); }});
handlers.insert({Op::ASL_ZPG, [this](Machine& machine) { asl_zpg(machine); }});
handlers.insert({Op::ASL_ZPG_X, [this](Machine& machine) { asl_zpg_x(machine); }});
handlers.insert({Op::ASL_ABS, [this](Machine& machine) { asl_abs(machine); }});
handlers.insert({Op::ASL_ABS_X, [this](Machine& machine) { asl_abs_x(machine); }});
handlers.insert({Op::LSR_ACC, [this](Machine& machine) { lsr_acc(machine); }});
handlers.insert({Op::LSR_ZPG, [this](Machine& machine) { lsr_zpg(machine); }});
handlers.insert({Op::LSR_ZPG_X, [this](Machine& machine) { lsr_zpg_x(machine); }});
handlers.insert({Op::LSR_ABS, [this](Machine& machine) { lsr_abs(machine); }});
handlers.insert({Op::LSR_ABS_X, [this](Machine& machine) { lsr_abs_x(machine); }});
handlers.insert({Op::ROL_ACC, [this](Machine& machine) { rol_acc(machine); }});
handlers.insert({Op::ROL_ZPG, [this](Machine& machine) { rol_zpg(machine); }});
handlers.insert({Op::ROL_ZPG_X, [this](Machine& machine) { rol_zpg_x(machine); }});
handlers.insert({Op::ROL_ABS, [this](Machine& machine) { rol_abs(machine); }});
handlers.insert({Op::ROL_ABS_X, [this](Machine& machine) { rol_abs_x(machine); }});
handlers.insert({Op::ROR_ACC, [this](Machine& machine) { ror_acc(machine); }});
handlers.insert({Op::ROR_ZPG, [this](Machine& machine) { ror_zpg(machine); }});
handlers.insert({Op::ROR_ZPG_X, [this](Machine& machine) { ror_zpg_x(machine); }});
handlers.insert({Op::ROR_ABS, [this](Machine& machine) { ror_abs(machine); }});
handlers.insert({Op::ROR_ABS_X, [this](Machine& machine) { ror_abs_x(machine); }});
}
void BitwiseOpcodeHandlerContainer::do_and(Machine& machine, uint8_t value) {
auto& cpu = machine.get_cpu();
auto result = cpu.get_a().get_value() & value;
cpu.get_a().set_value(result);
set_zero_and_neg_flags(machine.get_cpu().get_ps(), result);
}
void BitwiseOpcodeHandlerContainer::do_and_with(Machine& machine, uint16_t address) {
do_and(machine, machine.get_memory().get_at(address));
}
void BitwiseOpcodeHandlerContainer::and_imm(Machine& machine) {
do_and(machine, machine.read_program_byte());
}
void BitwiseOpcodeHandlerContainer::and_zpg(Machine& machine) {
do_and_with(machine, get_zpg_address(machine));
}
void BitwiseOpcodeHandlerContainer::and_zpg_x(Machine& machine) {
do_and_with(machine, get_zpg_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::and_abs(Machine& machine) {
do_and_with(machine, get_abs_address(machine));
}
void BitwiseOpcodeHandlerContainer::and_abs_x(Machine& machine) {
do_and_with(machine, get_abs_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::and_abs_y(Machine& machine) {
do_and_with(machine, get_abs_y_address(machine));
}
void BitwiseOpcodeHandlerContainer::and_ind_x(Machine& machine) {
do_and_with(machine, get_ind_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::and_ind_y(Machine& machine) {
do_and_with(machine, get_ind_y_address(machine));
}
void BitwiseOpcodeHandlerContainer::do_or(Machine& machine, uint8_t value) {
auto& cpu = machine.get_cpu();
auto result = cpu.get_a().get_value() | value;
cpu.get_a().set_value(result);
set_zero_and_neg_flags(machine.get_cpu().get_ps(), result);
}
void BitwiseOpcodeHandlerContainer::do_or_with(Machine& machine, uint16_t address) {
do_or(machine, machine.get_memory().get_at(address));
}
void BitwiseOpcodeHandlerContainer::or_imm(Machine& machine) {
do_or(machine, machine.read_program_byte());
}
void BitwiseOpcodeHandlerContainer::or_zpg(Machine& machine) {
do_or_with(machine, get_zpg_address(machine));
}
void BitwiseOpcodeHandlerContainer::or_zpg_x(Machine& machine) {
do_or_with(machine, get_zpg_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::or_abs(Machine& machine) {
do_or_with(machine, get_abs_address(machine));
}
void BitwiseOpcodeHandlerContainer::or_abs_x(Machine& machine) {
do_or_with(machine, get_abs_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::or_abs_y(Machine& machine) {
do_or_with(machine, get_abs_y_address(machine));
}
void BitwiseOpcodeHandlerContainer::or_ind_x(Machine& machine) {
do_or_with(machine, get_ind_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::or_ind_y(Machine& machine) {
do_or_with(machine, get_ind_y_address(machine));
}
void BitwiseOpcodeHandlerContainer::do_xor(Machine& machine, uint8_t value) {
auto& cpu = machine.get_cpu();
auto result = cpu.get_a().get_value() ^value;
cpu.get_a().set_value(result);
set_zero_and_neg_flags(machine.get_cpu().get_ps(), result);
}
void BitwiseOpcodeHandlerContainer::do_xor_with(Machine& machine, uint16_t address) {
do_xor(machine, machine.get_memory().get_at(address));
}
void BitwiseOpcodeHandlerContainer::xor_imm(Machine& machine) {
do_xor(machine, machine.read_program_byte());
}
void BitwiseOpcodeHandlerContainer::xor_zpg(Machine& machine) {
do_xor_with(machine, get_zpg_address(machine));
}
void BitwiseOpcodeHandlerContainer::xor_zpg_x(Machine& machine) {
do_xor_with(machine, get_zpg_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::xor_abs(Machine& machine) {
do_xor_with(machine, get_abs_address(machine));
}
void BitwiseOpcodeHandlerContainer::xor_abs_x(Machine& machine) {
do_xor_with(machine, get_abs_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::xor_abs_y(Machine& machine) {
do_xor_with(machine, get_abs_y_address(machine));
}
void BitwiseOpcodeHandlerContainer::xor_ind_x(Machine& machine) {
do_xor_with(machine, get_ind_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::xor_ind_y(Machine& machine) {
do_xor_with(machine, get_ind_y_address(machine));
}
void BitwiseOpcodeHandlerContainer::bit(Machine& machine, uint16_t address) {
auto a = machine.get_cpu().get_a().get_value();
auto mem = machine.get_memory().get_at(address);
auto& ps = machine.get_cpu().get_ps();
ps.set_zero((a & mem) == 0);
ps.set_negative((mem & 0x80) == 0x80);
ps.set_overflow((mem & 0x40) == 0x40);
}
void BitwiseOpcodeHandlerContainer::bit_zpg(Machine& machine) {
bit(machine, get_zpg_address(machine));
}
void BitwiseOpcodeHandlerContainer::bit_abs(Machine& machine) {
bit(machine, get_abs_address(machine));
}
void BitwiseOpcodeHandlerContainer::asl(emu_6502::Machine& machine, function<uint8_t()> get_value,
function<void(uint8_t)> set_value) {
uint16_t result = get_value() << 1;
set_value(result);
auto& ps = machine.get_cpu().get_ps();
ps.set_carry((result & 0x100) == 0x100);
set_zero_and_neg_flags(ps, result);
}
void BitwiseOpcodeHandlerContainer::asl_at(Machine& machine, uint16_t address) {
asl(machine,
[&]() { return machine.get_memory().get_at(address); },
[&](uint8_t value) { machine.get_memory().set_at(address, value); });
}
void BitwiseOpcodeHandlerContainer::asl_acc(Machine& machine) {
asl(machine,
[&]() { return machine.get_cpu().get_a().get_value(); },
[&](uint8_t value) { machine.get_cpu().get_a().set_value(value); });
}
void BitwiseOpcodeHandlerContainer::asl_zpg(Machine& machine) {
asl_at(machine, get_zpg_address(machine));
}
void BitwiseOpcodeHandlerContainer::asl_zpg_x(Machine& machine) {
asl_at(machine, get_zpg_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::asl_abs(Machine& machine) {
asl_at(machine, get_abs_address(machine));
}
void BitwiseOpcodeHandlerContainer::asl_abs_x(Machine& machine) {
asl_at(machine, get_abs_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::lsr(emu_6502::Machine& machine, function<uint8_t()> get_value,
function<void(uint8_t)> set_value) {
auto orig = get_value();
auto result = orig >> 1;
set_value(result);
auto& ps = machine.get_cpu().get_ps();
ps.set_carry((orig & 1) == 1);
ps.set_zero(result == 0);
}
void BitwiseOpcodeHandlerContainer::lsr_at(Machine& machine, uint16_t address) {
lsr(machine,
[&]() { return machine.get_memory().get_at(address); },
[&](uint8_t value) { machine.get_memory().set_at(address, value); });
}
void BitwiseOpcodeHandlerContainer::lsr_acc(Machine& machine) {
lsr(machine,
[&]() { return machine.get_cpu().get_a().get_value(); },
[&](uint8_t value) { machine.get_cpu().get_a().set_value(value); });
}
void BitwiseOpcodeHandlerContainer::lsr_zpg(Machine& machine) {
lsr_at(machine, get_zpg_address(machine));
}
void BitwiseOpcodeHandlerContainer::lsr_zpg_x(Machine& machine) {
lsr_at(machine, get_zpg_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::lsr_abs(Machine& machine) {
lsr_at(machine, get_abs_address(machine));
}
void BitwiseOpcodeHandlerContainer::lsr_abs_x(Machine& machine) {
lsr_at(machine, get_abs_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::rol(emu_6502::Machine& machine, function<uint8_t()> get_value,
function<void(uint8_t)> set_value) {
uint16_t result = get_value() << 1;
auto& ps = machine.get_cpu().get_ps();
if (ps.is_carry_set())
result += 1;
set_value(result);
ps.set_carry((result & 0x100) == 0x100);
set_zero_and_neg_flags(ps, result);
}
void BitwiseOpcodeHandlerContainer::rol_at(Machine& machine, uint16_t address) {
rol(machine,
[&]() { return machine.get_memory().get_at(address); },
[&](uint8_t value) { machine.get_memory().set_at(address, value); });
}
void BitwiseOpcodeHandlerContainer::rol_acc(Machine& machine) {
rol(machine,
[&]() { return machine.get_cpu().get_a().get_value(); },
[&](uint8_t value) { machine.get_cpu().get_a().set_value(value); });
}
void BitwiseOpcodeHandlerContainer::rol_zpg(Machine& machine) {
rol_at(machine, get_zpg_address(machine));
}
void BitwiseOpcodeHandlerContainer::rol_zpg_x(Machine& machine) {
rol_at(machine, get_zpg_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::rol_abs(Machine& machine) {
rol_at(machine, get_abs_address(machine));
}
void BitwiseOpcodeHandlerContainer::rol_abs_x(Machine& machine) {
rol_at(machine, get_abs_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::ror(Machine& machine, function<uint8_t()> get_value,
function<void(uint8_t)> set_value) {
auto orig = get_value();
auto result = orig >> 1;
auto& ps = machine.get_cpu().get_ps();
if (ps.is_carry_set())
result += 0x80;
set_value(result);
ps.set_carry((orig & 1) == 1);
set_zero_and_neg_flags(ps, result);
}
void BitwiseOpcodeHandlerContainer::ror_at(Machine& machine, uint16_t address) {
ror(machine,
[&]() { return machine.get_memory().get_at(address); },
[&](uint8_t value) { machine.get_memory().set_at(address, value); });
}
void BitwiseOpcodeHandlerContainer::ror_acc(Machine& machine) {
ror(machine,
[&]() { return machine.get_cpu().get_a().get_value(); },
[&](uint8_t value) { machine.get_cpu().get_a().set_value(value); });
}
void BitwiseOpcodeHandlerContainer::ror_zpg(Machine& machine) {
ror_at(machine, get_zpg_address(machine));
}
void BitwiseOpcodeHandlerContainer::ror_zpg_x(Machine& machine) {
ror_at(machine, get_zpg_x_address(machine));
}
void BitwiseOpcodeHandlerContainer::ror_abs(Machine& machine) {
ror_at(machine, get_abs_address(machine));
}
void BitwiseOpcodeHandlerContainer::ror_abs_x(Machine& machine) {
ror_at(machine, get_abs_x_address(machine));
}
}