diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp index a478d35..9a61baa 100644 --- a/sources/CPU/CPU.hpp +++ b/sources/CPU/CPU.hpp @@ -395,6 +395,8 @@ namespace ComSquare::CPU int INC(uint24_t, AddressingMode); //! @brief Decrement int DEC(uint24_t, AddressingMode); + //! @brief XOR, Exclusive OR accumulator with memory. + int EOR(uint24_t, AddressingMode); //! @brief All the instructions of the CPU. //! @info Instructions are indexed by their opcode @@ -464,37 +466,37 @@ namespace ComSquare::CPU {&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 3E {&CPU::AND, 5, "and", AddressingMode::AbsoluteIndexedByXLong, 4}, // 3F {&CPU::RTI, 6, "rti", AddressingMode::Implied, 1}, // 40 - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 41 + {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 41 {&CPU::BRK, 7, "wdm #-#", AddressingMode::Implied, 2}, // 42 - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 43 + {&CPU::EOR, 4, "eor", AddressingMode::StackRelative, 2}, // 43 {&CPU::BRK, 7, "mvp #-#", AddressingMode::Implied, 2}, // 44 - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 45 + {&CPU::EOR, 3, "eor", AddressingMode::DirectPage, 2}, // 45 {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 46 - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 47 + {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectLong, 2}, // 47 {&CPU::PHA, 3, "pha", AddressingMode::Implied, 1}, // 48 - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 49 + {&CPU::EOR, 2, "eor", AddressingMode::ImmediateForA, 2}, // 49 {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 4A {&CPU::PHK, 3, "phk", AddressingMode::Implied, 1}, // 4B {&CPU::JMP, 3, "jmp", AddressingMode::Absolute, 3}, // 4C - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 4D + {&CPU::EOR, 4, "eor", AddressingMode::Absolute, 3}, // 4D {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 4E - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 4F + {&CPU::EOR, 5, "eor", AddressingMode::AbsoluteLong, 4}, // 4F {&CPU::BVC, 2, "bvc", AddressingMode::Implied, 2}, // 50 - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 51 - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 52 - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 53 + {&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::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 55 + {&CPU::EOR, 4, "eor", AddressingMode::DirectPageIndexedByX, 2}, // 55 {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 56 - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 57 + {&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 57 {&CPU::CLI, 2, "cli", AddressingMode::Implied, 1}, // 58 - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 59 + {&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::JML, 4, "jml", AddressingMode::Implied, 4}, // 5C - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 5D + {&CPU::EOR, 4, "eor", AddressingMode::AbsoluteIndexedByX, 3}, // 5D {&CPU::BRK, 7, "lsr #-#", AddressingMode::Implied, 2}, // 5E - {&CPU::BRK, 7, "eor #-#", AddressingMode::Implied, 2}, // 5F + {&CPU::EOR, 5, "eor", AddressingMode::AbsoluteIndexedByXLong, 4}, // 5F {&CPU::RTL, 6, "rtl", AddressingMode::Implied, 1}, // 60 {&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 61 {&CPU::BRK, 7, "per #-#", AddressingMode::Implied, 2}, // 62 diff --git a/sources/CPU/Instructions/MathematicalOperations.cpp b/sources/CPU/Instructions/MathematicalOperations.cpp index ff2d63e..f723978 100644 --- a/sources/CPU/Instructions/MathematicalOperations.cpp +++ b/sources/CPU/Instructions/MathematicalOperations.cpp @@ -365,4 +365,37 @@ namespace ComSquare::CPU return 0; } } + + int CPU::EOR(uint24_t valueAddr, AddressingMode mode) + { + unsigned negativeMask = this->_registers.p.m ? 0x80u : 0x8000u; + unsigned value = this->_bus->read(valueAddr); + if (!this->_registers.p.m) + value += this->_bus->read(valueAddr + 1) << 8u; + this->_registers.a ^= value; + this->_registers.p.z = this->_registers.a == 0; + this->_registers.p.n = this->_registers.a & negativeMask; + + int cycles = !this->_registers.p.m; + switch (mode) { + case DirectPage: + case DirectPageIndirect: + case DirectPageIndirectLong: + case DirectPageIndexedByX: + case DirectPageIndirectIndexedByX: + case DirectPageIndirectIndexedByYLong: + cycles += this->_registers.dl != 0; + break; + case AbsoluteIndexedByX: + case AbsoluteIndexedByY: + cycles += this->_hasIndexCrossedPageBoundary; + break; + case DirectPageIndirectIndexedByY: + cycles += this->_registers.dl != 0 + this->_hasIndexCrossedPageBoundary; + break; + default: + break; + } + return cycles; + } } \ No newline at end of file diff --git a/tests/CPU/Math/testOthersMath.cpp b/tests/CPU/Math/testOthersMath.cpp index 1f293aa..294f4f9 100644 --- a/tests/CPU/Math/testOthersMath.cpp +++ b/tests/CPU/Math/testOthersMath.cpp @@ -284,4 +284,40 @@ Test(DEC, negativeNativeAccumulator) cr_assert_eq(snes.cpu->_registers.a, 0x9000, "The incremented value should be 0x9000 but it was 0x%x.", snes.cpu->_registers.a); cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flags should be set."); cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flags should not be set."); -} \ No newline at end of file +} + +Test(EOR, simple) +{ + Init() + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.a = 0x80; + snes.wram->_data[0] = 0x0F; + snes.cpu->EOR(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0x8F, "The accumulator's value should be 0x8F but it was 0x%x.", snes.cpu->_registers.a); + cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flags should be set."); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flags should not be set."); +} + +Test(EOR, simple2) +{ + Init() + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.a = 0x80; + snes.wram->_data[0] = 0xF0; + snes.cpu->EOR(0x00, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0x70, "The accumulator's value should be 0x70 but it was 0x%x.", snes.cpu->_registers.a); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flags should not be set."); + cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flags should not be set."); +} + +Test(EOR, zero) +{ + Init() + snes.cpu->_registers.p.m = true; + snes.cpu->_registers.a = 0x00; + snes.wram->_data[0] = 0x00; + snes.cpu->EOR(0x0, ComSquare::CPU::AddressingMode::Implied); + cr_assert_eq(snes.cpu->_registers.a, 0x00, "The accumulator's value should be 0x00 but it was 0x%x.", snes.cpu->_registers.a); + cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flags should not be set."); + cr_assert_eq(snes.cpu->_registers.p.z, true, "The zero flags should be set."); +}