#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_at(Machine& machine, uint16_t address) { uint16_t result = machine.get_memory().get_at(address) << 1; machine.get_memory().set_at(address, result); auto& ps = machine.get_cpu().get_ps(); ps.set_carry((result & 0x100) == 0x100); set_zero_and_neg_flags(ps, result); } void BitwiseOpcodeHandlerContainer::asl_acc(Machine& machine) { uint16_t result = machine.get_cpu().get_a().get_value() << 1; machine.get_cpu().get_a().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_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_at(Machine& machine, uint16_t address) { auto orig = machine.get_memory().get_at(address); auto result = orig >> 1; machine.get_memory().set_at(address, result); auto& ps = machine.get_cpu().get_ps(); ps.set_carry((orig & 1) == 1); ps.set_zero(result == 0); } void BitwiseOpcodeHandlerContainer::lsr_acc(Machine& machine) { auto orig = machine.get_cpu().get_a().get_value(); auto result = orig >> 1; machine.get_cpu().get_a().set_value(result); auto& ps = machine.get_cpu().get_ps(); ps.set_carry((orig & 1) == 1); ps.set_zero(result == 0); } 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_at(Machine& machine, uint16_t address) { uint16_t result = machine.get_memory().get_at(address) << 1; auto& ps = machine.get_cpu().get_ps(); if (ps.is_carry_set()) result += 1; machine.get_memory().set_at(address, result); ps.set_carry((result & 0x100) == 0x100); set_zero_and_neg_flags(ps, result); } void BitwiseOpcodeHandlerContainer::rol_acc(Machine& machine) { uint16_t result = machine.get_cpu().get_a().get_value() << 1; auto& ps = machine.get_cpu().get_ps(); if (ps.is_carry_set()) result += 1; machine.get_cpu().get_a().set_value(result); ps.set_carry((result & 0x100) == 0x100); set_zero_and_neg_flags(ps, result); } 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_at(Machine& machine, uint16_t address) { auto orig = machine.get_memory().get_at(address); auto result = orig >> 1; auto& ps = machine.get_cpu().get_ps(); if (ps.is_carry_set()) result += 0x80; machine.get_memory().set_at(address, result); ps.set_carry((orig & 1) == 1); set_zero_and_neg_flags(ps, result); } void BitwiseOpcodeHandlerContainer::ror_acc(Machine& machine) { auto orig = machine.get_cpu().get_a().get_value(); auto result = orig >> 1; auto& ps = machine.get_cpu().get_ps(); if (ps.is_carry_set()) result += 0x80; machine.get_cpu().get_a().set_value(result); ps.set_carry((orig & 1) == 1); set_zero_and_neg_flags(ps, result); } 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)); } }