diff --git a/src/opcode/handler/bitwise-opcode-handler-container.cpp b/src/opcode/handler/bitwise-opcode-handler-container.cpp index 75bc44a..dcdee18 100644 --- a/src/opcode/handler/bitwise-opcode-handler-container.cpp +++ b/src/opcode/handler/bitwise-opcode-handler-container.cpp @@ -50,6 +50,12 @@ namespace emu_6502 { 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) { @@ -311,4 +317,46 @@ namespace emu_6502 { 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)); + } } \ No newline at end of file diff --git a/src/opcode/handler/bitwise-opcode-handler-container.h b/src/opcode/handler/bitwise-opcode-handler-container.h index a35a002..cbab570 100644 --- a/src/opcode/handler/bitwise-opcode-handler-container.h +++ b/src/opcode/handler/bitwise-opcode-handler-container.h @@ -120,7 +120,12 @@ namespace emu_6502 { void rol_abs(Machine& machine); void rol_abs_x(Machine& machine); - + void ror_at(Machine& machine, uint16_t address); + void ror_acc(Machine& machine); + void ror_zpg(Machine& machine); + void ror_zpg_x(Machine& machine); + void ror_abs(Machine& machine); + void ror_abs_x(Machine& machine); public: BitwiseOpcodeHandlerContainer(); diff --git a/test/bitwise-opcode-handler-test.cpp b/test/bitwise-opcode-handler-test.cpp index dbf5eb5..91777df 100644 --- a/test/bitwise-opcode-handler-test.cpp +++ b/test/bitwise-opcode-handler-test.cpp @@ -52,6 +52,12 @@ const uint8_t ROL_ZPG_X = 0x36; const uint8_t ROL_ABS = 0x2E; const uint8_t ROL_ABS_X = 0x3E; +const uint8_t ROR_ACC = 0x6A; +const uint8_t ROR_ZPG = 0x66; +const uint8_t ROR_ZPG_X = 0x76; +const uint8_t ROR_ABS = 0x6E; +const uint8_t ROR_ABS_X = 0x7E; + TEST(LoadOpcodeHandlerContainer, AND_IMM) { auto machine = create_machine({AND_IMM, 0x23}); machine->get_cpu().get_a().set_value(0x13); @@ -783,3 +789,153 @@ TEST(LoadOpcodeHandlerContainer, ROL_ZPG_ZeroFlag) { flags.zero = true; ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags)); } + +TEST(LoadOpcodeHandlerContainer, ROL_ZPG_X) { + auto machine = create_machine({ROL_ZPG_X, 0x10}); + machine->get_cpu().get_x().set_value(0x5); + machine->get_memory().set_at(0x15, 0x09); + machine->execute(); + + ASSERT_EQ(0x12, machine->get_memory().get_at(0x15)); + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{})); +} + +TEST(LoadOpcodeHandlerContainer, ROL_ABS) { + auto machine = create_machine({ROL_ABS, 0x10, 0x11}); + machine->get_memory().set_at(0x1110, 0x09); + machine->execute(); + + ASSERT_EQ(0x12, machine->get_memory().get_at(0x1110)); + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{})); +} + +TEST(LoadOpcodeHandlerContainer, ROL_ABS_X) { + auto machine = create_machine({ROL_ABS_X, 0x10, 0x11}); + machine->get_cpu().get_x().set_value(0x5); + machine->get_memory().set_at(0x1115, 0x09); + machine->execute(); + + ASSERT_EQ(0x12, machine->get_memory().get_at(0x1115)); + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{})); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ACC) { + auto machine = create_machine({ROR_ACC}); + machine->get_cpu().get_a().set_value(0x08); + machine->execute(); + + ASSERT_EQ(0x4, machine->get_cpu().get_a().get_value()); + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{})); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ACC_OldCarry) { + auto machine = create_machine({ROR_ACC}); + machine->get_cpu().get_ps().set_carry(true); + machine->get_cpu().get_a().set_value(0x08); + machine->execute(); + + ASSERT_EQ(0x84, machine->get_cpu().get_a().get_value()); + RegisterFlagSet flags{}; + flags.negative = true; + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags)); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ACC_NegativeAndCarryFlag) { + auto machine = create_machine({ROR_ACC}); + machine->get_cpu().get_ps().set_carry(true); + machine->get_cpu().get_a().set_value(0x09); + machine->execute(); + + ASSERT_EQ(0x84, machine->get_cpu().get_a().get_value()); + RegisterFlagSet flags{}; + flags.carry = true; + flags.negative = true; + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags)); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ACC_ZeroFlag) { + auto machine = create_machine({ROR_ACC}); + machine->get_cpu().get_a().set_value(0x01); + machine->execute(); + + ASSERT_EQ(0x0, machine->get_cpu().get_a().get_value()); + RegisterFlagSet flags{}; + flags.carry = true; + flags.zero = true; + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags)); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ZPG) { + auto machine = create_machine({ROR_ZPG, 0x10}); + machine->get_memory().set_at(0x10, 0x08); + machine->execute(); + + ASSERT_EQ(0x4, machine->get_memory().get_at(0x10)); + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{})); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ZPG_OldCarry) { + auto machine = create_machine({ROR_ZPG, 0x10}); + machine->get_cpu().get_ps().set_carry(true); + machine->get_memory().set_at(0x10, 0x08); + machine->execute(); + + ASSERT_EQ(0x84, machine->get_memory().get_at(0x10)); + RegisterFlagSet flags{}; + flags.negative = true; + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags)); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ZPG_NegativeAndCarryFlag) { + auto machine = create_machine({ROR_ZPG, 0x10}); + machine->get_cpu().get_ps().set_carry(true); + machine->get_memory().set_at(0x10, 0x09); + machine->execute(); + + ASSERT_EQ(0x84, machine->get_memory().get_at(0x10)); + RegisterFlagSet flags{}; + flags.carry = true; + flags.negative = true; + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags)); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ZPG_ZeroFlag) { + auto machine = create_machine({ROR_ZPG, 0x10}); + machine->get_memory().set_at(0x10, 0x01); + machine->execute(); + + ASSERT_EQ(0x0, machine->get_memory().get_at(0x10)); + RegisterFlagSet flags{}; + flags.carry = true; + flags.zero = true; + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), flags)); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ZPG_X) { + auto machine = create_machine({ROR_ZPG_X, 0x10}); + machine->get_cpu().get_x().set_value(0x5); + machine->get_memory().set_at(0x15, 0x08); + machine->execute(); + + ASSERT_EQ(0x4, machine->get_memory().get_at(0x15)); + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{})); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ABS) { + auto machine = create_machine({ROR_ABS, 0x10, 0x75}); + machine->get_memory().set_at(0x7510, 0x08); + machine->execute(); + + ASSERT_EQ(0x4, machine->get_memory().get_at(0x7510)); + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{})); +} + +TEST(LoadOpcodeHandlerContainer, ROR_ABS_X) { + auto machine = create_machine({ROR_ABS_X, 0x10, 0x75}); + machine->get_cpu().get_x().set_value(0x5); + machine->get_memory().set_at(0x7515, 0x08); + machine->execute(); + + ASSERT_EQ(0x4, machine->get_memory().get_at(0x7515)); + ASSERT_TRUE(are_flags_set(machine->get_cpu().get_ps(), RegisterFlagSet{})); +}