|
From: <ste...@us...> - 2009-05-17 19:30:32
|
Revision: 1729
http://stella.svn.sourceforge.net/stella/?rev=1729&view=rev
Author: stephena
Date: 2009-05-17 19:30:10 +0000 (Sun, 17 May 2009)
Log Message:
-----------
The CPU emulation now always uses what was previously called 'Hi' mode.
The low-compatibility mode was removed, as it hasn't been tested in years,
and for the CPU work I have to do in the coming months, I only want to
worry about one CPU class. All reference to M6502Hi/M6502Low has been
removed; the CPU class is now simply known as M6502.
Commented out the recent fix for Q-Bert screen refresh issues, since
there's an underlying TIA emulation problem that is causing it.
Modified Paths:
--------------
trunk/stella/src/emucore/CartAR.cxx
trunk/stella/src/emucore/CartAR.hxx
trunk/stella/src/emucore/Console.cxx
trunk/stella/src/emucore/EventHandler.cxx
trunk/stella/src/emucore/m6502/Copyright.txt
trunk/stella/src/emucore/m6502/module.mk
trunk/stella/src/emucore/m6502/src/M6502.cxx
trunk/stella/src/emucore/m6502/src/M6502.hxx
trunk/stella/src/emucore/m6502/src/M6502.m4
trunk/stella/src/emucore/m6502/src/bspf/Copyright.txt
Added Paths:
-----------
trunk/stella/src/emucore/m6502/src/M6502.ins
Removed Paths:
-------------
trunk/stella/src/emucore/m6502/src/M6502Hi.cxx
trunk/stella/src/emucore/m6502/src/M6502Hi.hxx
trunk/stella/src/emucore/m6502/src/M6502Hi.ins
trunk/stella/src/emucore/m6502/src/M6502Hi.m4
trunk/stella/src/emucore/m6502/src/M6502Low.cxx
trunk/stella/src/emucore/m6502/src/M6502Low.hxx
trunk/stella/src/emucore/m6502/src/M6502Low.ins
trunk/stella/src/emucore/m6502/src/M6502Low.m4
Modified: trunk/stella/src/emucore/CartAR.cxx
===================================================================
--- trunk/stella/src/emucore/CartAR.cxx 2009-05-16 18:49:10 UTC (rev 1728)
+++ trunk/stella/src/emucore/CartAR.cxx 2009-05-17 19:30:10 UTC (rev 1729)
@@ -19,7 +19,7 @@
#include <cassert>
#include <cstring>
-#include "M6502Hi.hxx"
+#include "M6502.hxx"
#include "Random.hxx"
#include "System.hxx"
#include "CartAR.hxx"
@@ -80,7 +80,7 @@
uInt16 shift = mySystem->pageShift();
uInt16 mask = mySystem->pageMask();
- my6502 = &(M6502High&)mySystem->m6502();
+ my6502 = &(mySystem->m6502());
// Make sure the system we're being installed in has a page size that'll work
assert((0x1000 & mask) == 0);
Modified: trunk/stella/src/emucore/CartAR.hxx
===================================================================
--- trunk/stella/src/emucore/CartAR.hxx 2009-05-16 18:49:10 UTC (rev 1728)
+++ trunk/stella/src/emucore/CartAR.hxx 2009-05-17 19:30:10 UTC (rev 1729)
@@ -19,7 +19,7 @@
#ifndef CARTRIDGEAR_HXX
#define CARTRIDGEAR_HXX
-class M6502High;
+class M6502;
class System;
#include "bspf.hxx"
@@ -165,7 +165,7 @@
private:
// Pointer to the 6502 processor in the system
- M6502High* my6502;
+ M6502* my6502;
// Indicates the offest within the image for the corresponding bank
uInt32 myImageOffset[2];
Modified: trunk/stella/src/emucore/Console.cxx
===================================================================
--- trunk/stella/src/emucore/Console.cxx 2009-05-16 18:49:10 UTC (rev 1728)
+++ trunk/stella/src/emucore/Console.cxx 2009-05-17 19:30:10 UTC (rev 1729)
@@ -32,8 +32,7 @@
#include "Joystick.hxx"
#include "Keyboard.hxx"
#include "KidVid.hxx"
-#include "M6502Hi.hxx"
-#include "M6502Low.hxx"
+#include "M6502.hxx"
#include "M6532.hxx"
#include "Paddles.hxx"
#include "Props.hxx"
@@ -98,11 +97,7 @@
myControllers[0] = new Joystick(Controller::Left, *myEvent, *mySystem);
myControllers[1] = new Joystick(Controller::Right, *myEvent, *mySystem);
- M6502* m6502;
- if(myOSystem->settings().getString("cpu") == "low")
- m6502 = new M6502Low(1);
- else
- m6502 = new M6502High(1);
+ M6502* m6502 = new M6502(1);
#ifdef DEBUGGER_SUPPORT
m6502->attach(myOSystem->debugger());
#endif
Modified: trunk/stella/src/emucore/EventHandler.cxx
===================================================================
--- trunk/stella/src/emucore/EventHandler.cxx 2009-05-16 18:49:10 UTC (rev 1728)
+++ trunk/stella/src/emucore/EventHandler.cxx 2009-05-17 19:30:10 UTC (rev 1729)
@@ -931,6 +931,7 @@
break;
////////////////////////////////////////////////////////////////////////
+#if 0
case Event::ConsoleReset:
if(state)
{
@@ -938,7 +939,7 @@
myOSystem->frameBuffer().refresh();
}
break;
-
+#endif
case Event::Fry:
myFryingFlag = bool(state);
return;
Modified: trunk/stella/src/emucore/m6502/Copyright.txt
===================================================================
--- trunk/stella/src/emucore/m6502/Copyright.txt 2009-05-16 18:49:10 UTC (rev 1728)
+++ trunk/stella/src/emucore/m6502/Copyright.txt 2009-05-17 19:30:10 UTC (rev 1729)
@@ -12,7 +12,7 @@
License Information and Copyright Notice
===============================================================================
-Copyright (C) 1995-2002 Bradford W. Mott <bw...@ac...>
+Copyright (C) 1995-2009 Bradford W. Mott <bw...@ac...>
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Modified: trunk/stella/src/emucore/m6502/module.mk
===================================================================
--- trunk/stella/src/emucore/m6502/module.mk 2009-05-16 18:49:10 UTC (rev 1728)
+++ trunk/stella/src/emucore/m6502/module.mk 2009-05-17 19:30:10 UTC (rev 1729)
@@ -3,8 +3,6 @@
MODULE_OBJS := \
src/emucore/m6502/src/Device.o \
src/emucore/m6502/src/M6502.o \
- src/emucore/m6502/src/M6502Low.o \
- src/emucore/m6502/src/M6502Hi.o \
src/emucore/m6502/src/NullDev.o \
src/emucore/m6502/src/System.o
Modified: trunk/stella/src/emucore/m6502/src/M6502.cxx
===================================================================
--- trunk/stella/src/emucore/m6502/src/M6502.cxx 2009-05-16 18:49:10 UTC (rev 1728)
+++ trunk/stella/src/emucore/m6502/src/M6502.cxx 2009-05-17 19:30:10 UTC (rev 1729)
@@ -16,25 +16,36 @@
// $Id$
//============================================================================
-#include "M6502.hxx"
+//#define DEBUG_OUTPUT
+#define debugStream cout
+#include "Serializer.hxx"
+#include "Deserializer.hxx"
+
#ifdef DEBUGGER_SUPPORT
+ #include "Debugger.hxx"
#include "Expression.hxx"
#endif
+#include "M6502.hxx"
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
M6502::M6502(uInt32 systemCyclesPerProcessorCycle)
: myExecutionStatus(0),
mySystem(0),
mySystemCyclesPerProcessorCycle(systemCyclesPerProcessorCycle),
myLastAccessWasRead(true),
- myTotalInstructionCount(0)
+ myTotalInstructionCount(0),
+ myNumberOfDistinctAccesses(0),
+ myLastAddress(0)
{
#ifdef DEBUGGER_SUPPORT
myDebugger = NULL;
myBreakPoints = NULL;
myReadTraps = NULL;
myWriteTraps = NULL;
+
+ myJustHitTrapFlag = false;
#endif
// Compute the System Cycle table
@@ -43,6 +54,11 @@
myInstructionSystemCycleTable[t] = ourInstructionProcessorCycleTable[t] *
mySystemCyclesPerProcessorCycle;
}
+
+
+debugStream << "( Fm Ln Cyc Clk) ( P0 P1 M0 M1 BL) "
+ << "flags A X Y SP Code Disasm" << endl
+ << endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -135,6 +151,280 @@
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+inline uInt8 M6502::peek(uInt16 address)
+{
+ if(address != myLastAddress)
+ {
+ myNumberOfDistinctAccesses++;
+ myLastAddress = address;
+ }
+ mySystem->incrementCycles(mySystemCyclesPerProcessorCycle);
+
+#ifdef DEBUGGER_SUPPORT
+ if(myReadTraps != NULL && myReadTraps->isSet(address))
+ {
+ myJustHitTrapFlag = true;
+ myHitTrapInfo.message = "RTrap: ";
+ myHitTrapInfo.address = address;
+ }
+#endif
+
+ uInt8 result = mySystem->peek(address);
+ myLastAccessWasRead = true;
+ return result;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+inline void M6502::poke(uInt16 address, uInt8 value)
+{
+ if(address != myLastAddress)
+ {
+ myNumberOfDistinctAccesses++;
+ myLastAddress = address;
+ }
+ mySystem->incrementCycles(mySystemCyclesPerProcessorCycle);
+
+#ifdef DEBUGGER_SUPPORT
+ if(myWriteTraps != NULL && myWriteTraps->isSet(address))
+ {
+ myJustHitTrapFlag = true;
+ myHitTrapInfo.message = "WTrap: ";
+ myHitTrapInfo.address = address;
+ }
+#endif
+
+ mySystem->poke(address, value);
+ myLastAccessWasRead = false;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool M6502::execute(uInt32 number)
+{
+ // Clear all of the execution status bits except for the fatal error bit
+ myExecutionStatus &= FatalErrorBit;
+
+ // Loop until execution is stopped or a fatal error occurs
+ for(;;)
+ {
+ for(; !myExecutionStatus && (number != 0); --number)
+ {
+ uInt16 operandAddress = 0;
+ uInt8 operand = 0;
+
+#ifdef DEBUGGER_SUPPORT
+ if(myJustHitTrapFlag)
+ {
+ if(myDebugger->start(myHitTrapInfo.message, myHitTrapInfo.address))
+ {
+ myJustHitTrapFlag = false;
+ return true;
+ }
+ }
+
+ if(myBreakPoints != NULL)
+ {
+ if(myBreakPoints->isSet(PC))
+ {
+ if(myDebugger->start("BP: ", PC))
+ return true;
+ }
+ }
+
+ int cond = evalCondBreaks();
+ if(cond > -1)
+ {
+ string buf = "CBP: " + myBreakCondNames[cond];
+ if(myDebugger->start(buf))
+ return true;
+ }
+#endif
+
+ // Fetch instruction at the program counter
+ IR = peek(PC++);
+
+#ifdef DEBUG_OUTPUT
+ debugStream << ::hex << setw(2) << (int)A << " "
+ << ::hex << setw(2) << (int)X << " "
+ << ::hex << setw(2) << (int)Y << " "
+ << ::hex << setw(2) << (int)SP << " "
+ << setw(4) << (PC-1) << ": "
+ << setw(2) << (int)IR << " "
+// << "<" << ourAddressingModeTable[IR] << " ";
+// debugStream << hex << setw(4) << operandAddress << " ";
+ << setw(3) << ourInstructionMnemonicTable[IR]
+
+// debugStream << "PS=" << ::hex << setw(2) << (int)PS() << " ";
+
+// debugStream << "Cyc=" << dec << mySystem->cycles();
+ << endl;
+#endif
+
+ // Call code to execute the instruction
+ switch(IR)
+ {
+ // 6502 instruction emulation is generated by an M4 macro file
+ #include "M6502.ins"
+
+ default:
+ // Oops, illegal instruction executed so set fatal error flag
+ myExecutionStatus |= FatalErrorBit;
+ }
+
+ myTotalInstructionCount++;
+ }
+
+ // See if we need to handle an interrupt
+ if((myExecutionStatus & MaskableInterruptBit) ||
+ (myExecutionStatus & NonmaskableInterruptBit))
+ {
+ // Yes, so handle the interrupt
+ interruptHandler();
+ }
+
+ // See if execution has been stopped
+ if(myExecutionStatus & StopExecutionBit)
+ {
+ // Yes, so answer that everything finished fine
+ return true;
+ }
+
+ // See if a fatal error has occured
+ if(myExecutionStatus & FatalErrorBit)
+ {
+ // Yes, so answer that something when wrong
+ return false;
+ }
+
+ // See if we've executed the specified number of instructions
+ if(number == 0)
+ {
+ // Yes, so answer that everything finished fine
+ return true;
+ }
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void M6502::interruptHandler()
+{
+ // Handle the interrupt
+ if((myExecutionStatus & MaskableInterruptBit) && !I)
+ {
+ mySystem->incrementCycles(7 * mySystemCyclesPerProcessorCycle);
+ mySystem->poke(0x0100 + SP--, (PC - 1) >> 8);
+ mySystem->poke(0x0100 + SP--, (PC - 1) & 0x00ff);
+ mySystem->poke(0x0100 + SP--, PS() & (~0x10));
+ D = false;
+ I = true;
+ PC = (uInt16)mySystem->peek(0xFFFE) | ((uInt16)mySystem->peek(0xFFFF) << 8);
+ }
+ else if(myExecutionStatus & NonmaskableInterruptBit)
+ {
+ mySystem->incrementCycles(7 * mySystemCyclesPerProcessorCycle);
+ mySystem->poke(0x0100 + SP--, (PC - 1) >> 8);
+ mySystem->poke(0x0100 + SP--, (PC - 1) & 0x00ff);
+ mySystem->poke(0x0100 + SP--, PS() & (~0x10));
+ D = false;
+ PC = (uInt16)mySystem->peek(0xFFFA) | ((uInt16)mySystem->peek(0xFFFB) << 8);
+ }
+
+ // Clear the interrupt bits in myExecutionStatus
+ myExecutionStatus &= ~(MaskableInterruptBit | NonmaskableInterruptBit);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool M6502::save(Serializer& out)
+{
+ string CPU = name();
+
+ try
+ {
+ out.putString(CPU);
+
+ out.putByte((char)A); // Accumulator
+ out.putByte((char)X); // X index register
+ out.putByte((char)Y); // Y index register
+ out.putByte((char)SP); // Stack Pointer
+ out.putByte((char)IR); // Instruction register
+ out.putInt(PC); // Program Counter
+
+ out.putBool(N); // N flag for processor status register
+ out.putBool(V); // V flag for processor status register
+ out.putBool(B); // B flag for processor status register
+ out.putBool(D); // D flag for processor status register
+ out.putBool(I); // I flag for processor status register
+ out.putBool(notZ); // Z flag complement for processor status register
+ out.putBool(C); // C flag for processor status register
+
+ out.putByte((char)myExecutionStatus);
+
+ // Indicates the number of distinct memory accesses
+ out.putInt(myNumberOfDistinctAccesses);
+ // Indicates the last address which was accessed
+ out.putInt(myLastAddress);
+
+ }
+ catch(char *msg)
+ {
+ cerr << msg << endl;
+ return false;
+ }
+ catch(...)
+ {
+ cerr << "Unknown error in save state for " << CPU << endl;
+ return false;
+ }
+
+ return true;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool M6502::load(Deserializer& in)
+{
+ string CPU = name();
+
+ try
+ {
+ if(in.getString() != CPU)
+ return false;
+
+ A = (uInt8) in.getByte(); // Accumulator
+ X = (uInt8) in.getByte(); // X index register
+ Y = (uInt8) in.getByte(); // Y index register
+ SP = (uInt8) in.getByte(); // Stack Pointer
+ IR = (uInt8) in.getByte(); // Instruction register
+ PC = (uInt16) in.getInt(); // Program Counter
+
+ N = in.getBool(); // N flag for processor status register
+ V = in.getBool(); // V flag for processor status register
+ B = in.getBool(); // B flag for processor status register
+ D = in.getBool(); // D flag for processor status register
+ I = in.getBool(); // I flag for processor status register
+ notZ = in.getBool(); // Z flag complement for processor status register
+ C = in.getBool(); // C flag for processor status register
+
+ myExecutionStatus = (uInt8) in.getByte();
+
+ // Indicates the number of distinct memory accesses
+ myNumberOfDistinctAccesses = (uInt32) in.getInt();
+ // Indicates the last address which was accessed
+ myLastAddress = (uInt16) in.getInt();
+ }
+ catch(char *msg)
+ {
+ cerr << msg << endl;
+ return false;
+ }
+ catch(...)
+ {
+ cerr << "Unknown error in load state for " << CPU << endl;
+ return false;
+ }
+
+ return true;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ostream& operator<<(ostream& out, const M6502::AddressingMode& mode)
{
switch(mode)
Modified: trunk/stella/src/emucore/m6502/src/M6502.hxx
===================================================================
--- trunk/stella/src/emucore/m6502/src/M6502.hxx 2009-05-16 18:49:10 UTC (rev 1728)
+++ trunk/stella/src/emucore/m6502/src/M6502.hxx 2009-05-17 19:30:10 UTC (rev 1729)
@@ -36,12 +36,17 @@
typedef Common::Array<Expression*> ExpressionList;
/**
- This is an abstract base class for classes that emulate the
- 6502 microprocessor. The 6502 is an 8-bit microprocessor that
- has a 64K addressing space.
+ The 6502 is an 8-bit microprocessor that has a 64K addressing space.
+ This class provides a high compatibility 6502 microprocessor emulator.
+ The memory accesses and cycle counts it generates are valid at the
+ sub-instruction level and "false" reads are generated (such as the ones
+ produced by the Indirect,X addressing when it crosses a page boundary).
+ This provides provides better compatibility for hardware that has side
+ effects and for games which are very time sensitive.
+
@author Bradford W. Mott
- @version $Id$
+ @version $Id$
*/
class M6502
{
@@ -92,69 +97,26 @@
@param system The system the processor should install itself in
*/
- virtual void install(System& system);
+ void install(System& system);
/**
Reset the processor to its power-on state. This method should not
be invoked until the entire 6502 system is constructed and installed
since it involves reading the reset vector from memory.
*/
- virtual void reset();
+ void reset();
/**
Request a maskable interrupt
*/
- virtual void irq();
+ void irq();
/**
Request a non-maskable interrupt
*/
- virtual void nmi();
+ void nmi();
/**
- Saves the current state of this device to the given Serializer.
-
- @param out The serializer device to save to.
- @return The result of the save. True on success, false on failure.
- */
- virtual bool save(Serializer& out) = 0;
-
- /**
- Loads the current state of this device from the given Deserializer.
-
- @param in The deserializer device to load from.
- @return The result of the load. True on success, false on failure.
- */
- virtual bool load(Deserializer& in) = 0;
-
- /**
- Get a null terminated string which is the processor's name (i.e. "M6532")
-
- @return The name of the device
- */
- virtual const char* name() const = 0;
-
- public:
- /**
- Get the addressing mode of the specified instruction
-
- @param opcode The opcode of the instruction
- @return The addressing mode of the instruction
- */
- AddressingMode addressingMode(uInt8 opcode) const
- { return ourAddressingModeTable[opcode]; }
-
- /**
- Get the access mode of the specified instruction
-
- @param opcode The opcode of the instruction
- @return The access mode of the instruction
- */
- AccessMode accessMode(uInt8 opcode) const
- { return ourAccessModeTable[opcode]; }
-
- public:
- /**
Execute instructions until the specified number of instructions
is executed, someone stops execution, or an error occurs. Answers
true iff execution stops normally.
@@ -162,7 +124,7 @@
@param number Indicates the number of instructions to execute
@return true iff execution stops normally
*/
- virtual bool execute(uInt32 number) = 0;
+ bool execute(uInt32 number);
/**
Tell the processor to stop executing instructions. Invoking this
@@ -177,10 +139,7 @@
@return true iff a fatal error has occured
*/
- bool fatalError() const
- {
- return myExecutionStatus & FatalErrorBit;
- }
+ bool fatalError() const { return myExecutionStatus & FatalErrorBit; }
/**
Get the 16-bit value of the Program Counter register.
@@ -203,8 +162,14 @@
*/
int totalInstructionCount() const { return myTotalInstructionCount; }
- public:
/**
+ Get the number of memory accesses to distinct memory locations
+
+ @return The number of memory accesses to distinct memory locations
+ */
+ uInt32 distinctAccesses() const { return myNumberOfDistinctAccesses; }
+
+ /**
Overload the ostream output operator for addressing modes.
@param out The stream to output the addressing mode to
@@ -212,8 +177,50 @@
*/
friend ostream& operator<<(ostream& out, const AddressingMode& mode);
+ /**
+ Saves the current state of this device to the given Serializer.
+
+ @param out The serializer device to save to.
+ @return The result of the save. True on success, false on failure.
+ */
+ bool save(Serializer& out);
+
+ /**
+ Loads the current state of this device from the given Deserializer.
+
+ @param in The deserializer device to load from.
+ @return The result of the load. True on success, false on failure.
+ */
+ bool load(Deserializer& in);
+
+ /**
+ Get a null terminated string which is the processor's name (i.e. "M6532")
+
+ @return The name of the device
+ */
+ const char* name() const { return "M6502High"; }
+
public:
+ /**
+ Get the addressing mode of the specified instruction
+
+ @param opcode The opcode of the instruction
+ @return The addressing mode of the instruction
+ */
+ AddressingMode addressingMode(uInt8 opcode) const
+ { return ourAddressingModeTable[opcode]; }
+
+ /**
+ Get the access mode of the specified instruction
+
+ @param opcode The opcode of the instruction
+ @return The access mode of the instruction
+ */
+ AccessMode accessMode(uInt8 opcode) const
+ { return ourAccessModeTable[opcode]; }
+
#ifdef DEBUGGER_SUPPORT
+ public:
/**
Attach the specified debugger.
@@ -232,8 +239,24 @@
int evalCondBreaks();
#endif
- protected:
+ private:
/**
+ Get the byte at the specified address and update the cycle count.
+
+ @return The byte at the specified address
+ */
+ inline uInt8 peek(uInt16 address);
+
+ /**
+ Change the byte at the specified address to the given value and
+ update the cycle count.
+
+ @param address The address where the value should be stored
+ @param value The value to be stored at the address
+ */
+ inline void poke(uInt16 address, uInt8 value);
+
+ /**
Get the 8-bit value of the Processor Status register.
@return The processor status register
@@ -247,7 +270,12 @@
*/
void PS(uInt8 ps);
- protected:
+ /**
+ Called after an interrupt has be requested using irq() or nmi()
+ */
+ void interruptHandler();
+
+ private:
uInt8 A; // Accumulator
uInt8 X; // X index register
uInt8 Y; // Y index register
@@ -266,13 +294,8 @@
/**
Bit fields used to indicate that certain conditions need to be
handled such as stopping execution, fatal errors, maskable interrupts
- and non-maskable interrupts
+ and non-maskable interrupts (in myExecutionStatus)
*/
- uInt8 myExecutionStatus;
-
- /**
- Constants used for setting bits in myExecutionStatus
- */
enum
{
StopExecutionBit = 0x01,
@@ -280,6 +303,7 @@
MaskableInterruptBit = 0x04,
NonmaskableInterruptBit = 0x08
};
+ uInt8 myExecutionStatus;
/// Pointer to the system the processor is installed in or the null pointer
System* mySystem;
@@ -296,6 +320,12 @@
/// The total number of instructions executed so far
int myTotalInstructionCount;
+ /// Indicates the numer of distinct memory accesses
+ uInt32 myNumberOfDistinctAccesses;
+
+ /// Indicates the last address which was accessed
+ uInt16 myLastAddress;
+
#ifdef DEBUGGER_SUPPORT
/// Pointer to the debugger for this processor or the null pointer
Debugger* myDebugger;
@@ -316,7 +346,7 @@
ExpressionList myBreakConds;
#endif
- protected:
+ private:
/// Addressing mode for each of the 256 opcodes
/// This specifies how the opcode argument is addressed
static AddressingMode ourAddressingModeTable[256];
Added: trunk/stella/src/emucore/m6502/src/M6502.ins
===================================================================
--- trunk/stella/src/emucore/m6502/src/M6502.ins (rev 0)
+++ trunk/stella/src/emucore/m6502/src/M6502.ins 2009-05-17 19:30:10 UTC (rev 1729)
@@ -0,0 +1,4427 @@
+//============================================================================
+//
+// MM MM 6666 555555 0000 2222
+// MMMM MMMM 66 66 55 00 00 22 22
+// MM MMM MM 66 55 00 00 22
+// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator"
+// MM MM 66 66 55 00 00 22
+// MM MM 66 66 55 55 00 00 22
+// MM MM 6666 5555 0000 222222
+//
+// Copyright (c) 1995-2005 by Bradford W. Mott and the Stella team
+//
+// See the file "license" for information on usage and redistribution of
+// this file, and for a DISCLAIMER OF ALL WARRANTIES.
+//
+// $Id: M6502.ins 1724 2009-05-13 13:55:40Z stephena $
+//============================================================================
+
+/**
+ Code and cases to emulate each of the 6502 instructions.
+
+ Recompile with the following:
+ 'm4 M6502.m4 > M6502.ins'
+
+ @author Bradford W. Mott
+ @version $Id: M6502.m4 1724 2009-05-13 13:55:40Z stephena $
+*/
+
+#ifndef NOTSAMEPAGE
+ #define NOTSAMEPAGE(_addr1, _addr2) (((_addr1) ^ (_addr2)) & 0xff00)
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+case 0x69:
+{
+ operand = peek(PC++);
+}
+{
+ if(!D)
+ {
+ Int32 sum = A + operand + (C ? 1 : 0);
+ N = sum & 0x80;
+ V = ~(A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+ C = sum & 0xff00;
+
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
+ Int32 hi = (A & 0xf0) + (operand & 0xf0);
+ notZ = (lo+hi) & 0xff;
+ if(lo > 0x09)
+ {
+ hi += 0x10;
+ lo += 0x06;
+ }
+ N = hi & 0x80;
+ V = ~(A ^ operand) & (A ^ hi) & 0x80;
+ if(hi > 0x90)
+ hi += 0x60;
+ C = hi & 0xff00;
+
+ A = (lo & 0x0f) + (hi & 0xf0);
+ }
+}
+break;
+
+case 0x65:
+{
+ operand = peek(peek(PC++));
+}
+{
+ if(!D)
+ {
+ Int32 sum = A + operand + (C ? 1 : 0);
+ N = sum & 0x80;
+ V = ~(A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+ C = sum & 0xff00;
+
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
+ Int32 hi = (A & 0xf0) + (operand & 0xf0);
+ notZ = (lo+hi) & 0xff;
+ if(lo > 0x09)
+ {
+ hi += 0x10;
+ lo += 0x06;
+ }
+ N = hi & 0x80;
+ V = ~(A ^ operand) & (A ^ hi) & 0x80;
+ if(hi > 0x90)
+ hi += 0x60;
+ C = hi & 0xff00;
+
+ A = (lo & 0x0f) + (hi & 0xf0);
+ }
+}
+break;
+
+case 0x75:
+{
+ uInt8 address = peek(PC++);
+ peek(address);
+ address += X;
+ operand = peek(address);
+}
+{
+ if(!D)
+ {
+ Int32 sum = A + operand + (C ? 1 : 0);
+ N = sum & 0x80;
+ V = ~(A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+ C = sum & 0xff00;
+
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
+ Int32 hi = (A & 0xf0) + (operand & 0xf0);
+ notZ = (lo+hi) & 0xff;
+ if(lo > 0x09)
+ {
+ hi += 0x10;
+ lo += 0x06;
+ }
+ N = hi & 0x80;
+ V = ~(A ^ operand) & (A ^ hi) & 0x80;
+ if(hi > 0x90)
+ hi += 0x60;
+ C = hi & 0xff00;
+
+ A = (lo & 0x0f) + (hi & 0xf0);
+ }
+}
+break;
+
+case 0x6d:
+{
+ uInt16 address = peek(PC++);
+ address |= ((uInt16)peek(PC++) << 8);
+ operand = peek(address);
+}
+{
+ if(!D)
+ {
+ Int32 sum = A + operand + (C ? 1 : 0);
+ N = sum & 0x80;
+ V = ~(A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+ C = sum & 0xff00;
+
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
+ Int32 hi = (A & 0xf0) + (operand & 0xf0);
+ notZ = (lo+hi) & 0xff;
+ if(lo > 0x09)
+ {
+ hi += 0x10;
+ lo += 0x06;
+ }
+ N = hi & 0x80;
+ V = ~(A ^ operand) & (A ^ hi) & 0x80;
+ if(hi > 0x90)
+ hi += 0x60;
+ C = hi & 0xff00;
+
+ A = (lo & 0x0f) + (hi & 0xf0);
+ }
+}
+break;
+
+case 0x7d:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + X));
+ if((low + X) > 0xFF)
+ operand = peek((high | low) + X);
+}
+{
+ if(!D)
+ {
+ Int32 sum = A + operand + (C ? 1 : 0);
+ N = sum & 0x80;
+ V = ~(A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+ C = sum & 0xff00;
+
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
+ Int32 hi = (A & 0xf0) + (operand & 0xf0);
+ notZ = (lo+hi) & 0xff;
+ if(lo > 0x09)
+ {
+ hi += 0x10;
+ lo += 0x06;
+ }
+ N = hi & 0x80;
+ V = ~(A ^ operand) & (A ^ hi) & 0x80;
+ if(hi > 0x90)
+ hi += 0x60;
+ C = hi & 0xff00;
+
+ A = (lo & 0x0f) + (hi & 0xf0);
+ }
+}
+break;
+
+case 0x79:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ if(!D)
+ {
+ Int32 sum = A + operand + (C ? 1 : 0);
+ N = sum & 0x80;
+ V = ~(A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+ C = sum & 0xff00;
+
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
+ Int32 hi = (A & 0xf0) + (operand & 0xf0);
+ notZ = (lo+hi) & 0xff;
+ if(lo > 0x09)
+ {
+ hi += 0x10;
+ lo += 0x06;
+ }
+ N = hi & 0x80;
+ V = ~(A ^ operand) & (A ^ hi) & 0x80;
+ if(hi > 0x90)
+ hi += 0x60;
+ C = hi & 0xff00;
+
+ A = (lo & 0x0f) + (hi & 0xf0);
+ }
+}
+break;
+
+case 0x61:
+{
+ uInt8 pointer = peek(PC++);
+ peek(pointer);
+ pointer += X;
+ uInt16 address = peek(pointer++);
+ address |= ((uInt16)peek(pointer) << 8);
+ operand = peek(address);
+}
+{
+ if(!D)
+ {
+ Int32 sum = A + operand + (C ? 1 : 0);
+ N = sum & 0x80;
+ V = ~(A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+ C = sum & 0xff00;
+
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
+ Int32 hi = (A & 0xf0) + (operand & 0xf0);
+ notZ = (lo+hi) & 0xff;
+ if(lo > 0x09)
+ {
+ hi += 0x10;
+ lo += 0x06;
+ }
+ N = hi & 0x80;
+ V = ~(A ^ operand) & (A ^ hi) & 0x80;
+ if(hi > 0x90)
+ hi += 0x60;
+ C = hi & 0xff00;
+
+ A = (lo & 0x0f) + (hi & 0xf0);
+ }
+}
+break;
+
+case 0x71:
+{
+ uInt8 pointer = peek(PC++);
+ uInt16 low = peek(pointer++);
+ uInt16 high = ((uInt16)peek(pointer) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ if(!D)
+ {
+ Int32 sum = A + operand + (C ? 1 : 0);
+ N = sum & 0x80;
+ V = ~(A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+ C = sum & 0xff00;
+
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) + (operand & 0x0f) + (C ? 1 : 0);
+ Int32 hi = (A & 0xf0) + (operand & 0xf0);
+ notZ = (lo+hi) & 0xff;
+ if(lo > 0x09)
+ {
+ hi += 0x10;
+ lo += 0x06;
+ }
+ N = hi & 0x80;
+ V = ~(A ^ operand) & (A ^ hi) & 0x80;
+ if(hi > 0x90)
+ hi += 0x60;
+ C = hi & 0xff00;
+
+ A = (lo & 0x0f) + (hi & 0xf0);
+ }
+}
+break;
+
+
+case 0x4b:
+{
+ operand = peek(PC++);
+}
+{
+ A &= operand;
+
+ // Set carry flag according to the right-most bit
+ C = A & 0x01;
+
+ A = (A >> 1) & 0x7f;
+
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+
+case 0x0b:
+case 0x2b:
+{
+ operand = peek(PC++);
+}
+{
+ A &= operand;
+ notZ = A;
+ N = A & 0x80;
+ C = N;
+}
+break;
+
+
+case 0x29:
+{
+ operand = peek(PC++);
+}
+{
+ A &= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x25:
+{
+ operand = peek(peek(PC++));
+}
+{
+ A &= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x35:
+{
+ uInt8 address = peek(PC++);
+ peek(address);
+ address += X;
+ operand = peek(address);
+}
+{
+ A &= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x2d:
+{
+ uInt16 address = peek(PC++);
+ address |= ((uInt16)peek(PC++) << 8);
+ operand = peek(address);
+}
+{
+ A &= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x3d:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + X));
+ if((low + X) > 0xFF)
+ operand = peek((high | low) + X);
+}
+{
+ A &= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x39:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ A &= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x21:
+{
+ uInt8 pointer = peek(PC++);
+ peek(pointer);
+ pointer += X;
+ uInt16 address = peek(pointer++);
+ address |= ((uInt16)peek(pointer) << 8);
+ operand = peek(address);
+}
+{
+ A &= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x31:
+{
+ uInt8 pointer = peek(PC++);
+ uInt16 low = peek(pointer++);
+ uInt16 high = ((uInt16)peek(pointer) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ A &= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+
+case 0x8b:
+{
+ operand = peek(PC++);
+}
+{
+ // NOTE: The implementation of this instruction is based on
+ // information from the 64doc.txt file. This instruction is
+ // reported to be unstable!
+ A = (A | 0xee) & X & operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+
+case 0x6b:
+{
+ operand = peek(PC++);
+}
+{
+ // NOTE: The implementation of this instruction is based on
+ // information from the 64doc.txt file. There are mixed
+ // reports on its operation!
+ if(!D)
+ {
+ A &= operand;
+ A = ((A >> 1) & 0x7f) | (C ? 0x80 : 0x00);
+
+ C = A & 0x40;
+ V = (A & 0x40) ^ ((A & 0x20) << 1);
+
+ notZ = A;
+ N = A & 0x80;
+ }
+ else
+ {
+ uInt8 value = A & operand;
+
+ A = ((value >> 1) & 0x7f) | (C ? 0x80 : 0x00);
+ N = C;
+ notZ = A;
+ V = (value ^ A) & 0x40;
+
+ if(((value & 0x0f) + (value & 0x01)) > 0x05)
+ {
+ A = (A & 0xf0) | ((A + 0x06) & 0x0f);
+ }
+
+ if(((value & 0xf0) + (value & 0x10)) > 0x50)
+ {
+ A = (A + 0x60) & 0xff;
+ C = 1;
+ }
+ else
+ {
+ C = 0;
+ }
+ }
+}
+break;
+
+
+case 0x0a:
+{
+ peek(PC);
+}
+{
+ // Set carry flag according to the left-most bit in A
+ C = A & 0x80;
+
+ A <<= 1;
+
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x06:
+{
+ operandAddress = peek(PC++);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ // Set carry flag according to the left-most bit in value
+ C = operand & 0x80;
+
+ operand <<= 1;
+ poke(operandAddress, operand);
+
+ notZ = operand;
+ N = operand & 0x80;
+}
+break;
+
+case 0x16:
+{
+ operandAddress = peek(PC++);
+ peek(operandAddress);
+ operandAddress = (operandAddress + X) & 0xFF;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ // Set carry flag according to the left-most bit in value
+ C = operand & 0x80;
+
+ operand <<= 1;
+ poke(operandAddress, operand);
+
+ notZ = operand;
+ N = operand & 0x80;
+}
+break;
+
+case 0x0e:
+{
+ operandAddress = peek(PC++);
+ operandAddress |= ((uInt16)peek(PC++) << 8);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ // Set carry flag according to the left-most bit in value
+ C = operand & 0x80;
+
+ operand <<= 1;
+ poke(operandAddress, operand);
+
+ notZ = operand;
+ N = operand & 0x80;
+}
+break;
+
+case 0x1e:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ peek(high | (uInt8)(low + X));
+ operandAddress = (high | low) + X;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ // Set carry flag according to the left-most bit in value
+ C = operand & 0x80;
+
+ operand <<= 1;
+ poke(operandAddress, operand);
+
+ notZ = operand;
+ N = operand & 0x80;
+}
+break;
+
+
+case 0x90:
+{
+ operand = peek(PC++);
+}
+{
+ if(!C)
+ {
+ peek(PC);
+ uInt16 address = PC + (Int8)operand;
+ if(NOTSAMEPAGE(PC, address))
+ peek((PC & 0xFF00) | (address & 0x00FF));
+ PC = address;
+ }
+}
+break;
+
+
+case 0xb0:
+{
+ operand = peek(PC++);
+}
+{
+ if(C)
+ {
+ peek(PC);
+ uInt16 address = PC + (Int8)operand;
+ if(NOTSAMEPAGE(PC, address))
+ peek((PC & 0xFF00) | (address & 0x00FF));
+ PC = address;
+ }
+}
+break;
+
+
+case 0xf0:
+{
+ operand = peek(PC++);
+}
+{
+ if(!notZ)
+ {
+ peek(PC);
+ uInt16 address = PC + (Int8)operand;
+ if(NOTSAMEPAGE(PC, address))
+ peek((PC & 0xFF00) | (address & 0x00FF));
+ PC = address;
+ }
+}
+break;
+
+
+case 0x24:
+{
+ operand = peek(peek(PC++));
+}
+{
+ notZ = (A & operand);
+ N = operand & 0x80;
+ V = operand & 0x40;
+}
+break;
+
+case 0x2C:
+{
+ uInt16 address = peek(PC++);
+ address |= ((uInt16)peek(PC++) << 8);
+ operand = peek(address);
+}
+{
+ notZ = (A & operand);
+ N = operand & 0x80;
+ V = operand & 0x40;
+}
+break;
+
+
+case 0x30:
+{
+ operand = peek(PC++);
+}
+{
+ if(N)
+ {
+ peek(PC);
+ uInt16 address = PC + (Int8)operand;
+ if(NOTSAMEPAGE(PC, address))
+ peek((PC & 0xFF00) | (address & 0x00FF));
+ PC = address;
+ }
+}
+break;
+
+
+case 0xD0:
+{
+ operand = peek(PC++);
+}
+{
+ if(notZ)
+ {
+ peek(PC);
+ uInt16 address = PC + (Int8)operand;
+ if(NOTSAMEPAGE(PC, address))
+ peek((PC & 0xFF00) | (address & 0x00FF));
+ PC = address;
+ }
+}
+break;
+
+
+case 0x10:
+{
+ operand = peek(PC++);
+}
+{
+ if(!N)
+ {
+ peek(PC);
+ uInt16 address = PC + (Int8)operand;
+ if(NOTSAMEPAGE(PC, address))
+ peek((PC & 0xFF00) | (address & 0x00FF));
+ PC = address;
+ }
+}
+break;
+
+
+case 0x00:
+{
+ peek(PC++);
+
+ B = true;
+
+ poke(0x0100 + SP--, PC >> 8);
+ poke(0x0100 + SP--, PC & 0x00ff);
+ poke(0x0100 + SP--, PS());
+
+ I = true;
+
+ PC = peek(0xfffe);
+ PC |= ((uInt16)peek(0xffff) << 8);
+}
+break;
+
+
+case 0x50:
+{
+ operand = peek(PC++);
+}
+{
+ if(!V)
+ {
+ peek(PC);
+ uInt16 address = PC + (Int8)operand;
+ if(NOTSAMEPAGE(PC, address))
+ peek((PC & 0xFF00) | (address & 0x00FF));
+ PC = address;
+ }
+}
+break;
+
+
+case 0x70:
+{
+ operand = peek(PC++);
+}
+{
+ if(V)
+ {
+ peek(PC);
+ uInt16 address = PC + (Int8)operand;
+ if(NOTSAMEPAGE(PC, address))
+ peek((PC & 0xFF00) | (address & 0x00FF));
+ PC = address;
+ }
+}
+break;
+
+
+case 0x18:
+{
+ peek(PC);
+}
+{
+ C = false;
+}
+break;
+
+
+case 0xd8:
+{
+ peek(PC);
+}
+{
+ D = false;
+}
+break;
+
+
+case 0x58:
+{
+ peek(PC);
+}
+{
+ I = false;
+}
+break;
+
+
+case 0xb8:
+{
+ peek(PC);
+}
+{
+ V = false;
+}
+break;
+
+
+case 0xc9:
+{
+ operand = peek(PC++);
+}
+{
+ uInt16 value = (uInt16)A - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xc5:
+{
+ operand = peek(peek(PC++));
+}
+{
+ uInt16 value = (uInt16)A - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xd5:
+{
+ uInt8 address = peek(PC++);
+ peek(address);
+ address += X;
+ operand = peek(address);
+}
+{
+ uInt16 value = (uInt16)A - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xcd:
+{
+ uInt16 address = peek(PC++);
+ address |= ((uInt16)peek(PC++) << 8);
+ operand = peek(address);
+}
+{
+ uInt16 value = (uInt16)A - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xdd:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + X));
+ if((low + X) > 0xFF)
+ operand = peek((high | low) + X);
+}
+{
+ uInt16 value = (uInt16)A - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xd9:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ uInt16 value = (uInt16)A - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xc1:
+{
+ uInt8 pointer = peek(PC++);
+ peek(pointer);
+ pointer += X;
+ uInt16 address = peek(pointer++);
+ address |= ((uInt16)peek(pointer) << 8);
+ operand = peek(address);
+}
+{
+ uInt16 value = (uInt16)A - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xd1:
+{
+ uInt8 pointer = peek(PC++);
+ uInt16 low = peek(pointer++);
+ uInt16 high = ((uInt16)peek(pointer) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ uInt16 value = (uInt16)A - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+
+case 0xe0:
+{
+ operand = peek(PC++);
+}
+{
+ uInt16 value = (uInt16)X - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xe4:
+{
+ operand = peek(peek(PC++));
+}
+{
+ uInt16 value = (uInt16)X - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xec:
+{
+ uInt16 address = peek(PC++);
+ address |= ((uInt16)peek(PC++) << 8);
+ operand = peek(address);
+}
+{
+ uInt16 value = (uInt16)X - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+
+case 0xc0:
+{
+ operand = peek(PC++);
+}
+{
+ uInt16 value = (uInt16)Y - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xc4:
+{
+ operand = peek(peek(PC++));
+}
+{
+ uInt16 value = (uInt16)Y - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+case 0xcc:
+{
+ uInt16 address = peek(PC++);
+ address |= ((uInt16)peek(PC++) << 8);
+ operand = peek(address);
+}
+{
+ uInt16 value = (uInt16)Y - (uInt16)operand;
+
+ notZ = value;
+ N = value & 0x0080;
+ C = !(value & 0x0100);
+}
+break;
+
+
+case 0xcf:
+{
+ operandAddress = peek(PC++);
+ operandAddress |= ((uInt16)peek(PC++) << 8);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ uInt16 value2 = (uInt16)A - (uInt16)value;
+ notZ = value2;
+ N = value2 & 0x0080;
+ C = !(value2 & 0x0100);
+}
+break;
+
+case 0xdf:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ peek(high | (uInt8)(low + X));
+ operandAddress = (high | low) + X;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ uInt16 value2 = (uInt16)A - (uInt16)value;
+ notZ = value2;
+ N = value2 & 0x0080;
+ C = !(value2 & 0x0100);
+}
+break;
+
+case 0xdb:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ peek(high | (uInt8)(low + Y));
+ operandAddress = (high | low) + Y;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ uInt16 value2 = (uInt16)A - (uInt16)value;
+ notZ = value2;
+ N = value2 & 0x0080;
+ C = !(value2 & 0x0100);
+}
+break;
+
+case 0xc7:
+{
+ operandAddress = peek(PC++);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ uInt16 value2 = (uInt16)A - (uInt16)value;
+ notZ = value2;
+ N = value2 & 0x0080;
+ C = !(value2 & 0x0100);
+}
+break;
+
+case 0xd7:
+{
+ operandAddress = peek(PC++);
+ peek(operandAddress);
+ operandAddress = (operandAddress + X) & 0xFF;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ uInt16 value2 = (uInt16)A - (uInt16)value;
+ notZ = value2;
+ N = value2 & 0x0080;
+ C = !(value2 & 0x0100);
+}
+break;
+
+case 0xc3:
+{
+ uInt8 pointer = peek(PC++);
+ peek(pointer);
+ pointer += X;
+ operandAddress = peek(pointer++);
+ operandAddress |= ((uInt16)peek(pointer) << 8);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ uInt16 value2 = (uInt16)A - (uInt16)value;
+ notZ = value2;
+ N = value2 & 0x0080;
+ C = !(value2 & 0x0100);
+}
+break;
+
+case 0xd3:
+{
+ uInt8 pointer = peek(PC++);
+ uInt16 low = peek(pointer++);
+ uInt16 high = ((uInt16)peek(pointer) << 8);
+ peek(high | (uInt8)(low + Y));
+ operandAddress = (high | low) + Y;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ uInt16 value2 = (uInt16)A - (uInt16)value;
+ notZ = value2;
+ N = value2 & 0x0080;
+ C = !(value2 & 0x0100);
+}
+break;
+
+
+case 0xc6:
+{
+ operandAddress = peek(PC++);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ notZ = value;
+ N = value & 0x80;
+}
+break;
+
+case 0xd6:
+{
+ operandAddress = peek(PC++);
+ peek(operandAddress);
+ operandAddress = (operandAddress + X) & 0xFF;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ notZ = value;
+ N = value & 0x80;
+}
+break;
+
+case 0xce:
+{
+ operandAddress = peek(PC++);
+ operandAddress |= ((uInt16)peek(PC++) << 8);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ notZ = value;
+ N = value & 0x80;
+}
+break;
+
+case 0xde:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ peek(high | (uInt8)(low + X));
+ operandAddress = (high | low) + X;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand - 1;
+ poke(operandAddress, value);
+
+ notZ = value;
+ N = value & 0x80;
+}
+break;
+
+
+case 0xca:
+{
+ peek(PC);
+}
+{
+ X--;
+
+ notZ = X;
+ N = X & 0x80;
+}
+break;
+
+
+case 0x88:
+{
+ peek(PC);
+}
+{
+ Y--;
+
+ notZ = Y;
+ N = Y & 0x80;
+}
+break;
+
+
+case 0x49:
+{
+ operand = peek(PC++);
+}
+{
+ A ^= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x45:
+{
+ operand = peek(peek(PC++));
+}
+{
+ A ^= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x55:
+{
+ uInt8 address = peek(PC++);
+ peek(address);
+ address += X;
+ operand = peek(address);
+}
+{
+ A ^= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x4d:
+{
+ uInt16 address = peek(PC++);
+ address |= ((uInt16)peek(PC++) << 8);
+ operand = peek(address);
+}
+{
+ A ^= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x5d:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + X));
+ if((low + X) > 0xFF)
+ operand = peek((high | low) + X);
+}
+{
+ A ^= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x59:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ A ^= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x41:
+{
+ uInt8 pointer = peek(PC++);
+ peek(pointer);
+ pointer += X;
+ uInt16 address = peek(pointer++);
+ address |= ((uInt16)peek(pointer) << 8);
+ operand = peek(address);
+}
+{
+ A ^= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0x51:
+{
+ uInt8 pointer = peek(PC++);
+ uInt16 low = peek(pointer++);
+ uInt16 high = ((uInt16)peek(pointer) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ A ^= operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+
+case 0xe6:
+{
+ operandAddress = peek(PC++);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand + 1;
+ poke(operandAddress, value);
+
+ notZ = value;
+ N = value & 0x80;
+}
+break;
+
+case 0xf6:
+{
+ operandAddress = peek(PC++);
+ peek(operandAddress);
+ operandAddress = (operandAddress + X) & 0xFF;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand + 1;
+ poke(operandAddress, value);
+
+ notZ = value;
+ N = value & 0x80;
+}
+break;
+
+case 0xee:
+{
+ operandAddress = peek(PC++);
+ operandAddress |= ((uInt16)peek(PC++) << 8);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand + 1;
+ poke(operandAddress, value);
+
+ notZ = value;
+ N = value & 0x80;
+}
+break;
+
+case 0xfe:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ peek(high | (uInt8)(low + X));
+ operandAddress = (high | low) + X;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ uInt8 value = operand + 1;
+ poke(operandAddress, value);
+
+ notZ = value;
+ N = value & 0x80;
+}
+break;
+
+
+case 0xe8:
+{
+ peek(PC);
+}
+{
+ X++;
+ notZ = X;
+ N = X & 0x80;
+}
+break;
+
+
+case 0xc8:
+{
+ peek(PC);
+}
+{
+ Y++;
+ notZ = Y;
+ N = Y & 0x80;
+}
+break;
+
+
+case 0xef:
+{
+ operandAddress = peek(PC++);
+ operandAddress |= ((uInt16)peek(PC++) << 8);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ operand = operand + 1;
+ poke(operandAddress, operand);
+
+ // N, V, Z, C flags are the same in either mode (C calculated at the end)
+ Int32 sum = A - operand - (C ? 0 : 1);
+ N = sum & 0x80;
+ V = (A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+
+ if(!D)
+ {
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
+ Int32 hi = (A & 0xf0) - (operand & 0xf0);
+ if(lo & 0x10)
+ {
+ lo -= 6;
+ hi--;
+ }
+ if(hi & 0x0100)
+ hi -= 0x60;
+
+ A = (lo & 0x0f) | (hi & 0xf0);
+ }
+ C = (sum & 0xff00) == 0;
+}
+break;
+
+case 0xff:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ peek(high | (uInt8)(low + X));
+ operandAddress = (high | low) + X;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ operand = operand + 1;
+ poke(operandAddress, operand);
+
+ // N, V, Z, C flags are the same in either mode (C calculated at the end)
+ Int32 sum = A - operand - (C ? 0 : 1);
+ N = sum & 0x80;
+ V = (A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+
+ if(!D)
+ {
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
+ Int32 hi = (A & 0xf0) - (operand & 0xf0);
+ if(lo & 0x10)
+ {
+ lo -= 6;
+ hi--;
+ }
+ if(hi & 0x0100)
+ hi -= 0x60;
+
+ A = (lo & 0x0f) | (hi & 0xf0);
+ }
+ C = (sum & 0xff00) == 0;
+}
+break;
+
+case 0xfb:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ peek(high | (uInt8)(low + Y));
+ operandAddress = (high | low) + Y;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ operand = operand + 1;
+ poke(operandAddress, operand);
+
+ // N, V, Z, C flags are the same in either mode (C calculated at the end)
+ Int32 sum = A - operand - (C ? 0 : 1);
+ N = sum & 0x80;
+ V = (A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+
+ if(!D)
+ {
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
+ Int32 hi = (A & 0xf0) - (operand & 0xf0);
+ if(lo & 0x10)
+ {
+ lo -= 6;
+ hi--;
+ }
+ if(hi & 0x0100)
+ hi -= 0x60;
+
+ A = (lo & 0x0f) | (hi & 0xf0);
+ }
+ C = (sum & 0xff00) == 0;
+}
+break;
+
+case 0xe7:
+{
+ operandAddress = peek(PC++);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ operand = operand + 1;
+ poke(operandAddress, operand);
+
+ // N, V, Z, C flags are the same in either mode (C calculated at the end)
+ Int32 sum = A - operand - (C ? 0 : 1);
+ N = sum & 0x80;
+ V = (A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+
+ if(!D)
+ {
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
+ Int32 hi = (A & 0xf0) - (operand & 0xf0);
+ if(lo & 0x10)
+ {
+ lo -= 6;
+ hi--;
+ }
+ if(hi & 0x0100)
+ hi -= 0x60;
+
+ A = (lo & 0x0f) | (hi & 0xf0);
+ }
+ C = (sum & 0xff00) == 0;
+}
+break;
+
+case 0xf7:
+{
+ operandAddress = peek(PC++);
+ peek(operandAddress);
+ operandAddress = (operandAddress + X) & 0xFF;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ operand = operand + 1;
+ poke(operandAddress, operand);
+
+ // N, V, Z, C flags are the same in either mode (C calculated at the end)
+ Int32 sum = A - operand - (C ? 0 : 1);
+ N = sum & 0x80;
+ V = (A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+
+ if(!D)
+ {
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
+ Int32 hi = (A & 0xf0) - (operand & 0xf0);
+ if(lo & 0x10)
+ {
+ lo -= 6;
+ hi--;
+ }
+ if(hi & 0x0100)
+ hi -= 0x60;
+
+ A = (lo & 0x0f) | (hi & 0xf0);
+ }
+ C = (sum & 0xff00) == 0;
+}
+break;
+
+case 0xe3:
+{
+ uInt8 pointer = peek(PC++);
+ peek(pointer);
+ pointer += X;
+ operandAddress = peek(pointer++);
+ operandAddress |= ((uInt16)peek(pointer) << 8);
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ operand = operand + 1;
+ poke(operandAddress, operand);
+
+ // N, V, Z, C flags are the same in either mode (C calculated at the end)
+ Int32 sum = A - operand - (C ? 0 : 1);
+ N = sum & 0x80;
+ V = (A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+
+ if(!D)
+ {
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
+ Int32 hi = (A & 0xf0) - (operand & 0xf0);
+ if(lo & 0x10)
+ {
+ lo -= 6;
+ hi--;
+ }
+ if(hi & 0x0100)
+ hi -= 0x60;
+
+ A = (lo & 0x0f) | (hi & 0xf0);
+ }
+ C = (sum & 0xff00) == 0;
+}
+break;
+
+case 0xf3:
+{
+ uInt8 pointer = peek(PC++);
+ uInt16 low = peek(pointer++);
+ uInt16 high = ((uInt16)peek(pointer) << 8);
+ peek(high | (uInt8)(low + Y));
+ operandAddress = (high | low) + Y;
+ operand = peek(operandAddress);
+ poke(operandAddress, operand);
+}
+{
+ operand = operand + 1;
+ poke(operandAddress, operand);
+
+ // N, V, Z, C flags are the same in either mode (C calculated at the end)
+ Int32 sum = A - operand - (C ? 0 : 1);
+ N = sum & 0x80;
+ V = (A ^ operand) & (A ^ sum) & 0x80;
+ notZ = sum & 0xff;
+
+ if(!D)
+ {
+ A = (uInt8) sum;
+ }
+ else
+ {
+ Int32 lo = (A & 0x0f) - (operand & 0x0f) - (C ? 0 : 1);
+ Int32 hi = (A & 0xf0) - (operand & 0xf0);
+ if(lo & 0x10)
+ {
+ lo -= 6;
+ hi--;
+ }
+ if(hi & 0x0100)
+ hi -= 0x60;
+
+ A = (lo & 0x0f) | (hi & 0xf0);
+ }
+ C = (sum & 0xff00) == 0;
+}
+break;
+
+
+case 0x4c:
+{
+ operandAddress = peek(PC++);
+ operandAddress |= ((uInt16)peek(PC++) << 8);
+}
+{
+ PC = operandAddress;
+}
+break;
+
+case 0x6c:
+{
+ uInt16 addr = peek(PC++);
+ addr |= ((uInt16)peek(PC++) << 8);
+
+ // Simulate the error in the indirect addressing mode!
+ uInt16 high = NOTSAMEPAGE(addr, addr + 1) ? (addr & 0xff00) : (addr + 1);
+
+ operandAddress = peek(addr);
+ operandAddress |= ((uInt16)peek(high) << 8);
+}
+{
+ PC = operandAddress;
+}
+break;
+
+
+case 0x20:
+{
+ uInt8 low = peek(PC++);
+ peek(0x0100 + SP);
+
+ // It seems that the 650x does not push the address of the next instruction
+ // on the stack it actually pushes the address of the next instruction
+ // minus one. This is compensated for in the RTS instruction
+ poke(0x0100 + SP--, PC >> 8);
+ poke(0x0100 + SP--, PC & 0xff);
+
+ PC = low | ((uInt16)peek(PC++) << 8);
+}
+break;
+
+
+case 0xbb:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ A = X = SP = SP & operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+
+case 0xaf:
+{
+ uInt16 address = peek(PC++);
+ address |= ((uInt16)peek(PC++) << 8);
+ operand = peek(address);
+}
+{
+ A = operand;
+ X = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xbf:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ A = operand;
+ X = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xa7:
+{
+ operand = peek(peek(PC++));
+}
+{
+ A = operand;
+ X = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xb7:
+{
+ uInt8 address = peek(PC++);
+ peek(address);
+ address += Y;
+ operand = peek(address);
+}
+{
+ A = operand;
+ X = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xa3:
+{
+ uInt8 pointer = peek(PC++);
+ peek(pointer);
+ pointer += X;
+ uInt16 address = peek(pointer++);
+ address |= ((uInt16)peek(pointer) << 8);
+ operand = peek(address);
+}
+{
+ A = operand;
+ X = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xb3:
+{
+ uInt8 pointer = peek(PC++);
+ uInt16 low = peek(pointer++);
+ uInt16 high = ((uInt16)peek(pointer) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ A = operand;
+ X = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+
+case 0xa9:
+{
+ operand = peek(PC++);
+}
+{
+ A = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xa5:
+{
+ operand = peek(peek(PC++));
+}
+{
+ A = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xb5:
+{
+ uInt8 address = peek(PC++);
+ peek(address);
+ address += X;
+ operand = peek(address);
+}
+{
+ A = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xad:
+{
+ uInt16 address = peek(PC++);
+ address |= ((uInt16)peek(PC++) << 8);
+ operand = peek(address);
+}
+{
+ A = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xbd:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + X));
+ if((low + X) > 0xFF)
+ operand = peek((high | low) + X);
+}
+{
+ A = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xb9:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ A = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xa1:
+{
+ uInt8 pointer = peek(PC++);
+ peek(pointer);
+ pointer += X;
+ uInt16 address = peek(pointer++);
+ address |= ((uInt16)peek(pointer) << 8);
+ operand = peek(address);
+}
+{
+ A = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+case 0xb1:
+{
+ uInt8 pointer = peek(PC++);
+ uInt16 low = peek(pointer++);
+ uInt16 high = ((uInt16)peek(pointer) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ A = operand;
+ notZ = A;
+ N = A & 0x80;
+}
+break;
+
+
+case 0xa2:
+{
+ operand = peek(PC++);
+}
+{
+ X = operand;
+ notZ = X;
+ N = X & 0x80;
+}
+break;
+
+case 0xa6:
+{
+ operand = peek(peek(PC++));
+}
+{
+ X = operand;
+ notZ = X;
+ N = X & 0x80;
+}
+break;
+
+case 0xb6:
+{
+ uInt8 address = peek(PC++);
+ peek(address);
+ address += Y;
+ operand = peek(address);
+}
+{
+ X = operand;
+ notZ = X;
+ N = X & 0x80;
+}
+break;
+
+case 0xae:
+{
+ uInt16 address = peek(PC++);
+ address |= ((uInt16)peek(PC++) << 8);
+ operand = peek(address);
+}
+{
+ X = operand;
+ notZ = X;
+ N = X & 0x80;
+}
+break;
+
+case 0xbe:
+{
+ uInt16 low = peek(PC++);
+ uInt16 high = ((uInt16)peek(PC++) << 8);
+ operand = peek(high | (uInt8)(low + Y));
+ if((low + Y) > 0xFF)
+ operand = peek((high | low) + Y);
+}
+{
+ X = opera...
[truncated message content] |