From 5ded0b44e8741c5dc567babef834331f3ea3a81e Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Mon, 6 Apr 2020 17:59:25 +0200
Subject: [PATCH] Implementing the INC
---
sources/CPU/CPU.hpp | 12 ++--
.../Instructions/MathematicalOperations.cpp | 42 +++++++++++-
tests/CPU/Math/testOthersMath.cpp | 66 +++++++++++++++++++
3 files changed, 114 insertions(+), 6 deletions(-)
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index 1f6dd1c..7159174 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -391,6 +391,8 @@ namespace ComSquare::CPU
int RTL(uint24_t, AddressingMode);
//! @brief Compare Accumulator with Memory.
int CMP(uint24_t, AddressingMode);
+ //! @brief Increment
+ int INC(uint24_t, AddressingMode);
//! @brief All the instructions of the CPU.
//! @info Instructions are indexed by their opcode
@@ -421,7 +423,7 @@ namespace ComSquare::CPU
{&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 17
{&CPU::CLC, 2, "clc", AddressingMode::Implied, 1}, // 18
{&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByY, 3}, // 19
- {&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // 1A
+ {&CPU::INC, 2, "inc", AddressingMode::Implied, 1}, // 1A
{&CPU::BRK, 7, "tcs #-#", AddressingMode::Implied, 2}, // 1B
{&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // 1C
{&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByX, 3}, // 1D
@@ -625,7 +627,7 @@ namespace ComSquare::CPU
{&CPU::SBC, 4, "sbc", AddressingMode::StackRelative, 2}, // E3
{&CPU::CPX, 3, "cpx", AddressingMode::DirectPage, 2}, // E4
{&CPU::SBC, 3, "sbc", AddressingMode::DirectPage, 2}, // E5
- {&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // E6
+ {&CPU::INC, 5, "inc", AddressingMode::DirectPage, 2}, // E6
{&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectLong, 2}, // E7
{&CPU::INX, 2, "inx", AddressingMode::Implied, 1}, // E8
{&CPU::SBC, 2, "sbc", AddressingMode::ImmediateForA, 2}, // E9
@@ -633,7 +635,7 @@ namespace ComSquare::CPU
{&CPU::BRK, 7, "xba #-#", AddressingMode::Implied, 2}, // EB
{&CPU::CPX, 4, "cpx", AddressingMode::Absolute, 3}, // EC
{&CPU::SBC, 4, "sbc", AddressingMode::Absolute, 3}, // ED
- {&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // EE
+ {&CPU::INC, 6, "inc", AddressingMode::Absolute, 3}, // EE
{&CPU::SBC, 5, "sbc", AddressingMode::AbsoluteLong, 4}, // EF
{&CPU::BEQ, 2, "beq", AddressingMode::Implied, 2}, // F0
{&CPU::SBC, 5, "sbc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // F1
@@ -641,7 +643,7 @@ namespace ComSquare::CPU
{&CPU::SBC, 7, "sbc", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // F3
{&CPU::BRK, 7, "pea #-#", AddressingMode::Implied, 2}, // F4
{&CPU::SBC, 4, "sbc", AddressingMode::DirectPageIndexedByX, 2}, // F5
- {&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // F6
+ {&CPU::INC, 6, "inc", AddressingMode::DirectPageIndexedByX, 2}, // F6
{&CPU::SBC, 6, "sbc", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // F7
{&CPU::SED, 2, "sed", AddressingMode::Implied, 1}, // F8
{&CPU::SBC, 4, "sbc", AddressingMode::AbsoluteIndexedByY, 3}, // F9
@@ -649,7 +651,7 @@ namespace ComSquare::CPU
{&CPU::XCE, 2, "xce", AddressingMode::Implied, 1}, // FB
{&CPU::JSR, 8, "jsr", AddressingMode::AbsoluteIndirectIndexedByX, 3}, // FC
{&CPU::SBC, 4, "sbc", AddressingMode::AbsoluteIndexedByX, 3}, // FD
- {&CPU::BRK, 7, "inc #-#", AddressingMode::Implied, 2}, // FE
+ {&CPU::INC, 7, "inc", AddressingMode::AbsoluteIndexedByX, 3}, // FE
{&CPU::SBC, 5, "sbc", AddressingMode::AbsoluteIndexedByXLong, 4}, // FF
};
public:
diff --git a/sources/CPU/Instructions/MathematicalOperations.cpp b/sources/CPU/Instructions/MathematicalOperations.cpp
index 35af999..df64f01 100644
--- a/sources/CPU/Instructions/MathematicalOperations.cpp
+++ b/sources/CPU/Instructions/MathematicalOperations.cpp
@@ -254,7 +254,7 @@ namespace ComSquare::CPU
int CPU::AND(uint24_t valueAddr, AddressingMode mode)
{
- unsigned negativeMask = this->_isEmulationMode ? 0x80u : 0x8000u;
+ unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u;
unsigned value = this->_bus->read(valueAddr);
if (!this->_registers.p.m)
value += this->_bus->read(valueAddr + 1) << 8u;
@@ -285,4 +285,44 @@ namespace ComSquare::CPU
}
return cycles;
}
+
+ int CPU::INC(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 3a65f92..48364f2 100644
--- a/tests/CPU/Math/testOthersMath.cpp
+++ b/tests/CPU/Math/testOthersMath.cpp
@@ -152,4 +152,70 @@ Test(ORA, zero)
cr_assert_eq(snes.cpu->_registers.a, 0x00, "The accumulator's value should be 0x00 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, true, "The zero flags should be set.");
+}
+
+Test(INC, simple)
+{
+ Init()
+ snes.cpu->_registers.p.m = true;
+ snes.wram->_data[0] = 0x56;
+ snes.cpu->INC(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(INC, negative)
+{
+ Init()
+ snes.cpu->_registers.p.m = true;
+ snes.wram->_data[0] = 0x7F;
+ snes.cpu->INC(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(INC, accumulator)
+{
+ Init()
+ snes.cpu->_registers.p.m = true;
+ snes.cpu->_registers.a = 0x56;
+ snes.cpu->INC(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(INC, negativeAccumulator)
+{
+ Init()
+ snes.cpu->_registers.p.m = true;
+ snes.cpu->_registers.a = 0x7F;
+ snes.cpu->INC(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(INC, nativeAccumulator)
+{
+ Init()
+ snes.cpu->_registers.p.m = false;
+ snes.cpu->_registers.a = 0x5600;
+ snes.cpu->INC(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(INC, negativeNativeAccumulator)
+{
+ Init()
+ snes.cpu->_registers.p.m = false;
+ snes.cpu->_registers.a = 0x8FFF;
+ snes.cpu->INC(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