diff --git a/CMakeLists.txt b/CMakeLists.txt index 05bc6a6..d8246de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ add_compile_options(-W -Wall -Wextra -Wshadow) add_executable(unit_tests tests/CPU/testAddressingMode.cpp tests/tests.cpp - tests/CPU/testCPU.cpp + tests/CPU/testInterupts.cpp tests/testMemoryBus.cpp tests/tests.hpp sources/SNES.cpp @@ -52,7 +52,7 @@ add_executable(unit_tests sources/CPU/Instructions/CommonInstructions.hpp sources/Exceptions/InvalidOpcode.hpp sources/CPU/Instructions/Interrupts.cpp - sources/CPU/Instructions/MathematicalOperations.cpp) + sources/CPU/Instructions/MathematicalOperations.cpp tests/CPU/testMath.cpp) # include criterion & coverage target_link_libraries(unit_tests criterion -lgcov) diff --git a/sources/CPU/Instructions/MathematicalOperations.cpp b/sources/CPU/Instructions/MathematicalOperations.cpp index e1b205c..ee1b6c7 100644 --- a/sources/CPU/Instructions/MathematicalOperations.cpp +++ b/sources/CPU/Instructions/MathematicalOperations.cpp @@ -2,14 +2,27 @@ // Created by anonymus-raccoon on 2/10/20. // +#include #include "../CPU.hpp" namespace ComSquare::CPU { int CPU::ADC(uint24_t valueAddr) { -// this->_registers.a += - (void)valueAddr; + unsigned value = this->_bus->read(valueAddr) + this->_registers.p.c; + unsigned negativeMask = this->_isEmulationMode ? 0xF0u : 0xF000u; + unsigned maxValue = this->_isEmulationMode ? UINT8_MAX : UINT16_MAX; + + this->_registers.p.c = static_cast(this->_registers.a) + value > maxValue; + if ((this->_registers.a & negativeMask) == (value & negativeMask)) + this->_registers.p.v = (this->_registers.a & negativeMask) != ((this->_registers.a + value) & negativeMask); + else + this->_registers.p.v = false; + this->_registers.a += value; + if (this->_isEmulationMode) + this->_registers.a %= 0x100; + this->_registers.p.z = this->_registers.a == 0; + this->_registers.p.n = this->_registers.a & negativeMask; return (0); } } \ No newline at end of file diff --git a/tests/CPU/testCPU.cpp b/tests/CPU/testInterupts.cpp similarity index 100% rename from tests/CPU/testCPU.cpp rename to tests/CPU/testInterupts.cpp diff --git a/tests/CPU/testMath.cpp b/tests/CPU/testMath.cpp new file mode 100644 index 0000000..0a07f97 --- /dev/null +++ b/tests/CPU/testMath.cpp @@ -0,0 +1,82 @@ +// +// Created by anonymus-raccoon on 2/11/20. +// + +#include +#include +#include +#include "../tests.hpp" +#include "../../sources/SNES.hpp" +#include "../../sources/Memory/MemoryBus.hpp" +using namespace ComSquare; + +Test(ADC, addingOne) +{ + auto pair = Init(); + pair.second.cpu->_isEmulationMode = false; + pair.second.cpu->_registers.a = 0; + pair.second.wram->_data[0] = 0x1; + pair.second.cpu->ADC(0x0); + cr_assert_eq(pair.second.cpu->_registers.a, 1, "The accumulator's value should be 0x1 but it was 0x%x.", pair.second.cpu->_registers.a); + cr_assert_eq(pair.second.cpu->_registers.p.c, false, "The carry flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.v, false, "The overflow flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.n, false, "The negative flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.z, false, "The zero flags should not be set."); +} + +Test(ADC, addingOneEmulation) +{ + auto pair = Init(); + pair.second.cpu->_isEmulationMode = true; + pair.second.cpu->_registers.a = 0; + pair.second.wram->_data[0] = 0x1; + pair.second.cpu->ADC(0x0); + cr_assert_eq(pair.second.cpu->_registers.a, 1, "The accumulator's value should be 0x1 but it was 0x%x.", pair.second.cpu->_registers.a); + cr_assert_eq(pair.second.cpu->_registers.p.c, false, "The carry flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.v, false, "The overflow flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.n, false, "The negative flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.z, false, "The zero flags should not be set."); +} + +Test(ADC, overflow) +{ + auto pair = Init(); + pair.second.cpu->_isEmulationMode = false; + pair.second.cpu->_registers.a = 0xFFFF; + pair.second.wram->_data[0] = 0x1; + pair.second.cpu->ADC(0x0); + cr_assert_eq(pair.second.cpu->_registers.a, 0, "The accumulator's value should be 0x0 but it was 0x%x.", pair.second.cpu->_registers.a); + cr_assert_eq(pair.second.cpu->_registers.p.c, true, "The carry flags should be set."); + cr_assert_eq(pair.second.cpu->_registers.p.v, false, "The overflow flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.n, false, "The negative flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.z, true, "The zero flags should be set."); +} + +Test(ADC, overflowEmulation) +{ + auto pair = Init(); + pair.second.cpu->_isEmulationMode = true; + pair.second.cpu->_registers.a = 0xFF; + pair.second.wram->_data[0] = 0x1; + pair.second.cpu->ADC(0x0); + cr_assert_eq(pair.second.cpu->_registers.a, 0, "The accumulator's value should be 0x0 but it was 0x%x.", pair.second.cpu->_registers.a); + cr_assert_eq(pair.second.cpu->_registers.p.c, true, "The carry flags should be set."); + cr_assert_eq(pair.second.cpu->_registers.p.v, false, "The overflow flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.n, false, "The negative flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.z, true, "The zero flags should be set."); +} + + +Test(ADC, signedOverflow) +{ + auto pair = Init(); + pair.second.cpu->_isEmulationMode = false; + pair.second.cpu->_registers.a = 0x0FFF; + pair.second.wram->_data[0] = 0x1; + pair.second.cpu->ADC(0x0); + cr_assert_eq(pair.second.cpu->_registers.a, 0x1000, "The accumulator's value should be 0xF000 but it was 0x%x.", pair.second.cpu->_registers.a); + cr_assert_eq(pair.second.cpu->_registers.p.c, false, "The carry flags should not be set."); + cr_assert_eq(pair.second.cpu->_registers.p.v, true, "The overflow flags should be set."); + cr_assert_eq(pair.second.cpu->_registers.p.n, true, "The negative flags should be set."); + cr_assert_eq(pair.second.cpu->_registers.p.z, false, "The zero flags should not be set."); +} \ No newline at end of file