add/sub simplifications

This commit is contained in:
Adrian Conlon 2024-03-22 15:57:51 +00:00
parent fc30360165
commit b812554cb6
2 changed files with 69 additions and 46 deletions

View File

@ -60,13 +60,12 @@ namespace EightBit {
void sbc() noexcept; void sbc() noexcept;
[[nodiscard]] virtual uint8_t sub(uint8_t operand, int borrow = 0) 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_b(uint8_t operand, int borrow = 0) noexcept;
[[nodiscard]] uint8_t sub_d(uint8_t operand, uint8_t data, int borrow = 0) noexcept; [[nodiscard]] uint8_t sub_d(uint8_t operand, int borrow = 0) noexcept;
void adc() noexcept; virtual void adc() noexcept;
[[nodiscard]] virtual uint8_t add(uint8_t operand, int carry = 0) noexcept; void adc_b() noexcept;
[[nodiscard]] uint8_t add_b(uint8_t operand, uint8_t data, int carry) noexcept; void adc_d() noexcept;
[[nodiscard]] uint8_t add_d(uint8_t operand, uint8_t data, int carry) noexcept;
// Undocumented compound instructions (with BCD effects) // Undocumented compound instructions (with BCD effects)
@ -96,6 +95,34 @@ namespace EightBit {
// Dummy stack push, used during RESET // Dummy stack push, used during RESET
void dummyPush() noexcept; 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 // Addressing modes
constexpr void noteFixedAddress(register16_t fixed) noexcept { m_fixed_page = fixed.high; BUS().ADDRESS().low = fixed.low; } 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); 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))); 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))); set_flag(VF, negative((operand ^ data) & (operand ^ intermediate)));
} }

View File

@ -34,17 +34,7 @@ int EightBit::MOS6502::step() noexcept {
if (LIKELY(raised(RDY()))) { if (LIKELY(raised(RDY()))) {
lowerSYNC(); // Instruction fetch beginning fetchInstruction();
// 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();
// Priority: RESET > NMI > INT // Priority: RESET > NMI > INT
if (UNLIKELY(lowered(RESET()))) 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 { void EightBit::MOS6502::busWrite() noexcept {
tick(); tick();
lowerRW(); writeToBus();
LittleEndianProcessor::busWrite();
} }
uint8_t EightBit::MOS6502::busRead() noexcept { uint8_t EightBit::MOS6502::busRead() noexcept {
tick(); tick();
raiseRW(); return readFromBus();
return LittleEndianProcessor::busRead();
} }
// //
@ -430,23 +418,25 @@ void EightBit::MOS6502::sbc() noexcept {
const auto operand = A(); const auto operand = A();
A() = sub(operand, carry(~P())); A() = sub(operand, carry(~P()));
const auto difference = m_intermediate; adjustOverflow_subtract(operand);
adjustOverflow_subtract(operand, BUS().DATA(), difference.low); adjustNZ(m_intermediate.low);
adjustNZ(difference.low); reset_flag(CF, m_intermediate.high);
reset_flag(CF, difference.high);
} }
uint8_t EightBit::MOS6502::sub(const uint8_t operand, const int borrow) noexcept { uint8_t EightBit::MOS6502::sub(const uint8_t operand, const int borrow) noexcept {
const auto data = BUS().DATA(); return decimal() ? sub_d(operand, borrow) : sub_b(operand, borrow);
return decimal() ? sub_d(operand, data, borrow) : sub_b(operand, data, 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; m_intermediate.word = operand - data - borrow;
return m_intermediate.low; 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; m_intermediate.word = operand - data - borrow;
uint8_t low = lowNibble(operand) - lowNibble(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 { 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(); 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 { adjustOverflow_add(operand);
m_intermediate.word = operand + data + carrying;
adjustOverflow_add(operand, data, m_intermediate.low);
set_flag(CF, carry(m_intermediate.high)); set_flag(CF, carry(m_intermediate.high));
adjustNZ(m_intermediate.low); 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; const auto operand = A();
register16_t high = higherNibble(operand) + higherNibble(data); 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); 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); adjustNegative(high.low);
adjustOverflow_add(operand, data, high.low); adjustOverflow_add(operand);
if (high.word > 0x90) if (high.word > 0x90)
high += 0x60; high += 0x60;
set_flag(CF, high.high); set_flag(CF, high.high);
return lowerNibble(low.low) | higherNibble(high.low); A() = lowerNibble(low.low) | higherNibble(high.low);
} }
void EightBit::MOS6502::andr() noexcept { void EightBit::MOS6502::andr() noexcept {
@ -605,7 +597,7 @@ void EightBit::MOS6502::arr_b(const uint8_t value) noexcept {
} }
void EightBit::MOS6502::axs() 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); reset_flag(CF, m_intermediate.high);
} }