From f35427f28ac32d3ef0c81b848a357e711b6936cb Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Tue, 7 Apr 2020 22:40:53 +0200 Subject: [PATCH] Adding most of the transfer instructions --- sources/CPU/CPU.hpp | 28 +- .../CPU/Instructions/TransferRegisters.cpp | 76 ++++++ tests/CPU/TransferRegisters.cpp | 241 +++++++++++++++++- 3 files changed, 337 insertions(+), 8 deletions(-) diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index 9a61baa..f928561 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -397,6 +397,20 @@ namespace ComSquare::CPU int DEC(uint24_t, AddressingMode); //! @brief XOR, Exclusive OR accumulator with memory. int EOR(uint24_t, AddressingMode); + //! @brief Transfer 16 bit A to DP + int TCD(uint24_t, AddressingMode); + //! @brief Transfer 16 bit A to SP + int TCS(uint24_t, AddressingMode); + //! @brief Transfer DP to 16 bit A + int TDC(uint24_t, AddressingMode); + //! @brief Transfer DP to 16 bit A + int TSC(uint24_t, AddressingMode); + //! @brief Transfer SP to X + int TSX(uint24_t, AddressingMode); + //! @brief Transfer X to A + int TXA(uint24_t, AddressingMode); + //! @brief Transfer Y to A + int TYA(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -428,7 +442,7 @@ namespace ComSquare::CPU {&CPU::CLC, 2, "clc", AddressingMode::Implied, 1}, // 18 {&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByY, 3}, // 19 {&CPU::INC, 2, "inc", AddressingMode::Implied, 1}, // 1A - {&CPU::BRK, 7, "tcs #-#", AddressingMode::Implied, 2}, // 1B + {&CPU::TCS, 2, "tcs", AddressingMode::Implied, 1}, // 1B {&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // 1C {&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByX, 3}, // 1D {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 1E @@ -460,7 +474,7 @@ namespace ComSquare::CPU {&CPU::SEC, 2, "sec", AddressingMode::Implied, 1}, // 38 {&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByY, 3}, // 39 {&CPU::DEC, 2, "dec", AddressingMode::Implied, 1}, // 3A - {&CPU::BRK, 7, "tsc #-#", AddressingMode::Implied, 2}, // 3B + {&CPU::TSC, 2, "tsc", AddressingMode::Implied, 1}, // 3B {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 3C {&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByX, 3}, // 3D {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 3E @@ -492,7 +506,7 @@ namespace ComSquare::CPU {&CPU::CLI, 2, "cli", AddressingMode::Implied, 1}, // 58 {&CPU::EOR, 4, "eor", AddressingMode::AbsoluteIndexedByY, 3}, // 59 {&CPU::PHY, 3, "phy", AddressingMode::Implied, 1}, // 5A - {&CPU::BRK, 7, "tcd #-#", AddressingMode::Implied, 2}, // 5B + {&CPU::TCD, 2, "tcd", AddressingMode::Implied, 1}, // 5B {&CPU::JML, 4, "jml", AddressingMode::Implied, 4}, // 5C {&CPU::EOR, 4, "eor", AddressingMode::AbsoluteIndexedByX, 3}, // 5D {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 5E @@ -524,7 +538,7 @@ namespace ComSquare::CPU {&CPU::SEI, 2, "sei", AddressingMode::Implied, 1}, // 78 {&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByY, 2}, // 79 {&CPU::PLY, 4, "ply", AddressingMode::Implied, 1}, // 7A - {&CPU::BRK, 7, "tdc #-#", AddressingMode::Implied, 2}, // 7B + {&CPU::TDC, 2, "tdc", AddressingMode::Implied, 1}, // 7B {&CPU::JMP, 6, "jmp", AddressingMode::AbsoluteIndirectIndexedByX, 3}, // 7C {&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByX, 3}, // 7D {&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 7E @@ -539,7 +553,7 @@ namespace ComSquare::CPU {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectLong, 2}, // 87 {&CPU::DEY, 2, "dey", AddressingMode::Implied, 1}, // 88 {&CPU::BRK, 7, "bit #-#", AddressingMode::Implied, 2}, // 89 - {&CPU::BRK, 7, "txa #-#", AddressingMode::Implied, 2}, // 8A + {&CPU::TXA, 2, "txa", AddressingMode::Implied, 2}, // 8A {&CPU::PHB, 3, "phb", AddressingMode::Implied, 1}, // 8B {&CPU::STY, 4, "sty", AddressingMode::Absolute, 3}, // 8C {&CPU::STA, 4, "sta", AddressingMode::Absolute, 3}, // 8D @@ -553,7 +567,7 @@ namespace ComSquare::CPU {&CPU::STA, 4, "sta", AddressingMode::DirectPageIndexedByX, 2}, // 95 {&CPU::STX, 4, "stx", AddressingMode::DirectPageIndexedByY, 2}, // 96 {&CPU::STA, 6, "sta", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 97 - {&CPU::BRK, 7, "tya #-#", AddressingMode::Implied, 2}, // 98 + {&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 @@ -587,7 +601,7 @@ namespace ComSquare::CPU {&CPU::LDA, 6, "lda", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // B7 {&CPU::CLV, 7, "clv", AddressingMode::Implied, 1}, // B8 {&CPU::LDA, 4, "lda", AddressingMode::AbsoluteIndexedByY, 3}, // B9 - {&CPU::BRK, 7, "mvn #-#", AddressingMode::Implied, 2}, // BA + {&CPU::TSX, 2, "tsx", AddressingMode::Implied, 1}, // BA {&CPU::BRK, 7, "tyx #-#", AddressingMode::Implied, 2}, // BB {&CPU::LDY, 4, "ldy", AddressingMode::AbsoluteIndexedByX, 3}, // BC {&CPU::LDA, 4, "lda", AddressingMode::AbsoluteIndexedByX, 3}, // BD diff --git a/sources/CPU/Instructions/TransferRegisters.cpp b/sources/CPU/Instructions/TransferRegisters.cpp index 4905071..6135ce3 100644 --- a/sources/CPU/Instructions/TransferRegisters.cpp +++ b/sources/CPU/Instructions/TransferRegisters.cpp @@ -48,4 +48,80 @@ namespace ComSquare::CPU } return 0; } + + int CPU::TCD(uint24_t, AddressingMode) + { + this->_registers.d = this->_registers.a; + this->_registers.p.n = this->_registers.d & 0x8000u; + this->_registers.p.z = this->_registers.d == 0; + return 0; + } + + int CPU::TCS(uint24_t, AddressingMode) + { + this->_registers.s = this->_registers.a; + if (this->_isEmulationMode) + this->_registers.sh = 1; + return 0; + } + + int CPU::TDC(uint24_t, AddressingMode) + { + this->_registers.a = this->_registers.d; + this->_registers.p.n = this->_registers.a & 0x8000u; + this->_registers.p.z = this->_registers.a == 0; + return 0; + } + + int CPU::TSC(uint24_t, AddressingMode) + { + this->_registers.a = this->_registers.s; + this->_registers.p.n = this->_registers.a & 0x8000u; + this->_registers.p.z = this->_registers.a == 0; + return 0; + } + + int CPU::TSX(uint24_t, AddressingMode) + { + unsigned negativeFlag = this->_registers.p.x_b ? 0x80u : 0x8000u; + + this->_registers.x = this->_registers.s; + if (this->_registers.p.x_b) + this->_registers.xh = 0; + this->_registers.p.n = this->_registers.x & negativeFlag; + this->_registers.p.z = this->_registers.x == 0; + return 0; + } + + int CPU::TXA(uint24_t, AddressingMode) + { + unsigned negativeFlag = this->_registers.p.m ? 0x80u : 0x8000u; + + if (this->_registers.p.m) + this->_registers.al = this->_registers.xl; + else { + this->_registers.a = this->_registers.x; + if (this->_registers.p.x_b) + this->_registers.ah = 0; + } + this->_registers.p.n = this->_registers.a & negativeFlag; + this->_registers.p.z = this->_registers.a == 0; + return 0; + } + + int CPU::TYA(uint24_t, AddressingMode) + { + unsigned negativeFlag = this->_registers.p.m ? 0x80u : 0x8000u; + + if (this->_registers.p.m) + this->_registers.al = this->_registers.yl; + else { + this->_registers.a = this->_registers.y; + if (this->_registers.p.x_b) + this->_registers.ah = 0; + } + this->_registers.p.n = this->_registers.a & negativeFlag; + this->_registers.p.z = this->_registers.a == 0; + return 0; + } } \ No newline at end of file diff --git a/tests/CPU/TransferRegisters.cpp b/tests/CPU/TransferRegisters.cpp index c840e2a..07cabcc 100644 --- a/tests/CPU/TransferRegisters.cpp +++ b/tests/CPU/TransferRegisters.cpp @@ -144,4 +144,243 @@ Test(TXS, 8bitsIndex) cr_assert_eq(snes.cpu->_registers.s, 0x00CD, "The stack pointer should be 0x00CD but it was %x", snes.cpu->_registers.s); 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 +} + +Test(TCD, emulationMode) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.d = 0x5656; + snes.cpu->_registers.a = 0xABCD; + snes.cpu->TCD(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.d, 0xABCD, "The direct page should be 0xABCD but it was %x", snes.cpu->_registers.d); + 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(TCD, zero) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.d = 0x5656; + snes.cpu->_registers.a = 0x0; + snes.cpu->TCD(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.d, 0, "The direct page should be 0x0 but it was %x", snes.cpu->_registers.d); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set."); +} + +Test(TCS, emulationMode) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.m = false; + snes.cpu->_registers.s = 0x0156; + snes.cpu->_registers.a = 0xABCD; + snes.cpu->TCS(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.s, 0x01CD, "The stack pointer should be 0x01CD but it was %x", snes.cpu->_registers.s); +} + +Test(TCS, native) +{ + Init() + snes.cpu->_isEmulationMode = false; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.s = 0x0156; + snes.cpu->_registers.a = 0xABCD; + snes.cpu->TCS(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.s, 0xABCD, "The stack pointer should be 0xABCD but it was %x", snes.cpu->_registers.s); +} + +Test(TDC, emulationMode) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.d = 0xABCD; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TDC(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0xABCD, "The accumulator should be 0xABCD but it was %x", snes.cpu->_registers.a); + 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(TDC, zero) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.d = 0x0; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TDC(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0, "The accumulator should be 0x0 but it was %x", snes.cpu->_registers.a); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set."); +} + +Test(TSC, emulationMode) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.s = 0xABCD; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TSC(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0xABCD, "The accumulator should be 0xABCD but it was %x", snes.cpu->_registers.a); + 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(TSC, zero) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.s = 0x0; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TSC(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0, "The accumulator should be 0x0 but it was %x", snes.cpu->_registers.a); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flag should be set."); +} + +Test(TSX, emulationMode) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.x_b = true; + snes.cpu->_registers.s = 0xABCD; + snes.cpu->_registers.x = 0x5656; + snes.cpu->TSX(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.x, 0x00CD, "The x index should be 0x00CD 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(TSX, native) +{ + Init() + snes.cpu->_isEmulationMode = false; + snes.cpu->_registers.p.x_b = false; + snes.cpu->_registers.s = 0x8F00; + snes.cpu->_registers.x = 0x5656; + snes.cpu->TSX(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.x, 0x8F00, "The x index should be 0x8F00 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(TXA, double8bits) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.p.x_b = true; + snes.cpu->_registers.x = 0xABCD; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TXA(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0x56CD, "The accumulator should be 0x56CD but it was %x", snes.cpu->_registers.a); + 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(TXA, index8bits) +{ + Init() + snes.cpu->_isEmulationMode = false; + snes.cpu->_registers.p.m = false; + snes.cpu->_registers.p.x_b = true; + snes.cpu->_registers.x = 0x0BCD; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TXA(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0x00CD, "The accumulator should be 0x00CD but it was %x", snes.cpu->_registers.a); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set."); +} + +Test(TXA, accumulator8bits) +{ + Init() + snes.cpu->_isEmulationMode = false; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.p.x_b = false; + snes.cpu->_registers.x = 0x0BCD; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TXA(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0x56CD, "The accumulator should be 0x56CD but it was %x", snes.cpu->_registers.a); + 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(TXA, double16bits) +{ + Init() + snes.cpu->_isEmulationMode = false; + snes.cpu->_registers.p.m = false; + snes.cpu->_registers.p.x_b = false; + snes.cpu->_registers.x = 0xAB0D; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TXA(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0xAB0D, "The accumulator should be 0xAB0D but it was %x", snes.cpu->_registers.a); + 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(TYA, double8bits) +{ + Init() + snes.cpu->_isEmulationMode = true; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.p.x_b = true; + snes.cpu->_registers.y = 0xABCD; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TYA(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0x56CD, "The accumulator should be 0x56CD but it was %x", snes.cpu->_registers.a); + 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(TYA, index8bits) +{ + Init() + snes.cpu->_isEmulationMode = false; + snes.cpu->_registers.p.m = false; + snes.cpu->_registers.p.x_b = true; + snes.cpu->_registers.y = 0x0BCD; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TYA(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0x00CD, "The accumulator should be 0x00CD but it was %x", snes.cpu->_registers.a); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set."); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should be not set."); +} + +Test(TYA, accumulator8bits) +{ + Init() + snes.cpu->_isEmulationMode = false; + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.p.x_b = false; + snes.cpu->_registers.y = 0x0BCD; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TYA(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0x56CD, "The accumulator should be 0x56CD but it was %x", snes.cpu->_registers.a); + 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(TYA, double16bits) +{ + Init() + snes.cpu->_isEmulationMode = false; + snes.cpu->_registers.p.m = false; + snes.cpu->_registers.p.x_b = false; + snes.cpu->_registers.y = 0xAB0D; + snes.cpu->_registers.a = 0x5656; + snes.cpu->TYA(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0xAB0D, "The accumulator should be 0xAB0D but it was %x", snes.cpu->_registers.a); + 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."); +}