#pragma once #include namespace m6502 { namespace opcodes { enum instruction { iADC, iAND, iASL, iBCC, iBCS, iBEQ, iBIT, iBMI, iBNE, iBPL, iBRK, iBVC, iBVS, iCLC, iCLD, iCLI, iCLV, iCMP, iCPX, iCPY, iDEC, iDEX, iDEY, iEOR, iINC, iINX, iINY, iJMP, iJSR, iLDA, iLDX, iLDY, iLSR, iNOP, iORA, iPHA, iPHP, iPLA, iPLP, iROL, iROR, iRTI, iRTS, iSBC, iSEC, iSED, iSEI, iSTA, iSTX, iSTY, iTAX, iTAY, iTSX, iTXA, iTXS, iTYA, iILL }; enum functionalGroup { fgLoadStore, fgTransfer, fgStack, fgLogical, fgArithmetic, fgIncDec, fgShift, fgJumpCall, fgBranch, fgStatusFlag, fgSystem, fgIllegal }; struct instructionProperties { const char *name; functionalGroup group; const char *longName; const char *operation; const char *description; }; inline const instructionProperties instructions[] = { {"ADC", fgArithmetic, "Add with Carry", "", "This instruction adds the contents of a memory location to the accumulator together with the carry bit. If overflow occurs the carry bit is set, this enables multiple byte addition to be performed." }, {"AND", fgLogical, "Logical AND", "", "A logical AND is performed, bit by bit, on the accumulator contents using the contents of a byte of memory." }, {"ASL", fgShift, "Arithmetic Shift Left", "", "This operation shifts all the bits of the accumulator or memory contents one bit left. Bit 0 is set to 0 and bit 7 is placed in the carry flag. The effect of this operation is to multiply the memory contents by 2 (ignoring 2's complement considerations), setting the carry if the result will not fit in 8 bits." }, {"BCC", fgBranch, "Branch if Carry Clear", "", "If the carry flag is clear then add the relative displacement to the program counter to cause a branch to a new location." }, {"BCS", fgBranch, "Branch if Carry Set", "", "If the carry flag is set then add the relative displacement to the program counter to cause a branch to a new location." }, {"BEQ", fgBranch, "Branch if Equal", "", "" }, {"BIT", fgLogical, "Bit Test", "", "" }, {"BMI", fgBranch, "Branch if Minus", "", "" }, {"BNE", fgBranch, "Branch if Not Equal", "", "" }, {"BPL", fgBranch, "Branch if Positive", "", "" }, {"BRK", fgSystem, "Force Interrupt", "", "" }, {"BVC", fgBranch, "Branch if Overflow Clear", "", "" }, {"BVS", fgBranch, "Branch if Overflow Set", "", "" }, {"CLC", fgStatusFlag, "Clear Carry Flag", "", "" }, {"CLD", fgStatusFlag, "Clear Decimal Mode", "", "" }, {"CLI", fgStatusFlag, "Clear Interrupt Disable", "", "" }, {"CLV", fgStatusFlag, "Clear Overflow Flag", "", "" }, {"CMP", fgArithmetic, "Compare", "", "" }, {"CPX", fgArithmetic, "Compare X Register", "", "" }, {"CPY", fgArithmetic, "Compare Y Register", "", "" }, {"DEC", fgIncDec, "Decrement Memory", "", "" }, {"DEX", fgIncDec, "Decrement X Register", "", "" }, {"DEY", fgIncDec, "Decrement Y Register", "", "" }, {"EOR", fgLogical, "Exclusive OR", "", "" }, {"INC", fgIncDec, "Increment Memory", "", "" }, {"INX", fgIncDec, "Increment X Register", "", "" }, {"INY", fgIncDec, "Increment Y Register", "", "" }, {"JMP", fgJumpCall, "Jump", "", "" }, {"JSR", fgJumpCall, "Jump to Subroutine", "", "" }, {"LDA", fgLoadStore, "Load Accumulator", "", "" }, {"LDX", fgLoadStore, "Load X Register", "", "" }, {"LDY", fgLoadStore, "Load Y Register", "", "" }, {"LSR", fgShift, "Logical Shift Right", "", "" }, {"NOP", fgSystem, "No Operation", "", "" }, {"ORA", fgLogical, "Logical Incluisve OR", "", "" }, {"PHA", fgStack, "Push Accumulator", "", "" }, {"PHP", fgStack, "Push Processor Status", "", "" }, {"PLA", fgStack, "Pull Accumulator", "", "" }, {"PLP", fgStack, "Pull Processor Status", "", "" }, {"ROL", fgShift, "Rotate Left", "", "" }, {"ROR", fgShift, "Rotate Right", "", "" }, {"RTI", fgSystem, "Return from Interrupt", "", "" }, {"RTS", fgJumpCall, "Return from Subroutine", "", "" }, {"SBC", fgArithmetic, "Substract with Carry", "", "" }, {"SEC", fgStatusFlag, "Set Carry Flag", "", "" }, {"SED", fgStatusFlag, "Set Decimal Flag", "", "" }, {"SEI", fgStatusFlag, "Set Interrupt Disable", "", "" }, {"STA", fgLoadStore, "Store Accumulator", "", "" }, {"STX", fgLoadStore, "Store X Register", "", "" }, {"STY", fgLoadStore, "Store Y Register", "", "" }, {"TAX", fgTransfer, "Transfer Accumulator to X", "", "" }, {"TAY", fgTransfer, "Transfer Accumulator to Y", "", "" }, {"TSX", fgStack, "Transfer Stack Pointer to X", "", "" }, {"TXA", fgTransfer, "Transfer X to Accumulator", "", "" }, {"TXS", fgStack, "Transfer X to Stack Pointer", "", "" }, {"TYA", fgTransfer, "Transfer Y to Accumulator", "", "" }, {"---", fgIllegal, "Illegal Instruction", "", ""} }; enum addressingMode { amImplicit, amAccumulator, amImmediate, amZeroPage, amZeroPageX, amZeroPageY, amRelative, amAbsolute, amAbsoluteX, amAbsoluteY, amIndirect, amIndirectX, amIndirectY }; struct addressingModeProperties { const char *name; uint8_t length; const char *preText; const char *postText; }; inline const addressingModeProperties addressingModes[] = { {"Implicit", 1, "", ""}, {"Accumulator", 1, "A", ""}, {"Immediate", 2, "#", ""}, {"ZeroPage", 2, "", ""}, {"ZeroPage,X", 2, "", ",X"}, {"ZeroPage,Y", 2, "", ",Y"}, {"Relative", 2, "", ""}, {"Absolute", 3, "", ""}, {"Absolute,X", 3, "", ",X"}, {"Absolute,Y", 3, "", ",Y"}, {"Indirect", 3, "(", ")"}, {"Indexed Indirect", 2, "(", ",X)"}, {"Indirect Indexed", 2, "(", "),Y"} }; struct opcodeProperties { instruction instr; addressingMode addrMode; uint8_t cycles; bool ifBoundaryCrossed; bool ifBranchTaken; }; inline const opcodeProperties opcodeDescriptors[256] = { {iBRK, amImplicit, 7, false, false}, {iORA, amIndirectX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iORA, amZeroPage, 3, false, false}, {iASL, amZeroPage, 5, false, false}, {iILL, amImplicit, 2, false, false}, {iPHP, amImplicit, 3, false, false}, {iORA, amImmediate, 2, false, false}, {iASL, amAccumulator, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iORA, amAbsolute, 4, false, false}, {iASL, amAbsolute, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iBPL, amRelative, 2, true, true }, {iORA, amIndirectY, 5, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iORA, amZeroPageX, 4, false, false}, {iASL, amZeroPageX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iCLC, amImplicit, 2, false, false}, {iORA, amAbsoluteY, 4, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iORA, amAbsoluteX, 4, true, false}, {iASL, amAbsoluteX, 7, false, false}, {iILL, amImplicit, 2, false, false}, {iJSR, amAbsolute, 6, false, false}, {iAND, amIndirectX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iBIT, amZeroPage, 3, false, false}, {iAND, amZeroPage, 3, false, false}, {iROL, amZeroPage, 5, false, false}, {iILL, amImplicit, 2, false, false}, {iPLP, amImplicit, 4, false, false}, {iAND, amImmediate, 2, false, false}, {iROL, amAccumulator, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iBIT, amAbsolute, 4, false, false}, {iAND, amAbsolute, 4, false, false}, {iROL, amAbsolute, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iBMI, amRelative, 2, true, true }, {iAND, amIndirectY, 5, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iAND, amZeroPageX, 4, false, false}, {iROL, amZeroPageX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iSEC, amImplicit, 2, false, false}, {iAND, amAbsoluteY, 4, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iAND, amAbsoluteX, 4, true, false}, {iROL, amAbsoluteX, 7, false, false}, {iILL, amImplicit, 2, false, false}, {iRTI, amImplicit, 6, false, false}, {iEOR, amIndirectX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iEOR, amZeroPage, 3, false, false}, {iLSR, amZeroPage, 5, false, false}, {iILL, amImplicit, 2, false, false}, {iPHA, amImplicit, 3, false, false}, {iEOR, amImmediate, 2, false, false}, {iLSR, amAccumulator, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iJMP, amAbsolute, 3, false, false}, {iEOR, amAbsolute, 4, false, false}, {iLSR, amAbsolute, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iBVC, amRelative, 2, true, true }, {iEOR, amIndirectY, 5, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iEOR, amZeroPageX, 4, false, false}, {iLSR, amZeroPageX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iCLI, amImplicit, 2, false, false}, {iEOR, amAbsoluteY, 4, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iEOR, amAbsoluteX, 4, true, false}, {iLSR, amAbsoluteX, 7, false, false}, {iILL, amImplicit, 2, false, false}, {iRTS, amImplicit, 6, false, false}, {iADC, amIndirectX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iADC, amZeroPage, 3, false, false}, {iROR, amZeroPage, 5, false, false}, {iILL, amImplicit, 2, false, false}, {iPLA, amImplicit, 4, false, false}, {iADC, amImmediate, 2, false, false}, {iROR, amAccumulator, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iJMP, amIndirect, 5, false, false}, {iADC, amAbsolute, 4, false, false}, {iROR, amAbsolute, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iBVS, amRelative, 2, true, true }, {iADC, amIndirectY, 5, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iADC, amZeroPageX, 4, false, false}, {iROR, amZeroPageX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iSEI, amImplicit, 2, false, false}, {iADC, amAbsoluteY, 4, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iADC, amAbsoluteX, 4, true, false}, {iROR, amAbsoluteX, 7, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iSTA, amIndirectX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iSTY, amZeroPage, 3, false, false}, {iSTA, amZeroPage, 3, false, false}, {iSTX, amZeroPage, 3, false, false}, {iILL, amImplicit, 2, false, false}, {iDEY, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iTXA, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iSTY, amAbsolute, 4, false, false}, {iSTA, amAbsolute, 4, false, false}, {iSTX, amAbsolute, 4, false, false}, {iILL, amImplicit, 2, false, false}, {iBCC, amRelative, 2, true, true }, {iSTA, amIndirectY, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iSTY, amZeroPageX, 4, false, false}, {iSTA, amZeroPageX, 4, false, false}, {iSTX, amZeroPageY, 4, false, false}, {iILL, amImplicit, 2, false, false}, {iTYA, amImplicit, 2, false, false}, {iSTA, amAbsoluteY, 5, false, false}, {iTXS, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iSTA, amAbsoluteX, 5, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iLDY, amImmediate, 2, false, false}, {iLDA, amIndirectX, 6, false, false}, {iLDX, amImmediate, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iLDY, amZeroPage, 3, false, false}, {iLDA, amZeroPage, 3, false, false}, {iLDX, amZeroPage, 3, false, false}, {iILL, amImplicit, 2, false, false}, {iTAY, amImplicit, 2, false, false}, {iLDA, amImmediate, 2, false, false}, {iTAX, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iLDY, amAbsolute, 4, false, false}, {iLDA, amAbsolute, 4, false, false}, {iLDX, amAbsolute, 4, false, false}, {iILL, amImplicit, 2, false, false}, {iBCS, amRelative, 2, true, true }, {iLDA, amIndirectY, 5, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iLDY, amZeroPageX, 4, false, false}, {iLDA, amZeroPageX, 4, false, false}, {iLDX, amZeroPageY, 4, false, false}, {iILL, amImplicit, 2, false, false}, {iCLV, amImplicit, 2, false, false}, {iLDA, amAbsoluteY, 4, true, false}, {iTSX, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iLDY, amAbsoluteX, 4, true, false}, {iLDA, amAbsoluteX, 4, true, false}, {iLDX, amAbsoluteY, 4, true, false}, {iILL, amImplicit, 2, false, false}, {iCPY, amImmediate, 2, false, false}, {iCMP, amIndirectX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iCPY, amZeroPage, 3, false, false}, {iCMP, amZeroPage, 3, false, false}, {iDEC, amZeroPage, 5, false, false}, {iILL, amImplicit, 2, false, false}, {iINY, amImplicit, 2, false, false}, {iCMP, amImmediate, 2, false, false}, {iDEX, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iCPY, amAbsolute, 4, false, false}, {iCMP, amAbsolute, 4, false, false}, {iDEC, amAbsolute, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iBNE, amRelative, 2, true, true }, {iCMP, amIndirectY, 5, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iCMP, amZeroPageX, 4, false, false}, {iDEC, amZeroPageX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iCLD, amImplicit, 2, false, false}, {iCMP, amAbsoluteY, 4, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iCMP, amAbsoluteX, 4, true, false}, {iDEC, amAbsoluteX, 7, false, false}, {iILL, amImplicit, 2, false, false}, {iCPX, amImmediate, 2, false, false}, {iSBC, amIndirectX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iCPX, amZeroPage, 3, false, false}, {iSBC, amZeroPage, 3, false, false}, {iINC, amZeroPage, 5, false, false}, {iILL, amImplicit, 2, false, false}, {iINX, amImplicit, 2, false, false}, {iSBC, amImmediate, 2, false, false}, {iNOP, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iCPX, amAbsolute, 4, false, false}, {iSBC, amAbsolute, 4, false, false}, {iINC, amAbsolute, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iBEQ, amRelative, 2, true, true }, {iSBC, amIndirectY, 5, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iSBC, amZeroPageX, 4, false, false}, {iINC, amZeroPageX, 6, false, false}, {iILL, amImplicit, 2, false, false}, {iSED, amImplicit, 2, false, false}, {iSBC, amAbsoluteY, 4, true, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iILL, amImplicit, 2, false, false}, {iSBC, amAbsoluteX, 4, true, false}, {iINC, amAbsoluteX, 7, false, false}, {iILL, amImplicit, 2, false, false}, }; } }