#include "system.h" #include "c65c02.h" void C65C02::Reset() { TRACE_CPU0("Reset()"); mRamPointer=mSystem.GetRamPointer(); mA=0; mX=0; mY=0; mSP=0xff; mOpcode=0; mOperand=0; mPC=CPU_PEEKW(BOOT_VECTOR); mN=FALSE; mV=FALSE; mB=FALSE; mD=FALSE; mI=TRUE; mZ=TRUE; mC=FALSE; mIRQActive=FALSE; mSystem.gSystemNMI=FALSE; mSystem.gSystemIRQ=FALSE; mSystem.gSystemCPUSleep=FALSE; } void C65C02::SetRegs(C6502_REGS ®s) { PS(regs.PS); mA=regs.A; mX=regs.X; mY=regs.Y; mSP=regs.SP; mOpcode=regs.Opcode; mOperand=regs.Operand; mPC=regs.PC; mSystem.gSystemCPUSleep=regs.WAIT; mSystem.gSystemNMI=regs.NMI; mSystem.gSystemIRQ=regs.IRQ; } void C65C02::GetRegs(C6502_REGS ®s) { regs.PS=PS(); regs.A=mA; regs.X=mX; regs.Y=mY; regs.SP=mSP; regs.Opcode=mOpcode; regs.Operand=mOperand; regs.PC=mPC; regs.WAIT=mSystem.gSystemCPUSleep; regs.NMI=mSystem.gSystemNMI; regs.IRQ=mSystem.gSystemIRQ; } SYNCFUNC(C65C02) { NSS(mA); NSS(mX); NSS(mY); NSS(mSP); NSS(mOpcode); NSS(mOperand); NSS(mPC); NSS(mN); NSS(mV); NSS(mB); NSS(mD); NSS(mI); NSS(mZ); NSS(mC); NSS(mIRQActive); // don't need to save these: // mRamPointer // mBCDTable } void C65C02::Update(void) { if(mSystem.gSystemCPUSleep) return; if(mSystem.gSystemIRQ && !mI && !mIRQActive) { // Push processor status PUSH(mPC>>8); PUSH(mPC&0xff); PUSH(PS()&0xef); // Clear B flag on stack mI=TRUE; // Stop further interrupts mD=FALSE; // Clear decimal mode // Pick up the new PC mPC=CPU_PEEKW(IRQ_VECTOR); } // Fetch opcode mOpcode=CPU_PEEK(mPC); TRACE_CPU2("Update() PC=$%04x, Opcode=%02x",mPC,mOpcode); mPC++; // Execute Opcode switch(mOpcode) { #define ADDCYC(x) { mSystem.gSystemCycleCount += ((x) * 4); if(mSystem.gSuzieDoneTime) mSystem.gSuzieDoneTime += ((x) * 4); } // // 0x00 // case 0x00: ADDCYC(7); // IMPLIED xBRK(); break; case 0x01: ADDCYC(6); xINDIRECT_X(); xORA(); break; case 0x04: ADDCYC(5); xZEROPAGE(); xTSB(); break; case 0x05: ADDCYC(3); xZEROPAGE(); xORA(); break; case 0x06: ADDCYC(5); xZEROPAGE(); xASL(); break; case 0x08: ADDCYC(3); // IMPLIED xPHP(); break; case 0x09: ADDCYC(3); xIMMEDIATE(); xORA(); break; case 0x0A: ADDCYC(2); // IMPLIED xASLA(); break; case 0x0C: ADDCYC(6); xABSOLUTE(); xTSB(); break; case 0x0D: ADDCYC(4); xABSOLUTE(); xORA(); break; case 0x0E: ADDCYC(6); mSystem.gSystemCycleCount+=(1+(5*CPU_RDWR_CYC)); xABSOLUTE(); xASL(); break; // // 0x10 // case 0x10: ADDCYC(2); // RELATIVE (IN FUNCTION) xBPL(); break; case 0x11: ADDCYC(5); xINDIRECT_Y(); xORA(); break; case 0x12: ADDCYC(5); xINDIRECT(); xORA(); break; case 0x14: ADDCYC(5); xZEROPAGE(); xTRB(); break; case 0x15: ADDCYC(4); xZEROPAGE_X(); xORA(); break; case 0x16: ADDCYC(6); xZEROPAGE_X(); xASL(); break; case 0x18: ADDCYC(2); // IMPLIED xCLC(); break; case 0x19: ADDCYC(4); xABSOLUTE_Y(); xORA(); break; case 0x1A: ADDCYC(2); // IMPLIED xINCA(); break; case 0x1C: ADDCYC(6); xABSOLUTE(); xTRB(); break; case 0x1D: ADDCYC(4); xABSOLUTE_X(); xORA(); break; case 0x1E: ADDCYC(7); xABSOLUTE_X(); xASL(); break; // // 0x20 // case 0x20: ADDCYC(6); xABSOLUTE(); xJSR(); break; case 0x21: ADDCYC(6); xINDIRECT_X(); xAND(); break; case 0x24: ADDCYC(3); xZEROPAGE(); xBIT(); break; case 0x25: ADDCYC(3); xZEROPAGE(); xAND(); break; case 0x26: ADDCYC(5); xZEROPAGE(); xROL(); break; case 0x28: ADDCYC(4); // IMPLIED xPLP(); break; case 0x29: ADDCYC(2); xIMMEDIATE(); xAND(); break; case 0x2A: ADDCYC(2); // IMPLIED xROLA(); break; case 0x2C: ADDCYC(4); xABSOLUTE(); xBIT(); break; case 0x2D: ADDCYC(4); xABSOLUTE(); xAND(); break; case 0x2E: ADDCYC(6); xABSOLUTE(); xROL(); break; // // 0x30 // case 0x30: ADDCYC(2); // RELATIVE (IN FUNCTION) xBMI(); break; case 0x31: ADDCYC(5); xINDIRECT_Y(); xAND(); break; case 0x32: ADDCYC(5); xINDIRECT(); xAND(); break; case 0x34: ADDCYC(4); xZEROPAGE_X(); xBIT(); break; case 0x35: ADDCYC(4); xZEROPAGE_X(); xAND(); break; case 0x36: ADDCYC(6); xZEROPAGE_X(); xROL(); break; case 0x38: ADDCYC(2); // IMPLIED xSEC(); break; case 0x39: ADDCYC(4); xABSOLUTE_Y(); xAND(); break; case 0x3A: ADDCYC(2); // IMPLIED xDECA(); break; case 0x3C: ADDCYC(4); xABSOLUTE_X(); xBIT(); break; case 0x3D: ADDCYC(4); xABSOLUTE_X(); xAND(); break; case 0x3E: ADDCYC(7); xABSOLUTE_X(); xROL(); break; // // 0x40 // case 0x40: ADDCYC(6); // IMPLIED xRTI(); break; case 0x41: ADDCYC(6); xINDIRECT_X(); xEOR(); break; case 0x45: ADDCYC(3); xZEROPAGE(); xEOR(); break; case 0x46: ADDCYC(5); xZEROPAGE(); xLSR(); break; case 0x48: ADDCYC(3); // IMPLIED xPHA(); break; case 0x49: ADDCYC(2); xIMMEDIATE(); xEOR(); break; case 0x4A: ADDCYC(2); // IMPLIED xLSRA(); break; case 0x4C: ADDCYC(3); xABSOLUTE(); xJMP(); break; case 0x4D: ADDCYC(4); xABSOLUTE(); xEOR(); break; case 0x4E: ADDCYC(6); xABSOLUTE(); xLSR(); break; // // 0x50 // case 0x50: ADDCYC(2); // RELATIVE (IN FUNCTION) xBVC(); break; case 0x51: ADDCYC(5); xINDIRECT_Y(); xEOR(); break; case 0x52: ADDCYC(5); xINDIRECT(); xEOR(); break; case 0x55: ADDCYC(4); xZEROPAGE_X(); xEOR(); break; case 0x56: ADDCYC(6); xZEROPAGE_X(); xLSR(); break; case 0x58: ADDCYC(2); // IMPLIED xCLI(); break; case 0x59: ADDCYC(4); xABSOLUTE_Y(); xEOR(); break; case 0x5A: ADDCYC(3); // IMPLIED xPHY(); break; case 0x5D: ADDCYC(4); xABSOLUTE_X(); xEOR(); break; case 0x5E: ADDCYC(7); xABSOLUTE_X(); xLSR(); break; // // 0x60 // case 0x60: ADDCYC(6); // IMPLIED xRTS(); break; case 0x61: ADDCYC(6); xINDIRECT_X(); xADC(); break; case 0x64: ADDCYC(3); xZEROPAGE(); xSTZ(); break; case 0x65: ADDCYC(3); xZEROPAGE(); xADC(); break; case 0x66: ADDCYC(5); xZEROPAGE(); xROR(); break; case 0x68: ADDCYC(4); // IMPLIED xPLA(); break; case 0x69: ADDCYC(2); xIMMEDIATE(); xADC(); break; case 0x6A: ADDCYC(2); // IMPLIED xRORA(); break; case 0x6C: ADDCYC(6); xINDIRECT_ABSOLUTE(); xJMP(); break; case 0x6D: ADDCYC(4); xABSOLUTE(); xADC(); break; case 0x6E: ADDCYC(6); xABSOLUTE(); xROR(); break; // // 0x70 // case 0x70: ADDCYC(2); // RELATIVE (IN FUNCTION) xBVS(); break; case 0x71: ADDCYC(5); xINDIRECT_Y(); xADC(); break; case 0x72: ADDCYC(5); xINDIRECT(); xADC(); break; case 0x74: ADDCYC(4); xZEROPAGE_X(); xSTZ(); break; case 0x75: ADDCYC(4); xZEROPAGE_X(); xADC(); break; case 0x76: ADDCYC(6); xZEROPAGE_X(); xROR(); break; case 0x78: ADDCYC(2); // IMPLIED xSEI(); break; case 0x79: mSystem.gSystemCycleCount+=(1+(3*CPU_RDWR_CYC)); xABSOLUTE_Y(); xADC(); break; case 0x7A: ADDCYC(4); // IMPLIED xPLY(); break; case 0x7C: ADDCYC(6); xINDIRECT_ABSOLUTE_X(); xJMP(); break; case 0x7D: ADDCYC(4); xABSOLUTE_X(); xADC(); break; case 0x7E: ADDCYC(7); xABSOLUTE_X(); xROR(); break; // // 0x80 // case 0x80: ADDCYC(3); // RELATIVE (IN FUNCTION) xBRA(); break; case 0x81: ADDCYC(6); xINDIRECT_X(); xSTA(); break; case 0x84: ADDCYC(3); xZEROPAGE(); xSTY(); break; case 0x85: ADDCYC(3); xZEROPAGE(); xSTA(); break; case 0x86: ADDCYC(3); xZEROPAGE(); xSTX(); break; case 0x88: ADDCYC(2); // IMPLIED xDEY(); break; case 0x89: ADDCYC(3); xIMMEDIATE(); xBIT(); break; case 0x8A: ADDCYC(2); // IMPLIED xTXA(); break; case 0x8C: ADDCYC(4); xABSOLUTE(); xSTY(); break; case 0x8D: ADDCYC(4); xABSOLUTE(); xSTA(); break; case 0x8E: ADDCYC(4); xABSOLUTE(); xSTX(); break; // // 0x90 // case 0x90: ADDCYC(2); // RELATIVE (IN FUNCTION) xBCC(); break; case 0x91: ADDCYC(6); xINDIRECT_Y(); xSTA(); break; case 0x92: ADDCYC(5); xINDIRECT(); xSTA(); break; case 0x94: ADDCYC(4); xZEROPAGE_X(); xSTY(); break; case 0x95: ADDCYC(4); xZEROPAGE_X(); xSTA(); break; case 0x96: ADDCYC(4); xZEROPAGE_Y(); xSTX(); break; case 0x98: ADDCYC(2); // IMPLIED xTYA(); break; case 0x99: ADDCYC(5); xABSOLUTE_Y(); xSTA(); break; case 0x9A: ADDCYC(2); // IMPLIED xTXS(); break; case 0x9C: ADDCYC(4); xABSOLUTE(); xSTZ(); break; case 0x9D: ADDCYC(5); xABSOLUTE_X(); xSTA(); break; case 0x9E: ADDCYC(5); xABSOLUTE_X(); xSTZ(); break; // // 0xA0 // case 0xA0: ADDCYC(2); xIMMEDIATE(); xLDY(); break; case 0xA1: ADDCYC(6); xINDIRECT_X(); xLDA(); break; case 0xA2: ADDCYC(2); xIMMEDIATE(); xLDX(); break; case 0xA4: ADDCYC(3); xZEROPAGE(); xLDY(); break; case 0xA5: ADDCYC(3); xZEROPAGE(); xLDA(); break; case 0xA6: ADDCYC(3); xZEROPAGE(); xLDX(); break; case 0xA8: ADDCYC(2); // IMPLIED xTAY(); break; case 0xA9: ADDCYC(2); xIMMEDIATE(); xLDA(); break; case 0xAA: ADDCYC(2); // IMPLIED xTAX(); break; case 0xAC: ADDCYC(4); xABSOLUTE(); xLDY(); break; case 0xAD: ADDCYC(4); xABSOLUTE(); xLDA(); break; case 0xAE: ADDCYC(4); xABSOLUTE(); xLDX(); break; // // 0xB0 // case 0xB0: ADDCYC(2); // RELATIVE (IN FUNCTION) xBCS(); break; case 0xB1: ADDCYC(5); xINDIRECT_Y(); xLDA(); break; case 0xB2: ADDCYC(5); xINDIRECT(); xLDA(); break; case 0xB4: ADDCYC(4); xZEROPAGE_X(); xLDY(); break; case 0xB5: ADDCYC(4); xZEROPAGE_X(); xLDA(); break; case 0xB6: ADDCYC(4); xZEROPAGE_Y(); xLDX(); break; case 0xB8: ADDCYC(2); // IMPLIED xCLV(); break; case 0xB9: ADDCYC(4); xABSOLUTE_Y(); xLDA(); break; case 0xBA: ADDCYC(2); // IMPLIED xTSX(); break; case 0xBC: ADDCYC(4); xABSOLUTE_X(); xLDY(); break; case 0xBD: ADDCYC(4); xABSOLUTE_X(); xLDA(); break; case 0xBE: ADDCYC(4); xABSOLUTE_Y(); xLDX(); break; // // 0xC0 // case 0xC0: ADDCYC(2); xIMMEDIATE(); xCPY(); break; case 0xC1: ADDCYC(6); xINDIRECT_X(); xCMP(); break; case 0xC4: ADDCYC(3); xZEROPAGE(); xCPY(); break; case 0xC5: ADDCYC(3); xZEROPAGE(); xCMP(); break; case 0xC6: ADDCYC(5); xZEROPAGE(); xDEC(); break; case 0xC8: ADDCYC(2); // IMPLIED xINY(); break; case 0xC9: ADDCYC(2); xIMMEDIATE(); xCMP(); break; case 0xCA: ADDCYC(2); // IMPLIED xDEX(); break; case 0xCB: ADDCYC(2); // IMPLIED xWAI(); break; case 0xCC: ADDCYC(4); xABSOLUTE(); xCPY(); break; case 0xCD: ADDCYC(4); xABSOLUTE(); xCMP(); break; case 0xCE: ADDCYC(6); xABSOLUTE(); xDEC(); break; // // 0xD0 // case 0xD0: ADDCYC(2); // RELATIVE (IN FUNCTION) xBNE(); break; case 0xD1: ADDCYC(5); xINDIRECT_Y(); xCMP(); break; case 0xD2: ADDCYC(5); xINDIRECT(); xCMP(); break; case 0xD5: ADDCYC(4); xZEROPAGE_X(); xCMP(); break; case 0xD6: ADDCYC(6); xZEROPAGE_X(); xDEC(); break; case 0xD8: ADDCYC(2); // IMPLIED xCLD(); break; case 0xD9: ADDCYC(4); xABSOLUTE_Y(); xCMP(); break; case 0xDA: ADDCYC(3); // IMPLIED xPHX(); break; case 0xDB: ADDCYC(2); // IMPLIED xSTP(); break; case 0xDD: ADDCYC(4); xABSOLUTE_X(); xCMP(); break; case 0xDE: ADDCYC(7); xABSOLUTE_X(); xDEC(); break; // // 0xE0 // case 0xE0: ADDCYC(2); xIMMEDIATE(); xCPX(); break; case 0xE1: ADDCYC(6); xINDIRECT_X(); xSBC(); break; case 0xE4: ADDCYC(3); xZEROPAGE(); xCPX(); break; case 0xE5: ADDCYC(3); xZEROPAGE(); xSBC(); break; case 0xE6: ADDCYC(5); xZEROPAGE(); xINC(); break; case 0xE8: ADDCYC(2); // IMPLIED xINX(); break; case 0xE9: ADDCYC(2); xIMMEDIATE(); xSBC(); break; default: case 0xEA: ADDCYC(2); // IMPLIED xNOP(); break; case 0xEC: ADDCYC(4); xABSOLUTE(); xCPX(); break; case 0xED: ADDCYC(4); xABSOLUTE(); xSBC(); break; case 0xEE: ADDCYC(6); xABSOLUTE(); xINC(); break; // // 0xF0 // case 0xF0: ADDCYC(2); // RELATIVE (IN FUNCTION) xBEQ(); break; case 0xF1: ADDCYC(5); xINDIRECT_Y(); xSBC(); break; case 0xF2: ADDCYC(5); xINDIRECT(); xSBC(); break; case 0xF5: ADDCYC(4); xZEROPAGE_X(); xSBC(); break; case 0xF6: ADDCYC(6); xZEROPAGE_X(); xINC(); break; case 0xF8: ADDCYC(2); // IMPLIED xSED(); break; case 0xF9: ADDCYC(4); xABSOLUTE_Y(); xSBC(); break; case 0xFA: ADDCYC(4); // IMPLIED xPLX(); break; case 0xFD: ADDCYC(4); xABSOLUTE_X(); xSBC(); break; case 0xFE: ADDCYC(7); xABSOLUTE_X(); xINC(); break; } }