kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
1831 wiersze
53 KiB
C++
1831 wiersze
53 KiB
C++
//
|
|
// Copyright (c) 2004 K. Wilkins
|
|
//
|
|
// This software is provided 'as-is', without any express or implied warranty.
|
|
// In no event will the authors be held liable for any damages arising from
|
|
// the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
//
|
|
// 2. Altered source versions must be plainly marked as such, and must not
|
|
// be misrepresented as being the original software.
|
|
//
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
//
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Handy - An Atari Lynx Emulator //
|
|
// Copyright (c) 1996,1997 //
|
|
// K. Wilkins //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// 65C02 Emulation class //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// This class emulates a 65C02 processor. It is interfaced to the rest of //
|
|
// the system via the PEEK/POKE macros and a number of global variables //
|
|
// //
|
|
// K. Wilkins //
|
|
// August 1997 //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Revision History: //
|
|
// ----------------- //
|
|
// //
|
|
// 01Aug1997 KW Document header added & class documented. //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef C65C02_H
|
|
#define C65C02_H
|
|
|
|
//#include <crtdbg.h>
|
|
//#define TRACE_CPU
|
|
|
|
#ifdef TRACE_CPU
|
|
|
|
#define TRACE_CPU0(msg) _RPT1(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",gSystemCycleCount)
|
|
#define TRACE_CPU1(msg,arg1) _RPT2(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",arg1,gSystemCycleCount)
|
|
#define TRACE_CPU2(msg,arg1,arg2) _RPT3(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",arg1,arg2,gSystemCycleCount)
|
|
#define TRACE_CPU3(msg,arg1,arg2,arg3) _RPT4(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",arg1,arg2,arg3,gSystemCycleCount)
|
|
|
|
#else
|
|
|
|
#define TRACE_CPU0(msg)
|
|
#define TRACE_CPU1(msg,arg1)
|
|
#define TRACE_CPU2(msg,arg1,arg2)
|
|
#define TRACE_CPU3(msg,arg1,arg2,arg3)
|
|
|
|
#endif
|
|
|
|
//
|
|
// Handy definitions
|
|
//
|
|
|
|
#define NMI_VECTOR 0xfffa
|
|
#define BOOT_VECTOR 0xfffc
|
|
#define IRQ_VECTOR 0xfffe
|
|
|
|
#define MAX_CPU_BREAKPOINTS 8
|
|
|
|
#define CPU_RDWR_CYC 5
|
|
|
|
//
|
|
// ACCESS MACROS
|
|
//
|
|
#define CPU_PEEK_RAM(m) (mRamPointer[m])
|
|
#define CPU_POKE_RAM(m1,m2) mRamPointer[m1]=m2
|
|
|
|
#define CPU_PEEK(m) (((m<0xfc00)?CPU_PEEK_RAM(m):mSystem.Peek_CPU(m)))
|
|
#define CPU_PEEKW(m) (((m<0xfc00)?(mRamPointer[m]+(mRamPointer[m+1]<<8)):mSystem.PeekW_CPU(m)))
|
|
#define CPU_POKE(m1,m2) {if(m1<0xfc00) CPU_POKE_RAM(m1,m2); else mSystem.Poke_CPU(m1,m2);}
|
|
|
|
|
|
enum
|
|
{
|
|
illegal=0,
|
|
accu,
|
|
imm,
|
|
absl,
|
|
zp,
|
|
zpx,
|
|
zpy,
|
|
absx,
|
|
absy,
|
|
iabsx,
|
|
impl,
|
|
rel,
|
|
zrel,
|
|
indx,
|
|
indy,
|
|
iabs,
|
|
ind
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
int PS; // Processor status register 8 bits
|
|
int A; // Accumulator 8 bits
|
|
int X; // X index register 8 bits
|
|
int Y; // Y index register 8 bits
|
|
int SP; // Stack Pointer 8 bits
|
|
int Opcode; // Instruction opcode 8 bits
|
|
int Operand;// Intructions operand 16 bits
|
|
int PC; // Program Counter 16 bits
|
|
bool NMI;
|
|
bool IRQ;
|
|
bool WAIT;
|
|
#ifdef _LYNXDBG
|
|
int cpuBreakpoints[MAX_CPU_BREAKPOINTS];
|
|
#endif
|
|
}C6502_REGS;
|
|
|
|
//
|
|
// The CPU emulation macros
|
|
//
|
|
#include "c6502mak.h"
|
|
//
|
|
// The CPU emulation macros
|
|
//
|
|
|
|
class C65C02
|
|
{
|
|
public:
|
|
C65C02(CSystemBase& parent)
|
|
:mSystem(parent)
|
|
{
|
|
TRACE_CPU0("C65C02()");
|
|
// Compute the BCD lookup table
|
|
// for(UWORD t=0;t<256;++t)
|
|
// {
|
|
// mBCDTable[0][t]=((t >> 4) * 10) + (t & 0x0f);
|
|
// mBCDTable[1][t]=(((t % 100) / 10) << 4) | (t % 10);
|
|
// }
|
|
#ifdef _LYNXDBG
|
|
for(int loop=0;loop<MAX_CPU_BREAKPOINTS;loop++) mPcBreakpoints[loop]=0xfffffff;
|
|
mDbgFlag=0;
|
|
#endif
|
|
Reset();
|
|
|
|
}
|
|
|
|
~C65C02()
|
|
{
|
|
TRACE_CPU0("~C65C02()");
|
|
}
|
|
|
|
public:
|
|
inline void Reset(void)
|
|
{
|
|
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;
|
|
|
|
gSystemNMI=FALSE;
|
|
gSystemIRQ=FALSE;
|
|
gSystemCPUSleep=FALSE;
|
|
gSystemCPUSleep_Saved=FALSE;
|
|
}
|
|
|
|
|
|
inline bool ContextSave(LSS_FILE *fp)
|
|
{
|
|
TRACE_CPU0("ContextSave()");
|
|
int mPS;
|
|
mPS=PS();
|
|
if(!lss_printf(fp,"C6502::ContextSave")) return 0;
|
|
if(!lss_write(&mA,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_write(&mX,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_write(&mY,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_write(&mSP,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_write(&mPS,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_write(&mPC,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_write(&mIRQActive,sizeof(ULONG),1,fp)) return 0;
|
|
return 1;
|
|
}
|
|
|
|
inline bool ContextLoad(LSS_FILE *fp)
|
|
{
|
|
TRACE_CPU0("ContextLoad()");
|
|
int mPS;
|
|
char teststr[32]="XXXXXXXXXXXXXXXXXX";
|
|
if(!lss_read(teststr,sizeof(char),18,fp)) return 0;
|
|
if(strcmp(teststr,"C6502::ContextSave")!=0) return 0;
|
|
if(!lss_read(&mA,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_read(&mX,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_read(&mY,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_read(&mSP,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_read(&mPS,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_read(&mPC,sizeof(ULONG),1,fp)) return 0;
|
|
if(!lss_read(&mIRQActive,sizeof(ULONG),1,fp)) return 0;
|
|
PS(mPS);
|
|
return 1;
|
|
}
|
|
|
|
inline void Update(void)
|
|
{
|
|
//
|
|
// NMI is currently unused by the lynx so lets save some time
|
|
//
|
|
// Check NMI & IRQ status, prioritise NMI then IRQ
|
|
// if(mNMI)
|
|
// {
|
|
// // Mark the NMI as services
|
|
// mNMI=FALSE;
|
|
// mProcessingInterrupt++;
|
|
//
|
|
// // Push processor status
|
|
// CPU_POKE(0x0100+mSP--,mPC>>8);
|
|
// CPU_POKE(0x0100+mSP--,mPC&0x00ff);
|
|
// CPU_POKE(0x0100+mSP--,PS());
|
|
//
|
|
// // Pick up the new PC
|
|
// mPC=CPU_PEEKW(NMI_VECTOR);
|
|
// }
|
|
|
|
if(gSystemIRQ && !mI)
|
|
{
|
|
TRACE_CPU1("Update() IRQ taken at PC=%04x",mPC);
|
|
// IRQ signal clearance is handled by CMikie::Update() as this
|
|
// is the only source of interrupts
|
|
|
|
// 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);
|
|
|
|
// Save the sleep state as an irq has possibly woken the processor
|
|
gSystemCPUSleep_Saved=gSystemCPUSleep;
|
|
gSystemCPUSleep=FALSE;
|
|
|
|
// Log the irq entry time
|
|
gIRQEntryCycle=gSystemCycleCount;
|
|
|
|
// Clear the interrupt status line
|
|
gSystemIRQ=FALSE;
|
|
}
|
|
|
|
//
|
|
// If the CPU is asleep then skip to the next timer event
|
|
//
|
|
if(gSystemCPUSleep) return;
|
|
|
|
// Fetch opcode
|
|
mOpcode=CPU_PEEK(mPC);
|
|
TRACE_CPU2("Update() PC=$%04x, Opcode=%02x",mPC,mOpcode);
|
|
mPC++;
|
|
|
|
// Execute Opcode
|
|
|
|
switch(mOpcode)
|
|
{
|
|
|
|
//
|
|
// 0x00
|
|
//
|
|
case 0x00:
|
|
gSystemCycleCount+=(1+(6*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xBRK();
|
|
break;
|
|
case 0x01:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_X();
|
|
xORA();
|
|
break;
|
|
case 0x02:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x03:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x04:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xTSB();
|
|
break;
|
|
case 0x05:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xORA();
|
|
break;
|
|
case 0x06:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xASL();
|
|
break;
|
|
case 0x07:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0x08:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xPHP();
|
|
break;
|
|
case 0x09:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xORA();
|
|
break;
|
|
case 0x0A:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xASLA();
|
|
break;
|
|
case 0x0B:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x0C:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xTSB();
|
|
break;
|
|
case 0x0D:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xORA();
|
|
break;
|
|
case 0x0E:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xASL();
|
|
break;
|
|
case 0x0F:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0x10
|
|
//
|
|
case 0x10:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// RELATIVE (IN FUNCTION)
|
|
xBPL();
|
|
break;
|
|
case 0x11:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT_Y();
|
|
xORA();
|
|
break;
|
|
case 0x12:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT();
|
|
xORA();
|
|
break;
|
|
case 0x13:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x14:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xTRB();
|
|
break;
|
|
case 0x15:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xORA();
|
|
break;
|
|
case 0x16:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xASL();
|
|
break;
|
|
case 0x17:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0x18:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xCLC();
|
|
break;
|
|
case 0x19:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_Y();
|
|
xORA();
|
|
break;
|
|
case 0x1A:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xINCA();
|
|
break;
|
|
case 0x1B:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x1C:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xTRB();
|
|
break;
|
|
case 0x1D:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xORA();
|
|
break;
|
|
case 0x1E:
|
|
gSystemCycleCount+=(1+(6*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xASL();
|
|
break;
|
|
case 0x1F:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0x20
|
|
//
|
|
case 0x20:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xJSR();
|
|
break;
|
|
case 0x21:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_X();
|
|
xAND();
|
|
break;
|
|
case 0x22:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x23:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x24:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xBIT();
|
|
break;
|
|
case 0x25:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xAND();
|
|
break;
|
|
case 0x26:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xROL();
|
|
break;
|
|
case 0x27:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0x28:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xPLP();
|
|
break;
|
|
case 0x29:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xAND();
|
|
break;
|
|
case 0x2A:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xROLA();
|
|
break;
|
|
case 0x2B:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x2C:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xBIT();
|
|
break;
|
|
case 0x2D:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xAND();
|
|
break;
|
|
case 0x2E:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xROL();
|
|
break;
|
|
case 0x2F:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0x30
|
|
//
|
|
case 0x30:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// RELATIVE (IN FUNCTION)
|
|
xBMI();
|
|
break;
|
|
case 0x31:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT_Y();
|
|
xAND();
|
|
break;
|
|
case 0x32:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT();
|
|
xAND();
|
|
break;
|
|
case 0x33:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x34:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xBIT();
|
|
break;
|
|
case 0x35:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xAND();
|
|
break;
|
|
case 0x36:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xROL();
|
|
break;
|
|
case 0x37:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0x38:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xSEC();
|
|
break;
|
|
case 0x39:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_Y();
|
|
xAND();
|
|
break;
|
|
case 0x3A:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xDECA();
|
|
break;
|
|
case 0x3B:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x3C:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xBIT();
|
|
break;
|
|
case 0x3D:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xAND();
|
|
break;
|
|
case 0x3E:
|
|
gSystemCycleCount+=(1+(6*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xROL();
|
|
break;
|
|
case 0x3F:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0x40
|
|
//
|
|
case 0x40:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
// Only clear IRQ if this is not a BRK instruction based RTI
|
|
|
|
// B flag is on the stack cant test the flag
|
|
int tmp;
|
|
PULL(tmp);
|
|
PUSH (tmp);
|
|
if(!(tmp&0x10))
|
|
{
|
|
gSystemCPUSleep=gSystemCPUSleep_Saved;
|
|
|
|
// If were in sleep mode then we need to push the
|
|
// wakeup counter along by the same number of cycles
|
|
// we have used during the sleep period
|
|
if(gSystemCPUSleep)
|
|
{
|
|
gCPUWakeupTime+=gSystemCycleCount-gIRQEntryCycle;
|
|
}
|
|
}
|
|
// IMPLIED
|
|
xRTI();
|
|
break;
|
|
case 0x41:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_X();
|
|
xEOR();
|
|
break;
|
|
case 0x42:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x43:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x44:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x45:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xEOR();
|
|
break;
|
|
case 0x46:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xLSR();
|
|
break;
|
|
case 0x47:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0x48:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xPHA();
|
|
break;
|
|
case 0x49:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xEOR();
|
|
break;
|
|
case 0x4A:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xLSRA();
|
|
break;
|
|
case 0x4B:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x4C:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xJMP();
|
|
break;
|
|
case 0x4D:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xEOR();
|
|
break;
|
|
case 0x4E:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xLSR();
|
|
break;
|
|
case 0x4F:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0x50
|
|
//
|
|
case 0x50:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// RELATIVE (IN FUNCTION)
|
|
xBVC();
|
|
break;
|
|
case 0x51:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT_Y();
|
|
xEOR();
|
|
break;
|
|
case 0x52:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT();
|
|
xEOR();
|
|
break;
|
|
case 0x53:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x54:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x55:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xEOR();
|
|
break;
|
|
case 0x56:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xLSR();
|
|
break;
|
|
case 0x57:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0x58:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xCLI();
|
|
break;
|
|
case 0x59:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_Y();
|
|
xEOR();
|
|
break;
|
|
case 0x5A:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xPHY();
|
|
break;
|
|
case 0x5B:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x5C:
|
|
gSystemCycleCount+=(1+(7*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x5D:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xEOR();
|
|
break;
|
|
case 0x5E:
|
|
gSystemCycleCount+=(1+(6*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xLSR();
|
|
break;
|
|
case 0x5F:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0x60
|
|
//
|
|
case 0x60:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xRTS();
|
|
break;
|
|
case 0x61:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_X();
|
|
xADC();
|
|
break;
|
|
case 0x62:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x63:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x64:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xSTZ();
|
|
break;
|
|
case 0x65:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xADC();
|
|
break;
|
|
case 0x66:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xROR();
|
|
break;
|
|
case 0x67:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0x68:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xPLA();
|
|
break;
|
|
case 0x69:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xADC();
|
|
break;
|
|
case 0x6A:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xRORA();
|
|
break;
|
|
case 0x6B:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x6C:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_ABSOLUTE();
|
|
xJMP();
|
|
break;
|
|
case 0x6D:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xADC();
|
|
break;
|
|
case 0x6E:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xROR();
|
|
break;
|
|
case 0x6F:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0x70
|
|
//
|
|
case 0x70:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// RELATIVE (IN FUNCTION)
|
|
xBVS();
|
|
break;
|
|
case 0x71:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT_Y();
|
|
xADC();
|
|
break;
|
|
case 0x72:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT();
|
|
xADC();
|
|
break;
|
|
case 0x73:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x74:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xSTZ();
|
|
break;
|
|
case 0x75:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xADC();
|
|
break;
|
|
case 0x76:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xROR();
|
|
break;
|
|
case 0x77:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0x78:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xSEI();
|
|
break;
|
|
case 0x79:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_Y();
|
|
xADC();
|
|
break;
|
|
case 0x7A:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xPLY();
|
|
break;
|
|
case 0x7B:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x7C:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_ABSOLUTE_X();
|
|
xJMP();
|
|
break;
|
|
case 0x7D:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xADC();
|
|
break;
|
|
case 0x7E:
|
|
gSystemCycleCount+=(1+(6*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xROR();
|
|
break;
|
|
case 0x7F:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0x80
|
|
//
|
|
case 0x80:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
// RELATIVE (IN FUNCTION)
|
|
xBRA();
|
|
break;
|
|
case 0x81:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_X();
|
|
xSTA();
|
|
break;
|
|
case 0x82:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x83:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x84:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xSTY();
|
|
break;
|
|
case 0x85:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xSTA();
|
|
break;
|
|
case 0x86:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xSTX();
|
|
break;
|
|
case 0x87:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0x88:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xDEY();
|
|
break;
|
|
case 0x89:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xBIT();
|
|
break;
|
|
case 0x8A:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xTXA();
|
|
break;
|
|
case 0x8B:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x8C:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xSTY();
|
|
break;
|
|
case 0x8D:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xSTA();
|
|
break;
|
|
case 0x8E:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xSTX();
|
|
break;
|
|
case 0x8F:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0x90
|
|
//
|
|
case 0x90:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// RELATIVE (IN FUNCTION)
|
|
xBCC();
|
|
break;
|
|
case 0x91:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_Y();
|
|
xSTA();
|
|
break;
|
|
case 0x92:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT();
|
|
xSTA();
|
|
break;
|
|
case 0x93:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x94:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xSTY();
|
|
break;
|
|
case 0x95:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xSTA();
|
|
break;
|
|
case 0x96:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_Y();
|
|
xSTX();
|
|
break;
|
|
case 0x97:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0x98:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xTYA();
|
|
break;
|
|
case 0x99:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xABSOLUTE_Y();
|
|
xSTA();
|
|
break;
|
|
case 0x9A:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xTXS();
|
|
break;
|
|
case 0x9B:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0x9C:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xSTZ();
|
|
break;
|
|
case 0x9D:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xSTA();
|
|
break;
|
|
case 0x9E:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xSTZ();
|
|
break;
|
|
case 0x9F:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0xA0
|
|
//
|
|
case 0xA0:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xLDY();
|
|
break;
|
|
case 0xA1:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_X();
|
|
xLDA();
|
|
break;
|
|
case 0xA2:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xLDX();
|
|
break;
|
|
case 0xA3:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xA4:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xLDY();
|
|
break;
|
|
case 0xA5:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xLDA();
|
|
break;
|
|
case 0xA6:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xLDX();
|
|
break;
|
|
case 0xA7:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0xA8:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xTAY();
|
|
break;
|
|
case 0xA9:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xLDA();
|
|
break;
|
|
case 0xAA:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xTAX();
|
|
break;
|
|
case 0xAB:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xAC:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xLDY();
|
|
break;
|
|
case 0xAD:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xLDA();
|
|
break;
|
|
case 0xAE:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xLDX();
|
|
break;
|
|
case 0xAF:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0xB0
|
|
//
|
|
case 0xB0:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// RELATIVE (IN FUNCTION)
|
|
xBCS();
|
|
break;
|
|
case 0xB1:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT_Y();
|
|
xLDA();
|
|
break;
|
|
case 0xB2:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT();
|
|
xLDA();
|
|
break;
|
|
case 0xB3:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xB4:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xLDY();
|
|
break;
|
|
case 0xB5:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xLDA();
|
|
break;
|
|
case 0xB6:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_Y();
|
|
xLDX();
|
|
break;
|
|
case 0xB7:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0xB8:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xCLV();
|
|
break;
|
|
case 0xB9:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_Y();
|
|
xLDA();
|
|
break;
|
|
case 0xBA:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xTSX();
|
|
break;
|
|
case 0xBB:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xBC:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xLDY();
|
|
break;
|
|
case 0xBD:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xLDA();
|
|
break;
|
|
case 0xBE:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_Y();
|
|
xLDX();
|
|
break;
|
|
case 0xBF:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0xC0
|
|
//
|
|
case 0xC0:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xCPY();
|
|
break;
|
|
case 0xC1:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_X();
|
|
xCMP();
|
|
break;
|
|
case 0xC2:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xC3:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xC4:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xCPY();
|
|
break;
|
|
case 0xC5:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xCMP();
|
|
break;
|
|
case 0xC6:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xDEC();
|
|
break;
|
|
case 0xC7:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0xC8:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xINY();
|
|
break;
|
|
case 0xC9:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xCMP();
|
|
break;
|
|
case 0xCA:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xDEX();
|
|
break;
|
|
case 0xCB:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xWAI();
|
|
break;
|
|
case 0xCC:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xCPY();
|
|
break;
|
|
case 0xCD:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xCMP();
|
|
break;
|
|
case 0xCE:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xDEC();
|
|
break;
|
|
case 0xCF:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0xD0
|
|
//
|
|
case 0xD0:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// RELATIVE (IN FUNCTION)
|
|
xBNE();
|
|
break;
|
|
case 0xD1:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT_Y();
|
|
xCMP();
|
|
break;
|
|
case 0xD2:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT();
|
|
xCMP();
|
|
break;
|
|
case 0xD3:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xD4:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xD5:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xCMP();
|
|
break;
|
|
case 0xD6:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xDEC();
|
|
break;
|
|
case 0xD7:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0xD8:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xCLD();
|
|
break;
|
|
case 0xD9:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_Y();
|
|
xCMP();
|
|
break;
|
|
case 0xDA:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xPHX();
|
|
break;
|
|
case 0xDB:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xSTP();
|
|
break;
|
|
case 0xDC:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xDD:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xCMP();
|
|
break;
|
|
case 0xDE:
|
|
gSystemCycleCount+=(1+(6*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xDEC();
|
|
break;
|
|
case 0xDF:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0xE0
|
|
//
|
|
case 0xE0:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xCPX();
|
|
break;
|
|
case 0xE1:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xINDIRECT_X();
|
|
xSBC();
|
|
break;
|
|
case 0xE2:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xE3:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xE4:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xCPX();
|
|
break;
|
|
case 0xE5:
|
|
gSystemCycleCount+=(1+(2*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xSBC();
|
|
break;
|
|
case 0xE6:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xZEROPAGE();
|
|
xINC();
|
|
break;
|
|
case 0xE7:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0xE8:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xINX();
|
|
break;
|
|
case 0xE9:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
xIMMEDIATE();
|
|
xSBC();
|
|
break;
|
|
case 0xEA:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xNOP();
|
|
break;
|
|
case 0xEB:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xEC:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xCPX();
|
|
break;
|
|
case 0xED:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xSBC();
|
|
break;
|
|
case 0xEE:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xABSOLUTE();
|
|
xINC();
|
|
break;
|
|
case 0xEF:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
//
|
|
// 0xF0
|
|
//
|
|
case 0xF0:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// RELATIVE (IN FUNCTION)
|
|
xBEQ();
|
|
break;
|
|
case 0xF1:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT_Y();
|
|
xSBC();
|
|
break;
|
|
case 0xF2:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
xINDIRECT();
|
|
xSBC();
|
|
break;
|
|
case 0xF3:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xF4:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xF5:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xSBC();
|
|
break;
|
|
case 0xF6:
|
|
gSystemCycleCount+=(1+(5*CPU_RDWR_CYC));
|
|
xZEROPAGE_X();
|
|
xINC();
|
|
break;
|
|
case 0xF7:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
|
|
case 0xF8:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xSED();
|
|
break;
|
|
case 0xF9:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_Y();
|
|
xSBC();
|
|
break;
|
|
case 0xFA:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
// IMPLIED
|
|
xPLX();
|
|
break;
|
|
case 0xFB:
|
|
gSystemCycleCount+=(1+(1*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xFC:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
case 0xFD:
|
|
gSystemCycleCount+=(1+(3*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xSBC();
|
|
break;
|
|
case 0xFE:
|
|
gSystemCycleCount+=(1+(6*CPU_RDWR_CYC));
|
|
xABSOLUTE_X();
|
|
xINC();
|
|
break;
|
|
case 0xFF:
|
|
gSystemCycleCount+=(1+(4*CPU_RDWR_CYC));
|
|
// *** ILLEGAL ***
|
|
xILLEGAL();
|
|
break;
|
|
}
|
|
|
|
#ifdef _LYNXDBG
|
|
|
|
// Trigger breakpoint if required
|
|
|
|
for(int loop=0;loop<MAX_CPU_BREAKPOINTS;loop++)
|
|
{
|
|
if(mPcBreakpoints[loop]==mPC)
|
|
{
|
|
gBreakpointHit=TRUE;
|
|
mSystem.DebugTrace(0);
|
|
}
|
|
}
|
|
|
|
// Check code level debug features
|
|
// back to back CPX ($Absolute)
|
|
// on the 2nd Occurance we do some debug
|
|
if(mOpcode==0xec)
|
|
{
|
|
if(mDbgFlag)
|
|
{
|
|
// We shoud do some debug now
|
|
if(!mOperand)
|
|
{
|
|
// Trigger a breakpoint
|
|
gBreakpointHit=TRUE;
|
|
// Generate a debug trail output
|
|
mSystem.DebugTrace(0);
|
|
}
|
|
else
|
|
{
|
|
// Generate a debug trail output
|
|
mSystem.DebugTrace(mOperand);
|
|
}
|
|
mDbgFlag=0;
|
|
}
|
|
else
|
|
{
|
|
if(mOperand==0x5aa5) mDbgFlag=1; else mDbgFlag=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mDbgFlag=0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// inline void SetBreakpoint(ULONG breakpoint) {mPcBreakpoint=breakpoint;};
|
|
|
|
inline void 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;
|
|
gSystemCPUSleep=regs.WAIT;
|
|
#ifdef _LYNXDBG
|
|
for(int loop=0;loop<MAX_CPU_BREAKPOINTS;loop++) mPcBreakpoints[loop]=regs.cpuBreakpoints[loop];
|
|
#endif
|
|
gSystemNMI=regs.NMI;
|
|
gSystemIRQ=regs.IRQ;
|
|
}
|
|
|
|
inline void 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=(gSystemCPUSleep)?true:false;
|
|
#ifdef _LYNXDBG
|
|
for(int loop=0;loop<MAX_CPU_BREAKPOINTS;loop++) regs.cpuBreakpoints[loop]=mPcBreakpoints[loop];
|
|
#endif
|
|
regs.NMI=(gSystemNMI)?true:false;
|
|
regs.IRQ=(gSystemIRQ)?true:false;
|
|
}
|
|
|
|
inline int GetPC(void) { return mPC; }
|
|
|
|
inline void xILLEGAL(void)
|
|
{
|
|
log_printf("CPU: Illegal opcode $%02x at PC=$%04x.\n", mOpcode, mPC);
|
|
}
|
|
|
|
private:
|
|
CSystemBase &mSystem;
|
|
|
|
// CPU Flags & status
|
|
|
|
int mA; // Accumulator 8 bits
|
|
int mX; // X index register 8 bits
|
|
int mY; // Y index register 8 bits
|
|
int mSP; // Stack Pointer 8 bits
|
|
int mOpcode; // Instruction opcode 8 bits
|
|
int mOperand; // Intructions operand 16 bits
|
|
int mPC; // Program Counter 16 bits
|
|
|
|
int mN; // N flag for processor status register
|
|
int mV; // V flag for processor status register
|
|
int mB; // B flag for processor status register
|
|
int mD; // D flag for processor status register
|
|
int mI; // I flag for processor status register
|
|
int mZ; // Z flag for processor status register
|
|
int mC; // C flag for processor status register
|
|
|
|
int mIRQActive;
|
|
|
|
#ifdef _LYNXDBG
|
|
int mPcBreakpoints[MAX_CPU_BREAKPOINTS];
|
|
int mDbgFlag;
|
|
#endif
|
|
UBYTE *mRamPointer;
|
|
|
|
// Associated lookup tables
|
|
|
|
// int mBCDTable[2][256];
|
|
|
|
//
|
|
// Opcode prototypes
|
|
//
|
|
|
|
private:
|
|
|
|
// Answers value of the Processor Status register
|
|
int PS() const
|
|
{
|
|
UBYTE ps = 0x20;
|
|
if(mN) ps|=0x80;
|
|
if(mV) ps|=0x40;
|
|
if(mB) ps|=0x10;
|
|
if(mD) ps|=0x08;
|
|
if(mI) ps|=0x04;
|
|
if(mZ) ps|=0x02;
|
|
if(mC) ps|=0x01;
|
|
return ps;
|
|
}
|
|
|
|
|
|
// Change the processor flags to correspond to the given value
|
|
void PS(int ps)
|
|
{
|
|
mN=ps&0x80;
|
|
mV=ps&0x40;
|
|
mB=ps&0x10;
|
|
mD=ps&0x08;
|
|
mI=ps&0x04;
|
|
mZ=ps&0x02;
|
|
mC=ps&0x01;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
#endif
|
|
|