BizHawk/lynx/c65c02.cpp

1072 lines
13 KiB
C++

#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 &regs)
{
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 &regs)
{
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;
}
}