From 2776be601e6a6b0cd70d48c049187f52b6882fac Mon Sep 17 00:00:00 2001 From: Melefo <42809472+Melefo@users.noreply.github.com> Date: Wed, 26 Feb 2020 13:12:42 +0100 Subject: [PATCH] Adding 8-bit Increment & Decrement Operations Creating a generic function to set Negative and Zero flags with a value --- CMakeLists.txt | 4 +- sources/APU/APU.cpp | 30 ++++++++ sources/APU/APU.hpp | 12 ++++ .../Instructions/16bitDataTransmission.cpp | 3 +- .../Instructions/8bitIncrementDecrement.cpp | 40 +++++++++++ .../APU/Instructions/8bitShiftRotation.cpp | 9 +-- sources/APU/Instructions/Bit.cpp | 6 +- .../APU/Instructions/DecimalCompensation.cpp | 6 +- .../Instructions/MultiplicationDivision.cpp | 3 +- tests/APU/testAPUInstructions.cpp | 68 +++++++++++++++++-- 10 files changed, 157 insertions(+), 24 deletions(-) create mode 100644 sources/APU/Instructions/8bitIncrementDecrement.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 02e9f3d..362eff4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ add_executable(unit_tests sources/APU/Instructions/16bitArithmetic.cpp sources/APU/Instructions/16bitDataTransmission.cpp sources/APU/Instructions/8bitShiftRotation.cpp -) + sources/APU/Instructions/8bitIncrementDecrement.cpp) # include criterion & coverage target_link_libraries(unit_tests criterion -lgcov) @@ -173,7 +173,7 @@ add_executable(ComSquare sources/APU/Instructions/16bitArithmetic.cpp sources/APU/Instructions/16bitDataTransmission.cpp sources/APU/Instructions/8bitShiftRotation.cpp -) + sources/APU/Instructions/8bitIncrementDecrement.cpp) target_compile_definitions(ComSquare PUBLIC DEBUGGER_ENABLED) diff --git a/sources/APU/APU.cpp b/sources/APU/APU.cpp index 04489be..99bd5ac 100644 --- a/sources/APU/APU.cpp +++ b/sources/APU/APU.cpp @@ -194,6 +194,8 @@ namespace ComSquare::APU return this->ASL(this->_getDirectAddrByX(), 5); case 0x1C: return this->ASL(this->_internalRegisters.a, 2, true); + case 0x1D: + return this->DECreg(this->_internalRegisters.x); case 0x1F: return this->JMP(this->_getAbsoluteAddrByX(), true); case 0x20: @@ -230,6 +232,8 @@ namespace ComSquare::APU return this->ROL(this->_getAbsoluteAddrByX(), 5); case 0x3C: return this->ROL(this->_internalRegisters.a, 2, true); + case 0x3D: + return this->INCreg(this->_internalRegisters.x); case 0x3F: return this->CALL(this->_getAbsoluteAddr()); case 0x40: @@ -314,6 +318,10 @@ namespace ComSquare::APU return this->BBS(this->_getDirectAddr(), 4); case 0x8A: return this->EOR1(this->_getAbsoluteBit()); + case 0x8B: + return this->DEC(this->_getDirectAddr(), 4); + case 0x8C: + return this->DEC(this->_getAbsoluteAddr(), 5); case 0x8E: return this->POP(this->_internalRegisters.psw); case 0x90: @@ -326,6 +334,10 @@ namespace ComSquare::APU return this->BBC(this->_getDirectAddr(), 4); case 0x9A: return this->SUBW(this->_getDirectAddr()); + case 0x9B: + return this->DEC(this->_getDirectAddrByX(), 5); + case 0x9C: + return this->DECreg(this->_internalRegisters.a); case 0x9E: return this->DIV(); case 0x9F: @@ -340,6 +352,10 @@ namespace ComSquare::APU return this->BBS(this->_getDirectAddr(), 5); case 0xAA: return this->MOV1(this->_getAbsoluteBit(), true); + case 0xAB: + return this->INC(this->_getDirectAddr(), 4); + case 0xAC: + return this->INC(this->_getAbsoluteAddr(), 5); case 0xAE: return this->POP(this->_internalRegisters.a); case 0xB0: @@ -352,6 +368,10 @@ namespace ComSquare::APU return this->BBC(this->_getDirectAddr(), 5); case 0xBA: return this->MOVW(this->_getDirectAddr(), true); + case 0xBB: + return this->INC(this->_getDirectAddrByX(), 5); + case 0xBC: + return this->INCreg(this->_internalRegisters.a); case 0xBE: return this->DAS(); case 0xC0: @@ -378,6 +398,8 @@ namespace ComSquare::APU return this->BBC(this->_getDirectAddr(), 6); case 0xDA: return this->MOVW(this->_getDirectAddr()); + case 0xDC: + return this->DECreg(this->_internalRegisters.y); case 0xDE: return this->CBNE(this->_getDirectAddrByX(), true); case 0xDF: @@ -398,6 +420,8 @@ namespace ComSquare::APU return this->CLR1(this->_getDirectAddr(), 7); case 0xF3: return this->BBC(this->_getDirectAddr(), 7); + case 0xFC: + return this->INCreg(this->_internalRegisters.y); case 0xEA: return this->NOT1(this->_getAbsoluteBit()); case 0xED: @@ -424,6 +448,12 @@ namespace ComSquare::APU this->_paddingCycles = total - cycles; } + void APU::_setNZflags(uint8_t value) + { + this->_internalRegisters.n = value & 0x80u; + this->_internalRegisters.z = !value; + } + MemoryMap::MemoryMap() : Page0(0x00F0), Page1(0x0100), diff --git a/sources/APU/APU.hpp b/sources/APU/APU.hpp index 815b06f..d98e57e 100644 --- a/sources/APU/APU.hpp +++ b/sources/APU/APU.hpp @@ -174,6 +174,9 @@ namespace ComSquare::APU //! @brief Get absolute offset and separate its bits std::pair _getAbsoluteBit(); + //! @brief Set Negative and Zero flags with value after an instruction + void _setNZflags(uint8_t value); + //! @brief Execute a single instruction. //! @return The number of cycles that the instruction took. virtual int _executeInstruction(); @@ -302,6 +305,15 @@ namespace ComSquare::APU int ROR(uint24_t operand, int cycles, bool accumulator = false); //! @brief Exchange Nibbles. int XCN(); + + //! @brief Increment a value at an address. + int INC(uint24_t addr, int cycles); + //! @brief Increment a register. + int INCreg(uint8_t &value); + //! @brief Decrement a value at an address. + int DEC(uint24_t addr, int cycles); + //! @brief Decrement a register. + int DECreg(uint8_t &value); public: explicit APU(std::shared_ptr &map); APU(const APU &) = default; diff --git a/sources/APU/Instructions/16bitDataTransmission.cpp b/sources/APU/Instructions/16bitDataTransmission.cpp index ffcf0a5..cfa8009 100644 --- a/sources/APU/Instructions/16bitDataTransmission.cpp +++ b/sources/APU/Instructions/16bitDataTransmission.cpp @@ -14,8 +14,7 @@ namespace ComSquare::APU uint16_t value = ((this->_internalRead(addr2) << 8u) | this->_internalRead(addr)); this->_internalRegisters.ya = value; - this->_internalRegisters.n = value & 0x8000u; - this->_internalRegisters.z = !value; + this->_setNZflags(value); } else { this->_internalWrite(addr, this->_internalRegisters.a); diff --git a/sources/APU/Instructions/8bitIncrementDecrement.cpp b/sources/APU/Instructions/8bitIncrementDecrement.cpp new file mode 100644 index 0000000..e4169a8 --- /dev/null +++ b/sources/APU/Instructions/8bitIncrementDecrement.cpp @@ -0,0 +1,40 @@ +// +// Created by Melefo on 26/02/2020. +// + +#include "../APU.hpp" + +namespace ComSquare::APU +{ + int APU::INC(uint24_t addr, int cycles) + { + uint8_t value = this->_internalRead(addr); + + this->_internalWrite(addr, ++value); + this->_setNZflags(value); + return cycles; + } + + int APU::INCreg(uint8_t &value) + { + value++; + this->_setNZflags(value); + return 2; + } + + int APU::DEC(uint24_t addr, int cycles) + { + uint8_t value = this->_internalRead(addr); + + this->_internalWrite(addr, --value); + this->_setNZflags(value); + return cycles; + } + + int APU::DECreg(uint8_t &value) + { + value--; + this->_setNZflags(value); + return 2; + } +} \ No newline at end of file diff --git a/sources/APU/Instructions/8bitShiftRotation.cpp b/sources/APU/Instructions/8bitShiftRotation.cpp index 4faab34..1aece45 100644 --- a/sources/APU/Instructions/8bitShiftRotation.cpp +++ b/sources/APU/Instructions/8bitShiftRotation.cpp @@ -16,8 +16,7 @@ namespace ComSquare::APU this->_internalRegisters.a = value; else this->_internalWrite(operand, value); - this->_internalRegisters.n = value & 0x80u; - this->_internalRegisters.z = !value; + this->_setNZflags(value); return cycles; } @@ -46,8 +45,7 @@ namespace ComSquare::APU this->_internalRegisters.a = result; else this->_internalWrite(operand, result); - this->_internalRegisters.n = result & 0x80u; - this->_internalRegisters.z = !result; + this->_setNZflags(result); return cycles; } @@ -69,8 +67,7 @@ namespace ComSquare::APU int APU::XCN() { this->_internalRegisters.a = (this->_internalRegisters.a >> 4u) | (this->_internalRegisters.a << 4u); - this->_internalRegisters.n = this->_internalRegisters.a & 0x80u; - this->_internalRegisters.z = !this->_internalRegisters.a; + this->_setNZflags(this->_internalRegisters.a); return 5; } } \ No newline at end of file diff --git a/sources/APU/Instructions/Bit.cpp b/sources/APU/Instructions/Bit.cpp index 4b8b8ba..74f172a 100644 --- a/sources/APU/Instructions/Bit.cpp +++ b/sources/APU/Instructions/Bit.cpp @@ -28,8 +28,7 @@ namespace ComSquare::APU uint8_t data = this->_internalRead(abs); this->_internalWrite(abs, data | this->_internalRegisters.a); - this->_internalRegisters.n = data & 0x80u; - this->_internalRegisters.z = !data; + this->_setNZflags(data); return 6; } @@ -38,8 +37,7 @@ namespace ComSquare::APU uint8_t data = this->_internalRead(abs); this->_internalWrite(abs, data & ~this->_internalRegisters.a); - this->_internalRegisters.n = data & 0x80u; - this->_internalRegisters.z = !data; + this->_setNZflags(data); return 6; } diff --git a/sources/APU/Instructions/DecimalCompensation.cpp b/sources/APU/Instructions/DecimalCompensation.cpp index 7098e0c..d93e562 100644 --- a/sources/APU/Instructions/DecimalCompensation.cpp +++ b/sources/APU/Instructions/DecimalCompensation.cpp @@ -15,8 +15,7 @@ namespace ComSquare::APU 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; + this->_setNZflags(this->_internalRegisters.a); return 3; } @@ -29,8 +28,7 @@ namespace ComSquare::APU 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; + this->_setNZflags(this->_internalRegisters.a); return 3; } } \ No newline at end of file diff --git a/sources/APU/Instructions/MultiplicationDivision.cpp b/sources/APU/Instructions/MultiplicationDivision.cpp index 4cc43d0..b43a08c 100644 --- a/sources/APU/Instructions/MultiplicationDivision.cpp +++ b/sources/APU/Instructions/MultiplicationDivision.cpp @@ -28,8 +28,7 @@ namespace ComSquare::APU 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; + this->_setNZflags(this->_internalRegisters.a); return 12; } } \ No newline at end of file diff --git a/tests/APU/testAPUInstructions.cpp b/tests/APU/testAPUInstructions.cpp index c1a6863..aa08bde 100644 --- a/tests/APU/testAPUInstructions.cpp +++ b/tests/APU/testAPUInstructions.cpp @@ -891,7 +891,7 @@ Test(XVIbitDataTransmission, MOVW) // // ////////////////////////////////////// -Test(VIIIShiftRotation, ASL) +Test(VIIIbitShiftRotation, ASL) { auto apu = Init().second.apu; int result = 0; @@ -913,7 +913,7 @@ Test(VIIIShiftRotation, ASL) cr_assert_eq(apu->_internalRegisters.z, false); } -Test(VIIIShiftRotation, LSR) +Test(VIIIbitShiftRotation, LSR) { auto apu = Init().second.apu; int result = 0; @@ -935,7 +935,7 @@ Test(VIIIShiftRotation, LSR) cr_assert_eq(apu->_internalRegisters.z, false); } -Test(VIIIShiftRotation, ROL) +Test(VIIIbitShiftRotation, ROL) { auto apu = Init().second.apu; int result = 0; @@ -957,7 +957,7 @@ Test(VIIIShiftRotation, ROL) cr_assert_eq(apu->_internalRegisters.z, false); } -Test(VIIIShiftRotation, ROR) +Test(VIIIbitShiftRotation, ROR) { auto apu = Init().second.apu; int result = 0; @@ -990,4 +990,64 @@ Test(VIIIShiftRotation, XCN) cr_assert_eq(apu->_internalRegisters.a, 0xAA); cr_assert_eq(apu->_internalRegisters.n, true); cr_assert_eq(apu->_internalRegisters.z, false); +} + +/////////////////////////////////////////// +// // +// (VIII)8-bit Increment Decrement tests // +// // +/////////////////////////////////////////// + +Test(VIIIbitIncrementDecrement, INC) +{ + auto apu = Init().second.apu; + int result = 0; + + apu->_internalWrite(apu->_internalRegisters.pc, 0x55); + apu->_internalWrite(0x55, 0xDD); + result = apu->INC(apu->_getDirectAddr(), 4); + cr_assert_eq(result, 4); + cr_assert_eq(apu->_internalRead(0x55), 0xDE); + cr_assert_eq(apu->_internalRegisters.z, false); + cr_assert_eq(apu->_internalRegisters.n, true); +} + +Test(VIIIbitIncrementDecrement, INCreg) +{ + auto apu = Init().second.apu; + int result = 0; + + apu->_internalRegisters.a = 0x76; + result = apu->INCreg(apu->_internalRegisters.a); + cr_assert_eq(result, 2); + cr_assert_eq(apu->_internalRegisters.a, 0x77); + cr_assert_eq(apu->_internalRegisters.z, false); + cr_assert_eq(apu->_internalRegisters.n, false); +} + +Test(VIIIbitIncrementDecrement, DEC) +{ + auto apu = Init().second.apu; + int result = 0; + + apu->_internalWrite(apu->_internalRegisters.pc, 0x55); + apu->_internalWrite(0x55, 0xDD); + result = apu->DEC(apu->_getDirectAddr(), 4); + cr_assert_eq(result, 4); + cr_assert_eq(apu->_internalRead(0x55), 0xDC); + cr_assert_eq(apu->_internalRegisters.z, false); + cr_assert_eq(apu->_internalRegisters.n, true); +} + +Test(VIIIbitIncrementDecrement, DECreg) +{ + auto apu = Init().second.apu; + int result = 0; + + apu->_internalRegisters.a = 0x76; + result = apu->DECreg(apu->_internalRegisters.a); + cr_assert_eq(result, 2); + cr_assert_eq(apu->_internalRegisters.a, 0x75); + cr_assert_eq(apu->_internalRegisters.z, false); + cr_assert_eq(apu->_internalRegisters.n, false); } \ No newline at end of file