From d0e4caf12e35185feaadeded54233025cef1a1e4 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Wed, 13 May 2020 23:12:31 +0200 Subject: [PATCH] Implementing MVN --- CMakeLists.txt | 2 +- sources/CPU/CPU.hpp | 13 ++++++++++--- .../CPU/Instructions/InternalInstruction.cpp | 5 +++++ .../CPU/Instructions/TransferRegisters.cpp | 18 ++++++++++++++++++ ...ransferRegisters.cpp => testTransfers.cpp} | 19 +++++++++++++++++++ 5 files changed, 53 insertions(+), 4 deletions(-) rename tests/CPU/{TransferRegisters.cpp => testTransfers.cpp} (94%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18c98a8..302d68a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,7 +90,7 @@ add_executable(unit_tests sources/APU/IPL/IPL.cpp tests/CPU/Math/testSBC.cpp sources/CPU/Instructions/TransferRegisters.cpp - tests/CPU/TransferRegisters.cpp + tests/CPU/testTransfers.cpp sources/CPU/AddressingModes.cpp sources/Models/Components.hpp sources/CPU/Instruction.hpp diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 1baa090..39e483f 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -443,6 +443,13 @@ namespace ComSquare::CPU int PEA(uint24_t, AddressingMode); //! @brief Stop the processor int STP(uint24_t, AddressingMode); + //! @brief WDM Reserved for Future Expansion (used as a code breakpoint) + int WDM(uint24_t, AddressingMode); + //! @brief Block Move Next. This instruction is special: it takes parameter in the registers + //! @param X_register Source address + //! @param Y_register Destination address + //! @param C_register (16 bits accumulator) Length -1 + int MVN(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -513,7 +520,7 @@ namespace ComSquare::CPU {&CPU::AND, 5, "and", AddressingMode::AbsoluteIndexedByXLong, 4}, // 3F {&CPU::RTI, 6, "rti", AddressingMode::Implied, 1}, // 40 {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 41 - {&CPU::BRK, 7, "wdm #-#", AddressingMode::Implied, 2}, // 42 + {&CPU::WDM, 2, "wdm", AddressingMode::Immediate8bits, 2}, // 42 {&CPU::EOR, 4, "eor", AddressingMode::StackRelative, 2}, // 43 {&CPU::BRK, 7, "mvp #-#", AddressingMode::Implied, 2}, // 44 {&CPU::EOR, 3, "eor", AddressingMode::DirectPage, 2}, // 45 @@ -531,7 +538,7 @@ namespace ComSquare::CPU {&CPU::EOR, 5, "eor", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 51 {&CPU::EOR, 5, "eor", AddressingMode::DirectPageIndirect, 2}, // 52 {&CPU::EOR, 4, "eor", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 53 - {&CPU::BRK, 7, "mvn #-#", AddressingMode::Implied, 2}, // 54 + {&CPU::MVN, 0, "mvn", AddressingMode::Immediate16bits, 2}, // 54 {&CPU::EOR, 4, "eor", AddressingMode::DirectPageIndexedByX, 2}, // 55 {&CPU::LSR, 6, "lsr", AddressingMode::DirectPageIndexedByX, 2}, // 56 {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 57 @@ -618,7 +625,7 @@ namespace ComSquare::CPU {&CPU::TAY, 2, "tay", AddressingMode::Implied, 1}, // A8 {&CPU::LDA, 2, "lda", AddressingMode::ImmediateForA, 2}, // A9 {&CPU::TAX, 2, "tax", AddressingMode::Implied, 1}, // AA - {&CPU::BRK, 7, "plb #-#", AddressingMode::Implied, 2}, // AB + {&CPU::PLB, 4, "plb", AddressingMode::Implied, 1}, // AB {&CPU::LDY, 4, "ldy", AddressingMode::Absolute, 4}, // AC {&CPU::LDA, 4, "lda", AddressingMode::Absolute, 3}, // AD {&CPU::LDX, 4, "ldx", AddressingMode::Absolute, 3}, // AE diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp index 59eddbc..8430522 100644 --- a/sources/CPU/Instructions/InternalInstruction.cpp +++ b/sources/CPU/Instructions/InternalInstruction.cpp @@ -326,4 +326,9 @@ namespace ComSquare::CPU this->_isStopped = true; return 0; } + + int CPU::WDM(uint24_t, AddressingMode) + { + return 0; + } } \ No newline at end of file diff --git a/sources/CPU/Instructions/TransferRegisters.cpp b/sources/CPU/Instructions/TransferRegisters.cpp index 18efae8..64821e3 100644 --- a/sources/CPU/Instructions/TransferRegisters.cpp +++ b/sources/CPU/Instructions/TransferRegisters.cpp @@ -2,6 +2,7 @@ // Created by anonymus-raccoon on 2/28/20. // +#include #include "../CPU.hpp" namespace ComSquare::CPU @@ -150,4 +151,21 @@ namespace ComSquare::CPU this->_registers.p.z = this->_registers.y == 0; return 0; } + + int CPU::MVN(uint24_t params, AddressingMode) + { + uint8_t srcBank = params; + uint8_t destBank = params >> 8u; + int length = this->_registers.a + 1; + + this->_registers.dbr = destBank; + while (this->_registers.a != 0xFFFF) { + uint8_t data = this->_bus->read(srcBank << 24u | this->_registers.x); + this->_bus->write(destBank << 24u | this->_registers.y, data); + this->_registers.x++; + this->_registers.y++; + this->_registers.a--; + } + return 7 * length; + } } \ No newline at end of file diff --git a/tests/CPU/TransferRegisters.cpp b/tests/CPU/testTransfers.cpp similarity index 94% rename from tests/CPU/TransferRegisters.cpp rename to tests/CPU/testTransfers.cpp index 91ab304..6550cc5 100644 --- a/tests/CPU/TransferRegisters.cpp +++ b/tests/CPU/testTransfers.cpp @@ -435,4 +435,23 @@ Test(TYX, nativeMode) cr_assert_eq(snes.cpu->_registers.x, 0xAB0D, "The x index should be 0xAB0D but it was %x", snes.cpu->_registers.x); cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set."); cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set."); +} + +Test(MVN, hardCase) +{ + Init() + snes.cpu->_registers.a = 0x10; + snes.cpu->_registers.x = 0x0000; + snes.cpu->_registers.y = 0x1000; + for (int i = 0; i <= snes.cpu->_registers.a; i++) + snes.wram->_data[i] = i; + + int cycles = snes.cpu->MVN(0x2010, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(cycles, 0x77, "The MVN should take 0x77 cycles but it took %x.", cycles); + cr_assert_eq(snes.cpu->_registers.dbr, 0x20, "The data bank register should be 0x20 but it was %x", snes.cpu->_registers.dbr); + cr_assert_eq(snes.cpu->_registers.a, 0xFFFF, "The c accumulator should be 0xFFFF but it was %x", snes.cpu->_registers.a); + cr_assert_eq(snes.cpu->_registers.x, 0x0011, "The x index should be 0x0011 but it was %x", snes.cpu->_registers.x); + cr_assert_eq(snes.cpu->_registers.y, 0x1011, "The y index should be 0x1011 but it was %x", snes.cpu->_registers.y); + for (int i = 0; i < 0x11; i++) + cr_assert_eq(snes.wram->_data[i + 0x1000], i, "The data in ram should be %x but it was %x", i, snes.wram->_data[i + 0x1000]); } \ No newline at end of file