From a0f53ebd70efa2666d80033fab8eb9159e9d355c Mon Sep 17 00:00:00 2001 From: Melefo <42809472+Melefo@users.noreply.github.com> Date: Tue, 25 Feb 2020 11:48:48 +0100 Subject: [PATCH] Adding Multiplication Division Operations --- CMakeLists.txt | 4 +-- sources/APU/APU.cpp | 4 +++ sources/APU/APU.hpp | 9 +++-- .../Instructions/MultiplicationDivision.cpp | 35 ++++++++++++++++++ tests/APU/testAPUInstructions.cpp | 36 +++++++++++++++++++ 5 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 sources/APU/Instructions/MultiplicationDivision.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d8c8975..a0934b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ add_executable(unit_tests sources/APU/Instructions/ProgramFlow.cpp sources/APU/Operand.cpp sources/APU/Instructions/DecimalCompensation.cpp; -) + sources/APU/Instructions/MultiplicationDivision.cpp) # include criterion & coverage target_link_libraries(unit_tests criterion -lgcov) @@ -165,7 +165,7 @@ add_executable(ComSquare sources/APU/Instructions/ProgramFlow.cpp sources/APU/Operand.cpp sources/APU/Instructions/DecimalCompensation.cpp -) + sources/APU/Instructions/MultiplicationDivision.cpp) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index 0eb04b8..caa1165 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -284,6 +284,8 @@ namespace ComSquare::APU return this->CLR1(this->_getDirectAddr(), 4); case 0x93: return this->BBC(this->_getDirectAddr(), 4); + case 0x9E: + return this->DIV(); case 0xA0: return this->EI(); case 0xA1: @@ -318,6 +320,8 @@ namespace ComSquare::APU return this->MOV1(this->_getAbsoluteBit()); case 0xCE: return this->POP(this->_internalRegisters.x); + case 0xCF: + return this->MUL(); case 0xD0: return this->BNE(); case 0xD1: diff --git a/sources/APU/APU.hpp b/sources/APU/APU.hpp index ed8db1f..f9f883d 100644 --- a/sources/APU/APU.hpp +++ b/sources/APU/APU.hpp @@ -268,10 +268,15 @@ namespace ComSquare::APU //! @brief Jump to the specified location. int JMP(uint24_t addr, bool by_x = false); - //! @brief Decimal adjusts A for addition. + //! @brief Decimal adjust A for addition. int DAA(); - //! @brief Decimal adjusts A for subtraction. + //! @brief Decimal adjust A for subtraction. int DAS(); + + //! @brief Store the 16-bit value of Y * A into YA + int MUL(); + //! @brief Divide the 16-bit value YA by X, storing the quotient in A and the remainder in Y. + int DIV(); public: explicit APU(std::shared_ptr &map); APU(const APU &) = default; diff --git a/sources/APU/Instructions/MultiplicationDivision.cpp b/sources/APU/Instructions/MultiplicationDivision.cpp new file mode 100644 index 0000000..4cc43d0 --- /dev/null +++ b/sources/APU/Instructions/MultiplicationDivision.cpp @@ -0,0 +1,35 @@ +// +// Created by Melefo on 25/02/2020. +// + +#include "../APU.hpp" + +namespace ComSquare::APU +{ + int APU::MUL() + { + this->_internalRegisters.ya = this->_internalRegisters.y * this->_internalRegisters.a; + this->_internalRegisters.n = this->_internalRegisters.a & 0x80u; + this->_internalRegisters.z = !this->_internalRegisters.y; + return 9; + } + + int APU::DIV() + { + uint16_t ya = this->_internalRegisters.ya; + + this->_internalRegisters.v = this->_internalRegisters.y >= this->_internalRegisters.x; + this->_internalRegisters.h = (this->_internalRegisters.y & 0x0Fu) >= (this->_internalRegisters.x & 0x0Fu); + if (this->_internalRegisters.y < (this->_internalRegisters.x << 1u)) { + this->_internalRegisters.a = ya / this->_internalRegisters.x; + this->_internalRegisters.y = ya % this->_internalRegisters.x; + } + else { + this->_internalRegisters.a = 0xFF - (ya - (this->_internalRegisters.x << 9u)) / (0x100 - this->_internalRegisters.x); + this->_internalRegisters.y = this->_internalRegisters.x + (ya - (this->_internalRegisters.x << 9u)) % (0x100 - this->_internalRegisters.x); + } + this->_internalRegisters.z = !this->_internalRegisters.a; + this->_internalRegisters.n = this->_internalRegisters.a & 0x80u; + return 12; + } +} \ No newline at end of file diff --git a/tests/APU/testAPUInstructions.cpp b/tests/APU/testAPUInstructions.cpp index 2403348..bdf0c8a 100644 --- a/tests/APU/testAPUInstructions.cpp +++ b/tests/APU/testAPUInstructions.cpp @@ -732,4 +732,40 @@ Test(DecimalCompensation, DAS) cr_assert_eq(apu->_internalRegisters.a, 0x99); cr_assert_eq(apu->_internalRegisters.n, true); cr_assert_eq(apu->_internalRegisters.z, false); +} + +/////////////////////////////////// +// // +// Multiplication Division tests // +// // +/////////////////////////////////// + +Test(MultiplicationDivision, MUL) +{ + auto apu = Init().second.apu; + int result = 0; + + apu->_internalRegisters.a = 10; + apu->_internalRegisters.y = 23; + result = apu->MUL(); + cr_assert_eq(result, 9); + cr_assert_eq(apu->_internalRegisters.ya, 230); +} + +Test(MultiplicationDivision, DIV) +{ + auto apu = Init().second.apu; + int result = 0; + + apu->_internalRegisters.ya = 235; + apu->_internalRegisters.x = 10; + result = apu->DIV(); + cr_assert_eq(result, 12); + cr_assert_eq(apu->_internalRegisters.y, 5); + cr_assert_eq(apu->_internalRegisters.a, 23); + apu->_internalRegisters.ya = 12345; + apu->_internalRegisters.x = 2; + result = apu->DIV(); + cr_assert_eq(apu->_internalRegisters.y, 147); + cr_assert_eq(apu->_internalRegisters.a, 211); } \ No newline at end of file