From 8240fbd54c4808393a6b4272acbae822962d2c2d Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 14 May 2020 01:06:29 +0200 Subject: [PATCH] Implementing MVP --- sources/CPU/CPU.hpp | 7 ++++++- .../CPU/Instructions/TransferRegisters.cpp | 17 +++++++++++++++++ tests/CPU/testTransfers.cpp | 19 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 39e483f..2b95861 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -450,6 +450,11 @@ namespace ComSquare::CPU //! @param Y_register Destination address //! @param C_register (16 bits accumulator) Length -1 int MVN(uint24_t, AddressingMode); + //! @brief Block Move Previous. This instruction is special: it takes parameter in the registers + //! @param X_register Source address (last byte) + //! @param Y_register Destination address (last byte) + //! @param C_register (16 bits accumulator) Length -1 + int MVP(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -522,7 +527,7 @@ namespace ComSquare::CPU {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 41 {&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::MVP, 0, "mvp", AddressingMode::Immediate16bits, 3}, // 44 {&CPU::EOR, 3, "eor", AddressingMode::DirectPage, 2}, // 45 {&CPU::LSR, 5, "lsr", AddressingMode::DirectPage, 2}, // 46 {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectLong, 2}, // 47 diff --git a/sources/CPU/Instructions/TransferRegisters.cpp b/sources/CPU/Instructions/TransferRegisters.cpp index 64821e3..496a5d6 100644 --- a/sources/CPU/Instructions/TransferRegisters.cpp +++ b/sources/CPU/Instructions/TransferRegisters.cpp @@ -168,4 +168,21 @@ namespace ComSquare::CPU } return 7 * length; } + + int CPU::MVP(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/testTransfers.cpp b/tests/CPU/testTransfers.cpp index 6550cc5..87497b6 100644 --- a/tests/CPU/testTransfers.cpp +++ b/tests/CPU/testTransfers.cpp @@ -454,4 +454,23 @@ Test(MVN, hardCase) 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]); +} + +Test(MVP, hardCase) +{ + Init() + snes.cpu->_registers.a = 0x10; + snes.cpu->_registers.x = 0x0010; + snes.cpu->_registers.y = 0x1010; + for (int i = 0; i <= snes.cpu->_registers.a; i++) + snes.wram->_data[i] = i; + + int cycles = snes.cpu->MVP(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, 0xFFFF, "The x index should be 0xFFFF but it was %x", snes.cpu->_registers.x); + cr_assert_eq(snes.cpu->_registers.y, 0x0FFF, "The y index should be 0x0FFF 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