diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eb91ef..d8c8975 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,12 +69,15 @@ add_executable(unit_tests tests/CPU/testInternal.cpp sources/Ram/ExtendedRam.cpp sources/Ram/ExtendedRam.hpp - sources/Utility/Utility.hpp sources/Utility/Utility.cpp + sources/Utility/Utility.hpp + sources/Utility/Utility.cpp sources/APU/Instructions/Bit.cpp sources/APU/Instructions/Stack.cpp sources/APU/Instructions/Subroutine.cpp sources/APU/Instructions/ProgramFlow.cpp - sources/APU/Operand.cpp) + sources/APU/Operand.cpp + sources/APU/Instructions/DecimalCompensation.cpp; +) # include criterion & coverage target_link_libraries(unit_tests criterion -lgcov) @@ -160,7 +163,9 @@ add_executable(ComSquare sources/APU/Instructions/Stack.cpp sources/APU/Instructions/Subroutine.cpp sources/APU/Instructions/ProgramFlow.cpp - sources/APU/Operand.cpp) + sources/APU/Operand.cpp + sources/APU/Instructions/DecimalCompensation.cpp +) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index 2658bf5..0eb04b8 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -304,6 +304,8 @@ namespace ComSquare::APU return this->CLR1(this->_getDirectAddr(), 5); case 0xB3: return this->BBC(this->_getDirectAddr(), 5); + case 0xBE: + return this->DAS(); case 0xC0: return this->DI(); case 0xC1: @@ -326,6 +328,8 @@ namespace ComSquare::APU return this->BBC(this->_getDirectAddr(), 6); case 0xDE: return this->CBNE(this->_getDirectAddrByX(), true); + case 0xDF: + return this->DAA(); case 0xE1: return this->TCALL(14); case 0xE2: diff --git a/sources/APU/APU.hpp b/sources/APU/APU.hpp index 1088166..ed8db1f 100644 --- a/sources/APU/APU.hpp +++ b/sources/APU/APU.hpp @@ -267,6 +267,11 @@ namespace ComSquare::APU int DBNZ(bool direct_addr = false); //! @brief Jump to the specified location. int JMP(uint24_t addr, bool by_x = false); + + //! @brief Decimal adjusts A for addition. + int DAA(); + //! @brief Decimal adjusts A for subtraction. + int DAS(); public: explicit APU(std::shared_ptr &map); APU(const APU &) = default; diff --git a/sources/APU/Instructions/DecimalCompensation.cpp b/sources/APU/Instructions/DecimalCompensation.cpp new file mode 100644 index 0000000..7098e0c --- /dev/null +++ b/sources/APU/Instructions/DecimalCompensation.cpp @@ -0,0 +1,36 @@ +// +// Created by Melefo on 25/02/2020. +// + +#include "../APU.hpp" + +namespace ComSquare::APU +{ + int APU::DAA() + { + if (this->_internalRegisters.c || this->_internalRegisters.a > 0x99) { + this->_internalRegisters.c = true; + this->_internalRegisters.a += 0x60; + } + if (this->_internalRegisters.h || (this->_internalRegisters.a & 0x0Fu) > 0x09) { + this->_internalRegisters.a += 0x06; + } + this->_internalRegisters.n = this->_internalRegisters.a & 0x80u; + this->_internalRegisters.z = !this->_internalRegisters.a; + return 3; + } + + int APU::DAS() + { + if (!this->_internalRegisters.c || this->_internalRegisters.a > 0x99) { + this->_internalRegisters.c = false; + this->_internalRegisters.a -= 0x60; + } + if (!this->_internalRegisters.h || (this->_internalRegisters.a & 0x0Fu) > 0x09) { + this->_internalRegisters.a -= 0x06; + } + this->_internalRegisters.n = this->_internalRegisters.a & 0x80u; + this->_internalRegisters.z = !this->_internalRegisters.a; + return 3; + } +} \ No newline at end of file diff --git a/tests/APU/testAPUInstructions.cpp b/tests/APU/testAPUInstructions.cpp index 2eb273a..2403348 100644 --- a/tests/APU/testAPUInstructions.cpp +++ b/tests/APU/testAPUInstructions.cpp @@ -466,11 +466,11 @@ Test(Subroutine, RETI) cr_assert_eq(apu->_internalRegisters.pcl, 0x56); } -///////////////////////////// -// // -// Subroutine Program Flow // -// // -///////////////////////////// +//////////////////////// +// // +// Program Flow tests // +// // +//////////////////////// Test(ProgramFlow, BRA) { @@ -696,4 +696,40 @@ Test(ProgramFlow, JMP) result = apu->JMP(apu->_getAbsoluteAddrByX(), true); cr_assert_eq(result, 6); cr_assert_eq(apu->_internalRegisters.pc, 61712); +} + +//////////////////////////////// +// // +// Decimal Compensation tests // +// // +//////////////////////////////// + +Test(DecimalCompensation, DAA) +{ + auto apu = Init().second.apu; + int result = 0; + + apu->_internalRegisters.c = true; + apu->_internalRegisters.h = true; + apu->_internalRegisters.a = 0x1A; + result = apu->DAA(); + cr_assert_eq(result, 3); + cr_assert_eq(apu->_internalRegisters.a, 0x80); + cr_assert_eq(apu->_internalRegisters.n, true); + cr_assert_eq(apu->_internalRegisters.z, false); +} + +Test(DecimalCompensation, DAS) +{ + auto apu = Init().second.apu; + int result = 0; + + apu->_internalRegisters.c = false; + apu->_internalRegisters.h = false; + apu->_internalRegisters.a = 0xFF; + result = apu->DAS(); + cr_assert_eq(result, 3); + cr_assert_eq(apu->_internalRegisters.a, 0x99); + cr_assert_eq(apu->_internalRegisters.n, true); + cr_assert_eq(apu->_internalRegisters.z, false); } \ No newline at end of file