diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h index 9415bb7..3bc1955 100644 --- a/M6502/inc/mos6502.h +++ b/M6502/inc/mos6502.h @@ -60,13 +60,12 @@ namespace EightBit { void sbc() noexcept; [[nodiscard]] virtual uint8_t sub(uint8_t operand, int borrow = 0) noexcept; - [[nodiscard]] uint8_t sub_b(uint8_t operand, uint8_t data, int borrow = 0) noexcept; - [[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow = 0) noexcept; + [[nodiscard]] uint8_t sub_b(uint8_t operand, int borrow = 0) noexcept; + [[nodiscard]] uint8_t sub_d(uint8_t operand, int borrow = 0) noexcept; - void adc() noexcept; - [[nodiscard]] virtual uint8_t add(uint8_t operand, int carry = 0) noexcept; - [[nodiscard]] uint8_t add_b(uint8_t operand, uint8_t data, int carry) noexcept; - [[nodiscard]] uint8_t add_d(uint8_t operand, uint8_t data, int carry) noexcept; + virtual void adc() noexcept; + void adc_b() noexcept; + void adc_d() noexcept; // Undocumented compound instructions (with BCD effects) @@ -96,6 +95,34 @@ namespace EightBit { // Dummy stack push, used during RESET void dummyPush() noexcept; + uint8_t readFromBus() noexcept { + raiseRW(); + return LittleEndianProcessor::busRead(); + } + + void writeToBus() noexcept { + lowerRW(); + LittleEndianProcessor::busWrite(); + } + + // Read the opcode within the existing cycle + void fetchInstruction() noexcept { + + // Instruction fetch beginning + lowerSYNC(); + + assert(cycles() == 1 && "An extra cycle has occurred"); + + // Can't use fetchByte, since that would add an extra tick. + Address_Immediate(); + opcode() = readFromBus(); + + assert(cycles() == 1 && "BUS read has introduced stray cycles"); + + // Instruction fetch has now completed + raiseSYNC(); + } + // Addressing modes constexpr void noteFixedAddress(register16_t fixed) noexcept { m_fixed_page = fixed.high; BUS().ADDRESS().low = fixed.low; } @@ -153,11 +180,15 @@ namespace EightBit { adjustNegative(datum); } - constexpr void adjustOverflow_add(uint8_t operand, uint8_t data, uint8_t intermediate) noexcept { + constexpr void adjustOverflow_add(uint8_t operand) noexcept { + const auto data = BUS().DATA(); + const auto intermediate = m_intermediate.low; set_flag(VF, negative(~(operand ^ data) & (operand ^ intermediate))); } - constexpr void adjustOverflow_subtract(uint8_t operand, uint8_t data, uint8_t intermediate) noexcept { + constexpr void adjustOverflow_subtract(uint8_t operand) noexcept { + const auto data = BUS().DATA(); + const auto intermediate = m_intermediate.low; set_flag(VF, negative((operand ^ data) & (operand ^ intermediate))); } diff --git a/M6502/src/mos6502.cpp b/M6502/src/mos6502.cpp index ae08294..2857b23 100644 --- a/M6502/src/mos6502.cpp +++ b/M6502/src/mos6502.cpp @@ -34,17 +34,7 @@ int EightBit::MOS6502::step() noexcept { if (LIKELY(raised(RDY()))) { - lowerSYNC(); // Instruction fetch beginning - - // Read the opcode within the existing cycle - assert(cycles() == 1 && "An extra cycle has occurred"); - // Can't use fetchByte, since that would add an extra tick. - raiseRW(); - opcode() = BUS().read(PC()++); - assert(cycles() == 1 && "BUS read has introduced stray cycles"); - - // Instruction fetch has now completed - raiseSYNC(); + fetchInstruction(); // Priority: RESET > NMI > INT if (UNLIKELY(lowered(RESET()))) @@ -102,14 +92,12 @@ void EightBit::MOS6502::interrupt(uint8_t vector, interrupt_source_t source, int void EightBit::MOS6502::busWrite() noexcept { tick(); - lowerRW(); - LittleEndianProcessor::busWrite(); + writeToBus(); } uint8_t EightBit::MOS6502::busRead() noexcept { tick(); - raiseRW(); - return LittleEndianProcessor::busRead(); + return readFromBus(); } // @@ -430,23 +418,25 @@ void EightBit::MOS6502::sbc() noexcept { const auto operand = A(); A() = sub(operand, carry(~P())); - const auto difference = m_intermediate; - adjustOverflow_subtract(operand, BUS().DATA(), difference.low); - adjustNZ(difference.low); - reset_flag(CF, difference.high); + adjustOverflow_subtract(operand); + adjustNZ(m_intermediate.low); + reset_flag(CF, m_intermediate.high); } uint8_t EightBit::MOS6502::sub(const uint8_t operand, const int borrow) noexcept { - const auto data = BUS().DATA(); - return decimal() ? sub_d(operand, data, borrow) : sub_b(operand, data, borrow); + return decimal() ? sub_d(operand, borrow) : sub_b(operand, borrow); } -uint8_t EightBit::MOS6502::sub_b(const uint8_t operand, const uint8_t data, const int borrow) noexcept { +uint8_t EightBit::MOS6502::sub_b(const uint8_t operand, const int borrow) noexcept { + const auto data = BUS().DATA(); m_intermediate.word = operand - data - borrow; return m_intermediate.low; } -uint8_t EightBit::MOS6502::sub_d(const uint8_t operand, const uint8_t data, const int borrow) noexcept { +uint8_t EightBit::MOS6502::sub_d(const uint8_t operand, const int borrow) noexcept { + + const auto data = BUS().DATA(); + m_intermediate.word = operand - data - borrow; uint8_t low = lowNibble(operand) - lowNibble(data) - borrow; @@ -463,29 +453,31 @@ uint8_t EightBit::MOS6502::sub_d(const uint8_t operand, const uint8_t data, cons } void EightBit::MOS6502::adc() noexcept { - A() = add(A(), carry()); + decimal() ? adc_d() : adc_b(); } -uint8_t EightBit::MOS6502::add(uint8_t operand, int carrying) noexcept { +void EightBit::MOS6502::adc_b() noexcept { + + const auto operand = A(); const auto data = BUS().DATA(); - return decimal() ? add_d(operand, data, carrying) : add_b(operand, data, carrying); -} + m_intermediate.word = operand + data + carry(); -uint8_t EightBit::MOS6502::add_b(uint8_t operand, uint8_t data, int carrying) noexcept { - m_intermediate.word = operand + data + carrying; - - adjustOverflow_add(operand, data, m_intermediate.low); + adjustOverflow_add(operand); set_flag(CF, carry(m_intermediate.high)); adjustNZ(m_intermediate.low); - return m_intermediate.low; + A() = m_intermediate.low; } -uint8_t EightBit::MOS6502::add_d(uint8_t operand, uint8_t data, int carry) noexcept { +void EightBit::MOS6502::adc_d() noexcept { - register16_t low = lowerNibble(operand) + lowerNibble(data) + carry; - register16_t high = higherNibble(operand) + higherNibble(data); + const auto operand = A(); + const auto data = BUS().DATA(); + + register16_t low = lowerNibble(operand) + lowerNibble(data) + carry(); + m_intermediate = higherNibble(operand) + higherNibble(data); + auto& high = m_intermediate; adjustZero((low + high).low); @@ -495,14 +487,14 @@ uint8_t EightBit::MOS6502::add_d(uint8_t operand, uint8_t data, int carry) noexc } adjustNegative(high.low); - adjustOverflow_add(operand, data, high.low); + adjustOverflow_add(operand); if (high.word > 0x90) high += 0x60; set_flag(CF, high.high); - return lowerNibble(low.low) | higherNibble(high.low); + A() = lowerNibble(low.low) | higherNibble(high.low); } void EightBit::MOS6502::andr() noexcept { @@ -605,7 +597,7 @@ void EightBit::MOS6502::arr_b(const uint8_t value) noexcept { } void EightBit::MOS6502::axs() noexcept { - X() = through(sub_b(A() & X(), BUS().DATA())); + X() = through(sub_b(A() & X())); reset_flag(CF, m_intermediate.high); }