Files
VirtualC64-Core/C64/Instructions.cpp
T
2015-11-18 00:34:41 -06:00

7317 lines
159 KiB
C++
Executable File

/*
* (C) 2006 Dirk W. Hoffmann. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "C64.h"
// DIRK DEBUG, REMOVE ASAP
extern unsigned dirktrace;
extern unsigned dirkcnt;
// Cycle 0
void
CPU::fetch() {
bool doNMI = false, doIRQ = false;
PC_at_cycle_0 = PC;
// Check interrupt lines
// if (interruptsPending) {
if (1) {
if (nmiEdge && NMILineRaisedLongEnough()) {
if (tracingEnabled())
debug(1, "NMI (source = %02X)\n", nmiLine);
nmiEdge = false;
next = &CPU::nmi_2;
doNMI = true;
return;
} else if (irqLine && !IRQsAreBlocked() && IRQLineRaisedLongEnough()) {
if (tracingEnabled())
debug(1, "IRQ (source = %02X)\n", irqLine);
/*
if (debugirq) {
debugirq = 0;
debug("IRQ (source = %02X, cycle = %lld)\n", irqLine, c64->getCycles());
}
*/
/*
if (c64->mem->peek(0x0315) == 0xF9 && c64->mem->peek(0x0314) == 0x2C) {
debug("INTERRUPTING TO %02X%02X CASETTE ROUTINE at cycle %lld (CIA1.timerB = %04X) irqline = %02X\n",
c64->mem->peek(0xFFFF), c64->mem->peek(0xFFFE), c64->getCycles(), c64->cia1->counterB, irqLine);
// c64->cpu->setTraceMode(true);
}
*/
next = &CPU::irq_2;
doIRQ = true;
return;
}
}
// Execute fetch phase
FETCH_OPCODE
next = actionFunc[opcode];
// Disassemble command if requested
if (tracingEnabled()) {
debug(1, "%s\n", disassemble());
}
// Check breakpoint tag
if (breakpoint[PC_at_cycle_0] != NO_BREAKPOINT) {
if (breakpoint[PC_at_cycle_0] & SOFT_BREAKPOINT) {
breakpoint[PC_at_cycle_0] &= ~SOFT_BREAKPOINT; // Soft breakpoints get deleted when reached
setErrorState(SOFT_BREAKPOINT_REACHED);
} else {
setErrorState(HARD_BREAKPOINT_REACHED);
}
debug(1, "Breakpoint reached\n");
}
}
void
CPU::registerCallback(uint8_t opcode, void (CPU::*func)())
{
registerCallback(opcode, "???", ADDR_IMPLIED, func);
}
void
CPU::registerCallback(uint8_t opcode, const char *mnc, AddressingMode mode, void (CPU::*func)())
{
// table is write once!
if (func != &CPU::JAM)
assert(actionFunc[opcode] == &CPU::JAM);
actionFunc[opcode] = func;
mnemonic[opcode] = mnc;
addressingMode[opcode] = mode;
}
void
CPU::registerIllegalInstructions()
{
registerCallback(0x93, "SHA*", ADDR_INDIRECT_Y, &CPU::SHA_indirect_y);
registerCallback(0x9F, "SHA*", ADDR_ABSOLUTE_Y, &CPU::SHA_absolute_y);
registerCallback(0x4B, "ALR*", ADDR_IMMEDIATE, &CPU::ALR_immediate);
registerCallback(0x0B, "ANC*", ADDR_IMMEDIATE, &CPU::ANC_immediate);
registerCallback(0x2B, "ANC*", ADDR_IMMEDIATE, &CPU::ANC_immediate);
registerCallback(0x8B, "ANE*", ADDR_IMMEDIATE, &CPU::ANE_immediate);
registerCallback(0x6B, "ARR*", ADDR_IMMEDIATE, &CPU::ARR_immediate);
registerCallback(0xCB, "AXS*", ADDR_IMMEDIATE, &CPU::AXS_immediate);
registerCallback(0xC7, "DCP*", ADDR_ZERO_PAGE, &CPU::DCP_zero_page);
registerCallback(0xD7, "DCP*", ADDR_ZERO_PAGE_X, &CPU::DCP_zero_page_x);
registerCallback(0xC3, "DCP*", ADDR_INDIRECT_X, &CPU::DCP_indirect_x);
registerCallback(0xD3, "DCP*", ADDR_INDIRECT_Y, &CPU::DCP_indirect_y);
registerCallback(0xCF, "DCP*", ADDR_ABSOLUTE, &CPU::DCP_absolute);
registerCallback(0xDF, "DCP*", ADDR_ABSOLUTE_X, &CPU::DCP_absolute_x);
registerCallback(0xDB, "DCP*", ADDR_ABSOLUTE_Y, &CPU::DCP_absolute_y);
registerCallback(0xE7, "ISC*", ADDR_ZERO_PAGE, &CPU::ISC_zero_page);
registerCallback(0xF7, "ISC*", ADDR_ZERO_PAGE_X, &CPU::ISC_zero_page_x);
registerCallback(0xE3, "ISC*", ADDR_INDIRECT_X, &CPU::ISC_indirect_x);
registerCallback(0xF3, "ISC*", ADDR_INDIRECT_Y, &CPU::ISC_indirect_y);
registerCallback(0xEF, "ISC*", ADDR_ABSOLUTE, &CPU::ISC_absolute);
registerCallback(0xFF, "ISC*", ADDR_ABSOLUTE_X, &CPU::ISC_absolute_x);
registerCallback(0xFB, "ISC*", ADDR_ABSOLUTE_Y, &CPU::ISC_absolute_y);
registerCallback(0xBB, "LAS*", ADDR_ABSOLUTE_Y, &CPU::LAS_absolute_y);
registerCallback(0xA7, "LAX*", ADDR_ZERO_PAGE, &CPU::LAX_zero_page);
registerCallback(0xB7, "LAX*", ADDR_ZERO_PAGE_Y, &CPU::LAX_zero_page_y);
registerCallback(0xA3, "LAX*", ADDR_INDIRECT_X, &CPU::LAX_indirect_x);
registerCallback(0xB3, "LAX*", ADDR_INDIRECT_Y, &CPU::LAX_indirect_y);
registerCallback(0xAF, "LAX*", ADDR_ABSOLUTE, &CPU::LAX_absolute);
registerCallback(0xBF, "LAX*", ADDR_ABSOLUTE_Y, &CPU::LAX_absolute_y);
registerCallback(0xAB, "LXA*", ADDR_IMMEDIATE, &CPU::LXA_immediate);
registerCallback(0x80, "NOP*", ADDR_IMMEDIATE, &CPU::NOP_immediate);
registerCallback(0x82, "NOP*", ADDR_IMMEDIATE, &CPU::NOP_immediate);
registerCallback(0x89, "NOP*", ADDR_IMMEDIATE, &CPU::NOP_immediate);
registerCallback(0xC2, "NOP*", ADDR_IMMEDIATE, &CPU::NOP_immediate);
registerCallback(0xE2, "NOP*", ADDR_IMMEDIATE, &CPU::NOP_immediate);
registerCallback(0x1A, "NOP*", ADDR_IMPLIED, &CPU::NOP);
registerCallback(0x3A, "NOP*", ADDR_IMPLIED, &CPU::NOP);
registerCallback(0x5A, "NOP*", ADDR_IMPLIED, &CPU::NOP);
registerCallback(0x7A, "NOP*", ADDR_IMPLIED, &CPU::NOP);
registerCallback(0xDA, "NOP*", ADDR_IMPLIED, &CPU::NOP);
registerCallback(0xFA, "NOP*", ADDR_IMPLIED, &CPU::NOP);
registerCallback(0x04, "NOP*", ADDR_ZERO_PAGE, &CPU::NOP_zero_page);
registerCallback(0x44, "NOP*", ADDR_ZERO_PAGE, &CPU::NOP_zero_page);
registerCallback(0x64, "NOP*", ADDR_ZERO_PAGE, &CPU::NOP_zero_page);
registerCallback(0x0C, "NOP*", ADDR_ABSOLUTE, &CPU::NOP_absolute);
registerCallback(0x14, "NOP*", ADDR_ZERO_PAGE_X, &CPU::NOP_zero_page_x);
registerCallback(0x34, "NOP*", ADDR_ZERO_PAGE_X, &CPU::NOP_zero_page_x);
registerCallback(0x54, "NOP*", ADDR_ZERO_PAGE_X, &CPU::NOP_zero_page_x);
registerCallback(0x74, "NOP*", ADDR_ZERO_PAGE_X, &CPU::NOP_zero_page_x);
registerCallback(0xD4, "NOP*", ADDR_ZERO_PAGE_X, &CPU::NOP_zero_page_x);
registerCallback(0xF4, "NOP*", ADDR_ZERO_PAGE_X, &CPU::NOP_zero_page_x);
registerCallback(0x1C, "NOP*", ADDR_ABSOLUTE_X, &CPU::NOP_absolute_x);
registerCallback(0x3C, "NOP*", ADDR_ABSOLUTE_X, &CPU::NOP_absolute_x);
registerCallback(0x5C, "NOP*", ADDR_ABSOLUTE_X, &CPU::NOP_absolute_x);
registerCallback(0x7C, "NOP*", ADDR_ABSOLUTE_X, &CPU::NOP_absolute_x);
registerCallback(0xDC, "NOP*", ADDR_ABSOLUTE_X, &CPU::NOP_absolute_x);
registerCallback(0xFC, "NOP*", ADDR_ABSOLUTE_X, &CPU::NOP_absolute_x);
registerCallback(0x27, "RLA*", ADDR_ZERO_PAGE, &CPU::RLA_zero_page);
registerCallback(0x37, "RLA*", ADDR_ZERO_PAGE_X, &CPU::RLA_zero_page_x);
registerCallback(0x23, "RLA*", ADDR_INDIRECT_X, &CPU::RLA_indirect_x);
registerCallback(0x33, "RLA*", ADDR_INDIRECT_Y, &CPU::RLA_indirect_y);
registerCallback(0x2F, "RLA*", ADDR_ABSOLUTE, &CPU::RLA_absolute);
registerCallback(0x3F, "RLA*", ADDR_ABSOLUTE_X, &CPU::RLA_absolute_x);
registerCallback(0x3B, "RLA*", ADDR_ABSOLUTE_Y, &CPU::RLA_absolute_y);
registerCallback(0x67, "RRA*", ADDR_ZERO_PAGE, &CPU::RRA_zero_page);
registerCallback(0x77, "RRA*", ADDR_ZERO_PAGE_X, &CPU::RRA_zero_page_x);
registerCallback(0x63, "RRA*", ADDR_INDIRECT_X, &CPU::RRA_indirect_x);
registerCallback(0x73, "RRA*", ADDR_INDIRECT_Y, &CPU::RRA_indirect_y);
registerCallback(0x6F, "RRA*", ADDR_ABSOLUTE, &CPU::RRA_absolute);
registerCallback(0x7F, "RRA*", ADDR_ABSOLUTE_X, &CPU::RRA_absolute_x);
registerCallback(0x7B, "RRA*", ADDR_ABSOLUTE_Y, &CPU::RRA_absolute_y);
registerCallback(0x87, "SAX*", ADDR_ZERO_PAGE, &CPU::SAX_zero_page);
registerCallback(0x97, "SAX*", ADDR_ZERO_PAGE_Y, &CPU::SAX_zero_page_y);
registerCallback(0x83, "SAX*", ADDR_INDIRECT_X, &CPU::SAX_indirect_x);
registerCallback(0x8F, "SAX*", ADDR_ABSOLUTE, &CPU::SAX_absolute);
registerCallback(0xEB, "SBC*", ADDR_IMMEDIATE, &CPU::SBC_immediate);
registerCallback(0x9E, "SHX*", ADDR_ABSOLUTE_Y, &CPU::SHX_absolute_y);
registerCallback(0x9C, "SHY*", ADDR_ABSOLUTE_X, &CPU::SHY_absolute_x);
registerCallback(0x07, "SLO*", ADDR_ZERO_PAGE, &CPU::SLO_zero_page);
registerCallback(0x17, "SLO*", ADDR_ZERO_PAGE_X, &CPU::SLO_zero_page_x);
registerCallback(0x03, "SLO*", ADDR_INDIRECT_X, &CPU::SLO_indirect_x);
registerCallback(0x13, "SLO*", ADDR_INDIRECT_Y, &CPU::SLO_indirect_y);
registerCallback(0x0F, "SLO*", ADDR_ABSOLUTE, &CPU::SLO_absolute);
registerCallback(0x1F, "SLO*", ADDR_ABSOLUTE_X, &CPU::SLO_absolute_x);
registerCallback(0x1B, "SLO*", ADDR_ABSOLUTE_Y, &CPU::SLO_absolute_y);
registerCallback(0x47, "SRE*", ADDR_ZERO_PAGE, &CPU::SRE_zero_page);
registerCallback(0x57, "SRE*", ADDR_ZERO_PAGE_X, &CPU::SRE_zero_page_x);
registerCallback(0x43, "SRE*", ADDR_INDIRECT_X, &CPU::SRE_indirect_x);
registerCallback(0x53, "SRE*", ADDR_INDIRECT_Y, &CPU::SRE_indirect_y);
registerCallback(0x4F, "SRE*", ADDR_ABSOLUTE, &CPU::SRE_absolute);
registerCallback(0x5F, "SRE*", ADDR_ABSOLUTE_X, &CPU::SRE_absolute_x);
registerCallback(0x5B, "SRE*", ADDR_ABSOLUTE_Y, &CPU::SRE_absolute_y);
registerCallback(0x9B, "TAS*", ADDR_ABSOLUTE_Y, &CPU::TAS_absolute_y);
}
void CPU::registerInstructions()
{
for (int i=0; i<256; i++)
registerCallback(i, &CPU::JAM);
registerCallback(0x69, "ADC", ADDR_IMMEDIATE, &CPU::ADC_immediate);
registerCallback(0x65, "ADC", ADDR_ZERO_PAGE, &CPU::ADC_zero_page);
registerCallback(0x75, "ADC", ADDR_ZERO_PAGE_X, &CPU::ADC_zero_page_x);
registerCallback(0x6D, "ADC", ADDR_ABSOLUTE, &CPU::ADC_absolute);
registerCallback(0x7D, "ADC", ADDR_ABSOLUTE_X, &CPU::ADC_absolute_x);
registerCallback(0x79, "ADC", ADDR_ABSOLUTE_Y, &CPU::ADC_absolute_y);
registerCallback(0x61, "ADC", ADDR_INDIRECT_X, &CPU::ADC_indirect_x);
registerCallback(0x71, "ADC", ADDR_INDIRECT_Y, &CPU::ADC_indirect_y);
registerCallback(0x29, "AND", ADDR_IMMEDIATE, &CPU::AND_immediate);
registerCallback(0x25, "AND", ADDR_ZERO_PAGE, &CPU::AND_zero_page);
registerCallback(0x35, "AND", ADDR_ZERO_PAGE_X, &CPU::AND_zero_page_x);
registerCallback(0x2D, "AND", ADDR_ABSOLUTE, &CPU::AND_absolute);
registerCallback(0x3D, "AND", ADDR_ABSOLUTE_X, &CPU::AND_absolute_x);
registerCallback(0x39, "AND", ADDR_ABSOLUTE_Y, &CPU::AND_absolute_y);
registerCallback(0x21, "AND", ADDR_INDIRECT_X, &CPU::AND_indirect_x);
registerCallback(0x31, "AND", ADDR_INDIRECT_Y, &CPU::AND_indirect_y);
registerCallback(0x0A, "ASL", ADDR_ACCUMULATOR, &CPU::ASL_accumulator);
registerCallback(0x06, "ASL", ADDR_ZERO_PAGE, &CPU::ASL_zero_page);
registerCallback(0x16, "ASL", ADDR_ZERO_PAGE_X, &CPU::ASL_zero_page_x);
registerCallback(0x0E, "ASL", ADDR_ABSOLUTE, &CPU::ASL_absolute);
registerCallback(0x1E, "ASL", ADDR_ABSOLUTE_X, &CPU::ASL_absolute_x);
registerCallback(0x90, "BCC", ADDR_RELATIVE, &CPU::BCC_relative);
registerCallback(0xB0, "BCS", ADDR_RELATIVE, &CPU::BCS_relative);
registerCallback(0xF0, "BEQ", ADDR_RELATIVE, &CPU::BEQ_relative);
registerCallback(0x24, "BIT", ADDR_ZERO_PAGE, &CPU::BIT_zero_page);
registerCallback(0x2C, "BIT", ADDR_ABSOLUTE, &CPU::BIT_absolute);
registerCallback(0x30, "BMI", ADDR_RELATIVE, &CPU::BMI_relative);
registerCallback(0xD0, "BNE", ADDR_RELATIVE, &CPU::BNE_relative);
registerCallback(0x10, "BPL", ADDR_RELATIVE, &CPU::BPL_relative);
registerCallback(0x00, "BRK", ADDR_IMPLIED, &CPU::BRK);
registerCallback(0x50, "BVC", ADDR_RELATIVE, &CPU::BVC_relative);
registerCallback(0x70, "BVS", ADDR_RELATIVE, &CPU::BVS_relative);
registerCallback(0x18, "CLC", ADDR_IMPLIED, &CPU::CLC);
registerCallback(0xD8, "CLD", ADDR_IMPLIED, &CPU::CLD);
registerCallback(0x58, "CLI", ADDR_IMPLIED, &CPU::CLI);
registerCallback(0xB8, "CLV", ADDR_IMPLIED, &CPU::CLV);
registerCallback(0xC9, "CMP", ADDR_IMMEDIATE, &CPU::CMP_immediate);
registerCallback(0xC5, "CMP", ADDR_ZERO_PAGE, &CPU::CMP_zero_page);
registerCallback(0xD5, "CMP", ADDR_ZERO_PAGE_X, &CPU::CMP_zero_page_x);
registerCallback(0xCD, "CMP", ADDR_ABSOLUTE, &CPU::CMP_absolute);
registerCallback(0xDD, "CMP", ADDR_ABSOLUTE_X, &CPU::CMP_absolute_x);
registerCallback(0xD9, "CMP", ADDR_ABSOLUTE_Y, &CPU::CMP_absolute_y);
registerCallback(0xC1, "CMP", ADDR_INDIRECT_X, &CPU::CMP_indirect_x);
registerCallback(0xD1, "CMP", ADDR_INDIRECT_Y, &CPU::CMP_indirect_y);
registerCallback(0xE0, "CPX", ADDR_IMMEDIATE, &CPU::CPX_immediate);
registerCallback(0xE4, "CPX", ADDR_ZERO_PAGE, &CPU::CPX_zero_page);
registerCallback(0xEC, "CPX", ADDR_ABSOLUTE, &CPU::CPX_absolute);
registerCallback(0xC0, "CPY", ADDR_IMMEDIATE, &CPU::CPY_immediate);
registerCallback(0xC4, "CPY", ADDR_ZERO_PAGE, &CPU::CPY_zero_page);
registerCallback(0xCC, "CPY", ADDR_ABSOLUTE, &CPU::CPY_absolute);
registerCallback(0xC6, "DEC", ADDR_ZERO_PAGE, &CPU::DEC_zero_page);
registerCallback(0xD6, "DEC", ADDR_ZERO_PAGE_X, &CPU::DEC_zero_page_x);
registerCallback(0xCE, "DEC", ADDR_ABSOLUTE, &CPU::DEC_absolute);
registerCallback(0xDE, "DEC", ADDR_ABSOLUTE_X, &CPU::DEC_absolute_x);
registerCallback(0xCA, "DEX", ADDR_IMPLIED, &CPU::DEX);
registerCallback(0x88, "DEY", ADDR_IMPLIED, &CPU::DEY);
registerCallback(0x49, "EOR", ADDR_IMMEDIATE, &CPU::EOR_immediate);
registerCallback(0x45, "EOR", ADDR_ZERO_PAGE, &CPU::EOR_zero_page);
registerCallback(0x55, "EOR", ADDR_ZERO_PAGE_X, &CPU::EOR_zero_page_x);
registerCallback(0x4D, "EOR", ADDR_ABSOLUTE, &CPU::EOR_absolute);
registerCallback(0x5D, "EOR", ADDR_ABSOLUTE_X, &CPU::EOR_absolute_x);
registerCallback(0x59, "EOR", ADDR_ABSOLUTE_Y, &CPU::EOR_absolute_y);
registerCallback(0x41, "EOR", ADDR_INDIRECT_X, &CPU::EOR_indirect_x);
registerCallback(0x51, "EOR", ADDR_INDIRECT_Y, &CPU::EOR_indirect_y);
registerCallback(0xE6, "INC", ADDR_ZERO_PAGE, &CPU::INC_zero_page);
registerCallback(0xF6, "INC", ADDR_ZERO_PAGE_X, &CPU::INC_zero_page_x);
registerCallback(0xEE, "INC", ADDR_ABSOLUTE, &CPU::INC_absolute);
registerCallback(0xFE, "INC", ADDR_ABSOLUTE_X, &CPU::INC_absolute_x);
registerCallback(0xE8, "INX", ADDR_IMPLIED, &CPU::INX);
registerCallback(0xC8, "INY", ADDR_IMPLIED, &CPU::INY);
registerCallback(0x4C, "JMP", ADDR_DIRECT, &CPU::JMP_absolute);
registerCallback(0x6C, "JMP", ADDR_INDIRECT, &CPU::JMP_absolute_indirect);
registerCallback(0x20, "JSR", ADDR_DIRECT, &CPU::JSR);
registerCallback(0xA9, "LDA", ADDR_IMMEDIATE, &CPU::LDA_immediate);
registerCallback(0xA5, "LDA", ADDR_ZERO_PAGE, &CPU::LDA_zero_page);
registerCallback(0xB5, "LDA", ADDR_ZERO_PAGE_X, &CPU::LDA_zero_page_x);
registerCallback(0xAD, "LDA", ADDR_ABSOLUTE, &CPU::LDA_absolute);
registerCallback(0xBD, "LDA", ADDR_ABSOLUTE_X, &CPU::LDA_absolute_x);
registerCallback(0xB9, "LDA", ADDR_ABSOLUTE_Y, &CPU::LDA_absolute_y);
registerCallback(0xA1, "LDA", ADDR_INDIRECT_X, &CPU::LDA_indirect_x);
registerCallback(0xB1, "LDA", ADDR_INDIRECT_Y, &CPU::LDA_indirect_y);
registerCallback(0xA2, "LDX", ADDR_IMMEDIATE, &CPU::LDX_immediate);
registerCallback(0xA6, "LDX", ADDR_ZERO_PAGE, &CPU::LDX_zero_page);
registerCallback(0xB6, "LDX", ADDR_ZERO_PAGE_Y,&CPU::LDX_zero_page_y);
registerCallback(0xAE, "LDX", ADDR_ABSOLUTE, &CPU::LDX_absolute);
registerCallback(0xBE, "LDX", ADDR_ABSOLUTE_Y, &CPU::LDX_absolute_y);
registerCallback(0xA0, "LDY", ADDR_IMMEDIATE, &CPU::LDY_immediate);
registerCallback(0xA4, "LDY", ADDR_ZERO_PAGE, &CPU::LDY_zero_page);
registerCallback(0xB4, "LDY", ADDR_ZERO_PAGE_X, &CPU::LDY_zero_page_x);
registerCallback(0xAC, "LDY", ADDR_ABSOLUTE, &CPU::LDY_absolute);
registerCallback(0xBC, "LDY", ADDR_ABSOLUTE_X, &CPU::LDY_absolute_x);
registerCallback(0x4A, "LSR", ADDR_ACCUMULATOR, &CPU::LSR_accumulator);
registerCallback(0x46, "LSR", ADDR_ZERO_PAGE, &CPU::LSR_zero_page);
registerCallback(0x56, "LSR", ADDR_ZERO_PAGE_X, &CPU::LSR_zero_page_x);
registerCallback(0x4E, "LSR", ADDR_ABSOLUTE, &CPU::LSR_absolute);
registerCallback(0x5E, "LSR", ADDR_ABSOLUTE_X, &CPU::LSR_absolute_x);
registerCallback(0xEA, "NOP", ADDR_IMPLIED, &CPU::NOP);
registerCallback(0x09, "ORA", ADDR_IMMEDIATE, &CPU::ORA_immediate);
registerCallback(0x05, "ORA", ADDR_ZERO_PAGE, &CPU::ORA_zero_page);
registerCallback(0x15, "ORA", ADDR_ZERO_PAGE_X, &CPU::ORA_zero_page_x);
registerCallback(0x0D, "ORA", ADDR_ABSOLUTE, &CPU::ORA_absolute);
registerCallback(0x1D, "ORA", ADDR_ABSOLUTE_X, &CPU::ORA_absolute_x);
registerCallback(0x19, "ORA", ADDR_ABSOLUTE_Y, &CPU::ORA_absolute_y);
registerCallback(0x01, "ORA", ADDR_INDIRECT_X, &CPU::ORA_indirect_x);
registerCallback(0x11, "ORA", ADDR_INDIRECT_Y, &CPU::ORA_indirect_y);
registerCallback(0x48, "PHA", ADDR_IMPLIED, &CPU::PHA);
registerCallback(0x08, "PHP", ADDR_IMPLIED, &CPU::PHP);
registerCallback(0x68, "PLA", ADDR_IMPLIED, &CPU::PLA);
registerCallback(0x28, "PLP", ADDR_IMPLIED, &CPU::PLP);
registerCallback(0x2A, "ROL", ADDR_ACCUMULATOR, &CPU::ROL_accumulator);
registerCallback(0x26, "ROL", ADDR_ZERO_PAGE, &CPU::ROL_zero_page);
registerCallback(0x36, "ROL", ADDR_ZERO_PAGE_X, &CPU::ROL_zero_page_x);
registerCallback(0x2E, "ROL", ADDR_ABSOLUTE, &CPU::ROL_absolute);
registerCallback(0x3E, "ROL", ADDR_ABSOLUTE_X, &CPU::ROL_absolute_x);
registerCallback(0x6A, "ROR", ADDR_ACCUMULATOR, &CPU::ROR_accumulator);
registerCallback(0x66, "ROR", ADDR_ZERO_PAGE, &CPU::ROR_zero_page);
registerCallback(0x76, "ROR", ADDR_ZERO_PAGE_X, &CPU::ROR_zero_page_x);
registerCallback(0x6E, "ROR", ADDR_ABSOLUTE, &CPU::ROR_absolute);
registerCallback(0x7E, "ROR", ADDR_ABSOLUTE_X, &CPU::ROR_absolute_x);
registerCallback(0x40, "RTI", ADDR_IMPLIED, &CPU::RTI);
registerCallback(0x60, "RTS", ADDR_IMPLIED, &CPU::RTS);
registerCallback(0xE9, "SBC", ADDR_IMMEDIATE, &CPU::SBC_immediate);
registerCallback(0xE5, "SBC", ADDR_ZERO_PAGE, &CPU::SBC_zero_page);
registerCallback(0xF5, "SBC", ADDR_ZERO_PAGE_X, &CPU::SBC_zero_page_x);
registerCallback(0xED, "SBC", ADDR_ABSOLUTE, &CPU::SBC_absolute);
registerCallback(0xFD, "SBC", ADDR_ABSOLUTE_X, &CPU::SBC_absolute_x);
registerCallback(0xF9, "SBC", ADDR_ABSOLUTE_Y, &CPU::SBC_absolute_y);
registerCallback(0xE1, "SBC", ADDR_INDIRECT_X, &CPU::SBC_indirect_x);
registerCallback(0xF1, "SBC", ADDR_INDIRECT_Y, &CPU::SBC_indirect_y);
registerCallback(0x38, "SEC", ADDR_IMPLIED, &CPU::SEC);
registerCallback(0xF8, "SED", ADDR_IMPLIED, &CPU::SED);
registerCallback(0x78, "SEI", ADDR_IMPLIED, &CPU::SEI);
registerCallback(0x85, "STA", ADDR_ZERO_PAGE, &CPU::STA_zero_page);
registerCallback(0x95, "STA", ADDR_ZERO_PAGE_X, &CPU::STA_zero_page_x);
registerCallback(0x8D, "STA", ADDR_ABSOLUTE, &CPU::STA_absolute);
registerCallback(0x9D, "STA", ADDR_ABSOLUTE_X, &CPU::STA_absolute_x);
registerCallback(0x99, "STA", ADDR_ABSOLUTE_Y, &CPU::STA_absolute_y);
registerCallback(0x81, "STA", ADDR_INDIRECT_X, &CPU::STA_indirect_x);
registerCallback(0x91, "STA", ADDR_INDIRECT_Y, &CPU::STA_indirect_y);
registerCallback(0x86, "STX", ADDR_ZERO_PAGE, &CPU::STX_zero_page);
registerCallback(0x96, "STX", ADDR_ZERO_PAGE_Y, &CPU::STX_zero_page_y);
registerCallback(0x8E, "STX", ADDR_ABSOLUTE, &CPU::STX_absolute);
registerCallback(0x84, "STY", ADDR_ZERO_PAGE, &CPU::STY_zero_page);
registerCallback(0x94, "STY", ADDR_ZERO_PAGE_X, &CPU::STY_zero_page_x);
registerCallback(0x8C, "STY", ADDR_ABSOLUTE, &CPU::STY_absolute);
registerCallback(0xAA, "TAX", ADDR_IMPLIED, &CPU::TAX);
registerCallback(0xA8, "TAY", ADDR_IMPLIED, &CPU::TAY);
registerCallback(0xBA, "TSX", ADDR_IMPLIED, &CPU::TSX);
registerCallback(0x8A, "TXA", ADDR_IMPLIED, &CPU::TXA);
registerCallback(0x9A, "TXS", ADDR_IMPLIED, &CPU::TXS);
registerCallback(0x98, "TYA", ADDR_IMPLIED, &CPU::TYA);
// Register illegal instructions
registerIllegalInstructions();
}
// -------------------------------------------------------------------------------
// Illegal instructions
// -------------------------------------------------------------------------------
void CPU::JAM()
{
setErrorState(ILLEGAL_INSTRUCTION);
next = &CPU::JAM_2;
}
void CPU::JAM_2()
{
DONE;
}
// -------------------------------------------------------------------------------
// IRQ handling
// -------------------------------------------------------------------------------
void CPU::irq()
{
IDLE_READ_IMPLIED;
next = &CPU::irq_2;
}
void CPU::irq_2()
{
IDLE_READ_IMPLIED;
next = &CPU::irq_3;
}
void CPU::irq_3()
{
mem->poke(0x100+(SP--), HI_BYTE(PC));
next = &CPU::irq_4;
}
void CPU::irq_4()
{
mem->poke(0x100+(SP--), LO_BYTE(PC));
next = &CPU::irq_5;
}
void CPU::irq_5()
{
uint8_t p = getPWithClearedB();
mem->poke(0x100+(SP--), p);
setI(1);
next = &CPU::irq_6;
}
void CPU::irq_6()
{
data = mem->peek(0xFFFE);
next = &CPU::irq_7;
}
void CPU::irq_7()
{
setPCL(data);
setPCH(mem->peek(0xFFFF));
DONE;
}
// -------------------------------------------------------------------------------
// NMI handling
// -------------------------------------------------------------------------------
void CPU::nmi()
{
IDLE_READ_IMPLIED;
next = &CPU::nmi_2;
}
void CPU::nmi_2()
{
IDLE_READ_IMPLIED;
next = &CPU::nmi_3;
}
void CPU::nmi_3()
{
mem->poke(0x100+(SP--), HI_BYTE(PC));
next = &CPU::nmi_4;
}
void CPU::nmi_4()
{
mem->poke(0x100+(SP--), LO_BYTE(PC));
next = &CPU::nmi_5;
}
void CPU::nmi_5()
{
mem->poke(0x100+(SP--), getPWithClearedB());
setI(1);
next = &CPU::nmi_6;
}
void CPU::nmi_6()
{
data = mem->peek(0xFFFA);
next = &CPU::nmi_7;
}
void CPU::nmi_7()
{
setPCL(data);
setPCH(mem->peek(0xFFFB));
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: ADC
//
// Operation: A,C := A+M+C
//
// Flags: N Z C I D V
// / / / - - /
// -------------------------------------------------------------------------------
inline void CPU::adc(uint8_t op)
{
if (getD())
adc_bcd(op);
else
adc_binary(op);
}
inline void CPU::adc_binary(uint8_t op)
{
uint16_t sum = A + op + (getC() ? 1 : 0);
setC(sum > 255);
setV(!((A ^ op) & 0x80) && ((A ^ sum) & 0x80));
loadA((uint8_t)sum);
}
inline void CPU::adc_bcd(uint8_t op)
{
uint16_t sum = A + op + (getC() ? 1 : 0);
uint8_t highDigit = (A >> 4) + (op >> 4);
uint8_t lowDigit = (A & 0x0F) + (op & 0x0F) + (getC() ? 1 : 0);
// Check for overflow conditions
// If an overflow occurs on a BCD digit, it needs to be fixed by adding the pseudo-tetrade 0110 (=6)
if (lowDigit > 9) {
lowDigit = lowDigit + 6;
}
if (lowDigit > 0x0F) {
highDigit++;
}
setZ((sum & 0xFF) == 0);
setN(highDigit & 0x08);
setV((((highDigit << 4) ^ A) & 0x80) && !((A ^ op) & 0x80));
if (highDigit > 9) {
highDigit = (highDigit + 6);
}
if (highDigit > 0x0F) {
setC(1);
} else {
setC(0);
}
lowDigit &= 0x0F;
A = (uint8_t)((highDigit << 4) | lowDigit);
}
// -------------------------------------------------------------------------------
void CPU::ADC_immediate()
{
READ_IMMEDIATE;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ADC_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::ADC_zero_page_2;
}
void CPU::ADC_zero_page_2()
{
READ_FROM_ZERO_PAGE;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ADC_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::ADC_zero_page_x_2;
}
void CPU::ADC_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::ADC_zero_page_x_3;
}
void CPU::ADC_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ADC_absolute()
{
FETCH_ADDR_LO;
next = &CPU::ADC_absolute_2;
}
void CPU::ADC_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::ADC_absolute_3;
}
void CPU::ADC_absolute_3()
{
READ_FROM_ADDRESS;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ADC_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::ADC_absolute_x_2;
}
void CPU::ADC_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::ADC_absolute_x_3;
}
void CPU::ADC_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::ADC_absolute_x_4;
} else {
adc(data);
DONE;
}
}
void CPU::ADC_absolute_x_4()
{
READ_FROM_ADDRESS;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ADC_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::ADC_absolute_y_2;
}
void CPU::ADC_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::ADC_absolute_y_3;
}
void CPU::ADC_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::ADC_absolute_y_4;
} else {
adc(data);
DONE;
}
}
void CPU::ADC_absolute_y_4()
{
READ_FROM_ADDRESS;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ADC_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::ADC_indirect_x_2;
}
void CPU::ADC_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::ADC_indirect_x_3;
}
void CPU::ADC_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::ADC_indirect_x_4;
}
void CPU::ADC_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::ADC_indirect_x_5;
}
void CPU::ADC_indirect_x_5()
{
READ_FROM_ADDRESS;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ADC_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::ADC_indirect_y_2;
}
void CPU::ADC_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::ADC_indirect_y_3;
}
void CPU::ADC_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::ADC_indirect_y_4;
}
void CPU::ADC_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::ADC_indirect_y_5;
} else {
adc(data);
DONE;
}
}
void CPU::ADC_indirect_y_5()
{
READ_FROM_ADDRESS;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: AND
//
// Operation: A := A AND M
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::AND_immediate()
{
READ_IMMEDIATE;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::AND_absolute() {
FETCH_ADDR_LO;
next = &CPU::AND_absolute_2;
}
void CPU::AND_absolute_2() {
FETCH_ADDR_HI;
next = &CPU::AND_absolute_3;
}
void CPU::AND_absolute_3() {
READ_FROM_ADDRESS;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::AND_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::AND_zero_page_2;
}
void CPU::AND_zero_page_2()
{
READ_FROM_ZERO_PAGE;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::AND_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::AND_zero_page_x_2;
}
void CPU::AND_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::AND_zero_page_x_3;
}
void CPU::AND_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::AND_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::AND_absolute_x_2;
}
void CPU::AND_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::AND_absolute_x_3;
}
void CPU::AND_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::AND_absolute_x_4;
} else {
loadA(A & data);
DONE;
}
}
void CPU::AND_absolute_x_4()
{
READ_FROM_ADDRESS;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::AND_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::AND_absolute_y_2;
}
void CPU::AND_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::AND_absolute_y_3;
}
void CPU::AND_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::AND_absolute_y_4;
} else {
loadA(A & data);
DONE;
}
}
void CPU::AND_absolute_y_4()
{
READ_FROM_ADDRESS;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::AND_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::AND_indirect_x_2;
}
void CPU::AND_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::AND_indirect_x_3;
}
void CPU::AND_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::AND_indirect_x_4;
}
void CPU::AND_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::AND_indirect_x_5;
}
void CPU::AND_indirect_x_5()
{
READ_FROM_ADDRESS;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::AND_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::AND_indirect_y_2;
}
void CPU::AND_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::AND_indirect_y_3;
}
void CPU::AND_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::AND_indirect_y_4;
}
void CPU::AND_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::AND_indirect_y_5;
} else {
loadA(A & data);
DONE;
}
}
void CPU::AND_indirect_y_5()
{
READ_FROM_ADDRESS;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: ASL
//
// Operation: C <- (A|M << 1) <- 0
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
#define DO_ASL setC(data & 128); data = data << 1;
// -------------------------------------------------------------------------------
void CPU::ASL_accumulator()
{
IDLE_READ_IMPLIED;
setC(A & 128); loadA(A << 1);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ASL_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::ASL_zero_page_2;
}
void CPU::ASL_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::ASL_zero_page_3;
}
void CPU::ASL_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_ASL;
next = &CPU::ASL_zero_page_4;
}
void CPU::ASL_zero_page_4()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ASL_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::ASL_zero_page_x_2;
}
void CPU::ASL_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::ASL_zero_page_x_3;
}
void CPU::ASL_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::ASL_zero_page_x_4;
}
void CPU::ASL_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_ASL;
next = &CPU::ASL_zero_page_x_5;
}
void CPU::ASL_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ASL_absolute()
{
FETCH_ADDR_LO;
next = &CPU::ASL_absolute_2;
}
void CPU::ASL_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::ASL_absolute_3;
}
void CPU::ASL_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::ASL_absolute_4;
}
void CPU::ASL_absolute_4()
{
WRITE_TO_ADDRESS;
DO_ASL;
next = &CPU::ASL_absolute_5;
}
void CPU::ASL_absolute_5()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ASL_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::ASL_absolute_x_2;
}
void CPU::ASL_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::ASL_absolute_x_3;
}
void CPU::ASL_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::ASL_absolute_x_4;
}
void CPU::ASL_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::ASL_absolute_x_5;
}
void CPU::ASL_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_ASL;
next = &CPU::ASL_absolute_x_6;
}
void CPU::ASL_absolute_x_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ASL_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::ASL_indirect_x_2;
}
void CPU::ASL_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::ASL_indirect_x_3;
}
void CPU::ASL_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::ASL_indirect_x_4;
}
void CPU::ASL_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::ASL_indirect_x_5;
}
void CPU::ASL_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::ASL_indirect_x_6;
}
void CPU::ASL_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_ASL;
next = &CPU::ASL_indirect_x_7;
}
void CPU::ASL_indirect_x_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: BCC
//
// Operation: Branch on C = 0
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
inline void CPU::branch(int8_t offset)
{
PC += offset;
}
void CPU::branch_3_underflow()
{
IDLE_READ_FROM(PC + 0x100);
DONE;
}
void CPU::branch_3_overflow()
{
IDLE_READ_FROM(PC - 0x100);
DONE;
}
// ------------------------------------------------------------------------------
void CPU::BCC_relative()
{
READ_IMMEDIATE;
if (!getC()) {
next = &CPU::BCC_relative_2;
} else {
DONE;
}
}
void CPU::BCC_relative_2()
{
IDLE_READ_IMPLIED;
uint8_t pc_hi = HI_BYTE(PC);
PC += (int8_t)data;
if (pc_hi != HI_BYTE(PC)) {
next = (data & 0x80) ? &CPU::branch_3_underflow : &CPU::branch_3_overflow;
} else {
nextPossibleIrqCycle++; // Delay IRQs by one cycle
nextPossibleNmiCycle++;
DONE;
}
}
// -------------------------------------------------------------------------------
// Instruction: BCS
//
// Operation: Branch on C = 1
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::BCS_relative()
{
READ_IMMEDIATE;
if (getC()) {
next = &CPU::BCS_relative_2;
} else {
DONE;
}
}
void CPU::BCS_relative_2()
{
IDLE_READ_IMPLIED;
uint8_t pc_hi = HI_BYTE(PC);
PC += (int8_t)data;
if (pc_hi != HI_BYTE(PC)) {
next = (data & 0x80) ? &CPU::branch_3_underflow : &CPU::branch_3_overflow;
} else {
nextPossibleIrqCycle++; // Delay IRQs by one cycle
nextPossibleNmiCycle++;
DONE;
}
}
// -------------------------------------------------------------------------------
// Instruction: BEQ
//
// Operation: Branch on Z = 1
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::BEQ_relative()
{
READ_IMMEDIATE;
if (getZ()) {
next = &CPU::BEQ_relative_2;
} else {
DONE;
}
}
void CPU::BEQ_relative_2()
{
IDLE_READ_IMPLIED;
uint8_t pc_hi = HI_BYTE(PC);
PC += (int8_t)data;
if (pc_hi != HI_BYTE(PC)) {
next = (data & 0x80) ? &CPU::branch_3_underflow : &CPU::branch_3_overflow;
} else {
nextPossibleIrqCycle++; // Delay IRQs by one cycle
nextPossibleNmiCycle++;
DONE;
}
}
// -------------------------------------------------------------------------------
// Instruction: BIT
//
// Operation: A AND M, N := M7, V := M6
//
// Flags: N Z C I D V
// / / - - - /
// -------------------------------------------------------------------------------
void CPU::BIT_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::BIT_zero_page_2;
}
void CPU::BIT_zero_page_2()
{
READ_FROM_ZERO_PAGE;
setN(data & 128);
setV(data & 64);
setZ((data & A) == 0);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::BIT_absolute()
{
FETCH_ADDR_LO;
next = &CPU::BIT_absolute_2;
}
void CPU::BIT_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::BIT_absolute_3;
}
void CPU::BIT_absolute_3()
{
READ_FROM_ADDRESS;
setN(data & 128);
setV(data & 64);
setZ((data & A) == 0);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: BMI
//
// Operation: Branch on N = 1
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::BMI_relative()
{
READ_IMMEDIATE;
if (getN()) {
next = &CPU::BMI_relative_2;
} else {
DONE;
}
}
void CPU::BMI_relative_2()
{
IDLE_READ_IMPLIED;
uint8_t pc_hi = HI_BYTE(PC);
PC += (int8_t)data;
if (pc_hi != HI_BYTE(PC)) {
next = (data & 0x80) ? &CPU::branch_3_underflow : &CPU::branch_3_overflow;
} else {
nextPossibleIrqCycle++; // Delay IRQs by one cycle
nextPossibleNmiCycle++;
DONE;
}
}
// -------------------------------------------------------------------------------
// Instruction: BNE
//
// Operation: Branch on Z = 0
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::BNE_relative()
{
READ_IMMEDIATE;
if (!getZ()) {
next = &CPU::BNE_relative_2;
} else {
DONE;
}
}
void CPU::BNE_relative_2()
{
IDLE_READ_IMPLIED;
uint8_t pc_hi = HI_BYTE(PC);
PC += (int8_t)data;
if (pc_hi != HI_BYTE(PC)) {
next = (data & 0x80) ? &CPU::branch_3_underflow : &CPU::branch_3_overflow;
} else {
nextPossibleIrqCycle++; // Delay IRQs by one cycle
nextPossibleNmiCycle++;
DONE;
}
}
// -------------------------------------------------------------------------------
// Instruction: BPL
//
// Operation: Branch on N = 0
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::BPL_relative()
{
READ_IMMEDIATE;
if (!getN()) {
next = &CPU::BPL_relative_2;
} else {
DONE;
}
}
void CPU::BPL_relative_2()
{
IDLE_READ_IMPLIED;
uint8_t pc_hi = HI_BYTE(PC);
PC += (int8_t)data;
if (pc_hi != HI_BYTE(PC)) {
next = (data & 0x80) ? &CPU::branch_3_underflow : &CPU::branch_3_overflow;
} else {
nextPossibleIrqCycle++; // Delay IRQs by one cycle
nextPossibleNmiCycle++;
DONE;
}
}
// -------------------------------------------------------------------------------
// Instruction: BRK
//
// Operation: Forced Interrupt (Break)
//
// Flags: N Z C I D V B
// - - - 1 - - 1
// -------------------------------------------------------------------------------
void CPU::BRK()
{
IDLE_READ_IMMEDIATE;
next = &CPU::BRK_2;
}
void CPU::BRK_2()
{
setB(1);
PUSH_PCH;
next = &CPU::BRK_3;
}
void CPU::BRK_3()
{
PUSH_PCL;
// "The official NMOS 65xx documentation claims that the BRK instruction could only cause a jump to the IRQ
// vector ($FFFE). However, if an NMI interrupt occurs while executing a BRK instruction, the processor will
// jump to the NMI vector ($FFFA), and the P register will be pushed on the stack with the B flag set."
if (nmiEdge) {
clearNMIEdge();
next = &CPU::BRK_nmi_4;
} else {
next = &CPU::BRK_4;
}
}
void CPU::BRK_4()
{
PUSH_P;
next = &CPU::BRK_5;
}
void CPU::BRK_5()
{
data = mem->peek(0xFFFE);
next = &CPU::BRK_6;
}
void CPU::BRK_6()
{
setPCL(data);
setPCH(mem->peek(0xFFFF));
setI(1);
// "Ein NMI darf nicht sofort nach einem BRK oder IRQ ausgefhrt werden, sondern erst mit 1 Cycle Delay."
// [http://www.c64-wiki.de/index.php/Micro64]
if (nextPossibleNmiCycle < c64->getCycles() + 2)
nextPossibleNmiCycle = c64->getCycles() + 2;
DONE;
}
void CPU::BRK_nmi_4()
{
PUSH_P;
next = &CPU::BRK_nmi_5;
}
void CPU::BRK_nmi_5()
{
data = mem->peek(0xFFFA);
next = &CPU::BRK_nmi_6;
}
void CPU::BRK_nmi_6()
{
setPCL(data);
setPCH(mem->peek(0xFFFB));
setI(1);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: BVC
//
// Operation: Branch on V = 0
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::BVC_relative()
{
READ_IMMEDIATE;
if (chipModel == MOS6502 /* Drive CPU */ && !c64->floppy->getBitAccuracy()) {
// Special handling for the VC1541 CPU. Taken from Frodo
if (!((c64->floppy->via2.io[12] & 0x0E) == 0x0E || getV())) {
next = &CPU::BVC_relative_2;
} else {
DONE;
}
} else {
// Standard CPU behavior
if (!getV()) {
next = &CPU::BVC_relative_2;
} else {
DONE;
}
}
}
void CPU::BVC_relative_2()
{
IDLE_READ_IMPLIED;
uint8_t pc_hi = HI_BYTE(PC);
PC += (int8_t)data;
if (pc_hi != HI_BYTE(PC)) {
next = (data & 0x80) ? &CPU::branch_3_underflow : &CPU::branch_3_overflow;
} else {
nextPossibleIrqCycle++; // Delay IRQs by one cycle
nextPossibleNmiCycle++;
DONE;
}
}
// -------------------------------------------------------------------------------
// Instruction: BVS
//
// Operation: Branch on V = 1
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::BVS_relative()
{
READ_IMMEDIATE;
if (chipModel == MOS6502 /* Drive CPU */ && !c64->floppy->getBitAccuracy()) {
// Special handling for the VC1541 CPU. Taken from Frodo
if ((c64->floppy->via2.io[12] & 0x0E) == 0x0E || getV()) {
next = &CPU::BVS_relative_2;
} else {
DONE;
}
} else {
// Standard CPU behavior
if (getV()) {
next = &CPU::BVS_relative_2;
} else {
DONE;
}
}
}
void CPU::BVS_relative_2()
{
IDLE_READ_IMPLIED;
uint8_t pc_hi = HI_BYTE(PC);
PC += (int8_t)data;
if (pc_hi != HI_BYTE(PC)) {
next = (data & 0x80) ? &CPU::branch_3_underflow : &CPU::branch_3_overflow;
} else {
nextPossibleIrqCycle++; // Delay IRQs by one cycle
nextPossibleNmiCycle++;
DONE;
}
}
// -------------------------------------------------------------------------------
// Instruction: CLC
//
// Operation: C := 0
//
// Flags: N Z C I D V
// - - 0 - - -
// -------------------------------------------------------------------------------
void CPU::CLC()
{
IDLE_READ_IMPLIED;
setC(0);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: CLD
//
// Operation: D := 0
//
// Flags: N Z C I D V
// - - - - 0 -
// -------------------------------------------------------------------------------
void CPU::CLD()
{
IDLE_READ_IMPLIED;
setD(0);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: CLI
//
// Operation: I := 0
//
// Flags: N Z C I D V
// - - - 0 - -
// -------------------------------------------------------------------------------
void CPU::CLI()
{
IDLE_READ_IMPLIED;
oldI = I;
setI(0);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: CLV
//
// Operation: V := 0
//
// Flags: N Z C I D V
// - - - - - 0
// -------------------------------------------------------------------------------
void CPU::CLV()
{
IDLE_READ_IMPLIED;
setV(0);
/*
if (chipModel == MOS6502) {
if (!c64->floppy->getBitAccuracy()) {
setV(1); // A new byte is always ready
}
}
*/
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: CMP
//
// Operation: A-M
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
inline void CPU::cmp(uint8_t op1, uint8_t op2)
{
uint8_t tmp = op1 - op2;
setC(op1 >= op2);
setN(tmp & 128);
setZ(tmp == 0);
}
// -------------------------------------------------------------------------------
void CPU::CMP_immediate()
{
READ_IMMEDIATE;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CMP_absolute() {
FETCH_ADDR_LO;
next = &CPU::CMP_absolute_2;
}
void CPU::CMP_absolute_2() {
FETCH_ADDR_HI;
next = &CPU::CMP_absolute_3;
}
void CPU::CMP_absolute_3() {
READ_FROM_ADDRESS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CMP_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::CMP_zero_page_2;
}
void CPU::CMP_zero_page_2()
{
READ_FROM_ZERO_PAGE;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CMP_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::CMP_zero_page_x_2;
}
void CPU::CMP_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::CMP_zero_page_x_3;
}
void CPU::CMP_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CMP_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::CMP_absolute_x_2;
}
void CPU::CMP_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::CMP_absolute_x_3;
}
void CPU::CMP_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::CMP_absolute_x_4;
} else {
cmp(A, data);
DONE;
}
}
void CPU::CMP_absolute_x_4()
{
READ_FROM_ADDRESS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CMP_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::CMP_absolute_y_2;
}
void CPU::CMP_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::CMP_absolute_y_3;
}
void CPU::CMP_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::CMP_absolute_y_4;
} else {
cmp(A, data);
DONE;
}
}
void CPU::CMP_absolute_y_4()
{
READ_FROM_ADDRESS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CMP_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::CMP_indirect_x_2;
}
void CPU::CMP_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::CMP_indirect_x_3;
}
void CPU::CMP_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::CMP_indirect_x_4;
}
void CPU::CMP_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::CMP_indirect_x_5;
}
void CPU::CMP_indirect_x_5()
{
READ_FROM_ADDRESS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CMP_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::CMP_indirect_y_2;
}
void CPU::CMP_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::CMP_indirect_y_3;
}
void CPU::CMP_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::CMP_indirect_y_4;
}
void CPU::CMP_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::CMP_indirect_y_5;
} else {
cmp(A, data);
DONE;
}
}
void CPU::CMP_indirect_y_5()
{
READ_FROM_ADDRESS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: CPX
//
// Operation: X-M
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
void CPU::CPX_immediate()
{
READ_IMMEDIATE;
cmp(X, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CPX_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::CPX_zero_page_2;
}
void CPU::CPX_zero_page_2()
{
READ_FROM_ZERO_PAGE;
cmp(X, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CPX_absolute() {
FETCH_ADDR_LO;
next = &CPU::CPX_absolute_2;
}
void CPU::CPX_absolute_2() {
FETCH_ADDR_HI;
next = &CPU::CPX_absolute_3;
}
void CPU::CPX_absolute_3() {
READ_FROM_ADDRESS;
cmp(X, data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: CPY
//
// Operation: Y-M
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
void CPU::CPY_immediate()
{
READ_IMMEDIATE;
cmp(Y, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CPY_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::CPY_zero_page_2;
}
void CPU::CPY_zero_page_2()
{
READ_FROM_ZERO_PAGE;
cmp(Y, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::CPY_absolute() {
FETCH_ADDR_LO;
next = &CPU::CPY_absolute_2;
}
void CPU::CPY_absolute_2() {
FETCH_ADDR_HI;
next = &CPU::CPY_absolute_3;
}
void CPU::CPY_absolute_3() {
READ_FROM_ADDRESS;
cmp(Y, data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: DEC
//
// Operation: M := : M - 1
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
#define DO_DEC data--;
// -------------------------------------------------------------------------------
void CPU::DEC_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::DEC_zero_page_2;
}
void CPU::DEC_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::DEC_zero_page_3;
}
void CPU::DEC_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_DEC;
next = &CPU::DEC_zero_page_4;
}
void CPU::DEC_zero_page_4()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::DEC_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::DEC_zero_page_x_2;
}
void CPU::DEC_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::DEC_zero_page_x_3;
}
void CPU::DEC_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::DEC_zero_page_x_4;
}
void CPU::DEC_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_DEC;
next = &CPU::DEC_zero_page_x_5;
}
void CPU::DEC_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::DEC_absolute()
{
FETCH_ADDR_LO;
next = &CPU::DEC_absolute_2;
}
void CPU::DEC_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::DEC_absolute_3;
}
void CPU::DEC_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::DEC_absolute_4;
}
void CPU::DEC_absolute_4()
{
WRITE_TO_ADDRESS;
DO_DEC;
next = &CPU::DEC_absolute_5;
}
void CPU::DEC_absolute_5()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::DEC_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::DEC_absolute_x_2;
}
void CPU::DEC_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::DEC_absolute_x_3;
}
void CPU::DEC_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::DEC_absolute_x_4;
}
void CPU::DEC_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::DEC_absolute_x_5;
}
void CPU::DEC_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_DEC;
next = &CPU::DEC_absolute_x_6;
}
void CPU::DEC_absolute_x_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::DEC_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::DEC_indirect_x_2;
}
void CPU::DEC_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::DEC_indirect_x_3;
}
void CPU::DEC_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::DEC_indirect_x_4;
}
void CPU::DEC_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::DEC_indirect_x_5;
}
void CPU::DEC_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::DEC_indirect_x_6;
}
void CPU::DEC_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_DEC;
next = &CPU::DEC_indirect_x_7;
}
void CPU::DEC_indirect_x_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: DEX
//
// Operation: X := X - 1
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::DEX()
{
IDLE_READ_IMPLIED;
loadX(getX()-1);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: DEY
//
// Operation: Y := Y - 1
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::DEY()
{
IDLE_READ_IMPLIED;
loadY(getY()-1);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: EOR
//
// Operation: A := A XOR M
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::EOR_immediate()
{
READ_IMMEDIATE;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::EOR_absolute() {
FETCH_ADDR_LO;
next = &CPU::EOR_absolute_2;
}
void CPU::EOR_absolute_2() {
FETCH_ADDR_HI;
next = &CPU::EOR_absolute_3;
}
void CPU::EOR_absolute_3() {
READ_FROM_ADDRESS;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::EOR_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::EOR_zero_page_2;
}
void CPU::EOR_zero_page_2()
{
READ_FROM_ZERO_PAGE;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::EOR_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::EOR_zero_page_x_2;
}
void CPU::EOR_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::EOR_zero_page_x_3;
}
void CPU::EOR_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::EOR_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::EOR_absolute_x_2;
}
void CPU::EOR_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::EOR_absolute_x_3;
}
void CPU::EOR_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::EOR_absolute_x_4;
} else {
loadA(A ^ data);
DONE;
}
}
void CPU::EOR_absolute_x_4()
{
READ_FROM_ADDRESS;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::EOR_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::EOR_absolute_y_2;
}
void CPU::EOR_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::EOR_absolute_y_3;
}
void CPU::EOR_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::EOR_absolute_y_4;
} else {
loadA(A ^ data);
DONE;
}
}
void CPU::EOR_absolute_y_4()
{
READ_FROM_ADDRESS;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::EOR_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::EOR_indirect_x_2;
}
void CPU::EOR_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::EOR_indirect_x_3;
}
void CPU::EOR_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::EOR_indirect_x_4;
}
void CPU::EOR_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::EOR_indirect_x_5;
}
void CPU::EOR_indirect_x_5()
{
READ_FROM_ADDRESS;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::EOR_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::EOR_indirect_y_2;
}
void CPU::EOR_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::EOR_indirect_y_3;
}
void CPU::EOR_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::EOR_indirect_y_4;
}
void CPU::EOR_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::EOR_indirect_y_5;
} else {
loadA(A ^ data);
DONE;
}
}
void CPU::EOR_indirect_y_5()
{
READ_FROM_ADDRESS;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: INC
//
// Operation: M := M + 1
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
#define DO_INC data++;
// -------------------------------------------------------------------------------
void CPU::INC_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::INC_zero_page_2;
}
void CPU::INC_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::INC_zero_page_3;
}
void CPU::INC_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_INC;
next = &CPU::INC_zero_page_4;
}
void CPU::INC_zero_page_4()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::INC_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::INC_zero_page_x_2;
}
void CPU::INC_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::INC_zero_page_x_3;
}
void CPU::INC_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::INC_zero_page_x_4;
}
void CPU::INC_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_INC;
next = &CPU::INC_zero_page_x_5;
}
void CPU::INC_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::INC_absolute()
{
FETCH_ADDR_LO;
next = &CPU::INC_absolute_2;
}
void CPU::INC_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::INC_absolute_3;
}
void CPU::INC_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::INC_absolute_4;
}
void CPU::INC_absolute_4()
{
WRITE_TO_ADDRESS;
DO_INC;
next = &CPU::INC_absolute_5;
}
void CPU::INC_absolute_5()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::INC_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::INC_absolute_x_2;
}
void CPU::INC_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::INC_absolute_x_3;
}
void CPU::INC_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::INC_absolute_x_4;
}
void CPU::INC_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::INC_absolute_x_5;
}
void CPU::INC_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_INC;
next = &CPU::INC_absolute_x_6;
}
void CPU::INC_absolute_x_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::INC_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::INC_indirect_x_2;
}
void CPU::INC_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::INC_indirect_x_3;
}
void CPU::INC_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::INC_indirect_x_4;
}
void CPU::INC_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::INC_indirect_x_5;
}
void CPU::INC_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::INC_indirect_x_6;
}
void CPU::INC_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_INC;
next = &CPU::INC_indirect_x_7;
}
void CPU::INC_indirect_x_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: INX
//
// Operation: X := X + 1
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::INX()
{
IDLE_READ_IMPLIED;
loadX(getX()+1);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: INY
//
// Operation: Y := Y + 1
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::INY()
{
IDLE_READ_IMPLIED;
loadY(getY()+1);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: JMP
//
// Operation: PC := Operand
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::JMP_absolute()
{
FETCH_ADDR_LO;
next = &CPU::JMP_absolute_2;
}
void CPU::JMP_absolute_2()
{
FETCH_ADDR_HI;
setPC(LO_HI(addr_lo, addr_hi));
DONE;
}
// -------------------------------------------------------------------------------
void CPU::JMP_absolute_indirect()
{
FETCH_ADDR_LO;
next = &CPU::JMP_absolute_indirect_2;
}
void CPU::JMP_absolute_indirect_2()
{
FETCH_ADDR_HI;
next = &CPU::JMP_absolute_indirect_3;
}
void CPU::JMP_absolute_indirect_3()
{
READ_FROM_ADDRESS;
next = &CPU::JMP_absolute_indirect_4;
}
void CPU::JMP_absolute_indirect_4()
{
setPCL(data);
setPCH(mem->peek(addr_lo+1, addr_hi));
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: JSR
//
// Operation: PC to stack, PC := Operand
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::JSR()
{
FETCH_ADDR_LO;
callStack[callStackPointer++] = PC;
next = &CPU::JSR_2;
}
void CPU::JSR_2()
{
next = &CPU::JSR_3;
}
void CPU::JSR_3()
{
PUSH_PCH;
next = &CPU::JSR_4;
}
void CPU::JSR_4()
{
PUSH_PCL;
next = &CPU::JSR_5;
}
void CPU::JSR_5()
{
FETCH_ADDR_HI;
setPC(LO_HI(addr_lo, addr_hi));
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: LDA
//
// Operation: A := M
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
void CPU::LDA_immediate()
{
READ_IMMEDIATE;
loadA(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDA_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::LDA_zero_page_2;
}
void CPU::LDA_zero_page_2()
{
READ_FROM_ZERO_PAGE;
loadA(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDA_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::LDA_zero_page_x_2;
}
void CPU::LDA_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::LDA_zero_page_x_3;
}
void CPU::LDA_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
loadA(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDA_absolute()
{
FETCH_ADDR_LO;
next = &CPU::LDA_absolute_2;
}
void CPU::LDA_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::LDA_absolute_3;
}
void CPU::LDA_absolute_3()
{
READ_FROM_ADDRESS;
loadA(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDA_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::LDA_absolute_x_2;
}
void CPU::LDA_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::LDA_absolute_x_3;
}
void CPU::LDA_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::LDA_absolute_x_4;
} else {
loadA(data);
DONE;
}
}
void CPU::LDA_absolute_x_4()
{
READ_FROM_ADDRESS;
loadA(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDA_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::LDA_absolute_y_2;
}
void CPU::LDA_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::LDA_absolute_y_3;
}
void CPU::LDA_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::LDA_absolute_y_4;
} else {
loadA(data);
DONE;
}
}
void CPU::LDA_absolute_y_4()
{
READ_FROM_ADDRESS;
loadA(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDA_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::LDA_indirect_x_2;
}
void CPU::LDA_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::LDA_indirect_x_3;
}
void CPU::LDA_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::LDA_indirect_x_4;
}
void CPU::LDA_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::LDA_indirect_x_5;
}
void CPU::LDA_indirect_x_5()
{
READ_FROM_ADDRESS;
loadA(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDA_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::LDA_indirect_y_2;
}
void CPU::LDA_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::LDA_indirect_y_3;
}
void CPU::LDA_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::LDA_indirect_y_4;
}
void CPU::LDA_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::LDA_indirect_y_5;
} else {
loadA(data);
DONE;
}
}
void CPU::LDA_indirect_y_5()
{
READ_FROM_ADDRESS;
loadA(data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: LDX
//
// Operation: X := M
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
void CPU::LDX_immediate()
{
READ_IMMEDIATE;
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDX_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::LDX_zero_page_2;
}
void CPU::LDX_zero_page_2()
{
READ_FROM_ZERO_PAGE;
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDX_zero_page_y()
{
FETCH_ADDR_LO;
next = &CPU::LDX_zero_page_y_2;
}
void CPU::LDX_zero_page_y_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_Y;
next = &CPU::LDX_zero_page_y_3;
}
void CPU::LDX_zero_page_y_3()
{
READ_FROM_ZERO_PAGE;
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDX_absolute()
{
FETCH_ADDR_LO;
next = &CPU::LDX_absolute_2;
}
void CPU::LDX_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::LDX_absolute_3;
}
void CPU::LDX_absolute_3()
{
READ_FROM_ADDRESS;
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDX_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::LDX_absolute_y_2;
}
void CPU::LDX_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::LDX_absolute_y_3;
}
void CPU::LDX_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::LDX_absolute_y_4;
} else {
loadX(data);
DONE;
}
}
void CPU::LDX_absolute_y_4()
{
READ_FROM_ADDRESS;
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDX_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::LDX_indirect_x_2;
}
void CPU::LDX_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::LDX_indirect_x_3;
}
void CPU::LDX_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::LDX_indirect_x_4;
}
void CPU::LDX_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::LDX_indirect_x_5;
}
void CPU::LDX_indirect_x_5()
{
READ_FROM_ADDRESS;
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDX_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::LDX_indirect_y_2;
}
void CPU::LDX_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::LDX_indirect_y_3;
}
void CPU::LDX_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::LDX_indirect_y_4;
}
void CPU::LDX_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::LDX_indirect_y_5;
} else {
loadX(data);
DONE;
}
}
void CPU::LDX_indirect_y_5()
{
READ_FROM_ADDRESS;
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: LDY
//
// Operation: Y := M
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
void CPU::LDY_immediate()
{
READ_IMMEDIATE;
loadY(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDY_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::LDY_zero_page_2;
}
void CPU::LDY_zero_page_2()
{
READ_FROM_ZERO_PAGE;
loadY(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDY_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::LDY_zero_page_x_2;
}
void CPU::LDY_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::LDY_zero_page_x_3;
}
void CPU::LDY_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
loadY(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDY_absolute()
{
FETCH_ADDR_LO;
next = &CPU::LDY_absolute_2;
}
void CPU::LDY_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::LDY_absolute_3;
}
void CPU::LDY_absolute_3()
{
READ_FROM_ADDRESS;
loadY(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDY_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::LDY_absolute_x_2;
}
void CPU::LDY_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::LDY_absolute_x_3;
}
void CPU::LDY_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::LDY_absolute_x_4;
} else {
loadY(data);
DONE;
}
}
void CPU::LDY_absolute_x_4()
{
READ_FROM_ADDRESS;
loadY(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDY_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::LDY_indirect_x_2;
}
void CPU::LDY_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::LDY_indirect_x_3;
}
void CPU::LDY_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::LDY_indirect_x_4;
}
void CPU::LDY_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::LDY_indirect_x_5;
}
void CPU::LDY_indirect_x_5()
{
READ_FROM_ADDRESS;
loadY(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LDY_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::LDY_indirect_y_2;
}
void CPU::LDY_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::LDY_indirect_y_3;
}
void CPU::LDY_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::LDY_indirect_y_4;
}
void CPU::LDY_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::LDY_indirect_y_5;
} else {
loadY(data);
DONE;
}
}
void CPU::LDY_indirect_y_5()
{
READ_FROM_ADDRESS;
loadY(data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: LSR
//
// Operation: 0 -> (A|M >> 1) -> C
//
// Flags: N Z C I D V
// 0 / / - - -
// -------------------------------------------------------------------------------
#define DO_LSR setC(data & 1); data = data >> 1;
// -------------------------------------------------------------------------------
void CPU::LSR_accumulator()
{
IDLE_READ_IMPLIED;
setC(A & 1); loadA(A >> 1);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LSR_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::LSR_zero_page_2;
}
void CPU::LSR_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::LSR_zero_page_3;
}
void CPU::LSR_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_LSR;
next = &CPU::LSR_zero_page_4;
}
void CPU::LSR_zero_page_4()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LSR_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::LSR_zero_page_x_2;
}
void CPU::LSR_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::LSR_zero_page_x_3;
}
void CPU::LSR_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::LSR_zero_page_x_4;
}
void CPU::LSR_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_LSR;
next = &CPU::LSR_zero_page_x_5;
}
void CPU::LSR_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LSR_absolute()
{
FETCH_ADDR_LO;
next = &CPU::LSR_absolute_2;
}
void CPU::LSR_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::LSR_absolute_3;
}
void CPU::LSR_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::LSR_absolute_4;
}
void CPU::LSR_absolute_4()
{
WRITE_TO_ADDRESS;
DO_LSR;
next = &CPU::LSR_absolute_5;
}
void CPU::LSR_absolute_5()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LSR_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::LSR_absolute_x_2;
}
void CPU::LSR_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::LSR_absolute_x_3;
}
void CPU::LSR_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::LSR_absolute_x_4;
}
void CPU::LSR_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::LSR_absolute_x_5;
}
void CPU::LSR_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_LSR;
next = &CPU::LSR_absolute_x_6;
}
void CPU::LSR_absolute_x_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LSR_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::LSR_absolute_y_2;
}
void CPU::LSR_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::LSR_absolute_y_3;
}
void CPU::LSR_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::LSR_absolute_y_4;
}
void CPU::LSR_absolute_y_4()
{
READ_FROM_ADDRESS;
next = &CPU::LSR_absolute_y_5;
}
void CPU::LSR_absolute_y_5()
{
WRITE_TO_ADDRESS;
DO_LSR;
next = &CPU::LSR_absolute_y_6;
}
void CPU::LSR_absolute_y_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LSR_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::LSR_indirect_x_2;
}
void CPU::LSR_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::LSR_indirect_x_3;
}
void CPU::LSR_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::LSR_indirect_x_4;
}
void CPU::LSR_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::LSR_indirect_x_5;
}
void CPU::LSR_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::LSR_indirect_x_6;
}
void CPU::LSR_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_LSR;
next = &CPU::LSR_indirect_x_7;
}
void CPU::LSR_indirect_x_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LSR_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::LSR_indirect_y_2;
}
void CPU::LSR_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::LSR_indirect_y_3;
}
void CPU::LSR_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::LSR_indirect_y_4;
}
void CPU::LSR_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::LSR_indirect_y_5;
}
void CPU::LSR_indirect_y_5()
{
READ_FROM_ADDRESS;
next = &CPU::LSR_indirect_y_6;
}
void CPU::LSR_indirect_y_6()
{
WRITE_TO_ADDRESS;
DO_LSR;
next = &CPU::LSR_indirect_y_7;
}
void CPU::LSR_indirect_y_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: NOP
//
// Operation: No operation
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::NOP()
{
IDLE_READ_IMPLIED;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::NOP_immediate()
{
IDLE_READ_IMMEDIATE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::NOP_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::NOP_zero_page_2;
}
void CPU::NOP_zero_page_2()
{
READ_FROM_ZERO_PAGE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::NOP_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::NOP_zero_page_x_2;
}
void CPU::NOP_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::NOP_zero_page_x_3;
}
void CPU::NOP_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::NOP_absolute()
{
FETCH_ADDR_LO;
next = &CPU::NOP_absolute_2;
}
void CPU::NOP_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::NOP_absolute_3;
}
void CPU::NOP_absolute_3()
{
READ_FROM_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::NOP_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::NOP_absolute_x_2;
}
void CPU::NOP_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::NOP_absolute_x_3;
}
void CPU::NOP_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::NOP_absolute_x_4;
} else {
DONE;
}
}
void CPU::NOP_absolute_x_4()
{
READ_FROM_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: A := A v M
//
// Operation: No operation
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::ORA_immediate()
{
READ_IMMEDIATE;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ORA_absolute() {
FETCH_ADDR_LO;
next = &CPU::ORA_absolute_2;
}
void CPU::ORA_absolute_2() {
FETCH_ADDR_HI;
next = &CPU::ORA_absolute_3;
}
void CPU::ORA_absolute_3() {
READ_FROM_ADDRESS;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ORA_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::ORA_zero_page_2;
}
void CPU::ORA_zero_page_2()
{
READ_FROM_ZERO_PAGE;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ORA_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::ORA_zero_page_x_2;
}
void CPU::ORA_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::ORA_zero_page_x_3;
}
void CPU::ORA_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ORA_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::ORA_absolute_x_2;
}
void CPU::ORA_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::ORA_absolute_x_3;
}
void CPU::ORA_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::ORA_absolute_x_4;
} else {
loadA(A | data);
DONE;
}
}
void CPU::ORA_absolute_x_4()
{
READ_FROM_ADDRESS;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ORA_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::ORA_absolute_y_2;
}
void CPU::ORA_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::ORA_absolute_y_3;
}
void CPU::ORA_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::ORA_absolute_y_4;
} else {
loadA(A | data);
DONE;
}
}
void CPU::ORA_absolute_y_4()
{
READ_FROM_ADDRESS;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ORA_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::ORA_indirect_x_2;
}
void CPU::ORA_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::ORA_indirect_x_3;
}
void CPU::ORA_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::ORA_indirect_x_4;
}
void CPU::ORA_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::ORA_indirect_x_5;
}
void CPU::ORA_indirect_x_5()
{
READ_FROM_ADDRESS;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ORA_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::ORA_indirect_y_2;
}
void CPU::ORA_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::ORA_indirect_y_3;
}
void CPU::ORA_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::ORA_indirect_y_4;
}
void CPU::ORA_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::ORA_indirect_y_5;
} else {
loadA(A | data);
DONE;
}
}
void CPU::ORA_indirect_y_5()
{
READ_FROM_ADDRESS;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: PHA
//
// Operation: A to stack
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::PHA()
{
IDLE_READ_IMPLIED;
next = &CPU::PHA_2;
}
void CPU::PHA_2()
{
PUSH_A;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: PHA
//
// Operation: P to stack
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::PHP()
{
IDLE_READ_IMPLIED;
next = &CPU::PHP_2;
}
void CPU::PHP_2()
{
PUSH_P;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: PLA
//
// Operation: Stack to A
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::PLA()
{
IDLE_READ_IMPLIED;
next = &CPU::PLA_2;
}
void CPU::PLA_2()
{
SP++;
next = &CPU::PLA_3;
}
void CPU::PLA_3()
{
PULL_A;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: PLP
//
// Operation: Stack to p
//
// Flags: N Z C I D V
// / / / / / /
// -------------------------------------------------------------------------------
void CPU::PLP()
{
IDLE_READ_IMPLIED;
next = &CPU::PLP_2;
}
void CPU::PLP_2()
{
SP++;
next = &CPU::PLP_3;
}
void CPU::PLP_3()
{
PULL_P;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: ROL
//
// -----------------------
// | |
// Operation: ---(A|M << 1) <- C <---
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
inline uint8_t CPU::rol(uint8_t op)
{
uint8_t bit8 = (op & 128);
uint8_t shifted = (op << 1) + (getC() ? 1 : 0);
setC(bit8);
return shifted;
}
#define DO_ROL if (getC()) { setC(data & 128); data = (data << 1) + 1; } else { setC(data & 128); data = (data << 1); }
// -------------------------------------------------------------------------------
void CPU::ROL_accumulator()
{
IDLE_READ_IMPLIED;
if (getC()) {
setC(A & 128);
loadA((A << 1) + 1);
} else {
setC(A & 128);
loadA(A << 1);
}
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ROL_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::ROL_zero_page_2;
}
void CPU::ROL_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::ROL_zero_page_3;
}
void CPU::ROL_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_ROL;
next = &CPU::ROL_zero_page_4;
}
void CPU::ROL_zero_page_4()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ROL_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::ROL_zero_page_x_2;
}
void CPU::ROL_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::ROL_zero_page_x_3;
}
void CPU::ROL_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::ROL_zero_page_x_4;
}
void CPU::ROL_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_ROL;
next = &CPU::ROL_zero_page_x_5;
}
void CPU::ROL_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ROL_absolute()
{
FETCH_ADDR_LO;
next = &CPU::ROL_absolute_2;
}
void CPU::ROL_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::ROL_absolute_3;
}
void CPU::ROL_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::ROL_absolute_4;
}
void CPU::ROL_absolute_4()
{
WRITE_TO_ADDRESS;
DO_ROL;
next = &CPU::ROL_absolute_5;
}
void CPU::ROL_absolute_5()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ROL_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::ROL_absolute_x_2;
}
void CPU::ROL_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::ROL_absolute_x_3;
}
void CPU::ROL_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::ROL_absolute_x_4;
}
void CPU::ROL_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::ROL_absolute_x_5;
}
void CPU::ROL_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_ROL;
next = &CPU::ROL_absolute_x_6;
}
void CPU::ROL_absolute_x_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ROL_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::ROL_indirect_x_2;
}
void CPU::ROL_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::ROL_indirect_x_3;
}
void CPU::ROL_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::ROL_indirect_x_4;
}
void CPU::ROL_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::ROL_indirect_x_5;
}
void CPU::ROL_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::ROL_indirect_x_6;
}
void CPU::ROL_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_ROL;
next = &CPU::ROL_indirect_x_7;
}
void CPU::ROL_indirect_x_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: ROR
//
// -----------------------
// | |
// Operation: --->(A|M >> 1) -> C ---
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
inline uint8_t CPU::ror(uint8_t op)
{
uint8_t bit1 = (op & 1);
uint8_t shifted = (op >> 1) + (getC() ? 128 : 0);
setC(bit1);
return shifted;
}
#define DO_ROR if (getC()) { setC(data & 1); data = (data >> 1) + 128; } else { setC(data & 1); data = (data >> 1); }
// -------------------------------------------------------------------------------
void CPU::ROR_accumulator()
{
IDLE_READ_IMPLIED;
if (getC()) {
setC(A & 1);
loadA((A >> 1) + 128);
} else {
setC(A & 1);
loadA(A >> 1);
}
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ROR_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::ROR_zero_page_2;
}
void CPU::ROR_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::ROR_zero_page_3;
}
void CPU::ROR_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_ROR;
next = &CPU::ROR_zero_page_4;
}
void CPU::ROR_zero_page_4()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ROR_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::ROR_zero_page_x_2;
}
void CPU::ROR_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::ROR_zero_page_x_3;
}
void CPU::ROR_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::ROR_zero_page_x_4;
}
void CPU::ROR_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_ROR;
next = &CPU::ROR_zero_page_x_5;
}
void CPU::ROR_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ROR_absolute()
{
FETCH_ADDR_LO;
next = &CPU::ROR_absolute_2;
}
void CPU::ROR_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::ROR_absolute_3;
}
void CPU::ROR_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::ROR_absolute_4;
}
void CPU::ROR_absolute_4()
{
WRITE_TO_ADDRESS;
DO_ROR;
next = &CPU::ROR_absolute_5;
}
void CPU::ROR_absolute_5()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ROR_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::ROR_absolute_x_2;
}
void CPU::ROR_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::ROR_absolute_x_3;
}
void CPU::ROR_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::ROR_absolute_x_4;
}
void CPU::ROR_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::ROR_absolute_x_5;
}
void CPU::ROR_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_ROR;
next = &CPU::ROR_absolute_x_6;
}
void CPU::ROR_absolute_x_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ROR_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::ROR_indirect_x_2;
}
void CPU::ROR_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::ROR_indirect_x_3;
}
void CPU::ROR_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::ROR_indirect_x_4;
}
void CPU::ROR_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::ROR_indirect_x_5;
}
void CPU::ROR_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::ROR_indirect_x_6;
}
void CPU::ROR_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_ROR;
next = &CPU::ROR_indirect_x_7;
}
void CPU::ROR_indirect_x_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: RTI
//
// Operation: P from Stack, PC from Stack
//
// Flags: N Z C I D V
// / / / / / /
// -------------------------------------------------------------------------------
void CPU::RTI()
{
IDLE_READ_IMMEDIATE;
next = &CPU::RTI_2;
}
void CPU::RTI_2()
{
SP++;
next = &CPU::RTI_3;
}
void CPU::RTI_3()
{
PULL_P;
SP++;
next = &CPU::RTI_4;
}
void CPU::RTI_4()
{
PULL_PCL;
SP++;
next = &CPU::RTI_5;
}
void CPU::RTI_5()
{
PULL_PCH;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: RTS
//
// Operation: PC from Stack
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::RTS()
{
IDLE_READ_IMMEDIATE;
next = &CPU::RTS_2;
}
void CPU::RTS_2()
{
SP++;
next = &CPU::RTS_3;
}
void CPU::RTS_3()
{
PULL_PCL;
SP++;
next = &CPU::RTS_4;
}
void CPU::RTS_4()
{
PULL_PCH;
next = &CPU::RTS_5;
}
void CPU::RTS_5()
{
PC++;
callStackPointer--;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: SBC
//
// Operation: A := A - M - (~C)
//
// Flags: N Z C I D V
// / / / - - /
// -------------------------------------------------------------------------------
inline void CPU::sbc(uint8_t op)
{
if (getD())
sbc_bcd(op);
else
sbc_binary(op);
}
inline void CPU::sbc_binary(uint8_t op)
{
uint16_t sum = A - op - (getC() ? 0 : 1);
setC(sum <= 255);
setV(((A ^ sum) & 0x80) && ((A ^ op) & 0x80));
loadA((uint8_t)sum);
}
inline void CPU::sbc_bcd(uint8_t op)
{
uint16_t sum = A - op - (getC() ? 0 : 1);
uint8_t highDigit = (A >> 4) - (op >> 4);
uint8_t lowDigit = (A & 0x0F) - (op & 0x0F) - (getC() ? 0 : 1);
// Check for underflow conditions
// If an overflow occurs on a BCD digit, it needs to be fixed by subtracting the pseudo-tetrade 0110 (=6)
if (lowDigit & 0x10) {
lowDigit = lowDigit - 6;
highDigit--;
}
if (highDigit & 0x10) {
highDigit = highDigit - 6;
}
setC(sum < 0x100);
setV(((A ^ sum) & 0x80) && ((A ^ op) & 0x80));
setZ((sum & 0xFF) == 0);
setN(sum & 0x80);
A = (uint8_t)((highDigit << 4) | (lowDigit & 0x0f));
}
// -------------------------------------------------------------------------------
void CPU::SBC_immediate()
{
READ_IMMEDIATE;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SBC_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::SBC_zero_page_2;
}
void CPU::SBC_zero_page_2()
{
READ_FROM_ZERO_PAGE;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SBC_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::SBC_zero_page_x_2;
}
void CPU::SBC_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::SBC_zero_page_x_3;
}
void CPU::SBC_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SBC_absolute()
{
FETCH_ADDR_LO;
next = &CPU::SBC_absolute_2;
}
void CPU::SBC_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::SBC_absolute_3;
}
void CPU::SBC_absolute_3()
{
READ_FROM_ADDRESS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SBC_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::SBC_absolute_x_2;
}
void CPU::SBC_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::SBC_absolute_x_3;
}
void CPU::SBC_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::SBC_absolute_x_4;
} else {
sbc(data);
DONE;
}
}
void CPU::SBC_absolute_x_4()
{
READ_FROM_ADDRESS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SBC_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::SBC_absolute_y_2;
}
void CPU::SBC_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::SBC_absolute_y_3;
}
void CPU::SBC_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::SBC_absolute_y_4;
} else {
sbc(data);
DONE;
}
}
void CPU::SBC_absolute_y_4()
{
READ_FROM_ADDRESS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SBC_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::SBC_indirect_x_2;
}
void CPU::SBC_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::SBC_indirect_x_3;
}
void CPU::SBC_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::SBC_indirect_x_4;
}
void CPU::SBC_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::SBC_indirect_x_5;
}
void CPU::SBC_indirect_x_5()
{
READ_FROM_ADDRESS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SBC_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::SBC_indirect_y_2;
}
void CPU::SBC_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::SBC_indirect_y_3;
}
void CPU::SBC_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::SBC_indirect_y_4;
}
void CPU::SBC_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::SBC_indirect_y_5;
} else {
sbc(data);
DONE;
}
}
void CPU::SBC_indirect_y_5()
{
READ_FROM_ADDRESS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: SEC
//
// Operation: C := 1
//
// Flags: N Z C I D V
// - - 1 - - -
// -------------------------------------------------------------------------------
void CPU::SEC()
{
IDLE_READ_IMPLIED;
setC(1);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: SED
//
// Operation: D := 1
//
// Flags: N Z C I D V
// - - - - 1 -
// -------------------------------------------------------------------------------
void CPU::SED()
{
IDLE_READ_IMPLIED;
setD(1);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: SEI
//
// Operation: D := 1
//
// Flags: N Z C I D V
// - - - 1 - -
// -------------------------------------------------------------------------------
void CPU::SEI()
{
IDLE_READ_IMPLIED;
oldI = I;
setI(1);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: STA
//
// Operation: M := A
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::STA_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::STA_zero_page_2;
}
void CPU::STA_zero_page_2()
{
data = A;
WRITE_TO_ZERO_PAGE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::STA_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::STA_zero_page_x_2;
}
void CPU::STA_zero_page_x_2()
{
IDLE_READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::STA_zero_page_x_3;
}
void CPU::STA_zero_page_x_3()
{
data = A;
WRITE_TO_ZERO_PAGE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::STA_absolute()
{
FETCH_ADDR_LO;
next = &CPU::STA_absolute_2;
}
void CPU::STA_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::STA_absolute_3;
}
void CPU::STA_absolute_3()
{
data = A;
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::STA_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::STA_absolute_x_2;
}
void CPU::STA_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::STA_absolute_x_3;
}
void CPU::STA_absolute_x_3()
{
IDLE_READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::STA_absolute_x_4;
}
void CPU::STA_absolute_x_4()
{
data = A;
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::STA_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::STA_absolute_y_2;
}
void CPU::STA_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::STA_absolute_y_3;
}
void CPU::STA_absolute_y_3()
{
IDLE_READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::STA_absolute_y_4;
}
void CPU::STA_absolute_y_4()
{
data = A;
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::STA_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::STA_indirect_x_2;
}
void CPU::STA_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::STA_indirect_x_3;
}
void CPU::STA_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::STA_indirect_x_4;
}
void CPU::STA_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::STA_indirect_x_5;
}
void CPU::STA_indirect_x_5()
{
data = A;
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::STA_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::STA_indirect_y_2;
}
void CPU::STA_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::STA_indirect_y_3;
}
void CPU::STA_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::STA_indirect_y_4;
}
void CPU::STA_indirect_y_4()
{
IDLE_READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::STA_indirect_y_5;
}
void CPU::STA_indirect_y_5()
{
data = A;
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: STX
//
// Operation: M := X
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::STX_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::STX_zero_page_2;
}
void CPU::STX_zero_page_2()
{
data = X;
WRITE_TO_ZERO_PAGE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::STX_zero_page_y()
{
FETCH_ADDR_LO;
next = &CPU::STX_zero_page_y_2;
}
void CPU::STX_zero_page_y_2()
{
IDLE_READ_FROM_ZERO_PAGE;
ADD_INDEX_Y;
next = &CPU::STX_zero_page_y_3;
}
void CPU::STX_zero_page_y_3()
{
data = X;
WRITE_TO_ZERO_PAGE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::STX_absolute()
{
FETCH_ADDR_LO;
next = &CPU::STX_absolute_2;
}
void CPU::STX_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::STX_absolute_3;
}
void CPU::STX_absolute_3()
{
data = X;
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: STY
//
// Operation: M := Y
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::STY_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::STY_zero_page_2;
}
void CPU::STY_zero_page_2()
{
data = Y;
WRITE_TO_ZERO_PAGE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::STY_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::STY_zero_page_x_2;
}
void CPU::STY_zero_page_x_2()
{
IDLE_READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::STY_zero_page_x_3;
}
void CPU::STY_zero_page_x_3()
{
data = Y;
WRITE_TO_ZERO_PAGE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::STY_absolute()
{
FETCH_ADDR_LO;
next = &CPU::STY_absolute_2;
}
void CPU::STY_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::STY_absolute_3;
}
void CPU::STY_absolute_3()
{
data = Y;
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: TAX
//
// Operation: X := A
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::TAX()
{
IDLE_READ_IMPLIED;
loadX(A);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: TAY
//
// Operation: Y := A
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::TAY()
{
IDLE_READ_IMPLIED;
loadY(A);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: TSX
//
// Operation: X := Stack pointer
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::TSX()
{
IDLE_READ_IMPLIED;
loadX(SP);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: TXA
//
// Operation: A := X
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::TXA()
{
IDLE_READ_IMPLIED;
loadA(X);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: TXS
//
// Operation: Stack pointer := X
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::TXS()
{
IDLE_READ_IMPLIED;
SP = X;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: TYA
//
// Operation: A := Y
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::TYA()
{
IDLE_READ_IMPLIED;
loadA(Y);
DONE;
}
// -------------------------------------------------------------------------------
// Illegal instructions
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
// Instruction: ALR
//
// Operation: AND, followed by LSR
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
void CPU::ALR_immediate()
{
READ_IMMEDIATE;
A = A & data;
setC(A & 1);
loadA(A >> 1);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: ANC
//
// Operation: A := A & op, N flag is copied to C
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
void CPU::ANC_immediate()
{
READ_IMMEDIATE;
loadA(A & data);
setC(getN());
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: ARR
//
// Operation: AND, followed by ROR
//
// Flags: N Z C I D V
// / / / - - /
// -------------------------------------------------------------------------------
void CPU::ARR_immediate()
{
READ_IMMEDIATE;
uint8_t tmp2 = A & data;
// Taken from Frodo...
A = (getC() ? (tmp2 >> 1) | 0x80 : tmp2 >> 1);
if (!getD()) {
setN(A & 0x80);
setZ(A == 0);
setC(A & 0x40);
setV((A & 0x40) ^ ((A & 0x20) << 1));
} else {
int c_flag;
setN(getC());
setZ(A == 0);
setV((tmp2 ^ A) & 0x40);
if ((tmp2 & 0x0f) + (tmp2 & 0x01) > 5)
A = (A & 0xf0) | ((A + 6) & 0x0f);
c_flag = (tmp2 + (tmp2 & 0x10)) & 0x1f0;
if (c_flag > 0x50) {
setC(1);
A += 0x60;
} else {
setC(0);
}
}
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: AXS
//
// Operation: X = (A & X) - op
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
void CPU::AXS_immediate()
{
READ_IMMEDIATE;
uint8_t op2 = A & X;
uint8_t tmp = op2 - data;
setC(op2 >= data);
loadX(tmp);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: DCP
//
// Operation: DEC followed by CMP
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
void CPU::DCP_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::DCP_zero_page_2;
}
void CPU::DCP_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::DCP_zero_page_3;
}
void CPU::DCP_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_DEC;
next = &CPU::DCP_zero_page_4;
}
void CPU::DCP_zero_page_4()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::DCP_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::DCP_zero_page_x_2;
}
void CPU::DCP_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::DCP_zero_page_x_3;
}
void CPU::DCP_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::DCP_zero_page_x_4;
}
void CPU::DCP_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_DEC;
next = &CPU::DCP_zero_page_x_5;
}
void CPU::DCP_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::DCP_absolute()
{
FETCH_ADDR_LO;
next = &CPU::DCP_absolute_2;
}
void CPU::DCP_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::DCP_absolute_3;
}
void CPU::DCP_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::DCP_absolute_4;
}
void CPU::DCP_absolute_4()
{
WRITE_TO_ADDRESS;
DO_DEC;
next = &CPU::DCP_absolute_5;
}
void CPU::DCP_absolute_5()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::DCP_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::DCP_absolute_x_2;
}
void CPU::DCP_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::DCP_absolute_x_3;
}
void CPU::DCP_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::DCP_absolute_x_4;
}
void CPU::DCP_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::DCP_absolute_x_5;
}
void CPU::DCP_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_DEC;
next = &CPU::DCP_absolute_x_6;
}
void CPU::DCP_absolute_x_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::DCP_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::DCP_absolute_y_2;
}
void CPU::DCP_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::DCP_absolute_y_3;
}
void CPU::DCP_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::DCP_absolute_y_4;
}
void CPU::DCP_absolute_y_4()
{
READ_FROM_ADDRESS;
next = &CPU::DCP_absolute_y_5;
}
void CPU::DCP_absolute_y_5()
{
WRITE_TO_ADDRESS;
DO_DEC;
next = &CPU::DCP_absolute_y_6;
}
void CPU::DCP_absolute_y_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::DCP_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::DCP_indirect_x_2;
}
void CPU::DCP_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::DCP_indirect_x_3;
}
void CPU::DCP_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::DCP_indirect_x_4;
}
void CPU::DCP_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::DCP_indirect_x_5;
}
void CPU::DCP_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::DCP_indirect_x_6;
}
void CPU::DCP_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_DEC;
next = &CPU::DCP_indirect_x_7;
}
void CPU::DCP_indirect_x_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::DCP_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::DCP_indirect_y_2;
}
void CPU::DCP_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::DCP_indirect_y_3;
}
void CPU::DCP_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::DCP_indirect_y_4;
}
void CPU::DCP_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::DCP_indirect_y_5;
}
void CPU::DCP_indirect_y_5()
{
READ_FROM_ADDRESS;
next = &CPU::DCP_indirect_y_6;
}
void CPU::DCP_indirect_y_6()
{
WRITE_TO_ADDRESS;
DO_DEC;
next = &CPU::DCP_indirect_y_7;
}
void CPU::DCP_indirect_y_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
cmp(A, data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: ISC
//
// Operation: INC followed by SBC
//
// Flags: N Z C I D V
// / / / - - /
// -------------------------------------------------------------------------------
void CPU::ISC_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::ISC_zero_page_2;
}
void CPU::ISC_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::ISC_zero_page_3;
}
void CPU::ISC_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_INC;
next = &CPU::ISC_zero_page_4;
}
void CPU::ISC_zero_page_4()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ISC_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::ISC_zero_page_x_2;
}
void CPU::ISC_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::ISC_zero_page_x_3;
}
void CPU::ISC_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::ISC_zero_page_x_4;
}
void CPU::ISC_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_INC;
next = &CPU::ISC_zero_page_x_5;
}
void CPU::ISC_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE_AND_SET_FLAGS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ISC_absolute()
{
FETCH_ADDR_LO;
next = &CPU::ISC_absolute_2;
}
void CPU::ISC_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::ISC_absolute_3;
}
void CPU::ISC_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::ISC_absolute_4;
}
void CPU::ISC_absolute_4()
{
WRITE_TO_ADDRESS;
DO_INC;
next = &CPU::ISC_absolute_5;
}
void CPU::ISC_absolute_5()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ISC_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::ISC_absolute_x_2;
}
void CPU::ISC_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::ISC_absolute_x_3;
}
void CPU::ISC_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::ISC_absolute_x_4;
}
void CPU::ISC_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::ISC_absolute_x_5;
}
void CPU::ISC_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_INC;
next = &CPU::ISC_absolute_x_6;
}
void CPU::ISC_absolute_x_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ISC_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::ISC_absolute_y_2;
}
void CPU::ISC_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::ISC_absolute_y_3;
}
void CPU::ISC_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::ISC_absolute_y_4;
}
void CPU::ISC_absolute_y_4()
{
READ_FROM_ADDRESS;
next = &CPU::ISC_absolute_y_5;
}
void CPU::ISC_absolute_y_5()
{
WRITE_TO_ADDRESS;
DO_INC;
next = &CPU::ISC_absolute_y_6;
}
void CPU::ISC_absolute_y_6()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ISC_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::ISC_indirect_x_2;
}
void CPU::ISC_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::ISC_indirect_x_3;
}
void CPU::ISC_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::ISC_indirect_x_4;
}
void CPU::ISC_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::ISC_indirect_x_5;
}
void CPU::ISC_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::ISC_indirect_x_6;
}
void CPU::ISC_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_INC;
next = &CPU::ISC_indirect_x_7;
}
void CPU::ISC_indirect_x_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::ISC_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::ISC_indirect_y_2;
}
void CPU::ISC_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::ISC_indirect_y_3;
}
void CPU::ISC_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::ISC_indirect_y_4;
}
void CPU::ISC_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
}
next = &CPU::ISC_indirect_y_5;
}
void CPU::ISC_indirect_y_5()
{
READ_FROM_ADDRESS;
next = &CPU::ISC_indirect_y_6;
}
void CPU::ISC_indirect_y_6()
{
WRITE_TO_ADDRESS;
DO_INC;
next = &CPU::ISC_indirect_y_7;
}
void CPU::ISC_indirect_y_7()
{
WRITE_TO_ADDRESS_AND_SET_FLAGS;
sbc(data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: LAS
//
// Operation: SP,X,A = op & SP
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::LAS_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::LAS_absolute_y_2;
}
void CPU::LAS_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::LAS_absolute_y_3;
}
void CPU::LAS_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::LAS_absolute_y_4;
} else {
data &= SP;
SP = data;
X = data;
loadA(data);
DONE;
}
}
void CPU::LAS_absolute_y_4()
{
READ_FROM_ADDRESS;
data &= SP;
SP = data;
X = data;
loadA(data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: LAX
//
// Operation: LDA, followed by LDX
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::LAX_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::LAX_zero_page_2;
}
void CPU::LAX_zero_page_2()
{
READ_FROM_ZERO_PAGE;
loadA(data);
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LAX_zero_page_y()
{
FETCH_ADDR_LO;
next = &CPU::LAX_zero_page_y_2;
}
void CPU::LAX_zero_page_y_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_Y;
next = &CPU::LAX_zero_page_y_3;
}
void CPU::LAX_zero_page_y_3()
{
READ_FROM_ZERO_PAGE;
loadA(data);
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LAX_absolute()
{
FETCH_ADDR_LO;
next = &CPU::LAX_absolute_2;
}
void CPU::LAX_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::LAX_absolute_3;
}
void CPU::LAX_absolute_3()
{
READ_FROM_ADDRESS;
loadA(data);
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LAX_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::LAX_absolute_y_2;
}
void CPU::LAX_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::LAX_absolute_y_3;
}
void CPU::LAX_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::LAX_absolute_y_4;
} else {
loadA(data);
loadX(data);
DONE;
}
}
void CPU::LAX_absolute_y_4()
{
READ_FROM_ADDRESS;
loadA(data);
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LAX_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::LAX_indirect_x_2;
}
void CPU::LAX_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::LAX_indirect_x_3;
}
void CPU::LAX_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::LAX_indirect_x_4;
}
void CPU::LAX_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::LAX_indirect_x_5;
}
void CPU::LAX_indirect_x_5()
{
READ_FROM_ADDRESS;
loadA(data);
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::LAX_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::LAX_indirect_y_2;
}
void CPU::LAX_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::LAX_indirect_y_3;
}
void CPU::LAX_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::LAX_indirect_y_4;
}
void CPU::LAX_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::LAX_indirect_y_5;
} else {
loadA(data);
loadX(data);
DONE;
}
}
void CPU::LAX_indirect_y_5()
{
READ_FROM_ADDRESS;
loadA(data);
loadX(data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: RLA
//
// Operation: ROL, followed by AND
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
void CPU::RLA_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::RLA_zero_page_2;
}
void CPU::RLA_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::RLA_zero_page_3;
}
void CPU::RLA_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_ROL;
next = &CPU::RLA_zero_page_4;
}
void CPU::RLA_zero_page_4()
{
WRITE_TO_ZERO_PAGE;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RLA_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::RLA_zero_page_x_2;
}
void CPU::RLA_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::RLA_zero_page_x_3;
}
void CPU::RLA_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::RLA_zero_page_x_4;
}
void CPU::RLA_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_ROL;
next = &CPU::RLA_zero_page_x_5;
}
void CPU::RLA_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RLA_absolute()
{
FETCH_ADDR_LO;
next = &CPU::RLA_absolute_2;
}
void CPU::RLA_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::RLA_absolute_3;
}
void CPU::RLA_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::RLA_absolute_4;
}
void CPU::RLA_absolute_4()
{
WRITE_TO_ADDRESS;
DO_ROL;
next = &CPU::RLA_absolute_5;
}
void CPU::RLA_absolute_5()
{
WRITE_TO_ADDRESS;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RLA_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::RLA_absolute_x_2;
}
void CPU::RLA_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::RLA_absolute_x_3;
}
void CPU::RLA_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::RLA_absolute_x_4;
}
void CPU::RLA_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::RLA_absolute_x_5;
}
void CPU::RLA_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_ROL;
next = &CPU::RLA_absolute_x_6;
}
void CPU::RLA_absolute_x_6()
{
WRITE_TO_ADDRESS;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RLA_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::RLA_absolute_y_2;
}
void CPU::RLA_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::RLA_absolute_y_3;
}
void CPU::RLA_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::RLA_absolute_y_4;
}
void CPU::RLA_absolute_y_4()
{
READ_FROM_ADDRESS;
next = &CPU::RLA_absolute_y_5;
}
void CPU::RLA_absolute_y_5()
{
WRITE_TO_ADDRESS;
DO_ROL;
next = &CPU::RLA_absolute_y_6;
}
void CPU::RLA_absolute_y_6()
{
WRITE_TO_ADDRESS;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RLA_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::RLA_indirect_x_2;
}
void CPU::RLA_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::RLA_indirect_x_3;
}
void CPU::RLA_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::RLA_indirect_x_4;
}
void CPU::RLA_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::RLA_indirect_x_5;
}
void CPU::RLA_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::RLA_indirect_x_6;
}
void CPU::RLA_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_ROL;
next = &CPU::RLA_indirect_x_7;
}
void CPU::RLA_indirect_x_7()
{
WRITE_TO_ADDRESS;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RLA_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::RLA_indirect_y_2;
}
void CPU::RLA_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::RLA_indirect_y_3;
}
void CPU::RLA_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::RLA_indirect_y_4;
}
void CPU::RLA_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::RLA_indirect_y_5;
}
void CPU::RLA_indirect_y_5()
{
READ_FROM_ADDRESS;
next = &CPU::RLA_indirect_y_6;
}
void CPU::RLA_indirect_y_6()
{
WRITE_TO_ADDRESS;
DO_ROL;
next = &CPU::RLA_indirect_y_7;
}
void CPU::RLA_indirect_y_7()
{
WRITE_TO_ADDRESS;
loadA(A & data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: RRA
//
// Operation: ROR, followed by ADC
//
// Flags: N Z C I D V
// / / / - - /
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
void CPU::RRA_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::RRA_zero_page_2;
}
void CPU::RRA_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::RRA_zero_page_3;
}
void CPU::RRA_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_ROR;
next = &CPU::RRA_zero_page_4;
}
void CPU::RRA_zero_page_4()
{
WRITE_TO_ZERO_PAGE;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RRA_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::RRA_zero_page_x_2;
}
void CPU::RRA_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::RRA_zero_page_x_3;
}
void CPU::RRA_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::RRA_zero_page_x_4;
}
void CPU::RRA_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_ROR;
next = &CPU::RRA_zero_page_x_5;
}
void CPU::RRA_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RRA_absolute()
{
FETCH_ADDR_LO;
next = &CPU::RRA_absolute_2;
}
void CPU::RRA_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::RRA_absolute_3;
}
void CPU::RRA_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::RRA_absolute_4;
}
void CPU::RRA_absolute_4()
{
WRITE_TO_ADDRESS;
DO_ROR;
next = &CPU::RRA_absolute_5;
}
void CPU::RRA_absolute_5()
{
WRITE_TO_ADDRESS;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RRA_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::RRA_absolute_x_2;
}
void CPU::RRA_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::RRA_absolute_x_3;
}
void CPU::RRA_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::RRA_absolute_x_4;
}
void CPU::RRA_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::RRA_absolute_x_5;
}
void CPU::RRA_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_ROR;
next = &CPU::RRA_absolute_x_6;
}
void CPU::RRA_absolute_x_6()
{
WRITE_TO_ADDRESS;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RRA_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::RRA_absolute_y_2;
}
void CPU::RRA_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::RRA_absolute_y_3;
}
void CPU::RRA_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::RRA_absolute_y_4;
}
void CPU::RRA_absolute_y_4()
{
READ_FROM_ADDRESS;
next = &CPU::RRA_absolute_y_5;
}
void CPU::RRA_absolute_y_5()
{
WRITE_TO_ADDRESS;
DO_ROR;
next = &CPU::RRA_absolute_y_6;
}
void CPU::RRA_absolute_y_6()
{
WRITE_TO_ADDRESS;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RRA_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::RRA_indirect_x_2;
}
void CPU::RRA_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::RRA_indirect_x_3;
}
void CPU::RRA_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::RRA_indirect_x_4;
}
void CPU::RRA_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::RRA_indirect_x_5;
}
void CPU::RRA_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::RRA_indirect_x_6;
}
void CPU::RRA_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_ROR;
next = &CPU::RRA_indirect_x_7;
}
void CPU::RRA_indirect_x_7()
{
WRITE_TO_ADDRESS;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::RRA_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::RRA_indirect_y_2;
}
void CPU::RRA_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::RRA_indirect_y_3;
}
void CPU::RRA_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::RRA_indirect_y_4;
}
void CPU::RRA_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::RRA_indirect_y_5;
}
void CPU::RRA_indirect_y_5()
{
READ_FROM_ADDRESS;
next = &CPU::RRA_indirect_y_6;
}
void CPU::RRA_indirect_y_6()
{
WRITE_TO_ADDRESS;
DO_ROR;
next = &CPU::RRA_indirect_y_7;
}
void CPU::RRA_indirect_y_7()
{
WRITE_TO_ADDRESS;
adc(data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: SAX
//
// Operation: Mem := A & X
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::SAX_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::SAX_zero_page_2;
}
void CPU::SAX_zero_page_2()
{
data = A & X;
WRITE_TO_ZERO_PAGE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SAX_zero_page_y()
{
FETCH_ADDR_LO;
next = &CPU::SAX_zero_page_y_2;
}
void CPU::SAX_zero_page_y_2()
{
IDLE_READ_FROM_ZERO_PAGE;
ADD_INDEX_Y;
next = &CPU::SAX_zero_page_y_3;
}
void CPU::SAX_zero_page_y_3()
{
data = A & X;
WRITE_TO_ZERO_PAGE;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SAX_absolute()
{
FETCH_ADDR_LO;
next = &CPU::SAX_absolute_2;
}
void CPU::SAX_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::SAX_absolute_3;
}
void CPU::SAX_absolute_3()
{
data = A & X;
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SAX_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::SAX_indirect_x_2;
}
void CPU::SAX_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::SAX_indirect_x_3;
}
void CPU::SAX_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::SAX_indirect_x_4;
}
void CPU::SAX_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::SAX_indirect_x_5;
}
void CPU::SAX_indirect_x_5()
{
data = A & X;
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: SHA
//
// Operation: Mem := A & X & (M + 1)
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::SHA_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::SHA_absolute_y_2;
}
void CPU::SHA_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::SHA_absolute_y_3;
}
void CPU::SHA_absolute_y_3()
{
IDLE_READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::SHA_absolute_y_4;
}
void CPU::SHA_absolute_y_4()
{
data = A & X & (addr_hi + 1);
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SHA_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::SHA_indirect_y_2;
}
void CPU::SHA_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::SHA_indirect_y_3;
}
void CPU::SHA_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::SHA_indirect_y_4;
}
void CPU::SHA_indirect_y_4()
{
IDLE_READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::SHA_indirect_y_5;
}
void CPU::SHA_indirect_y_5()
{
data = A & X & (addr_hi + 1);
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: SHX
//
// Operation: Mem := X & (HI_BYTE(op) + 1)
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::SHX_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::SHX_absolute_y_2;
}
void CPU::SHX_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::SHX_absolute_y_3;
}
void CPU::SHX_absolute_y_3()
{
IDLE_READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::SHX_absolute_y_4;
}
void CPU::SHX_absolute_y_4()
{
data = X & (addr_hi + 1);
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: SHY
//
// Operation: Mem := Y & (HI_BYTE(op) + 1)
//
// Flags: N Z C I D V
// - - - - - -
// -------------------------------------------------------------------------------
void CPU::SHY_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::SHY_absolute_x_2;
}
void CPU::SHY_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::SHY_absolute_x_3;
}
void CPU::SHY_absolute_x_3()
{
IDLE_READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::SHY_absolute_x_4;
}
void CPU::SHY_absolute_x_4()
{
data = data = Y & (addr_hi + 1);
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: SLO (ASO)
//
// Operation: ASL memory location, followed by OR on accumulator
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
#define DO_SLO setC(data & 128); data <<= 1;
// -------------------------------------------------------------------------------
void CPU::SLO_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::SLO_zero_page_2;
}
void CPU::SLO_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::SLO_zero_page_3;
}
void CPU::SLO_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_SLO;
next = &CPU::SLO_zero_page_4;
}
void CPU::SLO_zero_page_4()
{
WRITE_TO_ZERO_PAGE;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SLO_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::SLO_zero_page_x_2;
}
void CPU::SLO_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::SLO_zero_page_x_3;
}
void CPU::SLO_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::SLO_zero_page_x_4;
}
void CPU::SLO_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_SLO;
next = &CPU::SLO_zero_page_x_5;
}
void CPU::SLO_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SLO_absolute()
{
FETCH_ADDR_LO;
next = &CPU::SLO_absolute_2;
}
void CPU::SLO_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::SLO_absolute_3;
}
void CPU::SLO_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::SLO_absolute_4;
}
void CPU::SLO_absolute_4()
{
WRITE_TO_ADDRESS;
DO_SLO;
next = &CPU::SLO_absolute_5;
}
void CPU::SLO_absolute_5()
{
WRITE_TO_ADDRESS;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SLO_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::SLO_absolute_x_2;
}
void CPU::SLO_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::SLO_absolute_x_3;
}
void CPU::SLO_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::SLO_absolute_x_4;
}
void CPU::SLO_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::SLO_absolute_x_5;
}
void CPU::SLO_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_SLO;
next = &CPU::SLO_absolute_x_6;
}
void CPU::SLO_absolute_x_6()
{
WRITE_TO_ADDRESS;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SLO_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::SLO_absolute_y_2;
}
void CPU::SLO_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::SLO_absolute_y_3;
}
void CPU::SLO_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::SLO_absolute_y_4;
}
void CPU::SLO_absolute_y_4()
{
READ_FROM_ADDRESS;
next = &CPU::SLO_absolute_y_5;
}
void CPU::SLO_absolute_y_5()
{
WRITE_TO_ADDRESS;
DO_SLO;
next = &CPU::SLO_absolute_y_6;
}
void CPU::SLO_absolute_y_6()
{
WRITE_TO_ADDRESS;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SLO_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::SLO_indirect_x_2;
}
void CPU::SLO_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::SLO_indirect_x_3;
}
void CPU::SLO_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::SLO_indirect_x_4;
}
void CPU::SLO_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::SLO_indirect_x_5;
}
void CPU::SLO_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::SLO_indirect_x_6;
}
void CPU::SLO_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_SLO;
next = &CPU::SLO_indirect_x_7;
}
void CPU::SLO_indirect_x_7()
{
WRITE_TO_ADDRESS;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SLO_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::SLO_indirect_y_2;
}
void CPU::SLO_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::SLO_indirect_y_3;
}
void CPU::SLO_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::SLO_indirect_y_4;
}
void CPU::SLO_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::SLO_indirect_y_5;
}
void CPU::SLO_indirect_y_5()
{
READ_FROM_ADDRESS;
next = &CPU::SLO_indirect_y_6;
}
void CPU::SLO_indirect_y_6()
{
WRITE_TO_ADDRESS;
DO_SLO;
next = &CPU::SLO_indirect_y_7;
}
void CPU::SLO_indirect_y_7()
{
WRITE_TO_ADDRESS;
loadA(A | data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: SRE (LSE)
//
// Operation: LSR, followed by EOR
//
// Flags: N Z C I D V
// / / / - - -
// -------------------------------------------------------------------------------
#define DO_SRE setC(data & 1); data >>= 1;
// -------------------------------------------------------------------------------
void CPU::SRE_zero_page()
{
FETCH_ADDR_LO;
next = &CPU::SRE_zero_page_2;
}
void CPU::SRE_zero_page_2()
{
READ_FROM_ZERO_PAGE;
next = &CPU::SRE_zero_page_3;
}
void CPU::SRE_zero_page_3()
{
WRITE_TO_ZERO_PAGE;
DO_SRE;
next = &CPU::SRE_zero_page_4;
}
void CPU::SRE_zero_page_4()
{
WRITE_TO_ZERO_PAGE;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SRE_zero_page_x()
{
FETCH_ADDR_LO;
next = &CPU::SRE_zero_page_x_2;
}
void CPU::SRE_zero_page_x_2()
{
READ_FROM_ZERO_PAGE;
ADD_INDEX_X;
next = &CPU::SRE_zero_page_x_3;
}
void CPU::SRE_zero_page_x_3()
{
READ_FROM_ZERO_PAGE;
next = &CPU::SRE_zero_page_x_4;
}
void CPU::SRE_zero_page_x_4()
{
WRITE_TO_ZERO_PAGE;
DO_SRE;
next = &CPU::SRE_zero_page_x_5;
}
void CPU::SRE_zero_page_x_5()
{
WRITE_TO_ZERO_PAGE;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SRE_absolute()
{
FETCH_ADDR_LO;
next = &CPU::SRE_absolute_2;
}
void CPU::SRE_absolute_2()
{
FETCH_ADDR_HI;
next = &CPU::SRE_absolute_3;
}
void CPU::SRE_absolute_3()
{
READ_FROM_ADDRESS;
next = &CPU::SRE_absolute_4;
}
void CPU::SRE_absolute_4()
{
WRITE_TO_ADDRESS;
DO_SRE;
next = &CPU::SRE_absolute_5;
}
void CPU::SRE_absolute_5()
{
WRITE_TO_ADDRESS;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SRE_absolute_x()
{
FETCH_ADDR_LO;
next = &CPU::SRE_absolute_x_2;
}
void CPU::SRE_absolute_x_2()
{
FETCH_ADDR_HI;
ADD_INDEX_X;
next = &CPU::SRE_absolute_x_3;
}
void CPU::SRE_absolute_x_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::SRE_absolute_x_4;
}
void CPU::SRE_absolute_x_4()
{
READ_FROM_ADDRESS;
next = &CPU::SRE_absolute_x_5;
}
void CPU::SRE_absolute_x_5()
{
WRITE_TO_ADDRESS;
DO_SRE;
next = &CPU::SRE_absolute_x_6;
}
void CPU::SRE_absolute_x_6()
{
WRITE_TO_ADDRESS;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SRE_absolute_y()
{
FETCH_ADDR_LO;
next = &CPU::SRE_absolute_y_2;
}
void CPU::SRE_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::SRE_absolute_y_3;
}
void CPU::SRE_absolute_y_3()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::SRE_absolute_y_4;
}
void CPU::SRE_absolute_y_4()
{
READ_FROM_ADDRESS;
next = &CPU::SRE_absolute_y_5;
}
void CPU::SRE_absolute_y_5()
{
WRITE_TO_ADDRESS;
DO_SRE;
next = &CPU::SRE_absolute_y_6;
}
void CPU::SRE_absolute_y_6()
{
WRITE_TO_ADDRESS;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SRE_indirect_x()
{
FETCH_POINTER_ADDR;
next = &CPU::SRE_indirect_x_2;
}
void CPU::SRE_indirect_x_2()
{
IDLE_READ_FROM_ADDRESS_INDIRECT;
ADD_INDEX_X_INDIRECT;
next = &CPU::SRE_indirect_x_3;
}
void CPU::SRE_indirect_x_3()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::SRE_indirect_x_4;
}
void CPU::SRE_indirect_x_4()
{
FETCH_ADDR_HI_INDIRECT;
next = &CPU::SRE_indirect_x_5;
}
void CPU::SRE_indirect_x_5()
{
READ_FROM_ADDRESS;
next = &CPU::SRE_indirect_x_6;
}
void CPU::SRE_indirect_x_6()
{
WRITE_TO_ADDRESS;
DO_SRE;
next = &CPU::SRE_indirect_x_7;
}
void CPU::SRE_indirect_x_7()
{
WRITE_TO_ADDRESS;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
void CPU::SRE_indirect_y()
{
FETCH_POINTER_ADDR;
next = &CPU::SRE_indirect_y_2;
}
void CPU::SRE_indirect_y_2()
{
FETCH_ADDR_LO_INDIRECT;
next = &CPU::SRE_indirect_y_3;
}
void CPU::SRE_indirect_y_3()
{
FETCH_ADDR_HI_INDIRECT;
ADD_INDEX_Y;
next = &CPU::SRE_indirect_y_4;
}
void CPU::SRE_indirect_y_4()
{
READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED)
FIX_ADDR_HI;
next = &CPU::SRE_indirect_y_5;
}
void CPU::SRE_indirect_y_5()
{
READ_FROM_ADDRESS;
next = &CPU::SRE_indirect_y_6;
}
void CPU::SRE_indirect_y_6()
{
WRITE_TO_ADDRESS;
DO_SRE;
next = &CPU::SRE_indirect_y_7;
}
void CPU::SRE_indirect_y_7()
{
WRITE_TO_ADDRESS;
loadA(A ^ data);
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: TAS (SHS)
//
// Operation: SP := A & X, Mem := SP & (HI_BYTE(op) + 1)
//
// Flags: N Z C I D V
// - - - - - -
//
// -------------------------------------------------------------------------------
void CPU::TAS_absolute_y()
{
data = mem->peek(PC + 1) + 1;
FETCH_ADDR_LO;
next = &CPU::TAS_absolute_y_2;
}
void CPU::TAS_absolute_y_2()
{
FETCH_ADDR_HI;
ADD_INDEX_Y;
next = &CPU::TAS_absolute_y_3;
}
void CPU::TAS_absolute_y_3()
{
IDLE_READ_FROM_ADDRESS;
if (PAGE_BOUNDARY_CROSSED) {
FIX_ADDR_HI;
next = &CPU::TAS_absolute_y_4;
} else {
// Note: We always perform an extra cycle here, even if page boundary is not crossed.
// Otherwise, the CPUTIMING test fails.
next = &CPU::TAS_absolute_y_4;
#if 0
SP = A & X;
data &= SP;
WRITE_TO_ADDRESS;
DONE;
#endif
}
}
void CPU::TAS_absolute_y_4()
{
IDLE_READ_FROM_ADDRESS;
SP = A & X;
data &= SP;
WRITE_TO_ADDRESS;
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: ANE
//
// Operation: A = X & op & (A | 0xEE) (taken from Frodo)
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::ANE_immediate()
{
READ_IMMEDIATE;
loadA(X & data & (A | 0xEE));
DONE;
}
// -------------------------------------------------------------------------------
// Instruction: LXA
//
// Operation: A = X = op & (A | 0xEE) (taken from Frodo)
//
// Flags: N Z C I D V
// / / - - - -
// -------------------------------------------------------------------------------
void CPU::LXA_immediate()
{
READ_IMMEDIATE;
X = data & (A | 0xEE);
loadA(X);
DONE;
}
void ((CPU::*CPU::callbacks[])(void)) = {
&CPU::fetch,
&CPU::JAM, &CPU::JAM_2,
&CPU::irq, &CPU::irq_2, &CPU::irq_3, &CPU::irq_4, &CPU::irq_5, &CPU::irq_6, &CPU::irq_7,
&CPU::nmi, &CPU::nmi_2, &CPU::nmi_3, &CPU::nmi_4, &CPU::nmi_5, &CPU::nmi_6, &CPU::nmi_7,
&CPU::ADC_immediate,
&CPU::ADC_zero_page, &CPU::ADC_zero_page_2,
&CPU::ADC_zero_page_x, &CPU::ADC_zero_page_x_2, &CPU::ADC_zero_page_x_3,
&CPU::ADC_absolute, &CPU::ADC_absolute_2, &CPU::ADC_absolute_3,
&CPU::ADC_absolute_x, &CPU::ADC_absolute_x_2, &CPU::ADC_absolute_x_3, &CPU::ADC_absolute_x_4,
&CPU::ADC_absolute_y, &CPU::ADC_absolute_y_2, &CPU::ADC_absolute_y_3, &CPU::ADC_absolute_y_4,
&CPU::ADC_indirect_x, &CPU::ADC_indirect_x_2, &CPU::ADC_indirect_x_3, &CPU::ADC_indirect_x_4, &CPU::ADC_indirect_x_5,
&CPU::ADC_indirect_y, &CPU::ADC_indirect_y_2, &CPU::ADC_indirect_y_3, &CPU::ADC_indirect_y_4, &CPU::ADC_indirect_y_5,
&CPU::AND_immediate,
&CPU::AND_zero_page, &CPU::AND_zero_page_2,
&CPU::AND_zero_page_x, &CPU::AND_zero_page_x_2, &CPU::AND_zero_page_x_3,
&CPU::AND_absolute, &CPU::AND_absolute_2, &CPU::AND_absolute_3,
&CPU::AND_absolute_x, &CPU::AND_absolute_x_2, &CPU::AND_absolute_x_3, &CPU::AND_absolute_x_4,
&CPU::AND_absolute_y, &CPU::AND_absolute_y_2, &CPU::AND_absolute_y_3, &CPU::AND_absolute_y_4,
&CPU::AND_indirect_x, &CPU::AND_indirect_x_2, &CPU::AND_indirect_x_3, &CPU::AND_indirect_x_4, &CPU::AND_indirect_x_5,
&CPU::AND_indirect_y, &CPU::AND_indirect_y_2, &CPU::AND_indirect_y_3, &CPU::AND_indirect_y_4, &CPU::AND_indirect_y_5,
&CPU::ASL_accumulator,
&CPU::ASL_zero_page, &CPU::ASL_zero_page_2, &CPU::ASL_zero_page_3, &CPU::ASL_zero_page_4,
&CPU::ASL_zero_page_x, &CPU::ASL_zero_page_x_2, &CPU::ASL_zero_page_x_3, &CPU::ASL_zero_page_x_4, &CPU::ASL_zero_page_x_5,
&CPU::ASL_absolute, &CPU::ASL_absolute_2, &CPU::ASL_absolute_3, &CPU::ASL_absolute_4, &CPU::ASL_absolute_5,
&CPU::ASL_absolute_x, &CPU::ASL_absolute_x_2, &CPU::ASL_absolute_x_3, &CPU::ASL_absolute_x_4, &CPU::ASL_absolute_x_5, &CPU::ASL_absolute_x_6,
&CPU::ASL_indirect_x, &CPU::ASL_indirect_x_2, &CPU::ASL_indirect_x_3, &CPU::ASL_indirect_x_4, &CPU::ASL_indirect_x_5, &CPU::ASL_indirect_x_6, &CPU::ASL_indirect_x_7,
&CPU::branch_3_underflow, &CPU::branch_3_overflow,
&CPU::BCC_relative, &CPU::BCC_relative_2,
&CPU::BCS_relative, &CPU::BCS_relative_2,
&CPU::BEQ_relative, &CPU::BEQ_relative_2,
&CPU::BIT_zero_page, &CPU::BIT_zero_page_2,
&CPU::BIT_absolute, &CPU::BIT_absolute_2, &CPU::BIT_absolute_3,
&CPU::BMI_relative, &CPU::BMI_relative_2,
&CPU::BNE_relative, &CPU::BNE_relative_2,
&CPU::BPL_relative, &CPU::BPL_relative_2,
&CPU::BRK, &CPU::BRK_2, &CPU::BRK_3, &CPU::BRK_4, &CPU::BRK_5, &CPU::BRK_6,
&CPU::BRK_nmi_4, &CPU::BRK_nmi_5, &CPU::BRK_nmi_6,
&CPU::BVC_relative, &CPU::BVC_relative_2,
&CPU::BVS_relative, &CPU::BVS_relative_2,
&CPU::CLC,
&CPU::CLD,
&CPU::CLI,
&CPU::CLV,
&CPU::CMP_immediate,
&CPU::CMP_zero_page, &CPU::CMP_zero_page_2,
&CPU::CMP_zero_page_x, &CPU::CMP_zero_page_x_2, &CPU::CMP_zero_page_x_3,
&CPU::CMP_absolute, &CPU::CMP_absolute_2, &CPU::CMP_absolute_3,
&CPU::CMP_absolute_x, &CPU::CMP_absolute_x_2, &CPU::CMP_absolute_x_3, &CPU::CMP_absolute_x_4,
&CPU::CMP_absolute_y, &CPU::CMP_absolute_y_2, &CPU::CMP_absolute_y_3, &CPU::CMP_absolute_y_4,
&CPU::CMP_indirect_x, &CPU::CMP_indirect_x_2, &CPU::CMP_indirect_x_3, &CPU::CMP_indirect_x_4, &CPU::CMP_indirect_x_5,
&CPU::CMP_indirect_y, &CPU::CMP_indirect_y_2, &CPU::CMP_indirect_y_3, &CPU::CMP_indirect_y_4, &CPU::CMP_indirect_y_5,
&CPU::CPX_immediate,
&CPU::CPX_zero_page, &CPU::CPX_zero_page_2,
&CPU::CPX_absolute, &CPU::CPX_absolute_2, &CPU::CPX_absolute_3,
&CPU::CPY_immediate,
&CPU::CPY_zero_page, &CPU::CPY_zero_page_2,
&CPU::CPY_absolute, &CPU::CPY_absolute_2, &CPU::CPY_absolute_3,
&CPU::DEC_zero_page, &CPU::DEC_zero_page_2, &CPU::DEC_zero_page_3, &CPU::DEC_zero_page_4,
&CPU::DEC_zero_page_x, &CPU::DEC_zero_page_x_2, &CPU::DEC_zero_page_x_3, &CPU::DEC_zero_page_x_4, &CPU::DEC_zero_page_x_5,
&CPU::DEC_absolute, &CPU::DEC_absolute_2, &CPU::DEC_absolute_3, &CPU::DEC_absolute_4, &CPU::DEC_absolute_5,
&CPU::DEC_absolute_x, &CPU::DEC_absolute_x_2, &CPU::DEC_absolute_x_3, &CPU::DEC_absolute_x_4, &CPU::DEC_absolute_x_5, &CPU::DEC_absolute_x_6,
&CPU::DEC_indirect_x, &CPU::DEC_indirect_x_2, &CPU::DEC_indirect_x_3, &CPU::DEC_indirect_x_4, &CPU::DEC_indirect_x_5, &CPU::DEC_indirect_x_6, &CPU::DEC_indirect_x_7,
&CPU::DEX,
&CPU::DEY,
&CPU::EOR_immediate,
&CPU::EOR_zero_page, &CPU::EOR_zero_page_2,
&CPU::EOR_zero_page_x, &CPU::EOR_zero_page_x_2, &CPU::EOR_zero_page_x_3,
&CPU::EOR_absolute, &CPU::EOR_absolute_2, &CPU::EOR_absolute_3,
&CPU::EOR_absolute_x, &CPU::EOR_absolute_x_2, &CPU::EOR_absolute_x_3, &CPU::EOR_absolute_x_4,
&CPU::EOR_absolute_y, &CPU::EOR_absolute_y_2, &CPU::EOR_absolute_y_3, &CPU::EOR_absolute_y_4,
&CPU::EOR_indirect_x, &CPU::EOR_indirect_x_2, &CPU::EOR_indirect_x_3, &CPU::EOR_indirect_x_4, &CPU::EOR_indirect_x_5,
&CPU::EOR_indirect_y, &CPU::EOR_indirect_y_2, &CPU::EOR_indirect_y_3, &CPU::EOR_indirect_y_4, &CPU::EOR_indirect_y_5,
&CPU::INC_zero_page, &CPU::INC_zero_page_2, &CPU::INC_zero_page_3, &CPU::INC_zero_page_4,
&CPU::INC_zero_page_x, &CPU::INC_zero_page_x_2, &CPU::INC_zero_page_x_3, &CPU::INC_zero_page_x_4, &CPU::INC_zero_page_x_5,
&CPU::INC_absolute, &CPU::INC_absolute_2, &CPU::INC_absolute_3, &CPU::INC_absolute_4, &CPU::INC_absolute_5,
&CPU::INC_absolute_x, &CPU::INC_absolute_x_2, &CPU::INC_absolute_x_3, &CPU::INC_absolute_x_4, &CPU::INC_absolute_x_5, &CPU::INC_absolute_x_6,
&CPU::INC_indirect_x, &CPU::INC_indirect_x_2, &CPU::INC_indirect_x_3, &CPU::INC_indirect_x_4, &CPU::INC_indirect_x_5, &CPU::INC_indirect_x_6, &CPU::INC_indirect_x_7,
&CPU::INX,
&CPU::INY,
&CPU::JMP_absolute, &CPU::JMP_absolute_2,
&CPU::JMP_absolute_indirect, &CPU::JMP_absolute_indirect_2, &CPU::JMP_absolute_indirect_3, &CPU::JMP_absolute_indirect_4,
&CPU::JSR, &CPU::JSR_2, &CPU::JSR_3, &CPU::JSR_4, &CPU::JSR_5,
&CPU::LDA_immediate,
&CPU::LDA_zero_page, &CPU::LDA_zero_page_2,
&CPU::LDA_zero_page_x, &CPU::LDA_zero_page_x_2, &CPU::LDA_zero_page_x_3,
&CPU::LDA_absolute, &CPU::LDA_absolute_2, &CPU::LDA_absolute_3,
&CPU::LDA_absolute_x, &CPU::LDA_absolute_x_2, &CPU::LDA_absolute_x_3, &CPU::LDA_absolute_x_4,
&CPU::LDA_absolute_y, &CPU::LDA_absolute_y_2, &CPU::LDA_absolute_y_3, &CPU::LDA_absolute_y_4,
&CPU::LDA_indirect_x, &CPU::LDA_indirect_x_2, &CPU::LDA_indirect_x_3, &CPU::LDA_indirect_x_4, &CPU::LDA_indirect_x_5,
&CPU::LDA_indirect_y, &CPU::LDA_indirect_y_2, &CPU::LDA_indirect_y_3, &CPU::LDA_indirect_y_4, &CPU::LDA_indirect_y_5,
&CPU::LDX_immediate,
&CPU::LDX_zero_page, &CPU::LDX_zero_page_2,
&CPU::LDX_zero_page_y, &CPU::LDX_zero_page_y_2, &CPU::LDX_zero_page_y_3,
&CPU::LDX_absolute, &CPU::LDX_absolute_2, &CPU::LDX_absolute_3,
&CPU::LDX_absolute_y, &CPU::LDX_absolute_y_2, &CPU::LDX_absolute_y_3, &CPU::LDX_absolute_y_4,
&CPU::LDX_indirect_x, &CPU::LDX_indirect_x_2, &CPU::LDX_indirect_x_3, &CPU::LDX_indirect_x_4, &CPU::LDX_indirect_x_5,
&CPU::LDX_indirect_y, &CPU::LDX_indirect_y_2, &CPU::LDX_indirect_y_3, &CPU::LDX_indirect_y_4, &CPU::LDX_indirect_y_5,
&CPU::LDY_immediate,
&CPU::LDY_zero_page, &CPU::LDY_zero_page_2,
&CPU::LDY_zero_page_x, &CPU::LDY_zero_page_x_2, &CPU::LDY_zero_page_x_3,
&CPU::LDY_absolute, &CPU::LDY_absolute_2, &CPU::LDY_absolute_3,
&CPU::LDY_absolute_x, &CPU::LDY_absolute_x_2, &CPU::LDY_absolute_x_3, &CPU::LDY_absolute_x_4,
&CPU::LDY_indirect_x, &CPU::LDY_indirect_x_2, &CPU::LDY_indirect_x_3, &CPU::LDY_indirect_x_4, &CPU::LDY_indirect_x_5,
&CPU::LDY_indirect_y, &CPU::LDY_indirect_y_2, &CPU::LDY_indirect_y_3, &CPU::LDY_indirect_y_4, &CPU::LDY_indirect_y_5,
&CPU::LSR_accumulator,
&CPU::LSR_zero_page, &CPU::LSR_zero_page_2, &CPU::LSR_zero_page_3, &CPU::LSR_zero_page_4,
&CPU::LSR_zero_page_x, &CPU::LSR_zero_page_x_2, &CPU::LSR_zero_page_x_3, &CPU::LSR_zero_page_x_4, &CPU::LSR_zero_page_x_5,
&CPU::LSR_absolute, &CPU::LSR_absolute_2, &CPU::LSR_absolute_3, &CPU::LSR_absolute_4, &CPU::LSR_absolute_5,
&CPU::LSR_absolute_x, &CPU::LSR_absolute_x_2, &CPU::LSR_absolute_x_3, &CPU::LSR_absolute_x_4, &CPU::LSR_absolute_x_5, &CPU::LSR_absolute_x_6,
&CPU::LSR_absolute_y, &CPU::LSR_absolute_y_2, &CPU::LSR_absolute_y_3, &CPU::LSR_absolute_y_4, &CPU::LSR_absolute_y_5, &CPU::LSR_absolute_y_6,
&CPU::LSR_indirect_x, &CPU::LSR_indirect_x_2, &CPU::LSR_indirect_x_3, &CPU::LSR_indirect_x_4, &CPU::LSR_indirect_x_5, &CPU::LSR_indirect_x_6, &CPU::LSR_indirect_x_7,
&CPU::LSR_indirect_y, &CPU::LSR_indirect_y_2, &CPU::LSR_indirect_y_3, &CPU::LSR_indirect_y_4, &CPU::LSR_indirect_y_5, &CPU::LSR_indirect_y_6, &CPU::LSR_indirect_y_7,
&CPU::NOP,
&CPU::NOP_immediate,
&CPU::NOP_zero_page, &CPU::NOP_zero_page_2,
&CPU::NOP_zero_page_x, &CPU::NOP_zero_page_x_2, &CPU::NOP_zero_page_x_3,
&CPU::NOP_absolute, &CPU::NOP_absolute_2, &CPU::NOP_absolute_3,
&CPU::NOP_absolute_x, &CPU::NOP_absolute_x_2, &CPU::NOP_absolute_x_3, &CPU::NOP_absolute_x_4,
&CPU::ORA_immediate,
&CPU::ORA_zero_page, &CPU::ORA_zero_page_2,
&CPU::ORA_zero_page_x, &CPU::ORA_zero_page_x_2, &CPU::ORA_zero_page_x_3,
&CPU::ORA_absolute, &CPU::ORA_absolute_2, &CPU::ORA_absolute_3,
&CPU::ORA_absolute_x, &CPU::ORA_absolute_x_2, &CPU::ORA_absolute_x_3, &CPU::ORA_absolute_x_4,
&CPU::ORA_absolute_y, &CPU::ORA_absolute_y_2, &CPU::ORA_absolute_y_3, &CPU::ORA_absolute_y_4,
&CPU::ORA_indirect_x, &CPU::ORA_indirect_x_2, &CPU::ORA_indirect_x_3, &CPU::ORA_indirect_x_4, &CPU::ORA_indirect_x_5,
&CPU::ORA_indirect_y, &CPU::ORA_indirect_y_2, &CPU::ORA_indirect_y_3, &CPU::ORA_indirect_y_4, &CPU::ORA_indirect_y_5,
&CPU::PHA, &CPU::PHA_2,
&CPU::PHP, &CPU::PHP_2,
&CPU::PLA, &CPU::PLA_2, &CPU::PLA_3,
&CPU::PLP, &CPU::PLP_2, &CPU::PLP_3,
&CPU::ROL_accumulator,
&CPU::ROL_zero_page, &CPU::ROL_zero_page_2, &CPU::ROL_zero_page_3, &CPU::ROL_zero_page_4,
&CPU::ROL_zero_page_x, &CPU::ROL_zero_page_x_2, &CPU::ROL_zero_page_x_3, &CPU::ROL_zero_page_x_4, &CPU::ROL_zero_page_x_5,
&CPU::ROL_absolute, &CPU::ROL_absolute_2, &CPU::ROL_absolute_3, &CPU::ROL_absolute_4, &CPU::ROL_absolute_5,
&CPU::ROL_absolute_x, &CPU::ROL_absolute_x_2, &CPU::ROL_absolute_x_3, &CPU::ROL_absolute_x_4, &CPU::ROL_absolute_x_5, &CPU::ROL_absolute_x_6,
&CPU::ROL_indirect_x, &CPU::ROL_indirect_x_2, &CPU::ROL_indirect_x_3, &CPU::ROL_indirect_x_4, &CPU::ROL_indirect_x_5, &CPU::ROL_indirect_x_6, &CPU::ROL_indirect_x_7,
&CPU::ROR_accumulator,
&CPU::ROR_zero_page, &CPU::ROR_zero_page_2, &CPU::ROR_zero_page_3, &CPU::ROR_zero_page_4,
&CPU::ROR_zero_page_x, &CPU::ROR_zero_page_x_2, &CPU::ROR_zero_page_x_3, &CPU::ROR_zero_page_x_4, &CPU::ROR_zero_page_x_5,
&CPU::ROR_absolute, &CPU::ROR_absolute_2, &CPU::ROR_absolute_3, &CPU::ROR_absolute_4, &CPU::ROR_absolute_5,
&CPU::ROR_absolute_x, &CPU::ROR_absolute_x_2, &CPU::ROR_absolute_x_3, &CPU::ROR_absolute_x_4, &CPU::ROR_absolute_x_5, &CPU::ROR_absolute_x_6,
&CPU::ROR_indirect_x, &CPU::ROR_indirect_x_2, &CPU::ROR_indirect_x_3, &CPU::ROR_indirect_x_4, &CPU::ROR_indirect_x_5, &CPU::ROR_indirect_x_6, &CPU::ROR_indirect_x_7,
&CPU::RTI, &CPU::RTI_2, &CPU::RTI_3, &CPU::RTI_4, &CPU::RTI_5,
&CPU::RTS, &CPU::RTS_2, &CPU::RTS_3, &CPU::RTS_4, &CPU::RTS_5,
&CPU::SBC_immediate,
&CPU::SBC_zero_page, &CPU::SBC_zero_page_2,
&CPU::SBC_zero_page_x, &CPU::SBC_zero_page_x_2, &CPU::SBC_zero_page_x_3,
&CPU::SBC_absolute, &CPU::SBC_absolute_2, &CPU::SBC_absolute_3,
&CPU::SBC_absolute_x, &CPU::SBC_absolute_x_2, &CPU::SBC_absolute_x_3, &CPU::SBC_absolute_x_4,
&CPU::SBC_absolute_y, &CPU::SBC_absolute_y_2, &CPU::SBC_absolute_y_3, &CPU::SBC_absolute_y_4,
&CPU::SBC_indirect_x, &CPU::SBC_indirect_x_2, &CPU::SBC_indirect_x_3, &CPU::SBC_indirect_x_4, &CPU::SBC_indirect_x_5,
&CPU::SBC_indirect_y, &CPU::SBC_indirect_y_2, &CPU::SBC_indirect_y_3, &CPU::SBC_indirect_y_4, &CPU::SBC_indirect_y_5,
&CPU::SEC,
&CPU::SED,
&CPU::SEI,
&CPU::STA_zero_page, &CPU::STA_zero_page_2,
&CPU::STA_zero_page_x, &CPU::STA_zero_page_x_2, &CPU::STA_zero_page_x_3,
&CPU::STA_absolute, &CPU::STA_absolute_2, &CPU::STA_absolute_3,
&CPU::STA_absolute_x, &CPU::STA_absolute_x_2, &CPU::STA_absolute_x_3, &CPU::STA_absolute_x_4,
&CPU::STA_absolute_y, &CPU::STA_absolute_y_2, &CPU::STA_absolute_y_3, &CPU::STA_absolute_y_4,
&CPU::STA_indirect_x, &CPU::STA_indirect_x_2, &CPU::STA_indirect_x_3, &CPU::STA_indirect_x_4, &CPU::STA_indirect_x_5,
&CPU::STA_indirect_y, &CPU::STA_indirect_y_2, &CPU::STA_indirect_y_3, &CPU::STA_indirect_y_4, &CPU::STA_indirect_y_5,
&CPU::STX_zero_page, &CPU::STX_zero_page_2,
&CPU::STX_zero_page_y, &CPU::STX_zero_page_y_2, &CPU::STX_zero_page_y_3,
&CPU::STX_absolute, &CPU::STX_absolute_2, &CPU::STX_absolute_3,
&CPU::STY_zero_page, &CPU::STY_zero_page_2,
&CPU::STY_zero_page_x, &CPU::STY_zero_page_x_2, &CPU::STY_zero_page_x_3,
&CPU::STY_absolute, &CPU::STY_absolute_2, &CPU::STY_absolute_3,
&CPU::TAX,
&CPU::TAY,
&CPU::TSX,
&CPU::TXA,
&CPU::TXS,
&CPU::TYA,
// Illegal instructions
&CPU::ALR_immediate,
&CPU::ANC_immediate,
&CPU::ANE_immediate,
&CPU::ARR_immediate,
&CPU::AXS_immediate,
&CPU::DCP_zero_page, &CPU::DCP_zero_page_2, &CPU::DCP_zero_page_3, &CPU::DCP_zero_page_4,
&CPU::DCP_zero_page_x, &CPU::DCP_zero_page_x_2, &CPU::DCP_zero_page_x_3, &CPU::DCP_zero_page_x_4, &CPU::DCP_zero_page_x_5,
&CPU::DCP_absolute, &CPU::DCP_absolute_2, &CPU::DCP_absolute_3, &CPU::DCP_absolute_4, &CPU::DCP_absolute_5,
&CPU::DCP_absolute_x, &CPU::DCP_absolute_x_2, &CPU::DCP_absolute_x_3, &CPU::DCP_absolute_x_4, &CPU::DCP_absolute_x_5, &CPU::DCP_absolute_x_6,
&CPU::DCP_absolute_y, &CPU::DCP_absolute_y_2, &CPU::DCP_absolute_y_3, &CPU::DCP_absolute_y_4, &CPU::DCP_absolute_y_5, &CPU::DCP_absolute_y_6,
&CPU::DCP_indirect_x, &CPU::DCP_indirect_x_2, &CPU::DCP_indirect_x_3, &CPU::DCP_indirect_x_4, &CPU::DCP_indirect_x_5, &CPU::DCP_indirect_x_6, &CPU::DCP_indirect_x_7,
&CPU::DCP_indirect_y, &CPU::DCP_indirect_y_2, &CPU::DCP_indirect_y_3, &CPU::DCP_indirect_y_4, &CPU::DCP_indirect_y_5, &CPU::DCP_indirect_y_6, &CPU::DCP_indirect_y_7,
&CPU::ISC_zero_page, &CPU::ISC_zero_page_2, &CPU::ISC_zero_page_3, &CPU::ISC_zero_page_4,
&CPU::ISC_zero_page_x, &CPU::ISC_zero_page_x_2, &CPU::ISC_zero_page_x_3, &CPU::ISC_zero_page_x_4, &CPU::ISC_zero_page_x_5,
&CPU::ISC_absolute, &CPU::ISC_absolute_2, &CPU::ISC_absolute_3, &CPU::ISC_absolute_4, &CPU::ISC_absolute_5,
&CPU::ISC_absolute_x, &CPU::ISC_absolute_x_2, &CPU::ISC_absolute_x_3, &CPU::ISC_absolute_x_4, &CPU::ISC_absolute_x_5, &CPU::ISC_absolute_x_6,
&CPU::ISC_absolute_y, &CPU::ISC_absolute_y_2, &CPU::ISC_absolute_y_3, &CPU::ISC_absolute_y_4, &CPU::ISC_absolute_y_5, &CPU::ISC_absolute_y_6,
&CPU::ISC_indirect_x, &CPU::ISC_indirect_x_2, &CPU::ISC_indirect_x_3, &CPU::ISC_indirect_x_4, &CPU::ISC_indirect_x_5, &CPU::ISC_indirect_x_6, &CPU::ISC_indirect_x_7,
&CPU::ISC_indirect_y, &CPU::ISC_indirect_y_2, &CPU::ISC_indirect_y_3, &CPU::ISC_indirect_y_4, &CPU::ISC_indirect_y_5, &CPU::ISC_indirect_y_6, &CPU::ISC_indirect_y_7,
&CPU::LAS_absolute_y, &CPU::LAS_absolute_y_2, &CPU::LAS_absolute_y_3, &CPU::LAS_absolute_y_4,
&CPU::LAX_zero_page, &CPU::LAX_zero_page_2,
&CPU::LAX_zero_page_y, &CPU::LAX_zero_page_y_2, &CPU::LAX_zero_page_y_3,
&CPU::LAX_absolute, &CPU::LAX_absolute_2, &CPU::LAX_absolute_3,
&CPU::LAX_absolute_y, &CPU::LAX_absolute_y_2, &CPU::LAX_absolute_y_3, &CPU::LAX_absolute_y_4,
&CPU::LAX_indirect_x, &CPU::LAX_indirect_x_2, &CPU::LAX_indirect_x_3, &CPU::LAX_indirect_x_4, &CPU::LAX_indirect_x_5,
&CPU::LAX_indirect_y, &CPU::LAX_indirect_y_2, &CPU::LAX_indirect_y_3, &CPU::LAX_indirect_y_4, &CPU::LAX_indirect_y_5,
&CPU::LXA_immediate,
&CPU::RLA_zero_page, &CPU::RLA_zero_page_2, &CPU::RLA_zero_page_3, &CPU::RLA_zero_page_4,
&CPU::RLA_zero_page_x, &CPU::RLA_zero_page_x_2, &CPU::RLA_zero_page_x_3, &CPU::RLA_zero_page_x_4, &CPU::RLA_zero_page_x_5,
&CPU::RLA_absolute, &CPU::RLA_absolute_2, &CPU::RLA_absolute_3, &CPU::RLA_absolute_4, &CPU::RLA_absolute_5,
&CPU::RLA_absolute_x, &CPU::RLA_absolute_x_2, &CPU::RLA_absolute_x_3, &CPU::RLA_absolute_x_4, &CPU::RLA_absolute_x_5, &CPU::RLA_absolute_x_6,
&CPU::RLA_absolute_y, &CPU::RLA_absolute_y_2, &CPU::RLA_absolute_y_3, &CPU::RLA_absolute_y_4, &CPU::RLA_absolute_y_5, &CPU::RLA_absolute_y_6,
&CPU::RLA_indirect_x, &CPU::RLA_indirect_x_2, &CPU::RLA_indirect_x_3, &CPU::RLA_indirect_x_4, &CPU::RLA_indirect_x_5, &CPU::RLA_indirect_x_6, &CPU::RLA_indirect_x_7,
&CPU::RLA_indirect_y, &CPU::RLA_indirect_y_2, &CPU::RLA_indirect_y_3, &CPU::RLA_indirect_y_4, &CPU::RLA_indirect_y_5, &CPU::RLA_indirect_y_6, &CPU::RLA_indirect_y_7,
&CPU::RRA_zero_page, &CPU::RRA_zero_page_2, &CPU::RRA_zero_page_3, &CPU::RRA_zero_page_4,
&CPU::RRA_zero_page_x, &CPU::RRA_zero_page_x_2, &CPU::RRA_zero_page_x_3, &CPU::RRA_zero_page_x_4, &CPU::RRA_zero_page_x_5,
&CPU::RRA_absolute, &CPU::RRA_absolute_2, &CPU::RRA_absolute_3, &CPU::RRA_absolute_4, &CPU::RRA_absolute_5,
&CPU::RRA_absolute_x, &CPU::RRA_absolute_x_2, &CPU::RRA_absolute_x_3, &CPU::RRA_absolute_x_4, &CPU::RRA_absolute_x_5, &CPU::RRA_absolute_x_6,
&CPU::RRA_absolute_y, &CPU::RRA_absolute_y_2, &CPU::RRA_absolute_y_3, &CPU::RRA_absolute_y_4, &CPU::RRA_absolute_y_5, &CPU::RRA_absolute_y_6,
&CPU::RRA_indirect_x, &CPU::RRA_indirect_x_2, &CPU::RRA_indirect_x_3, &CPU::RRA_indirect_x_4, &CPU::RRA_indirect_x_5, &CPU::RRA_indirect_x_6, &CPU::RRA_indirect_x_7,
&CPU::RRA_indirect_y, &CPU::RRA_indirect_y_2, &CPU::RRA_indirect_y_3, &CPU::RRA_indirect_y_4, &CPU::RRA_indirect_y_5, &CPU::RRA_indirect_y_6, &CPU::RRA_indirect_y_7,
&CPU::SAX_zero_page, &CPU::SAX_zero_page_2,
&CPU::SAX_zero_page_y, &CPU::SAX_zero_page_y_2, &CPU::SAX_zero_page_y_3,
&CPU::SAX_absolute, &CPU::SAX_absolute_2, &CPU::SAX_absolute_3,
&CPU::SAX_indirect_x, &CPU::SAX_indirect_x_2, &CPU::SAX_indirect_x_3, &CPU::SAX_indirect_x_4, &CPU::SAX_indirect_x_5,
&CPU::SHA_indirect_y, &CPU::SHA_indirect_y_2, &CPU::SHA_indirect_y_3, &CPU::SHA_indirect_y_4, &CPU::SHA_indirect_y_5,
&CPU::SHA_absolute_y, &CPU::SHA_absolute_y_2, &CPU::SHA_absolute_y_3, &CPU::SHA_absolute_y_4,
&CPU::SHX_absolute_y, &CPU::SHX_absolute_y_2, &CPU::SHX_absolute_y_3, &CPU::SHX_absolute_y_4,
&CPU::SHY_absolute_x, &CPU::SHY_absolute_x_2, &CPU::SHY_absolute_x_3, &CPU::SHY_absolute_x_4,
&CPU::SLO_zero_page, &CPU::SLO_zero_page_2, &CPU::SLO_zero_page_3, &CPU::SLO_zero_page_4,
&CPU::SLO_zero_page_x, &CPU::SLO_zero_page_x_2, &CPU::SLO_zero_page_x_3, &CPU::SLO_zero_page_x_4, &CPU::SLO_zero_page_x_5,
&CPU::SLO_absolute, &CPU::SLO_absolute_2, &CPU::SLO_absolute_3, &CPU::SLO_absolute_4, &CPU::SLO_absolute_5,
&CPU::SLO_absolute_x, &CPU::SLO_absolute_x_2, &CPU::SLO_absolute_x_3, &CPU::SLO_absolute_x_4, &CPU::SLO_absolute_x_5, &CPU::SLO_absolute_x_6,
&CPU::SLO_absolute_y, &CPU::SLO_absolute_y_2, &CPU::SLO_absolute_y_3, &CPU::SLO_absolute_y_4, &CPU::SLO_absolute_y_5, &CPU::SLO_absolute_y_6,
&CPU::SLO_indirect_x, &CPU::SLO_indirect_x_2, &CPU::SLO_indirect_x_3, &CPU::SLO_indirect_x_4, &CPU::SLO_indirect_x_5, &CPU::SLO_indirect_x_6, &CPU::SLO_indirect_x_7,
&CPU::SLO_indirect_y, &CPU::SLO_indirect_y_2, &CPU::SLO_indirect_y_3, &CPU::SLO_indirect_y_4, &CPU::SLO_indirect_y_5, &CPU::SLO_indirect_y_6, &CPU::SLO_indirect_y_7,
&CPU::SRE_zero_page, &CPU::SRE_zero_page_2, &CPU::SRE_zero_page_3, &CPU::SRE_zero_page_4,
&CPU::SRE_zero_page_x, &CPU::SRE_zero_page_x_2, &CPU::SRE_zero_page_x_3, &CPU::SRE_zero_page_x_4, &CPU::SRE_zero_page_x_5,
&CPU::SRE_absolute, &CPU::SRE_absolute_2, &CPU::SRE_absolute_3, &CPU::SRE_absolute_4, &CPU::SRE_absolute_5,
&CPU::SRE_absolute_x, &CPU::SRE_absolute_x_2, &CPU::SRE_absolute_x_3, &CPU::SRE_absolute_x_4, &CPU::SRE_absolute_x_5, &CPU::SRE_absolute_x_6,
&CPU::SRE_absolute_y, &CPU::SRE_absolute_y_2, &CPU::SRE_absolute_y_3, &CPU::SRE_absolute_y_4, &CPU::SRE_absolute_y_5, &CPU::SRE_absolute_y_6,
&CPU::SRE_indirect_x, &CPU::SRE_indirect_x_2, &CPU::SRE_indirect_x_3, &CPU::SRE_indirect_x_4, &CPU::SRE_indirect_x_5, &CPU::SRE_indirect_x_6, &CPU::SRE_indirect_x_7,
&CPU::SRE_indirect_y, &CPU::SRE_indirect_y_2, &CPU::SRE_indirect_y_3, &CPU::SRE_indirect_y_4, &CPU::SRE_indirect_y_5, &CPU::SRE_indirect_y_6, &CPU::SRE_indirect_y_7,
&CPU::TAS_absolute_y, &CPU::TAS_absolute_y_2, &CPU::TAS_absolute_y_3, &CPU::TAS_absolute_y_4,
NULL
};