// table.c #include"table.h" void* InstructionTable; void (*Instruction)(Addressing); // Macros for accessing the InstructionTable #define InstructionTableFunction(x) ((uintptr_t*)(InstructionTable + (sizeof(uintptr_t) * x))) #define InstructionTableAddressing(x) ((Addressing*)(InstructionTable + (sizeof(uintptr_t) * 256) + (sizeof(Addressing) * x))) #define InstructionTableCycles(x) ((int*)(InstructionTable + (sizeof(uintptr_t) * 256) + (sizeof(Addressing) * 256) + (sizeof(int) * x))) const InstructionTableSize = (256 * (sizeof(uintptr_t) + sizeof(Addressing) + sizeof(int))); void CallInstructionTable() { // Set function. memcpy(&Instruction, InstructionTableFunction((int)GetMemory(PC)), sizeof(uintptr_t)); // Find the addressing mode. Addressing r = *InstructionTableAddressing(GetMemory(PC)); // Set val int val = 0; if (fAddressGetLength(r) >= 2) val += GetMemory(PC+1); if (fAddressGetLength(r) == 3) val += ((address)GetMemory(PC+2)) << 8; // Set state state = fAddress(r, val); // Perform function Instruction(r); // Incrememt the program counter. PC += state.length; } void SetInstructionTable(int index, void* function, Addressing addressing, int cycles) { *InstructionTableFunction(index) = (uintptr_t)function; *InstructionTableAddressing(index) = addressing; *InstructionTableCycles(index) = cycles; } void InitInstructionTable() { // Create InstructionTable InstructionTable = malloc(InstructionTableSize); // Load and Store Instructions // LDA SetInstructionTable(0xA9, &LDA, eImmediate, 2); SetInstructionTable(0xA5, &LDA, eZeroPage, 3); SetInstructionTable(0xB5, &LDA, eZeroPageIndexedX, 4); SetInstructionTable(0xAD, &LDA, eAbsolute, 4); SetInstructionTable(0xBD, &LDA, eAbsoluteIndexedX, 4); SetInstructionTable(0xB9, &LDA, eAbsoluteIndexedY, 4); SetInstructionTable(0xA1, &LDA, eIndexedIndirect, 6); SetInstructionTable(0xB1, &LDA, eIndirectIndexed, 5); // LDX SetInstructionTable(0xA2, &LDX, eImmediate, 2); SetInstructionTable(0xA6, &LDX, eZeroPage, 3); SetInstructionTable(0xB6, &LDX, eZeroPageIndexedY, 4); SetInstructionTable(0xAE, &LDX, eAbsolute, 4); SetInstructionTable(0xBE, &LDX, eAbsoluteIndexedY, 4); // LDY SetInstructionTable(0xA0, &LDY, eImmediate, 2); SetInstructionTable(0xA4, &LDY, eZeroPage, 3); SetInstructionTable(0xB4, &LDY, eZeroPageIndexedX, 4); SetInstructionTable(0xAC, &LDY, eAbsolute, 4); SetInstructionTable(0xBC, &LDY, eAbsoluteIndexedX, 4); // STA SetInstructionTable(0x85, &STA, eZeroPage, 3); SetInstructionTable(0x95, &STA, eZeroPageIndexedX, 4); SetInstructionTable(0x8D, &STA, eAbsolute, 4); SetInstructionTable(0x9D, &STA, eAbsoluteIndexedX, 5); SetInstructionTable(0x99, &STA, eAbsoluteIndexedY, 5); SetInstructionTable(0x81, &STA, eIndexedIndirect, 6); SetInstructionTable(0x91, &STA, eIndirectIndexed, 6); // STX SetInstructionTable(0x86, &STX, eZeroPage, 3); SetInstructionTable(0x96, &STX, eZeroPageIndexedX, 4); SetInstructionTable(0x8E, &STX, eAbsolute, 4); // STY SetInstructionTable(0x84, &STY, eZeroPage, 3); SetInstructionTable(0x94, &STY, eZeroPageIndexedY, 4); SetInstructionTable(0x8C, &STY, eAbsolute, 4); // Arithmetic Instructions // ADC SetInstructionTable(0x69, &ADC, eImmediate, 2); SetInstructionTable(0x65, &ADC, eZeroPage, 3); SetInstructionTable(0x75, &ADC, eZeroPageIndexedX, 4); SetInstructionTable(0x6D, &ADC, eAbsolute, 4); SetInstructionTable(0x7D, &ADC, eAbsoluteIndexedX, 4); SetInstructionTable(0x79, &ADC, eAbsoluteIndexedY, 4); SetInstructionTable(0x61, &ADC, eIndexedIndirect, 6); SetInstructionTable(0x71, &ADC, eIndirectIndexed, 5); // SBC SetInstructionTable(0xE9, &SBC, eImmediate, 2); SetInstructionTable(0xE5, &SBC, eZeroPage, 3); SetInstructionTable(0xF5, &SBC, eZeroPageIndexedX, 4); SetInstructionTable(0xED, &SBC, eAbsolute, 4); SetInstructionTable(0xFD, &SBC, eAbsoluteIndexedX, 4); SetInstructionTable(0xF9, &SBC, eAbsoluteIndexedY, 4); SetInstructionTable(0xE1, &SBC, eIndexedIndirect, 6); SetInstructionTable(0xF1, &SBC, eIndirectIndexed, 5); // Increment and Decrement Instructions // INC SetInstructionTable(0xE6, &INC, eZeroPage, 5); SetInstructionTable(0xF6, &INC, eZeroPageIndexedX, 6); SetInstructionTable(0xEE, &INC, eAbsolute, 6); SetInstructionTable(0xFE, &INC, eAbsoluteIndexedX, 7); // INX SetInstructionTable(0xE8, &INX, eImplied, 2); // INY SetInstructionTable(0xC8, &INY, eImplied, 2); // DEC SetInstructionTable(0xC6, &DEC, eZeroPage, 5); SetInstructionTable(0xD6, &DEC, eZeroPageIndexedX, 6); SetInstructionTable(0xCE, &DEC, eAbsolute, 6); SetInstructionTable(0xDE, &DEC, eAbsoluteIndexedX, 7); // DEX SetInstructionTable(0xCA, &DEX, eImplied, 2); // DEY SetInstructionTable(0x88, &DEY, eImplied, 2); // Logical Instructions // AND SetInstructionTable(0x29, &AND, eImmediate, 2); SetInstructionTable(0x25, &AND, eZeroPage, 3); SetInstructionTable(0x35, &AND, eZeroPageIndexedX, 4); SetInstructionTable(0x2D, &AND, eAbsolute, 4); SetInstructionTable(0x3D, &AND, eAbsoluteIndexedX, 4); SetInstructionTable(0x39, &AND, eAbsoluteIndexedY, 4); SetInstructionTable(0x21, &AND, eIndexedIndirect, 6); SetInstructionTable(0x31, &AND, eIndirectIndexed, 5); // ORA SetInstructionTable(0x09, &ORA, eImmediate, 2); SetInstructionTable(0x05, &ORA, eZeroPage, 3); SetInstructionTable(0x15, &ORA, eZeroPageIndexedX, 4); SetInstructionTable(0x0D, &ORA, eAbsolute, 4); SetInstructionTable(0x1D, &ORA, eAbsoluteIndexedX, 4); SetInstructionTable(0x19, &ORA, eAbsoluteIndexedY, 4); SetInstructionTable(0x01, &ORA, eIndexedIndirect, 6); SetInstructionTable(0x11, &ORA, eIndirectIndexed, 5); // EOR SetInstructionTable(0x49, &EOR, eImmediate, 2); SetInstructionTable(0x45, &EOR, eZeroPage, 3); SetInstructionTable(0x55, &EOR, eZeroPageIndexedX, 4); SetInstructionTable(0x4D, &EOR, eAbsolute, 4); SetInstructionTable(0x5D, &EOR, eAbsoluteIndexedX, 4); SetInstructionTable(0x59, &EOR, eAbsoluteIndexedY, 4); SetInstructionTable(0x41, &EOR, eIndexedIndirect, 6); SetInstructionTable(0x51, &EOR, eIndirectIndexed, 5); // Jump, Branch, Compare, and Test Bits // JMP SetInstructionTable(0x4C, &JMP, eAbsolute, 3); SetInstructionTable(0x6C, &JMP, eIndirectAbsolute, 5); // BCC SetInstructionTable(0x90, &BCC, eRelative, 2); // BCS SetInstructionTable(0xB0, &BCS, eRelative, 2); // BEQ SetInstructionTable(0xF0, &BEQ, eRelative, 2); // BNE SetInstructionTable(0xD0, &BNE, eRelative, 2); // BMI SetInstructionTable(0x30, &BMI, eRelative, 2); // BPL SetInstructionTable(0x10, &BPL, eRelative, 2); // BVS SetInstructionTable(0x70, &BVS, eRelative, 2); // BVC SetInstructionTable(0x50, &BVC, eRelative, 2); // CMP SetInstructionTable(0xC9, &CMP, eImmediate, 2); SetInstructionTable(0xC5, &CMP, eZeroPage, 3); SetInstructionTable(0xD5, &CMP, eZeroPageIndexedX, 4); SetInstructionTable(0xCD, &CMP, eAbsolute, 4); SetInstructionTable(0xDD, &CMP, eAbsoluteIndexedX, 4); SetInstructionTable(0xD9, &CMP, eAbsoluteIndexedY, 4); SetInstructionTable(0xC1, &CMP, eIndexedIndirect, 6); SetInstructionTable(0xD1, &CMP, eIndirectIndexed, 5); // CPX SetInstructionTable(0xE0, &CPX, eImmediate, 2); SetInstructionTable(0xE4, &CPX, eZeroPage, 3); SetInstructionTable(0xEC, &CPX, eAbsolute, 4); // CPY SetInstructionTable(0xC0, &CPY, eImmediate, 2); SetInstructionTable(0xC4, &CPY, eZeroPage, 3); SetInstructionTable(0xCC, &CPY, eAbsolute, 4); // BIT SetInstructionTable(0x24, &BIT, eZeroPage, 3); SetInstructionTable(0x2C, &BIT, eAbsolute, 4); // Shift and Rotate Instructions // ASL SetInstructionTable(0x0A, &ASL, eAccumulator, 2); SetInstructionTable(0x06, &ASL, eZeroPage, 5); SetInstructionTable(0x16, &ASL, eZeroPageIndexedX, 6); SetInstructionTable(0x0E, &ASL, eAbsolute, 6); SetInstructionTable(0x1E, &ASL, eAbsoluteIndexedX, 7); // LSR SetInstructionTable(0x4A, &LSR, eAccumulator, 2); SetInstructionTable(0x46, &LSR, eZeroPage, 5); SetInstructionTable(0x56, &LSR, eZeroPageIndexedX, 6); SetInstructionTable(0x4E, &LSR, eAbsolute, 6); SetInstructionTable(0x5E, &LSR, eAbsoluteIndexedX, 7); // ROL SetInstructionTable(0x2A, &ROL, eAccumulator, 2); SetInstructionTable(0x26, &ROL, eZeroPage, 5); SetInstructionTable(0x36, &ROL, eZeroPageIndexedX, 6); SetInstructionTable(0x2E, &ROL, eAbsolute, 6); SetInstructionTable(0x3E, &ROL, eAbsoluteIndexedX, 7); // ROR SetInstructionTable(0x6A, &ROR, eAccumulator, 2); SetInstructionTable(0x66, &ROR, eZeroPage, 5); SetInstructionTable(0x76, &ROR, eZeroPageIndexedX, 6); SetInstructionTable(0x6E, &ROR, eAbsolute, 6); SetInstructionTable(0x7E, &ROR, eAbsoluteIndexedX, 7); // Transfer Instructions // TAX SetInstructionTable(0xAA, &TAX, eImplied, 2); // TAY SetInstructionTable(0xA8, &TAY, eImplied, 2); // TXA SetInstructionTable(0x8A, &TXA, eImplied, 2); // TYA SetInstructionTable(0x98, &TYA, eImplied, 2); // Stack Instructions // TSX SetInstructionTable(0xBA, &TSX, eImplied, 2); // TXS SetInstructionTable(0x9A, &TXS, eImplied, 2); // PHA SetInstructionTable(0x48, &PHA, eImplied, 3); // PHP SetInstructionTable(0x08, &PHP, eImplied, 3); // PLA SetInstructionTable(0x68, &PLA, eImplied, 4); // PLP SetInstructionTable(0x28, &PLP, eImplied, 4); // Subroutine Instructions // JSR SetInstructionTable(0x20, &JSR, eAbsolute, 6); // RTS SetInstructionTable(0x60, &RTS, eImplied, 6); // RTI SetInstructionTable(0x40, &RTI, eImplied, 6); // Set/Reset Insutrctions // CLC SetInstructionTable(0x18, &CLC, eImplied, 2); // CLD SetInstructionTable(0xD8, &CLD, eImplied, 2); // CLI SetInstructionTable(0x58, &CLI, eImplied, 2); // CLV SetInstructionTable(0xB8, &CLV, eImplied, 2); // SEC SetInstructionTable(0x38, &SEC, eImplied, 2); // SED SetInstructionTable(0xF8, &SED, eImplied, 2); // SEI SetInstructionTable(0x78, &SEI, eImplied, 2); // NOP/BRK Instructions // NOP SetInstructionTable(0xEA, &NOP, eImplied, 2); // BRK SetInstructionTable(0x00, &BRK, eImplied, 7); }