MCUME/MCUME_teensy41/teensy20/mos6502.cpp

1479 wiersze
28 KiB
C++

#include "mos6502.h"
#include "MOS6502Memory.h"
//BusRead Read;
//BusWrite Write;
#define Read(location) readWord(location)
#define Write(location,value) writeWord(location,value)
mos6502::mos6502()
{
//Write = (BusWrite)w;
//Read = (BusRead)r;
Instr instr;
// fill jump table with ILLEGALs
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_ILLEGAL;
for(int i = 0; i < 256; i++)
{
InstrTable[i] = instr;
}
// insert opcodes
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_ADC;
instr.cycles = 2;
InstrTable[0x69] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_ADC;
instr.cycles = 4;
InstrTable[0x6D] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_ADC;
instr.cycles = 3;
InstrTable[0x65] = instr;
instr.addr = &mos6502::Addr_INX;
instr.code = &mos6502::Op_ADC;
instr.cycles = 6;
InstrTable[0x61] = instr;
instr.addr = &mos6502::Addr_INY;
instr.code = &mos6502::Op_ADC;
instr.cycles = 6;
InstrTable[0x71] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_ADC;
instr.cycles = 4;
InstrTable[0x75] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_ADC;
instr.cycles = 4;
InstrTable[0x7D] = instr;
instr.addr = &mos6502::Addr_ABY;
instr.code = &mos6502::Op_ADC;
instr.cycles = 4;
InstrTable[0x79] = instr;
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_AND;
instr.cycles = 2;
InstrTable[0x29] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_AND;
instr.cycles = 4;
InstrTable[0x2D] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_AND;
instr.cycles = 3;
InstrTable[0x25] = instr;
instr.addr = &mos6502::Addr_INX;
instr.code = &mos6502::Op_AND;
instr.cycles = 6;
InstrTable[0x21] = instr;
instr.addr = &mos6502::Addr_INY;
instr.code = &mos6502::Op_AND;
instr.cycles = 5;
InstrTable[0x31] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_AND;
instr.cycles = 4;
InstrTable[0x35] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_AND;
instr.cycles = 4;
InstrTable[0x3D] = instr;
instr.addr = &mos6502::Addr_ABY;
instr.code = &mos6502::Op_AND;
instr.cycles = 4;
InstrTable[0x39] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_ASL;
instr.cycles = 6;
InstrTable[0x0E] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_ASL;
instr.cycles = 5;
InstrTable[0x06] = instr;
instr.addr = &mos6502::Addr_ACC;
instr.code = &mos6502::Op_ASL_ACC;
instr.cycles = 2;
InstrTable[0x0A] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_ASL;
instr.cycles = 6;
InstrTable[0x16] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_ASL;
instr.cycles = 7;
InstrTable[0x1E] = instr;
instr.addr = &mos6502::Addr_REL;
instr.code = &mos6502::Op_BCC;
instr.cycles = 2;
InstrTable[0x90] = instr;
instr.addr = &mos6502::Addr_REL;
instr.code = &mos6502::Op_BCS;
instr.cycles = 2;
InstrTable[0xB0] = instr;
instr.addr = &mos6502::Addr_REL;
instr.code = &mos6502::Op_BEQ;
instr.cycles = 2;
InstrTable[0xF0] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_BIT;
instr.cycles = 4;
InstrTable[0x2C] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_BIT;
instr.cycles = 3;
InstrTable[0x24] = instr;
instr.addr = &mos6502::Addr_REL;
instr.code = &mos6502::Op_BMI;
instr.cycles = 2;
InstrTable[0x30] = instr;
instr.addr = &mos6502::Addr_REL;
instr.code = &mos6502::Op_BNE;
instr.cycles = 2;
InstrTable[0xD0] = instr;
instr.addr = &mos6502::Addr_REL;
instr.code = &mos6502::Op_BPL;
instr.cycles = 2;
InstrTable[0x10] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_BRK;
instr.cycles = 7;
InstrTable[0x00] = instr;
instr.addr = &mos6502::Addr_REL;
instr.code = &mos6502::Op_BVC;
instr.cycles = 2;
InstrTable[0x50] = instr;
instr.addr = &mos6502::Addr_REL;
instr.code = &mos6502::Op_BVS;
instr.cycles = 2;
InstrTable[0x70] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_CLC;
instr.cycles = 2;
InstrTable[0x18] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_CLD;
instr.cycles = 2;
InstrTable[0xD8] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_CLI;
instr.cycles = 2;
InstrTable[0x58] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_CLV;
instr.cycles = 2;
InstrTable[0xB8] = instr;
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_CMP;
instr.cycles = 2;
InstrTable[0xC9] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_CMP;
instr.cycles = 4;
InstrTable[0xCD] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_CMP;
instr.cycles = 3;
InstrTable[0xC5] = instr;
instr.addr = &mos6502::Addr_INX;
instr.code = &mos6502::Op_CMP;
instr.cycles = 6;
InstrTable[0xC1] = instr;
instr.addr = &mos6502::Addr_INY;
instr.code = &mos6502::Op_CMP;
instr.cycles = 3;
InstrTable[0xD1] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_CMP;
instr.cycles = 4;
InstrTable[0xD5] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_CMP;
instr.cycles = 4;
InstrTable[0xDD] = instr;
instr.addr = &mos6502::Addr_ABY;
instr.code = &mos6502::Op_CMP;
instr.cycles = 4;
InstrTable[0xD9] = instr;
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_CPX;
instr.cycles = 2;
InstrTable[0xE0] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_CPX;
instr.cycles = 4;
InstrTable[0xEC] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_CPX;
instr.cycles = 3;
InstrTable[0xE4] = instr;
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_CPY;
instr.cycles = 2;
InstrTable[0xC0] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_CPY;
instr.cycles = 4;
InstrTable[0xCC] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_CPY;
instr.cycles = 3;
InstrTable[0xC4] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_DEC;
instr.cycles = 6;
InstrTable[0xCE] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_DEC;
instr.cycles = 5;
InstrTable[0xC6] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_DEC;
instr.cycles = 6;
InstrTable[0xD6] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_DEC;
instr.cycles = 7;
InstrTable[0xDE] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_DEX;
instr.cycles = 2;
InstrTable[0xCA] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_DEY;
instr.cycles = 2;
InstrTable[0x88] = instr;
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_EOR;
instr.cycles = 2;
InstrTable[0x49] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_EOR;
instr.cycles = 4;
InstrTable[0x4D] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_EOR;
instr.cycles = 3;
InstrTable[0x45] = instr;
instr.addr = &mos6502::Addr_INX;
instr.code = &mos6502::Op_EOR;
instr.cycles = 6;
InstrTable[0x41] = instr;
instr.addr = &mos6502::Addr_INY;
instr.code = &mos6502::Op_EOR;
instr.cycles = 5;
InstrTable[0x51] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_EOR;
instr.cycles = 4;
InstrTable[0x55] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_EOR;
instr.cycles = 4;
InstrTable[0x5D] = instr;
instr.addr = &mos6502::Addr_ABY;
instr.code = &mos6502::Op_EOR;
instr.cycles = 4;
InstrTable[0x59] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_INC;
instr.cycles = 6;
InstrTable[0xEE] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_INC;
instr.cycles = 5;
InstrTable[0xE6] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_INC;
instr.cycles = 6;
InstrTable[0xF6] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_INC;
instr.cycles = 7;
InstrTable[0xFE] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_INX;
instr.cycles = 2;
InstrTable[0xE8] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_INY;
instr.cycles = 2;
InstrTable[0xC8] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_JMP;
instr.cycles = 3;
InstrTable[0x4C] = instr;
instr.addr = &mos6502::Addr_ABI;
instr.code = &mos6502::Op_JMP;
instr.cycles = 5;
InstrTable[0x6C] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_JSR;
instr.cycles = 6;
InstrTable[0x20] = instr;
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_LDA;
instr.cycles = 2;
InstrTable[0xA9] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_LDA;
instr.cycles = 4;
InstrTable[0xAD] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_LDA;
instr.cycles = 3;
InstrTable[0xA5] = instr;
instr.addr = &mos6502::Addr_INX;
instr.code = &mos6502::Op_LDA;
instr.cycles = 6;
InstrTable[0xA1] = instr;
instr.addr = &mos6502::Addr_INY;
instr.code = &mos6502::Op_LDA;
instr.cycles = 5;
InstrTable[0xB1] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_LDA;
instr.cycles = 4;
InstrTable[0xB5] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_LDA;
instr.cycles = 4;
InstrTable[0xBD] = instr;
instr.addr = &mos6502::Addr_ABY;
instr.code = &mos6502::Op_LDA;
instr.cycles = 4;
InstrTable[0xB9] = instr;
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_LDX;
instr.cycles = 2;
InstrTable[0xA2] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_LDX;
instr.cycles = 4;
InstrTable[0xAE] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_LDX;
instr.cycles = 3;
InstrTable[0xA6] = instr;
instr.addr = &mos6502::Addr_ABY;
instr.code = &mos6502::Op_LDX;
instr.cycles = 4;
InstrTable[0xBE] = instr;
instr.addr = &mos6502::Addr_ZEY;
instr.code = &mos6502::Op_LDX;
instr.cycles = 4;
InstrTable[0xB6] = instr;
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_LDY;
instr.cycles = 2;
InstrTable[0xA0] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_LDY;
instr.cycles = 4;
InstrTable[0xAC] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_LDY;
instr.cycles = 3;
InstrTable[0xA4] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_LDY;
instr.cycles = 4;
InstrTable[0xB4] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_LDY;
instr.cycles = 4;
InstrTable[0xBC] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_LSR;
instr.cycles = 6;
InstrTable[0x4E] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_LSR;
instr.cycles = 5;
InstrTable[0x46] = instr;
instr.addr = &mos6502::Addr_ACC;
instr.code = &mos6502::Op_LSR_ACC;
instr.cycles = 2;
InstrTable[0x4A] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_LSR;
instr.cycles = 6;
InstrTable[0x56] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_LSR;
instr.cycles = 7;
InstrTable[0x5E] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_NOP;
instr.cycles = 2;
InstrTable[0xEA] = instr;
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_ORA;
instr.cycles = 2;
InstrTable[0x09] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_ORA;
instr.cycles = 4;
InstrTable[0x0D] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_ORA;
instr.cycles = 3;
InstrTable[0x05] = instr;
instr.addr = &mos6502::Addr_INX;
instr.code = &mos6502::Op_ORA;
instr.cycles = 6;
InstrTable[0x01] = instr;
instr.addr = &mos6502::Addr_INY;
instr.code = &mos6502::Op_ORA;
instr.cycles = 5;
InstrTable[0x11] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_ORA;
instr.cycles = 4;
InstrTable[0x15] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_ORA;
instr.cycles = 4;
InstrTable[0x1D] = instr;
instr.addr = &mos6502::Addr_ABY;
instr.code = &mos6502::Op_ORA;
instr.cycles = 4;
InstrTable[0x19] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_PHA;
instr.cycles = 3;
InstrTable[0x48] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_PHP;
instr.cycles = 3;
InstrTable[0x08] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_PLA;
instr.cycles = 4;
InstrTable[0x68] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_PLP;
instr.cycles = 4;
InstrTable[0x28] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_ROL;
instr.cycles = 6;
InstrTable[0x2E] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_ROL;
instr.cycles = 5;
InstrTable[0x26] = instr;
instr.addr = &mos6502::Addr_ACC;
instr.code = &mos6502::Op_ROL_ACC;
instr.cycles = 2;
InstrTable[0x2A] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_ROL;
instr.cycles = 6;
InstrTable[0x36] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_ROL;
instr.cycles = 7;
InstrTable[0x3E] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_ROR;
instr.cycles = 6;
InstrTable[0x6E] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_ROR;
instr.cycles = 5;
InstrTable[0x66] = instr;
instr.addr = &mos6502::Addr_ACC;
instr.code = &mos6502::Op_ROR_ACC;
instr.cycles = 2;
InstrTable[0x6A] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_ROR;
instr.cycles = 6;
InstrTable[0x76] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_ROR;
instr.cycles = 7;
InstrTable[0x7E] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_RTI;
instr.cycles = 6;
InstrTable[0x40] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_RTS;
instr.cycles = 6;
InstrTable[0x60] = instr;
instr.addr = &mos6502::Addr_IMM;
instr.code = &mos6502::Op_SBC;
instr.cycles = 2;
InstrTable[0xE9] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_SBC;
instr.cycles = 4;
InstrTable[0xED] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_SBC;
instr.cycles = 3;
InstrTable[0xE5] = instr;
instr.addr = &mos6502::Addr_INX;
instr.code = &mos6502::Op_SBC;
instr.cycles = 6;
InstrTable[0xE1] = instr;
instr.addr = &mos6502::Addr_INY;
instr.code = &mos6502::Op_SBC;
instr.cycles = 5;
InstrTable[0xF1] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_SBC;
instr.cycles = 4;
InstrTable[0xF5] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_SBC;
instr.cycles = 4;
InstrTable[0xFD] = instr;
instr.addr = &mos6502::Addr_ABY;
instr.code = &mos6502::Op_SBC;
instr.cycles = 4;
InstrTable[0xF9] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_SEC;
instr.cycles = 2;
InstrTable[0x38] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_SED;
instr.cycles = 2;
InstrTable[0xF8] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_SEI;
instr.cycles = 2;
InstrTable[0x78] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_STA;
instr.cycles = 4;
InstrTable[0x8D] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_STA;
instr.cycles = 3;
InstrTable[0x85] = instr;
instr.addr = &mos6502::Addr_INX;
instr.code = &mos6502::Op_STA;
instr.cycles = 6;
InstrTable[0x81] = instr;
instr.addr = &mos6502::Addr_INY;
instr.code = &mos6502::Op_STA;
instr.cycles = 6;
InstrTable[0x91] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_STA;
instr.cycles = 4;
InstrTable[0x95] = instr;
instr.addr = &mos6502::Addr_ABX;
instr.code = &mos6502::Op_STA;
instr.cycles = 5;
InstrTable[0x9D] = instr;
instr.addr = &mos6502::Addr_ABY;
instr.code = &mos6502::Op_STA;
instr.cycles = 5;
InstrTable[0x99] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_STX;
instr.cycles = 4;
InstrTable[0x8E] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_STX;
instr.cycles = 3;
InstrTable[0x86] = instr;
instr.addr = &mos6502::Addr_ZEY;
instr.code = &mos6502::Op_STX;
instr.cycles = 4;
InstrTable[0x96] = instr;
instr.addr = &mos6502::Addr_ABS;
instr.code = &mos6502::Op_STY;
instr.cycles = 4;
InstrTable[0x8C] = instr;
instr.addr = &mos6502::Addr_ZER;
instr.code = &mos6502::Op_STY;
instr.cycles = 3;
InstrTable[0x84] = instr;
instr.addr = &mos6502::Addr_ZEX;
instr.code = &mos6502::Op_STY;
instr.cycles = 4;
InstrTable[0x94] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_TAX;
instr.cycles = 2;
InstrTable[0xAA] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_TAY;
instr.cycles = 2;
InstrTable[0xA8] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_TSX;
instr.cycles = 2;
InstrTable[0xBA] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_TXA;
instr.cycles = 2;
InstrTable[0x8A] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_TXS;
instr.cycles = 2;
InstrTable[0x9A] = instr;
instr.addr = &mos6502::Addr_IMP;
instr.code = &mos6502::Op_TYA;
instr.cycles = 2;
InstrTable[0x98] = instr;
return;
}
uint16_t mos6502::Addr_ACC()
{
return 0; // not used
}
uint16_t mos6502::Addr_IMM()
{
return pc++;
}
uint16_t mos6502::Addr_ABS()
{
uint16_t addrL;
uint16_t addrH;
uint16_t addr;
addrL = Read(pc++);
addrH = Read(pc++);
addr = addrL + (addrH << 8);
return addr;
}
uint16_t mos6502::Addr_ZER()
{
return Read(pc++);
}
uint16_t mos6502::Addr_IMP()
{
return 0; // not used
}
uint16_t mos6502::Addr_REL()
{
uint16_t offset;
uint16_t addr;
offset = (uint16_t)Read(pc++);
if (offset & 0x80) offset |= 0xFF00;
addr = pc + (int16_t)offset;
return addr;
}
uint16_t mos6502::Addr_ABI()
{
uint16_t addrL;
uint16_t addrH;
uint16_t effL;
uint16_t effH;
uint16_t abs;
uint16_t addr;
addrL = Read(pc++);
addrH = Read(pc++);
abs = (addrH << 8) | addrL;
effL = Read(abs);
#ifndef CMOS_INDIRECT_JMP_FIX
effH = Read((abs & 0xFF00) + ((abs + 1) & 0x00FF) );
#else
effH = Read(abs + 1);
#endif
addr = effL + 0x100 * effH;
return addr;
}
uint16_t mos6502::Addr_ZEX()
{
uint16_t addr = (Read(pc++) + X) % 256;
return addr;
}
uint16_t mos6502::Addr_ZEY()
{
uint16_t addr = (Read(pc++) + Y) % 256;
return addr;
}
uint16_t mos6502::Addr_ABX()
{
uint16_t addr;
uint16_t addrL;
uint16_t addrH;
addrL = Read(pc++);
addrH = Read(pc++);
addr = addrL + (addrH << 8) + X;
return addr;
}
uint16_t mos6502::Addr_ABY()
{
uint16_t addr;
uint16_t addrL;
uint16_t addrH;
addrL = Read(pc++);
addrH = Read(pc++);
addr = addrL + (addrH << 8) + Y;
return addr;
}
uint16_t mos6502::Addr_INX()
{
uint16_t zeroL;
uint16_t zeroH;
uint16_t addr;
zeroL = (Read(pc++) + X) % 256;
zeroH = (zeroL + 1) % 256;
addr = Read(zeroL) + (Read(zeroH) << 8);
return addr;
}
uint16_t mos6502::Addr_INY()
{
uint16_t zeroL;
uint16_t zeroH;
uint16_t addr;
zeroL = Read(pc++);
zeroH = (zeroL + 1) % 256;
addr = Read(zeroL) + (Read(zeroH) << 8) + Y;
return addr;
}
void mos6502::Reset()
{
A = 0x00;
Y = 0x00;
X = 0x00;
pc = (Read(rstVectorH) << 8) + Read(rstVectorL); // load PC from reset vector
sp = 0xFD;
status |= CONSTANT;
illegalOpcode = false;
return;
}
void mos6502::StackPush(uint8_t byte)
{
Write(0x0100 + sp, byte);
if(sp == 0x00) sp = 0xFF;
else sp--;
}
uint8_t mos6502::StackPop()
{
if(sp == 0xFF) sp = 0x00;
else sp++;
return Read(0x0100 + sp);
}
int mos6502::IRQ()
{
int retval = 0;
if(!IF_INTERRUPT())
{
SET_BREAK(0);
StackPush((pc >> 8) & 0xFF);
StackPush(pc & 0xFF);
StackPush(status);
SET_INTERRUPT(1);
pc = (Read(irqVectorH) << 8) + Read(irqVectorL);
retval = 1;
}
return retval;
}
void mos6502::NMI()
{
SET_BREAK(0);
StackPush((pc >> 8) & 0xFF);
StackPush(pc & 0xFF);
StackPush(status);
SET_INTERRUPT(1);
pc = (Read(nmiVectorH) << 8) + Read(nmiVectorL);
return;
}
uint64_t mos6502::Run(
int32_t cyclesRemaining,
CycleMethod cycleMethod
) {
uint8_t opcode;
Instr instr;
uint64_t cycleCount=0;
while(cyclesRemaining > 0 && !illegalOpcode)
{
// fetch
opcode = Read(pc++);
// decode
instr = InstrTable[opcode];
// execute
Exec(instr);
cycleCount += instr.cycles;
cyclesRemaining -=
cycleMethod == CYCLE_COUNT ? instr.cycles
/* cycleMethod == INST_COUNT */ : 1;
}
return cycleCount;
}
void mos6502::Exec(Instr i)
{
uint16_t src = (this->*i.addr)();
(this->*i.code)(src);
}
void mos6502::Op_ILLEGAL(uint16_t src)
{
illegalOpcode = true;
}
void mos6502::Op_ADC(uint16_t src)
{
uint8_t m = Read(src);
unsigned int tmp = m + A + (IF_CARRY() ? 1 : 0);
SET_ZERO(!(tmp & 0xFF));
if (IF_DECIMAL())
{
if (((A & 0xF) + (m & 0xF) + (IF_CARRY() ? 1 : 0)) > 9) tmp += 6;
SET_NEGATIVE(tmp & 0x80);
SET_OVERFLOW(!((A ^ m) & 0x80) && ((A ^ tmp) & 0x80));
if (tmp > 0x99)
{
tmp += 96;
}
SET_CARRY(tmp > 0x99);
}
else
{
SET_NEGATIVE(tmp & 0x80);
SET_OVERFLOW(!((A ^ m) & 0x80) && ((A ^ tmp) & 0x80));
SET_CARRY(tmp > 0xFF);
}
A = tmp & 0xFF;
return;
}
void mos6502::Op_AND(uint16_t src)
{
uint8_t m = Read(src);
uint8_t res = m & A;
SET_NEGATIVE(res & 0x80);
SET_ZERO(!res);
A = res;
return;
}
void mos6502::Op_ASL(uint16_t src)
{
uint8_t m = Read(src);
SET_CARRY(m & 0x80);
m <<= 1;
m &= 0xFF;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
Write(src, m);
return;
}
void mos6502::Op_ASL_ACC(uint16_t src)
{
uint8_t m = A;
SET_CARRY(m & 0x80);
m <<= 1;
m &= 0xFF;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
A = m;
return;
}
void mos6502::Op_BCC(uint16_t src)
{
if (!IF_CARRY())
{
pc = src;
}
return;
}
void mos6502::Op_BCS(uint16_t src)
{
if (IF_CARRY())
{
pc = src;
}
return;
}
void mos6502::Op_BEQ(uint16_t src)
{
if (IF_ZERO())
{
pc = src;
}
return;
}
void mos6502::Op_BIT(uint16_t src)
{
uint8_t m = Read(src);
uint8_t res = m & A;
SET_NEGATIVE(res & 0x80);
status = (status & 0x3F) | (uint8_t)(m & 0xC0);
SET_ZERO(!res);
return;
}
void mos6502::Op_BMI(uint16_t src)
{
if (IF_NEGATIVE())
{
pc = src;
}
return;
}
void mos6502::Op_BNE(uint16_t src)
{
if (!IF_ZERO())
{
pc = src;
}
return;
}
void mos6502::Op_BPL(uint16_t src)
{
if (!IF_NEGATIVE())
{
pc = src;
}
return;
}
void mos6502::Op_BRK(uint16_t src)
{
pc++;
StackPush((pc >> 8) & 0xFF);
StackPush(pc & 0xFF);
StackPush(status | BREAK);
SET_INTERRUPT(1);
pc = (Read(irqVectorH) << 8) + Read(irqVectorL);
return;
}
void mos6502::Op_BVC(uint16_t src)
{
if (!IF_OVERFLOW())
{
pc = src;
}
return;
}
void mos6502::Op_BVS(uint16_t src)
{
if (IF_OVERFLOW())
{
pc = src;
}
return;
}
void mos6502::Op_CLC(uint16_t src)
{
SET_CARRY(0);
return;
}
void mos6502::Op_CLD(uint16_t src)
{
SET_DECIMAL(0);
return;
}
void mos6502::Op_CLI(uint16_t src)
{
SET_INTERRUPT(0);
return;
}
void mos6502::Op_CLV(uint16_t src)
{
SET_OVERFLOW(0);
return;
}
void mos6502::Op_CMP(uint16_t src)
{
unsigned int tmp = A - Read(src);
SET_CARRY(tmp < 0x100);
SET_NEGATIVE(tmp & 0x80);
SET_ZERO(!(tmp & 0xFF));
return;
}
void mos6502::Op_CPX(uint16_t src)
{
unsigned int tmp = X - Read(src);
SET_CARRY(tmp < 0x100);
SET_NEGATIVE(tmp & 0x80);
SET_ZERO(!(tmp & 0xFF));
return;
}
void mos6502::Op_CPY(uint16_t src)
{
unsigned int tmp = Y - Read(src);
SET_CARRY(tmp < 0x100);
SET_NEGATIVE(tmp & 0x80);
SET_ZERO(!(tmp & 0xFF));
return;
}
void mos6502::Op_DEC(uint16_t src)
{
uint8_t m = Read(src);
m = (m - 1) % 256;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
Write(src, m);
return;
}
void mos6502::Op_DEX(uint16_t src)
{
uint8_t m = X;
m = (m - 1) % 256;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
X = m;
return;
}
void mos6502::Op_DEY(uint16_t src)
{
uint8_t m = Y;
m = (m - 1) % 256;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
Y = m;
return;
}
void mos6502::Op_EOR(uint16_t src)
{
uint8_t m = Read(src);
m = A ^ m;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
A = m;
}
void mos6502::Op_INC(uint16_t src)
{
uint8_t m = Read(src);
m = (m + 1) % 256;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
Write(src, m);
}
void mos6502::Op_INX(uint16_t src)
{
uint8_t m = X;
m = (m + 1) % 256;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
X = m;
}
void mos6502::Op_INY(uint16_t src)
{
uint8_t m = Y;
m = (m + 1) % 256;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
Y = m;
}
void mos6502::Op_JMP(uint16_t src)
{
pc = src;
}
void mos6502::Op_JSR(uint16_t src)
{
pc--;
StackPush((pc >> 8) & 0xFF);
StackPush(pc & 0xFF);
pc = src;
}
void mos6502::Op_LDA(uint16_t src)
{
uint8_t m = Read(src);
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
A = m;
}
void mos6502::Op_LDX(uint16_t src)
{
uint8_t m = Read(src);
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
X = m;
}
void mos6502::Op_LDY(uint16_t src)
{
uint8_t m = Read(src);
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
Y = m;
}
void mos6502::Op_LSR(uint16_t src)
{
uint8_t m = Read(src);
SET_CARRY(m & 0x01);
m >>= 1;
SET_NEGATIVE(0);
SET_ZERO(!m);
Write(src, m);
}
void mos6502::Op_LSR_ACC(uint16_t src)
{
uint8_t m = A;
SET_CARRY(m & 0x01);
m >>= 1;
SET_NEGATIVE(0);
SET_ZERO(!m);
A = m;
}
void mos6502::Op_NOP(uint16_t src)
{
return;
}
void mos6502::Op_ORA(uint16_t src)
{
uint8_t m = Read(src);
m = A | m;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
A = m;
}
void mos6502::Op_PHA(uint16_t src)
{
StackPush(A);
return;
}
void mos6502::Op_PHP(uint16_t src)
{
StackPush(status | BREAK);
return;
}
void mos6502::Op_PLA(uint16_t src)
{
A = StackPop();
SET_NEGATIVE(A & 0x80);
SET_ZERO(!A);
return;
}
void mos6502::Op_PLP(uint16_t src)
{
status = StackPop();
SET_CONSTANT(1);
return;
}
void mos6502::Op_ROL(uint16_t src)
{
uint16_t m = Read(src);
m <<= 1;
if (IF_CARRY()) m |= 0x01;
SET_CARRY(m > 0xFF);
m &= 0xFF;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
Write(src, m);
return;
}
void mos6502::Op_ROL_ACC(uint16_t src)
{
uint16_t m = A;
m <<= 1;
if (IF_CARRY()) m |= 0x01;
SET_CARRY(m > 0xFF);
m &= 0xFF;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
A = m;
return;
}
void mos6502::Op_ROR(uint16_t src)
{
uint16_t m = Read(src);
if (IF_CARRY()) m |= 0x100;
SET_CARRY(m & 0x01);
m >>= 1;
m &= 0xFF;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
Write(src, m);
return;
}
void mos6502::Op_ROR_ACC(uint16_t src)
{
uint16_t m = A;
if (IF_CARRY()) m |= 0x100;
SET_CARRY(m & 0x01);
m >>= 1;
m &= 0xFF;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
A = m;
return;
}
void mos6502::Op_RTI(uint16_t src)
{
uint8_t lo, hi;
status = StackPop();
lo = StackPop();
hi = StackPop();
pc = (hi << 8) | lo;
return;
}
void mos6502::Op_RTS(uint16_t src)
{
uint8_t lo, hi;
lo = StackPop();
hi = StackPop();
pc = ((hi << 8) | lo) + 1;
return;
}
void mos6502::Op_SBC(uint16_t src)
{
uint8_t m = Read(src);
unsigned int tmp = A - m - (IF_CARRY() ? 0 : 1);
SET_NEGATIVE(tmp & 0x80);
SET_ZERO(!(tmp & 0xFF));
SET_OVERFLOW(((A ^ tmp) & 0x80) && ((A ^ m) & 0x80));
if (IF_DECIMAL())
{
if ( ((A & 0x0F) - (IF_CARRY() ? 0 : 1)) < (m & 0x0F)) tmp -= 6;
if (tmp > 0x99)
{
tmp -= 0x60;
}
}
SET_CARRY(tmp < 0x100);
A = (tmp & 0xFF);
return;
}
void mos6502::Op_SEC(uint16_t src)
{
SET_CARRY(1);
return;
}
void mos6502::Op_SED(uint16_t src)
{
SET_DECIMAL(1);
return;
}
void mos6502::Op_SEI(uint16_t src)
{
SET_INTERRUPT(1);
return;
}
void mos6502::Op_STA(uint16_t src)
{
Write(src, A);
return;
}
void mos6502::Op_STX(uint16_t src)
{
Write(src, X);
return;
}
void mos6502::Op_STY(uint16_t src)
{
Write(src, Y);
return;
}
void mos6502::Op_TAX(uint16_t src)
{
uint8_t m = A;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
X = m;
return;
}
void mos6502::Op_TAY(uint16_t src)
{
uint8_t m = A;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
Y = m;
return;
}
void mos6502::Op_TSX(uint16_t src)
{
uint8_t m = sp;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
X = m;
return;
}
void mos6502::Op_TXA(uint16_t src)
{
uint8_t m = X;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
A = m;
return;
}
void mos6502::Op_TXS(uint16_t src)
{
sp = X;
return;
}
void mos6502::Op_TYA(uint16_t src)
{
uint8_t m = Y;
SET_NEGATIVE(m & 0x80);
SET_ZERO(!m);
A = m;
return;
}