From 88b33042daa659dc5be95d51a6d3f90f1ddd0b35 Mon Sep 17 00:00:00 2001 From: Tony Di Nucci Date: Sun, 21 Apr 2019 19:03:51 +0100 Subject: [PATCH] Processor status opcodes --- .../compare-opcode-handler-container.cpp | 6 ++ .../compare-opcode-handler-container.h | 36 +++++++++ .../status-opcode-handler-container.cpp | 42 ++++++++++ .../handler/status-opcode-handler-container.h | 37 +++++++++ src/opcode/opcode-handler-directory.cpp | 2 + test/status-opcode-handler-test.cpp | 80 +++++++++++++++++++ 6 files changed, 203 insertions(+) create mode 100644 src/opcode/handler/compare-opcode-handler-container.cpp create mode 100644 src/opcode/handler/compare-opcode-handler-container.h create mode 100644 src/opcode/handler/status-opcode-handler-container.cpp create mode 100644 src/opcode/handler/status-opcode-handler-container.h create mode 100644 test/status-opcode-handler-test.cpp diff --git a/src/opcode/handler/compare-opcode-handler-container.cpp b/src/opcode/handler/compare-opcode-handler-container.cpp new file mode 100644 index 0000000..f7d1ed8 --- /dev/null +++ b/src/opcode/handler/compare-opcode-handler-container.cpp @@ -0,0 +1,6 @@ +#include "compare-opcode-handler-container.h" + +namespace emu_6502 { + CompareOpcodeHandlerContainer::CompareOpcodeHandlerContainer() { + } +} \ No newline at end of file diff --git a/src/opcode/handler/compare-opcode-handler-container.h b/src/opcode/handler/compare-opcode-handler-container.h new file mode 100644 index 0000000..cb65adc --- /dev/null +++ b/src/opcode/handler/compare-opcode-handler-container.h @@ -0,0 +1,36 @@ +#ifndef INC_6502_EMULATOR_COMPARE_OPCODE_HANDLER_CONTAINER_H +#define INC_6502_EMULATOR_COMPARE_OPCODE_HANDLER_CONTAINER_H + +#include "opcode-handler-container.h" + +namespace emu_6502 { + class CompareOpcodeHandlerContainer : public OpcodeHandlerContainer { + private: + enum Op { + CMP_IMM = 0xC9, + CMP_ZPG = 0xC5, + CMP_ZPX_X = 0xD5, + CMP_ABS = 0xCD, + CMP_ABS_X = 0xDD, + CMP_ABS_Y = 0xD9, + CMP_IND_X = 0xC1, + CMP_IND_Y = 0xD1, + + CPX_IMM = 0xE0, + CPX_ZPG = 0xE4, + CPX_ABS = 0xEC, + + CPY_IMM = 0x0, + CPY_ZPG = 0x0, + CPY_ABS = 0x0, + }; + + public: + CompareOpcodeHandlerContainer(); + CompareOpcodeHandlerContainer(const CompareOpcodeHandlerContainer&) = delete; + CompareOpcodeHandlerContainer& operator=(CompareOpcodeHandlerContainer&) = delete; + }; +} + + +#endif //INC_6502_EMULATOR_COMPARE_OPCODE_HANDLER_CONTAINER_H diff --git a/src/opcode/handler/status-opcode-handler-container.cpp b/src/opcode/handler/status-opcode-handler-container.cpp new file mode 100644 index 0000000..b8ff676 --- /dev/null +++ b/src/opcode/handler/status-opcode-handler-container.cpp @@ -0,0 +1,42 @@ +#include "status-opcode-handler-container.h" + +namespace emu_6502 { + StatusOpcodeHandlerContainer::StatusOpcodeHandlerContainer() { + handlers.insert({Op::CLC, [this](Machine& machine) { clc(machine); }}); + handlers.insert({Op::CLD, [this](Machine& machine) { cld(machine); }}); + handlers.insert({Op::CLI, [this](Machine& machine) { cli(machine); }}); + handlers.insert({Op::CLV, [this](Machine& machine) { clv(machine); }}); + + handlers.insert({Op::SEC, [this](Machine& machine) { sec(machine); }}); + handlers.insert({Op::SED, [this](Machine& machine) { sed(machine); }}); + handlers.insert({Op::SEI, [this](Machine& machine) { sei(machine); }}); + } + + void StatusOpcodeHandlerContainer::clc(Machine& machine) { + machine.get_cpu().get_ps().set_carry(false); + } + + void StatusOpcodeHandlerContainer::cld(Machine& machine) { + machine.get_cpu().get_ps().set_decimal(false); + } + + void StatusOpcodeHandlerContainer::cli(Machine& machine) { + machine.get_cpu().get_ps().set_interupt_disable(false); + } + + void StatusOpcodeHandlerContainer::clv(Machine& machine) { + machine.get_cpu().get_ps().set_overflow(false); + } + + void StatusOpcodeHandlerContainer::sec(Machine& machine) { + machine.get_cpu().get_ps().set_carry(true); + } + + void StatusOpcodeHandlerContainer::sed(Machine& machine) { + machine.get_cpu().get_ps().set_decimal(true); + } + + void StatusOpcodeHandlerContainer::sei(Machine& machine) { + machine.get_cpu().get_ps().set_interupt_disable(true); + } +} \ No newline at end of file diff --git a/src/opcode/handler/status-opcode-handler-container.h b/src/opcode/handler/status-opcode-handler-container.h new file mode 100644 index 0000000..21bcdf3 --- /dev/null +++ b/src/opcode/handler/status-opcode-handler-container.h @@ -0,0 +1,37 @@ +#ifndef INC_6502_EMULATOR_STATUS_OPCODE_HANDLER_CONTAINER_H +#define INC_6502_EMULATOR_STATUS_OPCODE_HANDLER_CONTAINER_H + +#include "opcode-handler-container.h" + +namespace emu_6502 { + class StatusOpcodeHandlerContainer : public OpcodeHandlerContainer { + private: + enum Op { + CLC = 0x18, + CLD = 0xD8, + CLI = 0x58, + CLV = 0xB8, + + SEC = 0x38, + SED = 0xF8, + SEI = 0x78 + }; + + void clc(Machine& machine); + void cld(Machine& machine); + void cli(Machine& machine); + void clv(Machine& machine); + + void sec(Machine& machine); + void sed(Machine& machine); + void sei(Machine& machine); + + public: + StatusOpcodeHandlerContainer(); + StatusOpcodeHandlerContainer(const StatusOpcodeHandlerContainer&) = delete; + StatusOpcodeHandlerContainer& operator=(const StatusOpcodeHandlerContainer&) = delete; + }; +} + + +#endif //INC_6502_EMULATOR_STATUS_OPCODE_HANDLER_CONTAINER_H diff --git a/src/opcode/opcode-handler-directory.cpp b/src/opcode/opcode-handler-directory.cpp index 715f86c..7c363b3 100644 --- a/src/opcode/opcode-handler-directory.cpp +++ b/src/opcode/opcode-handler-directory.cpp @@ -4,6 +4,7 @@ #include "handler/transfer-opcode-handler-container.h" #include "handler/maths-opcode-handler-container.h" #include "handler/bitwise-opcode-handler-container.h" +#include "handler/status-opcode-handler-container.h" #include "../utils.h" namespace emu_6502 { @@ -14,6 +15,7 @@ namespace emu_6502 { handler_containers.push_back(make_unique()); handler_containers.push_back(make_unique()); handler_containers.push_back(make_unique()); + handler_containers.push_back(make_unique()); init_handlers(); } diff --git a/test/status-opcode-handler-test.cpp b/test/status-opcode-handler-test.cpp new file mode 100644 index 0000000..2284374 --- /dev/null +++ b/test/status-opcode-handler-test.cpp @@ -0,0 +1,80 @@ +#include "gtest/gtest.h" +#include "test-utils.h" + +using namespace std; +using namespace emu_6502; + +const uint8_t CLC = 0x18; +const uint8_t CLD = 0xD8; +const uint8_t CLI = 0x58; +const uint8_t CLV = 0xB8; +const uint8_t SEC = 0x38; +const uint8_t SED = 0xF8; +const uint8_t SEI = 0x78; + +TEST(StatusOpcodeHandlerContainer, CLC) { + auto machine = create_machine({CLC}); + auto& ps = machine->get_cpu().get_ps(); + ps.set_carry(true); + + ASSERT_TRUE(ps.is_carry_set()); + machine->execute(); + ASSERT_FALSE(ps.is_carry_set()); +} + +TEST(StatusOpcodeHandlerContainer, CLD) { + auto machine = create_machine({CLD}); + auto& ps = machine->get_cpu().get_ps(); + ps.set_decimal(true); + + ASSERT_TRUE(ps.is_decimal_set()); + machine->execute(); + ASSERT_FALSE(ps.is_decimal_set()); +} + +TEST(StatusOpcodeHandlerContainer, CLI) { + auto machine = create_machine({CLI}); + auto& ps = machine->get_cpu().get_ps(); + ps.set_interupt_disable(true); + + ASSERT_TRUE(ps.is_interupt_disable_set()); + machine->execute(); + ASSERT_FALSE(ps.is_interupt_disable_set()); +} + +TEST(StatusOpcodeHandlerContainer, CLV) { + auto machine = create_machine({CLV}); + auto& ps = machine->get_cpu().get_ps(); + ps.set_overflow(true); + + ASSERT_TRUE(ps.is_overflow_set()); + machine->execute(); + ASSERT_FALSE(ps.is_overflow_set()); +} + +TEST(StatusOpcodeHandlerContainer, SEC) { + auto machine = create_machine({SEC}); + auto& ps = machine->get_cpu().get_ps(); + + ASSERT_FALSE(ps.is_carry_set()); + machine->execute(); + ASSERT_TRUE(ps.is_carry_set()); +} + +TEST(StatusOpcodeHandlerContainer, SED) { + auto machine = create_machine({SED}); + auto& ps = machine->get_cpu().get_ps(); + + ASSERT_FALSE(ps.is_decimal_set()); + machine->execute(); + ASSERT_TRUE(ps.is_decimal_set()); +} + +TEST(StatusOpcodeHandlerContainer, SEI) { + auto machine = create_machine({SEI}); + auto& ps = machine->get_cpu().get_ps(); + + ASSERT_FALSE(ps.is_interupt_disable_set()); + machine->execute(); + ASSERT_TRUE(ps.is_interupt_disable_set()); +}