diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index f928561..ee25dfc 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -411,6 +411,10 @@ namespace ComSquare::CPU int TXA(uint24_t, AddressingMode); //! @brief Transfer Y to A int TYA(uint24_t, AddressingMode); + //! @brief Transfer X to Y + int TXY(uint24_t, AddressingMode); + //! @brief Transfer Y to X + int TYX(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -570,7 +574,7 @@ namespace ComSquare::CPU {&CPU::TYA, 2, "tya", AddressingMode::Implied, 1}, // 98 {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByY, 3}, // 99 {&CPU::TXS, 2, "txs", AddressingMode::Implied, 1}, // 9A - {&CPU::BRK, 7, "txy #-#", AddressingMode::Implied, 2}, // 9B + {&CPU::TXY, 2, "txy", AddressingMode::Implied, 1}, // 9B {&CPU::STZ, 4, "stz", AddressingMode::Absolute, 3}, // 9C {&CPU::STA, 5, "sta", AddressingMode::AbsoluteIndexedByX, 3}, // 9D {&CPU::STZ, 5, "stz", AddressingMode::AbsoluteIndexedByX, 3}, // 9E @@ -602,7 +606,7 @@ namespace ComSquare::CPU {&CPU::CLV, 7, "clv", AddressingMode::Implied, 1}, // B8 {&CPU::LDA, 4, "lda", AddressingMode::AbsoluteIndexedByY, 3}, // B9 {&CPU::TSX, 2, "tsx", AddressingMode::Implied, 1}, // BA - {&CPU::BRK, 7, "tyx #-#", AddressingMode::Implied, 2}, // BB + {&CPU::TYX, 2, "tyx", AddressingMode::Implied, 1}, // BB {&CPU::LDY, 4, "ldy", AddressingMode::AbsoluteIndexedByX, 3}, // BC {&CPU::LDA, 4, "lda", AddressingMode::AbsoluteIndexedByX, 3}, // BD {&CPU::LDX, 4, "ldx", AddressingMode::AbsoluteIndexedByY, 3}, // BE diff --git a/sources/CPU/Instructions/TransferRegisters.cpp b/sources/CPU/Instructions/TransferRegisters.cpp index 6135ce3..18efae8 100644 --- a/sources/CPU/Instructions/TransferRegisters.cpp +++ b/sources/CPU/Instructions/TransferRegisters.cpp @@ -124,4 +124,30 @@ namespace ComSquare::CPU this->_registers.p.z = this->_registers.a == 0; return 0; } + + int CPU::TXY(uint24_t, AddressingMode) + { + unsigned negativeFlag = this->_registers.p.x_b ? 0x80u : 0x8000u; + + if (this->_registers.p.x_b) + this->_registers.yl = this->_registers.xl; + else + this->_registers.y = this->_registers.x; + this->_registers.p.n = this->_registers.y & negativeFlag; + this->_registers.p.z = this->_registers.y == 0; + return 0; + } + + int CPU::TYX(uint24_t, AddressingMode) + { + unsigned negativeFlag = this->_registers.p.x_b ? 0x80u : 0x8000u; + + if (this->_registers.p.x_b) + this->_registers.xl = this->_registers.yl; + else + this->_registers.x = this->_registers.y; + this->_registers.p.n = this->_registers.y & negativeFlag; + this->_registers.p.z = this->_registers.y == 0; + return 0; + } } \ No newline at end of file diff --git a/tests/CPU/TransferRegisters.cpp b/tests/CPU/TransferRegisters.cpp index 07cabcc..91ab304 100644 --- a/tests/CPU/TransferRegisters.cpp +++ b/tests/CPU/TransferRegisters.cpp @@ -384,3 +384,55 @@ Test(TYA, double16bits) 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(TXY, emulationMode) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.x_b = true; + snes.cpu->_registers.x = 0x0BCD; + snes.cpu->_registers.y = 0x5656; + snes.cpu->TXY(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.y, 0x56CD, "The y index should be 0x56CD but it was %x", snes.cpu->_registers.y); + 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(TXY, nativeMode) +{ + Init() + snes.cpu->_isEmulationMode = false; + snes.cpu->_registers.p.x_b = false; + snes.cpu->_registers.x = 0xAB0D; + snes.cpu->_registers.y = 0x5656; + snes.cpu->TXY(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.y, 0xAB0D, "The y index should be 0xAB0D but it was %x", snes.cpu->_registers.y); + 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(TYX, emulationMode) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.x_b = true; + snes.cpu->_registers.y = 0x0BCD; + snes.cpu->_registers.x = 0x5656; + snes.cpu->TYX(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.x, 0x56CD, "The x index should be 0x56CD 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(TYX, nativeMode) +{ + Init() + snes.cpu->_isEmulationMode = false; + snes.cpu->_registers.p.x_b = false; + snes.cpu->_registers.y = 0xAB0D; + snes.cpu->_registers.x = 0x5656; + snes.cpu->TYX(0x0, ComSquare::CPU::AddressingMode::Implied); + 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."); +} \ No newline at end of file