From f675e453858184b7e4c10e7d27c6d81eefd07fc8 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Mon, 6 Apr 2020 18:05:00 +0200
Subject: [PATCH] Implementing DEC
---
sources/CPU/CPU.hpp | 12 ++--
.../Instructions/MathematicalOperations.cpp | 40 +++++++++++
tests/CPU/Math/testOthersMath.cpp | 66 +++++++++++++++++++
3 files changed, 113 insertions(+), 5 deletions(-)
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index 7159174..a478d35 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -393,6 +393,8 @@ namespace ComSquare::CPU
int CMP(uint24_t, AddressingMode);
//! @brief Increment
int INC(uint24_t, AddressingMode);
+ //! @brief Decrement
+ int DEC(uint24_t, AddressingMode);
//! @brief All the instructions of the CPU.
//! @info Instructions are indexed by their opcode
@@ -455,7 +457,7 @@ namespace ComSquare::CPU
{&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 37
{&CPU::SEC, 2, "sec", AddressingMode::Implied, 1}, // 38
{&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByY, 3}, // 39
- {&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // 3A
+ {&CPU::DEC, 2, "dec", AddressingMode::Implied, 1}, // 3A
{&CPU::BRK, 7, "tsc #-#", AddressingMode::Implied, 2}, // 3B
{&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 3C
{&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByX, 3}, // 3D
@@ -595,7 +597,7 @@ namespace ComSquare::CPU
{&CPU::CMP, 4, "cmp", AddressingMode::StackRelative, 2}, // C3
{&CPU::CPY, 3, "cpy", AddressingMode::DirectPage, 2}, // C4
{&CPU::CMP, 3, "cmp", AddressingMode::DirectPage, 2}, // C5
- {&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // C6
+ {&CPU::DEC, 5, "dec", AddressingMode::DirectPage, 2}, // C6
{&CPU::CMP, 6, "cmp", AddressingMode::DirectPageIndirectLong, 2}, // C7
{&CPU::INY, 2, "iny", AddressingMode::Implied, 1}, // C8
{&CPU::CMP, 2, "cmp", AddressingMode::ImmediateForA, 2}, // C9
@@ -603,7 +605,7 @@ namespace ComSquare::CPU
{&CPU::BRK, 7, "wai #-#", AddressingMode::Implied, 2}, // CB
{&CPU::CPY, 4, "cpy", AddressingMode::Absolute, 3}, // CC
{&CPU::CMP, 4, "cmp", AddressingMode::Absolute, 3}, // CD
- {&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // CE
+ {&CPU::DEC, 6, "dec", AddressingMode::Absolute, 3}, // CE
{&CPU::CMP, 6, "cmp", AddressingMode::AbsoluteLong, 4}, // CF
{&CPU::BNE, 2, "bne", AddressingMode::Implied, 2}, // D0
{&CPU::CMP, 5, "cmp", AddressingMode::DirectPageIndirectIndexedByY, 2}, // D1
@@ -611,7 +613,7 @@ namespace ComSquare::CPU
{&CPU::CMP, 7, "cmp", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // D3
{&CPU::BRK, 7, "pei #-#", AddressingMode::Implied, 2}, // D4
{&CPU::CMP, 4, "cmp", AddressingMode::DirectPageIndexedByX, 2}, // D5
- {&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // D6
+ {&CPU::DEC, 6, "dec", AddressingMode::DirectPageIndexedByX, 2}, // D6
{&CPU::CMP, 6, "cmp", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // D7
{&CPU::CLD, 2, "cld", AddressingMode::Implied, 2}, // D8
{&CPU::CMP, 4, "cmp", AddressingMode::AbsoluteIndexedByY, 3}, // D9
@@ -619,7 +621,7 @@ namespace ComSquare::CPU
{&CPU::BRK, 7, "stp #-#", AddressingMode::Implied, 2}, // DB
{&CPU::JML, 7, "jml", AddressingMode::AbsoluteIndirectLong, 2}, // DC
{&CPU::CMP, 4, "cmp", AddressingMode::AbsoluteIndexedByX, 3}, // DD
- {&CPU::BRK, 7, "dec #-#", AddressingMode::Implied, 2}, // DE
+ {&CPU::DEC, 7, "dec", AddressingMode::AbsoluteIndexedByX, 3}, // DE
{&CPU::CMP, 5, "cmp", AddressingMode::AbsoluteIndexedByXLong, 4}, // DF
{&CPU::CPX, 2, "cpx", AddressingMode::ImmediateForX, 2}, // E0
{&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // E1
diff --git a/sources/CPU/Instructions/MathematicalOperations.cpp b/sources/CPU/Instructions/MathematicalOperations.cpp
index df64f01..ff2d63e 100644
--- a/sources/CPU/Instructions/MathematicalOperations.cpp
+++ b/sources/CPU/Instructions/MathematicalOperations.cpp
@@ -325,4 +325,44 @@ namespace ComSquare::CPU
return 0;
}
}
+
+ int CPU::DEC(uint24_t valueAddr, AddressingMode mode)
+ {
+ unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u;
+
+ unsigned result;
+ if (mode == Implied) {
+ this->_registers.a--;
+ if (this->_registers.p.m)
+ this->_registers.ah = 0;
+ result = this->_registers.a;
+ } else if (!this->_registers.p.m) {
+ result = this->_bus->read(valueAddr);
+ result += this->_bus->read(valueAddr + 1) << 8u;
+ result = (uint16_t)(result - 1);
+ this->_bus->write(valueAddr, result);
+ this->_bus->write(valueAddr + 1, result << 8u);
+ } else {
+ result = this->_bus->read(valueAddr);
+ result = (uint8_t)(result - 1);
+ this->_bus->write(valueAddr, result);
+ }
+
+ this->_registers.p.z = result == 0;
+ this->_registers.p.n = result & negativeMask;
+
+ switch (mode) {
+ case Implied:
+ return 0;
+ case Absolute:
+ return this->_registers.p.m == 0 ? 2 : 0;
+ case DirectPage:
+ case DirectPageIndexedByX:
+ return (this->_registers.p.m == 0 ? 2 : 0) + this->_registers.dl != 0 ;
+ case AbsoluteIndexedByX:
+ return (this->_registers.p.m == 0 ? 2 : 0) + this->_hasIndexCrossedPageBoundary;
+ default:
+ return 0;
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/CPU/Math/testOthersMath.cpp b/tests/CPU/Math/testOthersMath.cpp
index 48364f2..1f293aa 100644
--- a/tests/CPU/Math/testOthersMath.cpp
+++ b/tests/CPU/Math/testOthersMath.cpp
@@ -218,4 +218,70 @@ Test(INC, negativeNativeAccumulator)
cr_assert_eq(snes.cpu->_registers.a, 0x9000, "The incremented value should be 0x9000 but it was 0x%x.", snes.cpu->_registers.a);
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flags should be set.");
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flags should not be set.");
+}
+
+Test(DEC, simple)
+{
+ Init()
+ snes.cpu->_registers.p.m = true;
+ snes.wram->_data[0] = 0x58;
+ snes.cpu->DEC(0x0, ComSquare::CPU::AddressingMode::Absolute);
+ cr_assert_eq(snes.wram->_data[0], 0x57, "The incremented value should be 0x57 but it was 0x%x.", snes.wram->_data[0]);
+ cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flags should not be set.");
+ cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flags should not be set.");
+}
+
+Test(DEC, negative)
+{
+ Init()
+ snes.cpu->_registers.p.m = true;
+ snes.wram->_data[0] = 0x81;
+ snes.cpu->DEC(0x0, ComSquare::CPU::AddressingMode::Absolute);
+ cr_assert_eq(snes.wram->_data[0], 0x80, "The incremented value should be 0x80 but it was 0x%x.", snes.wram->_data[0]);
+ cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flags should be set.");
+ cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flags should not be set.");
+}
+
+Test(DEC, accumulator)
+{
+ Init()
+ snes.cpu->_registers.p.m = true;
+ snes.cpu->_registers.a = 0x58;
+ snes.cpu->DEC(0x0, ComSquare::CPU::AddressingMode::Implied);
+ cr_assert_eq(snes.cpu->_registers.a, 0x57, "The incremented value should be 0x57 but it was 0x%x.", snes.cpu->_registers.a);
+ cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flags should not be set.");
+ cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flags should not be set.");
+}
+
+Test(DEC, negativeAccumulator)
+{
+ Init()
+ snes.cpu->_registers.p.m = true;
+ snes.cpu->_registers.a = 0x81;
+ snes.cpu->DEC(0x0, ComSquare::CPU::AddressingMode::Implied);
+ cr_assert_eq(snes.cpu->_registers.a, 0x80, "The incremented value should be 0x80 but it was 0x%x.", snes.cpu->_registers.a);
+ cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flags should be set.");
+ cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flags should not be set.");
+}
+
+Test(DEC, nativeAccumulator)
+{
+ Init()
+ snes.cpu->_registers.p.m = false;
+ snes.cpu->_registers.a = 0x5602;
+ snes.cpu->DEC(0x0, ComSquare::CPU::AddressingMode::Implied);
+ cr_assert_eq(snes.cpu->_registers.a, 0x5601, "The incremented value should be 0x5601 but it was 0x%x.", snes.cpu->_registers.a);
+ cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flags should not be set.");
+ cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flags should not be set.");
+}
+
+Test(DEC, negativeNativeAccumulator)
+{
+ Init()
+ snes.cpu->_registers.p.m = false;
+ snes.cpu->_registers.a = 0x9001;
+ snes.cpu->DEC(0x0, ComSquare::CPU::AddressingMode::Implied);
+ cr_assert_eq(snes.cpu->_registers.a, 0x9000, "The incremented value should be 0x9000 but it was 0x%x.", snes.cpu->_registers.a);
+ cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flags should be set.");
+ cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flags should not be set.");
}
\ No newline at end of file