/* * (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 ausgefŸhrt 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 };