Implementing MVN

This commit is contained in:
Anonymus Raccoon
2020-05-13 23:12:31 +02:00
parent 7fe28a8bcc
commit d0e4caf12e
5 changed files with 53 additions and 4 deletions
+1 -1
View File
@@ -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
+10 -3
View File
@@ -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
@@ -326,4 +326,9 @@ namespace ComSquare::CPU
this->_isStopped = true;
return 0;
}
int CPU::WDM(uint24_t, AddressingMode)
{
return 0;
}
}
@@ -2,6 +2,7 @@
// Created by anonymus-raccoon on 2/28/20.
//
#include <iostream>
#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;
}
}
@@ -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]);
}