diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index d611346b1e..72b2266247 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -472,8 +472,6 @@ - - diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.sln b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/6502XXX.sln similarity index 53% rename from BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.sln rename to BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/6502XXX.sln index b76ba76f6c..8db457c27f 100644 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.sln +++ b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/6502XXX.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MOS6502XNative", "MOS6502XNative.vcxproj", "{3F8F3D38-25DB-45C9-84C9-943D0368BF47}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "6502XXX", "6502XXX.vcxproj", "{0EF7FBBC-3CA9-4121-AF6C-C46CD02354B4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -9,10 +9,10 @@ Global Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3F8F3D38-25DB-45C9-84C9-943D0368BF47}.Debug|Win32.ActiveCfg = Debug|Win32 - {3F8F3D38-25DB-45C9-84C9-943D0368BF47}.Debug|Win32.Build.0 = Debug|Win32 - {3F8F3D38-25DB-45C9-84C9-943D0368BF47}.Release|Win32.ActiveCfg = Release|Win32 - {3F8F3D38-25DB-45C9-84C9-943D0368BF47}.Release|Win32.Build.0 = Release|Win32 + {0EF7FBBC-3CA9-4121-AF6C-C46CD02354B4}.Debug|Win32.ActiveCfg = Debug|Win32 + {0EF7FBBC-3CA9-4121-AF6C-C46CD02354B4}.Debug|Win32.Build.0 = Debug|Win32 + {0EF7FBBC-3CA9-4121-AF6C-C46CD02354B4}.Release|Win32.ActiveCfg = Release|Win32 + {0EF7FBBC-3CA9-4121-AF6C-C46CD02354B4}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.vcxproj b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/6502XXX.vcxproj similarity index 75% rename from BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.vcxproj rename to BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/6502XXX.vcxproj index 5f480e1d4a..cf67eb6ee6 100644 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.vcxproj +++ b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/6502XXX.vcxproj @@ -11,9 +11,9 @@ - {3F8F3D38-25DB-45C9-84C9-943D0368BF47} + {0EF7FBBC-3CA9-4121-AF6C-C46CD02354B4} Win32Proj - MOS6502XNative + My6502XXX @@ -39,37 +39,35 @@ true - - false - - - NotUsing + + Level3 Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;MOS6502XNATIVE_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_USRDLL;MY6502XXX_EXPORTS;%(PreprocessorDefinitions) Windows true - copy "$(TargetDir)$(TargetName).dll" "$(SolutionDir)..\..\..\..\BizHawk.MultiClient\output\dll\$(TargetName).dll" + copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\..\..\output\dll\$(TargetFileName)" Level3 - NotUsing + + MaxSpeed true true - WIN32;NDEBUG;_WINDOWS;_USRDLL;MOS6502XNATIVE_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_USRDLL;MY6502XXX_EXPORTS;%(PreprocessorDefinitions) Windows @@ -78,18 +76,15 @@ true - copy "$(TargetDir)$(TargetName).dll" "$(SolutionDir)..\..\..\..\BizHawk.MultiClient\output\dll\$(TargetName).dll" + copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\..\..\output\dll\$(TargetFileName)" - - - + - - - + + diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.vcxproj.filters b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/6502XXX.vcxproj.filters similarity index 75% rename from BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.vcxproj.filters rename to BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/6502XXX.vcxproj.filters index 64c3c05705..41cfeacf23 100644 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.vcxproj.filters +++ b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/6502XXX.vcxproj.filters @@ -15,25 +15,16 @@ - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - Source Files - - Source Files - + + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/Execute.cpp b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/Execute.cpp new file mode 100644 index 0000000000..8304f2c4ed --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/Execute.cpp @@ -0,0 +1,2595 @@ +//http://nesdev.parodius.com/6502_cpu.txt + +#include + +#include "UopTable.cpp" + +typedef int8_t sbyte; +typedef uint8_t byte; +typedef uint16_t ushort; + +#include "TableNZ.h" + +const ushort NMIVector = 0xFFFA; +const ushort ResetVector = 0xFFFC; +const ushort BRKVector = 0xFFFE; +const ushort IRQVector = 0xFFFE; + +#ifdef __GNUC__ +#define INL __attribute__((always_inline)) +#else +#define INL +#endif + +template bool Bit(int b) +{ + return (b & (1 << index)) != 0; +} + +template bool Bit(byte b) +{ + return (b & (1 << index)) != 0; +} + +struct CPU +{ + int _anchor; + int _land0; + int _land1; + int _land2; + + // interface + void *_ReadMemory_Managed; + void *_DummyReadMemory_Managed; + void *_PeekMemory_Managed; + void *_WriteMemory_Managed; + void *_OnExecFetch_Managed; // this only calls when the first byte of an instruction is fetched. + void *_TraceCallback_Managed; // TODO + + byte (*ReadMemory)(ushort addr); + byte (*DummyReadMemory)(ushort addr); + byte (*PeekMemory)(ushort addr); + void (*WriteMemory)(ushort addr, byte val); + void (*OnExecFetch)(ushort addr); + + // config + bool BCD_Enabled; + bool debug; + + // state + byte A; + byte X; + byte Y; + //byte P; + /// Carry Flag + bool FlagC; + /// Zero Flag + bool FlagZ; + /// Interrupt Disable Flag + bool FlagI; + /// Decimal Mode Flag + bool FlagD; + /// Break Flag + bool FlagB; + /// T... Flag + bool FlagT; + /// Overflow Flag + bool FlagV; + /// Negative Flag + bool FlagN; + + ushort PC; + byte S; + + bool IRQ; + bool NMI; + bool RDY; + + int TotalExecutedCycles; + + //opcode bytes.. theoretically redundant with the temp variables? who knows. + int opcode; + byte opcode2, opcode3; + + int ea, alu_temp; //cpu internal temp variables + int mi; //microcode index + bool iflag_pending; //iflag must be stored after it is checked in some cases (CLI and SEI). + bool rdy_freeze; //true if the CPU must be frozen + + //tracks whether an interrupt condition has popped up recently. + //not sure if this is real or not but it helps with the branch_irq_hack + bool interrupt_pending; + bool branch_irq_hack; //see Uop.RelBranch_Stage3 for more details + + // transient state + byte value8, temp8; + ushort value16; + bool branch_taken; + bool my_iflag; + bool booltemp; + int tempint; + int lo, hi; + + + INL byte GetP() + { + byte ret = 0; + if (FlagC) ret |= 1; + if (FlagZ) ret |= 2; + if (FlagI) ret |= 4; + if (FlagD) ret |= 8; + if (FlagB) ret |= 16; + if (FlagT) ret |= 32; + if (FlagV) ret |= 64; + if (FlagN) ret |= 128; + return ret; + } + + + INL void SetP(byte value) + { + FlagC = (value & 1) != 0; + FlagZ = (value & 2) != 0; + FlagI = (value & 4) != 0; + FlagD = (value & 8) != 0; + FlagB = (value & 16) != 0; + FlagT = (value & 32) != 0; + FlagV = (value & 64) != 0; + FlagN = (value & 128) != 0; + } + + INL void NZ_V(byte value) + { + FlagZ = value == 0; + FlagN = (value & 0x80) != 0; + } + + + /* + void InitOpcodeHandlers() + { + //delegates arent faster than the switch. pretty sure. dont use it. + //opcodeHandlers = new Action[] { + // Unsupported,Fetch1, Fetch1_Real, Fetch2, Fetch3,FetchDummy, + // NOP,JSR,IncPC, + // Abs_WRITE_STA, Abs_WRITE_STX, Abs_WRITE_STY,Abs_WRITE_SAX,Abs_READ_BIT, Abs_READ_LDA, Abs_READ_LDY, Abs_READ_ORA, Abs_READ_LDX, Abs_READ_CMP, Abs_READ_ADC, Abs_READ_CPX, Abs_READ_SBC, Abs_READ_AND, Abs_READ_EOR, Abs_READ_CPY, Abs_READ_NOP, + // Abs_READ_LAX,Abs_RMW_Stage4, Abs_RMW_Stage6,Abs_RMW_Stage5_INC, Abs_RMW_Stage5_DEC, Abs_RMW_Stage5_LSR, Abs_RMW_Stage5_ROL, Abs_RMW_Stage5_ASL, Abs_RMW_Stage5_ROR,Abs_RMW_Stage5_SLO, Abs_RMW_Stage5_RLA, Abs_RMW_Stage5_SRE, Abs_RMW_Stage5_RRA, Abs_RMW_Stage5_DCP, Abs_RMW_Stage5_ISC, + // JMP_abs,ZpIdx_Stage3_X, ZpIdx_Stage3_Y,ZpIdx_RMW_Stage4, ZpIdx_RMW_Stage6,ZP_WRITE_STA, ZP_WRITE_STX, ZP_WRITE_STY, ZP_WRITE_SAX,ZP_RMW_Stage3, ZP_RMW_Stage5, + // ZP_RMW_DEC, ZP_RMW_INC, ZP_RMW_ASL, ZP_RMW_LSR, ZP_RMW_ROR, ZP_RMW_ROL,ZP_RMW_SLO, ZP_RMW_RLA, ZP_RMW_SRE, ZP_RMW_RRA, ZP_RMW_DCP, ZP_RMW_ISC, + // ZP_READ_EOR, ZP_READ_BIT, ZP_READ_ORA, ZP_READ_LDA, ZP_READ_LDY, ZP_READ_LDX, ZP_READ_CPX, ZP_READ_SBC, ZP_READ_CPY, ZP_READ_NOP, ZP_READ_ADC, ZP_READ_AND, ZP_READ_CMP, ZP_READ_LAX, + // IdxInd_Stage3, IdxInd_Stage4, IdxInd_Stage5,IdxInd_Stage6_READ_ORA, IdxInd_Stage6_READ_SBC, IdxInd_Stage6_READ_LDA, IdxInd_Stage6_READ_EOR, IdxInd_Stage6_READ_CMP, IdxInd_Stage6_READ_ADC, IdxInd_Stage6_READ_AND, + // IdxInd_Stage6_READ_LAX,IdxInd_Stage6_WRITE_STA, IdxInd_Stage6_WRITE_SAX,IdxInd_Stage6_RMW,IdxInd_Stage7_RMW_SLO, IdxInd_Stage7_RMW_RLA, IdxInd_Stage7_RMW_SRE, IdxInd_Stage7_RMW_RRA, IdxInd_Stage7_RMW_ISC, IdxInd_Stage7_RMW_DCP, + // IdxInd_Stage8_RMW,AbsIdx_Stage3_X, AbsIdx_Stage3_Y, AbsIdx_Stage4,AbsIdx_WRITE_Stage5_STA,AbsIdx_WRITE_Stage5_SHY, AbsIdx_WRITE_Stage5_SHX,AbsIdx_WRITE_Stage5_ERROR,AbsIdx_READ_Stage4, + // AbsIdx_READ_Stage5_LDA, AbsIdx_READ_Stage5_CMP, AbsIdx_READ_Stage5_SBC, AbsIdx_READ_Stage5_ADC, AbsIdx_READ_Stage5_EOR, AbsIdx_READ_Stage5_LDX, AbsIdx_READ_Stage5_AND, AbsIdx_READ_Stage5_ORA, AbsIdx_READ_Stage5_LDY, AbsIdx_READ_Stage5_NOP, + // AbsIdx_READ_Stage5_LAX,AbsIdx_READ_Stage5_ERROR,AbsIdx_RMW_Stage5, AbsIdx_RMW_Stage7,AbsIdx_RMW_Stage6_ROR, AbsIdx_RMW_Stage6_DEC, AbsIdx_RMW_Stage6_INC, AbsIdx_RMW_Stage6_ASL, AbsIdx_RMW_Stage6_LSR, AbsIdx_RMW_Stage6_ROL, + // AbsIdx_RMW_Stage6_SLO, AbsIdx_RMW_Stage6_RLA, AbsIdx_RMW_Stage6_SRE, AbsIdx_RMW_Stage6_RRA, AbsIdx_RMW_Stage6_DCP, AbsIdx_RMW_Stage6_ISC,IncS, DecS, + // PushPCL, PushPCH, PushP, PullP, PullPCL, PullPCH_NoInc, PushA, PullA_NoInc, PullP_NoInc,PushP_BRK, PushP_NMI, PushP_IRQ, PushP_Reset, PushDummy,FetchPCLVector, FetchPCHVector, + // Imp_ASL_A, Imp_ROL_A, Imp_ROR_A, Imp_LSR_A,Imp_SEC, Imp_CLI, Imp_SEI, Imp_CLD, Imp_CLC, Imp_CLV, Imp_SED,Imp_INY, Imp_DEY, Imp_INX, Imp_DEX,Imp_TSX, Imp_TXS, Imp_TAX, Imp_TAY, Imp_TYA, Imp_TXA, + // Imm_CMP, Imm_ADC, Imm_AND, Imm_SBC, Imm_ORA, Imm_EOR, Imm_CPY, Imm_CPX, Imm_ANC, Imm_ASR, Imm_ARR, Imm_LXA, Imm_AXS,Imm_LDA, Imm_LDX, Imm_LDY, + // Imm_Unsupported,NZ_X, NZ_Y, NZ_A,RelBranch_Stage2_BNE, RelBranch_Stage2_BPL, RelBranch_Stage2_BCC, RelBranch_Stage2_BCS, RelBranch_Stage2_BEQ, RelBranch_Stage2_BMI, RelBranch_Stage2_BVC, RelBranch_Stage2_BVS, + // RelBranch_Stage2, RelBranch_Stage3, RelBranch_Stage4,_Eor, _Bit, _Cpx, _Cpy, _Cmp, _Adc, _Sbc, _Ora, _And, _Anc, _Asr, _Arr, _Lxa, _Axs, + // AbsInd_JMP_Stage4, AbsInd_JMP_Stage5,IndIdx_Stage3, IndIdx_Stage4, IndIdx_READ_Stage5, IndIdx_WRITE_Stage5, + // IndIdx_WRITE_Stage6_STA, IndIdx_WRITE_Stage6_SHA,IndIdx_READ_Stage6_LDA, IndIdx_READ_Stage6_CMP, IndIdx_READ_Stage6_ORA, IndIdx_READ_Stage6_SBC, IndIdx_READ_Stage6_ADC, IndIdx_READ_Stage6_AND, IndIdx_READ_Stage6_EOR, + // IndIdx_READ_Stage6_LAX,IndIdx_RMW_Stage5,IndIdx_RMW_Stage6, IndIdx_RMW_Stage7_SLO, IndIdx_RMW_Stage7_RLA, IndIdx_RMW_Stage7_SRE, IndIdx_RMW_Stage7_RRA, IndIdx_RMW_Stage7_ISC, IndIdx_RMW_Stage7_DCP,IndIdx_RMW_Stage8, + // End,End_ISpecial,End_BranchSpecial,End_SuppressInterrupt, + //}; + } + */ + static const int VOP_Fetch1 = 256; + static const int VOP_RelativeStuff = 257; + static const int VOP_RelativeStuff2 = 258; + static const int VOP_RelativeStuff3 = 259; + static const int VOP_NMI = 260; + static const int VOP_IRQ = 261; + static const int VOP_RESET = 262; + static const int VOP_Fetch1_NoInterrupt = 263; + static const int VOP_NUM = 264; + + /* + bool Interrupted + { + get + { + return NMI || (IRQ && !FlagI); + } + } + */ + + INL void FetchDummy() + { + DummyReadMemory(PC); + } + + /* + void Execute(int cycles) + { + for (int i = 0; i < cycles; i++) + { + ExecuteOne(); + } + }*/ + + void Fetch1() + { + my_iflag = FlagI; + FlagI = iflag_pending; + if (!branch_irq_hack) + { + interrupt_pending = false; + if (NMI) + { + //if (TraceCallback != nullptr) + // TraceCallback("====NMI===="); + ea = NMIVector; + opcode = VOP_NMI; + NMI = false; + mi = 0; + ExecuteOneRetry(); + return; + } + else if (IRQ && !my_iflag) + { + //if (TraceCallback != nullptr) + // TraceCallback("====IRQ===="); + ea = IRQVector; + opcode = VOP_IRQ; + mi = 0; + ExecuteOneRetry(); + return; + } + } + Fetch1_Real(); + } + + INL void Fetch1_Real() + { + rdy_freeze = !RDY; + if (RDY) + { + //if (debug) Console.WriteLine(State()); + branch_irq_hack = false; + if (OnExecFetch != nullptr) OnExecFetch(PC); + //if (TraceCallback != nullptr) + // TraceCallback(State()); + opcode = ReadMemory(PC++); + mi = -1; + } + } + INL void Fetch2() + { + rdy_freeze = !RDY; + if (RDY) + { + opcode2 = ReadMemory(PC++); + } + } + INL void Fetch3() + { + rdy_freeze = !RDY; + if (RDY) + { + opcode3 = ReadMemory(PC++); + } + } + INL void PushPCH() + { + WriteMemory((ushort)(S-- + 0x100), (byte)(PC >> 8)); + } + INL void PushPCL() + { + WriteMemory((ushort)(S-- + 0x100), (byte)PC); + } + INL void PushP_BRK() + { + FlagB = true; + WriteMemory((ushort)(S-- + 0x100), GetP()); + FlagI = true; + ea = BRKVector; + + } + INL void PushP_IRQ() + { + FlagB = false; + WriteMemory((ushort)(S-- + 0x100), GetP()); + FlagI = true; + ea = IRQVector; + + } + INL void PushP_NMI() + { + FlagB = false; + WriteMemory((ushort)(S-- + 0x100), GetP()); + FlagI = true; //is this right? + ea = NMIVector; + + } + INL void PushP_Reset() + { + ea = ResetVector; + S--; + FlagI = true; + + } + INL void PushDummy() + { + S--; + + } + INL void FetchPCLVector() + { + rdy_freeze = !RDY; + if (RDY) + { + if (ea == BRKVector && FlagB && NMI) + { + NMI = false; + ea = NMIVector; + } + if (ea == IRQVector && !FlagB && NMI) + { + NMI = false; + ea = NMIVector; + } + alu_temp = ReadMemory((ushort)ea); + } + + } + INL void FetchPCHVector() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp += ReadMemory((ushort)(ea + 1)) << 8; + PC = (ushort)alu_temp; + } + + } + INL void Imp_INY() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); Y++; NZ_Y(); + } + } + INL void Imp_DEY() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); Y--; NZ_Y(); + } + } + INL void Imp_INX() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); X++; NZ_X(); + } + } + INL void Imp_DEX() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); X--; NZ_X(); + } + } + INL void NZ_A() + { + FlagZ = A == 0; + FlagN = (A & 0x80) != 0; + } + INL void NZ_X() + { + FlagZ = X == 0; + FlagN = (X & 0x80) != 0; + } + INL void NZ_Y() + { + FlagZ = Y == 0; + FlagN = (Y & 0x80) != 0; + } + INL void Imp_TSX() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); X = S; NZ_X(); + } + } + INL void Imp_TXS() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); S = X; + } + } + INL void Imp_TAX() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); X = A; NZ_X(); + } + } + INL void Imp_TAY() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); Y = A; NZ_Y(); + } + } + INL void Imp_TYA() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); A = Y; NZ_A(); + } + } + INL void Imp_TXA() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); A = X; NZ_A(); + } + + } + INL void Imp_SEI() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); iflag_pending = true; + } + } + INL void Imp_CLI() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); iflag_pending = false; + } + } + INL void Imp_SEC() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); FlagC = true; + } + } + INL void Imp_CLC() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); FlagC = false; + } + } + INL void Imp_SED() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); FlagD = true; + } + } + INL void Imp_CLD() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); FlagD = false; + } + } + INL void Imp_CLV() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); FlagV = false; + } + + } + INL void Abs_WRITE_STA() + { + WriteMemory((ushort)((opcode3 << 8) + opcode2), A); + } + INL void Abs_WRITE_STX() + { + WriteMemory((ushort)((opcode3 << 8) + opcode2), X); + } + INL void Abs_WRITE_STY() + { + WriteMemory((ushort)((opcode3 << 8) + opcode2), Y); + } + INL void Abs_WRITE_SAX() + { + WriteMemory((ushort)((opcode3 << 8) + opcode2), (byte)(X & A)); + + } + INL void ZP_WRITE_STA() + { + WriteMemory(opcode2, A); + } + INL void ZP_WRITE_STY() + { + WriteMemory(opcode2, Y); + } + INL void ZP_WRITE_STX() + { + WriteMemory(opcode2, X); + } + INL void ZP_WRITE_SAX() + { + WriteMemory(opcode2, (byte)(X & A)); + + } + INL void IndIdx_Stage3() + { + rdy_freeze = !RDY; + if (RDY) + { + ea = ReadMemory(opcode2); + } + + } + INL void IndIdx_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ea + Y; + ea = (ReadMemory((byte)(opcode2 + 1)) << 8) + | ((alu_temp & 0xFF)); + } + + } + INL void IndIdx_WRITE_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory((ushort)ea); + ea += (alu_temp >> 8) << 8; + } + + } + void IndIdx_READ_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + if (!Bit<8>(alu_temp)) + { + mi++; + ExecuteOneRetry(); + return; + } + else + { + ReadMemory((ushort)ea); + ea = (ushort)(ea + 0x100); + } + } + } + INL void IndIdx_RMW_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + if (Bit<8>(alu_temp)) + ea = (ushort)(ea + 0x100); + ReadMemory((ushort)ea); + } + + } + INL void IndIdx_WRITE_Stage6_STA() + { + WriteMemory((ushort)ea, A); + + } + INL void IndIdx_WRITE_Stage6_SHA() + { + WriteMemory((ushort)ea, (byte)(A & X & 7)); + + } + INL void IndIdx_READ_Stage6_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory((ushort)ea); + NZ_A(); + } + } + INL void IndIdx_READ_Stage6_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Cmp(); + } + } + INL void IndIdx_READ_Stage6_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _And(); + } + } + INL void IndIdx_READ_Stage6_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Eor(); + } + } + INL void IndIdx_READ_Stage6_LAX() + { + rdy_freeze = !RDY; + if (RDY) + { + A = X = ReadMemory((ushort)ea); + NZ_A(); + } + } + INL void IndIdx_READ_Stage6_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Adc(); + } + } + INL void IndIdx_READ_Stage6_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Sbc(); + } + } + INL void IndIdx_READ_Stage6_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Ora(); + } + } + INL void IndIdx_RMW_Stage6() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + } + + } + INL void IndIdx_RMW_Stage7_SLO() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)((value8 << 1)); + A |= value8; + NZ_A(); + } + INL void IndIdx_RMW_Stage7_SRE() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + A ^= value8; + NZ_A(); + } + INL void IndIdx_RMW_Stage7_RRA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((FlagC) << 7)); + FlagC = (temp8 & 1) != 0; + _Adc(); + } + INL void IndIdx_RMW_Stage7_ISC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 + 1); + _Sbc(); + } + INL void IndIdx_RMW_Stage7_DCP() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 - 1); + FlagC = (temp8 & 1) != 0; + _Cmp(); + } + INL void IndIdx_RMW_Stage7_RLA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (FlagC)); + FlagC = (temp8 & 0x80) != 0; + A &= value8; + NZ_A(); + } + INL void IndIdx_RMW_Stage8() + { + WriteMemory((ushort)ea, (byte)alu_temp); + + + } + INL void RelBranch_Stage2_BVS() + { + branch_taken = FlagV == true; + RelBranch_Stage2(); + } + INL void RelBranch_Stage2_BVC() + { + branch_taken = FlagV == false; + RelBranch_Stage2(); + } + INL void RelBranch_Stage2_BMI() + { + branch_taken = FlagN == true; + RelBranch_Stage2(); + } + INL void RelBranch_Stage2_BPL() + { + branch_taken = FlagN == false; + RelBranch_Stage2(); + } + INL void RelBranch_Stage2_BCS() + { + branch_taken = FlagC == true; + RelBranch_Stage2(); + } + INL void RelBranch_Stage2_BCC() + { + branch_taken = FlagC == false; + RelBranch_Stage2(); + } + INL void RelBranch_Stage2_BEQ() + { + branch_taken = FlagZ == true; + RelBranch_Stage2(); + } + INL void RelBranch_Stage2_BNE() + { + branch_taken = FlagZ == false; + RelBranch_Stage2(); + + } + INL void RelBranch_Stage2() + { + rdy_freeze = !RDY; + if (RDY) + { + opcode2 = ReadMemory(PC++); + if (branch_taken) + { + branch_taken = false; + //if the branch is taken, we enter a different bit of microcode to calculate the PC and complete the branch + opcode = VOP_RelativeStuff; + mi = -1; + } + } + + } + INL void RelBranch_Stage3() + { + FetchDummy(); + alu_temp = (byte)PC + (int)(sbyte)opcode2; + PC &= 0xFF00; + PC |= (ushort)((alu_temp & 0xFF)); + if (Bit<8>(alu_temp)) + { + //we need to carry the add, and then we'll be ready to fetch the next instruction + opcode = VOP_RelativeStuff2; + mi = -1; + } + else + { + //to pass cpu_interrupts_v2/5-branch_delays_irq we need to handle a quirk here + //if we decide to interrupt in the next cycle, this condition will cause it to get deferred by one instruction + if (!interrupt_pending) + branch_irq_hack = true; + } + + } + INL void RelBranch_Stage4() + { + FetchDummy(); + if (Bit<31>(alu_temp)) + PC = (ushort)(PC - 0x100); + else PC = (ushort)(PC + 0x100); + + + } + INL void NOP() + { + } + INL void DecS() + { + S--; + } + INL void IncS() + { + S++; + } + INL void JSR() + { + rdy_freeze = !RDY; + if (RDY) + { + PC = (ushort)((ReadMemory((ushort)(PC)) << 8) + opcode2); + } + } + INL void PullP() + { + rdy_freeze = !RDY; + if (RDY) + { + SetP(ReadMemory((ushort)(S++ + 0x100))); + FlagT = true; //force T always to remain true + } + + } + INL void PullPCL() + { + rdy_freeze = !RDY; + if (RDY) + { + PC &= 0xFF00; + PC |= ReadMemory((ushort)(S++ + 0x100)); + } + + } + INL void PullPCH_NoInc() + { + rdy_freeze = !RDY; + if (RDY) + { + PC &= 0xFF; + PC |= (ushort)(ReadMemory((ushort)(S + 0x100)) << 8); + } + + } + INL void Abs_READ_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + NZ_A(); + } + } + INL void Abs_READ_LDY() + { + rdy_freeze = !RDY; + if (RDY) + { + Y = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + NZ_Y(); + } + } + INL void Abs_READ_LDX() + { + rdy_freeze = !RDY; + if (RDY) + { + X = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + NZ_X(); + } + } + INL void Abs_READ_BIT() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Bit(); + } + } + INL void Abs_READ_LAX() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + A = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + X = A; + NZ_A(); + } + } + INL void Abs_READ_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _And(); + } + } + INL void Abs_READ_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Eor(); + } + } + INL void Abs_READ_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Ora(); + } + } + INL void Abs_READ_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Adc(); + } + } + INL void Abs_READ_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Cmp(); + } + } + INL void Abs_READ_CPY() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Cpy(); + } + } + INL void Abs_READ_NOP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + } + + } + INL void Abs_READ_CPX() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Cpx(); + } + } + INL void Abs_READ_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Sbc(); + } + + } + INL void ZpIdx_Stage3_X() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory(opcode2); + opcode2 = (byte)(opcode2 + X); //a bit sneaky to shove this into opcode2... but we can reuse all the zero page uops if we do that + } + + } + INL void ZpIdx_Stage3_Y() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory(opcode2); + opcode2 = (byte)(opcode2 + Y); //a bit sneaky to shove this into opcode2... but we can reuse all the zero page uops if we do that + } + + } + INL void ZpIdx_RMW_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + } + + } + INL void ZpIdx_RMW_Stage6() + { + WriteMemory(opcode2, (byte)alu_temp); + + + } + INL void ZP_READ_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Eor(); + } + } + INL void ZP_READ_BIT() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Bit(); + } + } + INL void ZP_READ_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory(opcode2); + NZ_A(); + } + } + INL void ZP_READ_LDY() + { + rdy_freeze = !RDY; + if (RDY) + { + Y = ReadMemory(opcode2); + NZ_Y(); + } + } + INL void ZP_READ_LDX() + { + rdy_freeze = !RDY; + if (RDY) + { + X = ReadMemory(opcode2); + NZ_X(); + } + } + INL void ZP_READ_LAX() + { + rdy_freeze = !RDY; + if (RDY) + { + //?? is this right?? + X = ReadMemory(opcode2); + A = X; + NZ_A(); + } + } + INL void ZP_READ_CPY() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Cpy(); + } + } + INL void ZP_READ_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Cmp(); + } + } + INL void ZP_READ_CPX() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Cpx(); + } + } + INL void ZP_READ_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Ora(); + } + } + INL void ZP_READ_NOP() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory(opcode2); //just a dummy + } + + } + INL void ZP_READ_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Sbc(); + } + } + INL void ZP_READ_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Adc(); + } + } + INL void ZP_READ_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _And(); + } + + } + INL void _Cpx() + { + value8 = (byte)alu_temp; + value16 = (ushort)(X - value8); + FlagC = (X >= value8); + NZ_V((byte)value16); + + } + INL void _Cpy() + { + value8 = (byte)alu_temp; + value16 = (ushort)(Y - value8); + FlagC = (Y >= value8); + NZ_V((byte)value16); + + } + INL void _Cmp() + { + value8 = (byte)alu_temp; + value16 = (ushort)(A - value8); + FlagC = (A >= value8); + NZ_V((byte)value16); + + } + INL void _Bit() + { + FlagN = (alu_temp & 0x80) != 0; + FlagV = (alu_temp & 0x40) != 0; + FlagZ = (A & alu_temp) == 0; + + } + INL void _Eor() + { + A ^= (byte)alu_temp; + NZ_A(); + } + INL void _And() + { + A &= (byte)alu_temp; + NZ_A(); + } + INL void _Ora() + { + A |= (byte)alu_temp; + NZ_A(); + } + INL void _Anc() + { + A &= (byte)alu_temp; + FlagC = Bit<7>(A); + NZ_A(); + } + INL void _Asr() + { + A &= (byte)alu_temp; + FlagC = Bit<0>(A); + A >>= 1; + NZ_A(); + } + INL void _Axs() + { + X &= A; + alu_temp = X - (byte)alu_temp; + X = (byte)alu_temp; + FlagC = !Bit<8>(alu_temp); + NZ_X(); + } + INL void _Arr() + { + { + A &= (byte)alu_temp; + booltemp = Bit<0>(A); + A = (byte)((A >> 1) | (FlagC ? 0x80 : 0x00)); + FlagC = booltemp; + if (Bit<5>(A)) + if (Bit<6>(A)) + { FlagC = true; FlagV = false; } + else { FlagV = true; FlagC = false; } + else if (Bit<6>(A)) + { FlagV = true; FlagC = true; } + else { FlagV = false; FlagC = false; } + FlagZ = (A == 0); + + } + } + INL void _Lxa() + { + A |= 0xFF; //there is some debate about what this should be. it may depend on the 6502 variant. this is suggested by qeed's doc for the nes and passes blargg's instruction test + A &= (byte)alu_temp; + X = A; + NZ_A(); + } + INL void _Sbc() + { + { + value8 = (byte)alu_temp; + tempint = A - value8 - (FlagC ? 0 : 1); + if (FlagD && BCD_Enabled) + { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ tempint) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte)((lo & 0x0F) | (hi & 0xF0)); + } + else + { + FlagV = ((A ^ value8) & (A ^ tempint) & 0x80) != 0; + FlagC = tempint >= 0; + A = (byte)tempint; + } + NZ_A(); + } + } + INL void _Adc() + { + { + //TODO - an extra cycle penalty? + value8 = (byte)alu_temp; + if (FlagD && BCD_Enabled) + { + lo = (A & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (A & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) + { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(A ^ value8) & (A ^ hi) & 0x80) != 0; + FlagC = hi > 0xFF; + A = (byte)((lo & 0x0F) | (hi & 0xF0)); + } + else + { + tempint = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ tempint) & 0x80) != 0; + FlagC = tempint > 0xFF; + A = (byte)tempint; + } + NZ_A(); + } + + } + INL void Unsupported() + { + + + } + INL void Imm_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Eor(); + } + } + INL void Imm_ANC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Anc(); + } + } + INL void Imm_ASR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Asr(); + } + } + INL void Imm_AXS() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Axs(); + } + } + INL void Imm_ARR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Arr(); + } + } + INL void Imm_LXA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Lxa(); + } + } + INL void Imm_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Ora(); + } + } + INL void Imm_CPY() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Cpy(); + } + } + INL void Imm_CPX() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Cpx(); + } + } + INL void Imm_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Cmp(); + } + } + INL void Imm_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Sbc(); + } + } + INL void Imm_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _And(); + } + } + INL void Imm_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Adc(); + } + } + INL void Imm_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory(PC++); + NZ_A(); + } + } + INL void Imm_LDX() + { + rdy_freeze = !RDY; + if (RDY) + { + X = ReadMemory(PC++); + NZ_X(); + } + } + INL void Imm_LDY() + { + rdy_freeze = !RDY; + if (RDY) + { + Y = ReadMemory(PC++); + NZ_Y(); + } + } + INL void Imm_Unsupported() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory(PC++); + } + + } + INL void IdxInd_Stage3() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory(opcode2); //dummy? + alu_temp = (opcode2 + X) & 0xFF; + } + + } + INL void IdxInd_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + ea = ReadMemory((ushort)alu_temp); + } + + } + INL void IdxInd_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + ea += (ReadMemory((byte)(alu_temp + 1)) << 8); + } + + } + INL void IdxInd_Stage6_READ_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + //TODO make uniform with others + A = ReadMemory((ushort)ea); + NZ_A(); + } + } + INL void IdxInd_Stage6_READ_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Ora(); + } + } + INL void IdxInd_Stage6_READ_LAX() + { + rdy_freeze = !RDY; + if (RDY) + { + A = X = ReadMemory((ushort)ea); + NZ_A(); + } + } + INL void IdxInd_Stage6_READ_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Cmp(); + } + } + INL void IdxInd_Stage6_READ_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Adc(); + } + } + INL void IdxInd_Stage6_READ_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _And(); + } + } + INL void IdxInd_Stage6_READ_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Eor(); + } + } + INL void IdxInd_Stage6_READ_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Sbc(); + } + } + INL void IdxInd_Stage6_WRITE_STA() + { + WriteMemory((ushort)ea, A); + + } + INL void IdxInd_Stage6_WRITE_SAX() + { + alu_temp = A & X; + WriteMemory((ushort)ea, (byte)alu_temp); + //flag writing skipped on purpose + + } + INL void IdxInd_Stage6_RMW() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + } + + } + INL void IdxInd_Stage7_RMW_SLO() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)((value8 << 1)); + A |= value8; + NZ_A(); + } + INL void IdxInd_Stage7_RMW_ISC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 + 1); + _Sbc(); + } + INL void IdxInd_Stage7_RMW_DCP() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 - 1); + FlagC = (temp8 & 1) != 0; + _Cmp(); + } + INL void IdxInd_Stage7_RMW_SRE() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + A ^= value8; + NZ_A(); + } + INL void IdxInd_Stage7_RMW_RRA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((FlagC) << 7)); + FlagC = (temp8 & 1) != 0; + _Adc(); + } + INL void IdxInd_Stage7_RMW_RLA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (FlagC)); + FlagC = (temp8 & 0x80) != 0; + A &= value8; + NZ_A(); + } + INL void IdxInd_Stage8_RMW() + { + WriteMemory((ushort)ea, (byte)alu_temp); + + + } + INL void PushP() + { + FlagB = true; + WriteMemory((ushort)(S-- + 0x100), GetP()); + + } + INL void PushA() + { + WriteMemory((ushort)(S-- + 0x100), A); + } + INL void PullA_NoInc() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory((ushort)(S + 0x100)); + NZ_A(); + } + } + INL void PullP_NoInc() + { + rdy_freeze = !RDY; + if (RDY) + { + my_iflag = FlagI; + SetP(ReadMemory((ushort)(S + 0x100))); + iflag_pending = FlagI; + FlagI = my_iflag; + FlagT = true; //force T always to remain true + + } + + } + INL void Imp_ASL_A() + { + FetchDummy(); + FlagC = (A & 0x80) != 0; + A = (byte)(A << 1); + NZ_A(); + } + INL void Imp_ROL_A() + { + FetchDummy(); + temp8 = A; + A = (byte)((A << 1) | (FlagC)); + FlagC = (temp8 & 0x80) != 0; + NZ_A(); + } + INL void Imp_ROR_A() + { + FetchDummy(); + temp8 = A; + A = (byte)((A >> 1) | ((FlagC) << 7)); + FlagC = (temp8 & 1) != 0; + NZ_A(); + } + INL void Imp_LSR_A() + { + FetchDummy(); + FlagC = (A & 1) != 0; + A = (byte)(A >> 1); + NZ_A(); + + } + INL void JMP_abs() + { + rdy_freeze = !RDY; + if (RDY) + { + PC = (ushort)((ReadMemory(PC) << 8) + opcode2); + } + + } + INL void IncPC() + { + PC++; + + + } + INL void ZP_RMW_Stage3() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + } + + } + INL void ZP_RMW_Stage5() + { + WriteMemory(opcode2, (byte)alu_temp); + + } + INL void ZP_RMW_INC() + { + WriteMemory(opcode2, (byte)alu_temp); + alu_temp = (byte)((alu_temp + 1) & 0xFF); + NZ_V((byte)alu_temp); + + } + INL void ZP_RMW_DEC() + { + WriteMemory(opcode2, (byte)alu_temp); + alu_temp = (byte)((alu_temp - 1) & 0xFF); + NZ_V((byte)alu_temp); + + } + INL void ZP_RMW_ASL() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)(value8 << 1); + NZ_V((byte)value8); + + } + INL void ZP_RMW_SRE() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + A ^= value8; + NZ_A(); + } + INL void ZP_RMW_RRA() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((FlagC) << 7)); + FlagC = (temp8 & 1) != 0; + _Adc(); + } + INL void ZP_RMW_DCP() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 - 1); + FlagC = (temp8 & 1) != 0; + _Cmp(); + } + INL void ZP_RMW_LSR() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + NZ_V((byte)value8); + + } + INL void ZP_RMW_ROR() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((FlagC) << 7)); + FlagC = (temp8 & 1) != 0; + NZ_V((byte)value8); + + } + INL void ZP_RMW_ROL() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (FlagC)); + FlagC = (temp8 & 0x80) != 0; + NZ_V((byte)value8); + + } + INL void ZP_RMW_SLO() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)((value8 << 1)); + A |= value8; + NZ_A(); + } + INL void ZP_RMW_ISC() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 + 1); + _Sbc(); + } + INL void ZP_RMW_RLA() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (FlagC)); + FlagC = (temp8 & 0x80) != 0; + A &= value8; + NZ_A(); + + } + INL void AbsIdx_Stage3_Y() + { + rdy_freeze = !RDY; + if (RDY) + { + opcode3 = ReadMemory(PC++); + alu_temp = opcode2 + Y; + ea = (opcode3 << 8) + (alu_temp & 0xFF); + + //new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_WRITE_Stage5_STA, Uop.End }, + } + } + INL void AbsIdx_Stage3_X() + { + rdy_freeze = !RDY; + if (RDY) + { + opcode3 = ReadMemory(PC++); + alu_temp = opcode2 + X; + ea = (opcode3 << 8) + (alu_temp & 0xFF); + } + + } + void AbsIdx_READ_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + if (!Bit<8>(alu_temp)) + { + mi++; + ExecuteOneRetry(); + return; + } + else + { + alu_temp = ReadMemory((ushort)ea); + ea = (ushort)(ea + 0x100); + } + } + + } + INL void AbsIdx_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + //bleh.. redundant code to make sure we dont clobber alu_temp before using it to decide whether to change ea + if (Bit<8>(alu_temp)) + { + alu_temp = ReadMemory((ushort)ea); + ea = (ushort)(ea + 0x100); + } + else alu_temp = ReadMemory((ushort)ea); + } + + } + INL void AbsIdx_WRITE_Stage5_STA() + { + WriteMemory((ushort)ea, A); + + } + INL void AbsIdx_WRITE_Stage5_SHY() + { + alu_temp = Y & (ea >> 8); + ea = (ea & 0xFF) | (alu_temp << 8); //"(the bank where the value is stored may be equal to the value stored)" -- more like IS. + WriteMemory((ushort)ea, (byte)alu_temp); + + } + INL void AbsIdx_WRITE_Stage5_SHX() + { + alu_temp = X & (ea >> 8); + ea = (ea & 0xFF) | (alu_temp << 8); //"(the bank where the value is stored may be equal to the value stored)" -- more like IS. + WriteMemory((ushort)ea, (byte)alu_temp); + + } + INL void AbsIdx_WRITE_Stage5_ERROR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + //throw new InvalidOperationException("UNSUPPORTED OPCODE [probably SHS] PLEASE REPORT"); + } + + } + INL void AbsIdx_RMW_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + } + + } + INL void AbsIdx_RMW_Stage7() + { + WriteMemory((ushort)ea, (byte)alu_temp); + + } + INL void AbsIdx_RMW_Stage6_DEC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + alu_temp = value8 = (byte)(alu_temp - 1); + NZ_V((byte)value8); + + } + INL void AbsIdx_RMW_Stage6_DCP() + { + WriteMemory((ushort)ea, (byte)alu_temp); + alu_temp = value8 = (byte)(alu_temp - 1); + _Cmp(); + } + INL void AbsIdx_RMW_Stage6_ISC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + alu_temp = value8 = (byte)(alu_temp + 1); + _Sbc(); + } + INL void AbsIdx_RMW_Stage6_INC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + alu_temp = value8 = (byte)(alu_temp + 1); + NZ_V((byte)value8); + + } + INL void AbsIdx_RMW_Stage6_ROL() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (FlagC)); + FlagC = (temp8 & 0x80) != 0; + NZ_V((byte)value8); + + } + INL void AbsIdx_RMW_Stage6_LSR() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + NZ_V((byte)value8); + + } + INL void AbsIdx_RMW_Stage6_SLO() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)(value8 << 1); + A |= value8; + NZ_A(); + } + INL void AbsIdx_RMW_Stage6_SRE() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + A ^= value8; + NZ_A(); + } + INL void AbsIdx_RMW_Stage6_RRA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((FlagC) << 7)); + FlagC = (temp8 & 1) != 0; + _Adc(); + } + INL void AbsIdx_RMW_Stage6_RLA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (FlagC)); + FlagC = (temp8 & 0x80) != 0; + A &= value8; + NZ_A(); + } + INL void AbsIdx_RMW_Stage6_ASL() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)(value8 << 1); + NZ_V((byte)value8); + + } + INL void AbsIdx_RMW_Stage6_ROR() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((FlagC) << 7)); + FlagC = (temp8 & 1) != 0; + NZ_V((byte)value8); + + + } + INL void AbsIdx_READ_Stage5_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory((ushort)ea); + NZ_A(); + } + } + INL void AbsIdx_READ_Stage5_LDX() + { + rdy_freeze = !RDY; + if (RDY) + { + X = ReadMemory((ushort)ea); + NZ_X(); + } + } + INL void AbsIdx_READ_Stage5_LAX() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory((ushort)ea); + X = A; + NZ_A(); + } + } + INL void AbsIdx_READ_Stage5_LDY() + { + rdy_freeze = !RDY; + if (RDY) + { + Y = ReadMemory((ushort)ea); + NZ_Y(); + } + } + INL void AbsIdx_READ_Stage5_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Ora(); + } + } + INL void AbsIdx_READ_Stage5_NOP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + } + + } + INL void AbsIdx_READ_Stage5_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Cmp(); + } + } + INL void AbsIdx_READ_Stage5_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Sbc(); + } + } + INL void AbsIdx_READ_Stage5_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Adc(); + } + } + INL void AbsIdx_READ_Stage5_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Eor(); + } + } + INL void AbsIdx_READ_Stage5_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _And(); + } + } + INL void AbsIdx_READ_Stage5_ERROR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + //throw new InvalidOperationException("UNSUPPORTED OPCODE [probably LAS] PLEASE REPORT"); + } + + } + INL void AbsInd_JMP_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + ea = (opcode3 << 8) + opcode2; + alu_temp = ReadMemory((ushort)ea); + } + } + INL void AbsInd_JMP_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + ea = (opcode3 << 8) + (byte)(opcode2 + 1); + alu_temp += ReadMemory((ushort)ea) << 8; + PC = (ushort)alu_temp; + } + + } + INL void Abs_RMW_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + ea = (opcode3 << 8) + opcode2; + alu_temp = ReadMemory((ushort)ea); + } + + } + INL void Abs_RMW_Stage5_INC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)(alu_temp + 1); + alu_temp = value8; + NZ_V((byte)value8); + + } + INL void Abs_RMW_Stage5_DEC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)(alu_temp - 1); + alu_temp = value8; + NZ_V((byte)value8); + + } + INL void Abs_RMW_Stage5_DCP() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)(alu_temp - 1); + alu_temp = value8; + _Cmp(); + } + INL void Abs_RMW_Stage5_ISC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)(alu_temp + 1); + alu_temp = value8; + _Sbc(); + } + INL void Abs_RMW_Stage5_ASL() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)(value8 << 1); + NZ_V((byte)value8); + + } + INL void Abs_RMW_Stage5_ROR() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((FlagC) << 7)); + FlagC = (temp8 & 1) != 0; + NZ_V((byte)value8); + + } + INL void Abs_RMW_Stage5_SLO() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)(value8 << 1); + A |= value8; + NZ_A(); + } + INL void Abs_RMW_Stage5_RLA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (FlagC)); + FlagC = (temp8 & 0x80) != 0; + A &= value8; + NZ_A(); + } + INL void Abs_RMW_Stage5_SRE() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + A ^= value8; + NZ_A(); + } + INL void Abs_RMW_Stage5_RRA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((FlagC) << 7)); + FlagC = (temp8 & 1) != 0; + _Adc(); + } + INL void Abs_RMW_Stage5_ROL() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (FlagC)); + FlagC = (temp8 & 0x80) != 0; + NZ_V((byte)value8); + + } + INL void Abs_RMW_Stage5_LSR() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + NZ_V((byte)value8); + + + } + INL void Abs_RMW_Stage6() + { + WriteMemory((ushort)ea, (byte)alu_temp); + + + } + void End_ISpecial() + { + opcode = VOP_Fetch1; + mi = 0; + ExecuteOneRetry(); + return; + + } + void End_SuppressInterrupt() + { + opcode = VOP_Fetch1_NoInterrupt; + mi = 0; + ExecuteOneRetry(); + return; + + } + void End() + { + opcode = VOP_Fetch1; + mi = 0; + iflag_pending = FlagI; + ExecuteOneRetry(); + return; + } + void End_BranchSpecial() + { + End(); + } + + + void ExecuteOneRetry() + { + //dont know whether this system is any faster. hard to get benchmarks someone else try it? + //Uop uop = (Uop)CompiledMicrocode[MicrocodeIndex[opcode] + mi]; + Uop uop = Microcode[opcode][mi]; + switch (uop) + { + case Uop_Fetch1: Fetch1(); break; + case Uop_Fetch1_Real: Fetch1_Real(); break; + case Uop_Fetch2: Fetch2(); break; + case Uop_Fetch3: Fetch3(); break; + case Uop_FetchDummy: FetchDummy(); break; + case Uop_PushPCH: PushPCH(); break; + case Uop_PushPCL: PushPCL(); break; + case Uop_PushP_BRK: PushP_BRK(); break; + case Uop_PushP_IRQ: PushP_IRQ(); break; + case Uop_PushP_NMI: PushP_NMI(); break; + case Uop_PushP_Reset: PushP_Reset(); break; + case Uop_PushDummy: PushDummy(); break; + case Uop_FetchPCLVector: FetchPCLVector(); break; + case Uop_FetchPCHVector: FetchPCHVector(); break; + case Uop_Imp_INY: Imp_INY(); break; + case Uop_Imp_DEY: Imp_DEY(); break; + case Uop_Imp_INX: Imp_INX(); break; + case Uop_Imp_DEX: Imp_DEX(); break; + case Uop_NZ_A: NZ_A(); break; + case Uop_NZ_X: NZ_X(); break; + case Uop_NZ_Y: NZ_Y(); break; + case Uop_Imp_TSX: Imp_TSX(); break; + case Uop_Imp_TXS: Imp_TXS(); break; + case Uop_Imp_TAX: Imp_TAX(); break; + case Uop_Imp_TAY: Imp_TAY(); break; + case Uop_Imp_TYA: Imp_TYA(); break; + case Uop_Imp_TXA: Imp_TXA(); break; + case Uop_Imp_SEI: Imp_SEI(); break; + case Uop_Imp_CLI: Imp_CLI(); break; + case Uop_Imp_SEC: Imp_SEC(); break; + case Uop_Imp_CLC: Imp_CLC(); break; + case Uop_Imp_SED: Imp_SED(); break; + case Uop_Imp_CLD: Imp_CLD(); break; + case Uop_Imp_CLV: Imp_CLV(); break; + case Uop_Abs_WRITE_STA: Abs_WRITE_STA(); break; + case Uop_Abs_WRITE_STX: Abs_WRITE_STX(); break; + case Uop_Abs_WRITE_STY: Abs_WRITE_STY(); break; + case Uop_Abs_WRITE_SAX: Abs_WRITE_SAX(); break; + case Uop_ZP_WRITE_STA: ZP_WRITE_STA(); break; + case Uop_ZP_WRITE_STY: ZP_WRITE_STY(); break; + case Uop_ZP_WRITE_STX: ZP_WRITE_STX(); break; + case Uop_ZP_WRITE_SAX: ZP_WRITE_SAX(); break; + case Uop_IndIdx_Stage3: IndIdx_Stage3(); break; + case Uop_IndIdx_Stage4: IndIdx_Stage4(); break; + case Uop_IndIdx_WRITE_Stage5: IndIdx_WRITE_Stage5(); break; + case Uop_IndIdx_READ_Stage5: IndIdx_READ_Stage5(); break; + case Uop_IndIdx_RMW_Stage5: IndIdx_RMW_Stage5(); break; + case Uop_IndIdx_WRITE_Stage6_STA: IndIdx_WRITE_Stage6_STA(); break; + case Uop_IndIdx_WRITE_Stage6_SHA: IndIdx_WRITE_Stage6_SHA(); break; + case Uop_IndIdx_READ_Stage6_LDA: IndIdx_READ_Stage6_LDA(); break; + case Uop_IndIdx_READ_Stage6_CMP: IndIdx_READ_Stage6_CMP(); break; + case Uop_IndIdx_READ_Stage6_AND: IndIdx_READ_Stage6_AND(); break; + case Uop_IndIdx_READ_Stage6_EOR: IndIdx_READ_Stage6_EOR(); break; + case Uop_IndIdx_READ_Stage6_LAX: IndIdx_READ_Stage6_LAX(); break; + case Uop_IndIdx_READ_Stage6_ADC: IndIdx_READ_Stage6_ADC(); break; + case Uop_IndIdx_READ_Stage6_SBC: IndIdx_READ_Stage6_SBC(); break; + case Uop_IndIdx_READ_Stage6_ORA: IndIdx_READ_Stage6_ORA(); break; + case Uop_IndIdx_RMW_Stage6: IndIdx_RMW_Stage6(); break; + case Uop_IndIdx_RMW_Stage7_SLO: IndIdx_RMW_Stage7_SLO(); break; + case Uop_IndIdx_RMW_Stage7_SRE: IndIdx_RMW_Stage7_SRE(); break; + case Uop_IndIdx_RMW_Stage7_RRA: IndIdx_RMW_Stage7_RRA(); break; + case Uop_IndIdx_RMW_Stage7_ISC: IndIdx_RMW_Stage7_ISC(); break; + case Uop_IndIdx_RMW_Stage7_DCP: IndIdx_RMW_Stage7_DCP(); break; + case Uop_IndIdx_RMW_Stage7_RLA: IndIdx_RMW_Stage7_RLA(); break; + case Uop_IndIdx_RMW_Stage8: IndIdx_RMW_Stage8(); break; + case Uop_RelBranch_Stage2_BVS: RelBranch_Stage2_BVS(); break; + case Uop_RelBranch_Stage2_BVC: RelBranch_Stage2_BVC(); break; + case Uop_RelBranch_Stage2_BMI: RelBranch_Stage2_BMI(); break; + case Uop_RelBranch_Stage2_BPL: RelBranch_Stage2_BPL(); break; + case Uop_RelBranch_Stage2_BCS: RelBranch_Stage2_BCS(); break; + case Uop_RelBranch_Stage2_BCC: RelBranch_Stage2_BCC(); break; + case Uop_RelBranch_Stage2_BEQ: RelBranch_Stage2_BEQ(); break; + case Uop_RelBranch_Stage2_BNE: RelBranch_Stage2_BNE(); break; + case Uop_RelBranch_Stage2: RelBranch_Stage2(); break; + case Uop_RelBranch_Stage3: RelBranch_Stage3(); break; + case Uop_RelBranch_Stage4: RelBranch_Stage4(); break; + case Uop_NOP: NOP(); break; + case Uop_DecS: DecS(); break; + case Uop_IncS: IncS(); break; + case Uop_JSR: JSR(); break; + case Uop_PullP: PullP(); break; + case Uop_PullPCL: PullPCL(); break; + case Uop_PullPCH_NoInc: PullPCH_NoInc(); break; + case Uop_Abs_READ_LDA: Abs_READ_LDA(); break; + case Uop_Abs_READ_LDY: Abs_READ_LDY(); break; + case Uop_Abs_READ_LDX: Abs_READ_LDX(); break; + case Uop_Abs_READ_BIT: Abs_READ_BIT(); break; + case Uop_Abs_READ_LAX: Abs_READ_LAX(); break; + case Uop_Abs_READ_AND: Abs_READ_AND(); break; + case Uop_Abs_READ_EOR: Abs_READ_EOR(); break; + case Uop_Abs_READ_ORA: Abs_READ_ORA(); break; + case Uop_Abs_READ_ADC: Abs_READ_ADC(); break; + case Uop_Abs_READ_CMP: Abs_READ_CMP(); break; + case Uop_Abs_READ_CPY: Abs_READ_CPY(); break; + case Uop_Abs_READ_NOP: Abs_READ_NOP(); break; + case Uop_Abs_READ_CPX: Abs_READ_CPX(); break; + case Uop_Abs_READ_SBC: Abs_READ_SBC(); break; + case Uop_ZpIdx_Stage3_X: ZpIdx_Stage3_X(); break; + case Uop_ZpIdx_Stage3_Y: ZpIdx_Stage3_Y(); break; + case Uop_ZpIdx_RMW_Stage4: ZpIdx_RMW_Stage4(); break; + case Uop_ZpIdx_RMW_Stage6: ZpIdx_RMW_Stage6(); break; + case Uop_ZP_READ_EOR: ZP_READ_EOR(); break; + case Uop_ZP_READ_BIT: ZP_READ_BIT(); break; + case Uop_ZP_READ_LDA: ZP_READ_LDA(); break; + case Uop_ZP_READ_LDY: ZP_READ_LDY(); break; + case Uop_ZP_READ_LDX: ZP_READ_LDX(); break; + case Uop_ZP_READ_LAX: ZP_READ_LAX(); break; + case Uop_ZP_READ_CPY: ZP_READ_CPY(); break; + case Uop_ZP_READ_CMP: ZP_READ_CMP(); break; + case Uop_ZP_READ_CPX: ZP_READ_CPX(); break; + case Uop_ZP_READ_ORA: ZP_READ_ORA(); break; + case Uop_ZP_READ_NOP: ZP_READ_NOP(); break; + case Uop_ZP_READ_SBC: ZP_READ_SBC(); break; + case Uop_ZP_READ_ADC: ZP_READ_ADC(); break; + case Uop_ZP_READ_AND: ZP_READ_AND(); break; + case Uop__Cpx: _Cpx(); break; + case Uop__Cpy: _Cpy(); break; + case Uop__Cmp: _Cmp(); break; + case Uop__Eor: _Eor(); break; + case Uop__And: _And(); break; + case Uop__Ora: _Ora(); break; + case Uop__Anc: _Anc(); break; + case Uop__Asr: _Asr(); break; + case Uop__Axs: _Axs(); break; + case Uop__Arr: _Arr(); break; + case Uop__Lxa: _Lxa(); break; + case Uop__Sbc: _Sbc(); break; + case Uop__Adc: _Adc(); break; + case Uop_Unsupported: Unsupported(); break; + case Uop_Imm_EOR: Imm_EOR(); break; + case Uop_Imm_ANC: Imm_ANC(); break; + case Uop_Imm_ASR: Imm_ASR(); break; + case Uop_Imm_AXS: Imm_AXS(); break; + case Uop_Imm_ARR: Imm_ARR(); break; + case Uop_Imm_LXA: Imm_LXA(); break; + case Uop_Imm_ORA: Imm_ORA(); break; + case Uop_Imm_CPY: Imm_CPY(); break; + case Uop_Imm_CPX: Imm_CPX(); break; + case Uop_Imm_CMP: Imm_CMP(); break; + case Uop_Imm_SBC: Imm_SBC(); break; + case Uop_Imm_AND: Imm_AND(); break; + case Uop_Imm_ADC: Imm_ADC(); break; + case Uop_Imm_LDA: Imm_LDA(); break; + case Uop_Imm_LDX: Imm_LDX(); break; + case Uop_Imm_LDY: Imm_LDY(); break; + case Uop_Imm_Unsupported: Imm_Unsupported(); break; + case Uop_IdxInd_Stage3: IdxInd_Stage3(); break; + case Uop_IdxInd_Stage4: IdxInd_Stage4(); break; + case Uop_IdxInd_Stage5: IdxInd_Stage5(); break; + case Uop_IdxInd_Stage6_READ_LDA: IdxInd_Stage6_READ_LDA(); break; + case Uop_IdxInd_Stage6_READ_ORA: IdxInd_Stage6_READ_ORA(); break; + case Uop_IdxInd_Stage6_READ_LAX: IdxInd_Stage6_READ_LAX(); break; + case Uop_IdxInd_Stage6_READ_CMP: IdxInd_Stage6_READ_CMP(); break; + case Uop_IdxInd_Stage6_READ_ADC: IdxInd_Stage6_READ_ADC(); break; + case Uop_IdxInd_Stage6_READ_AND: IdxInd_Stage6_READ_AND(); break; + case Uop_IdxInd_Stage6_READ_EOR: IdxInd_Stage6_READ_EOR(); break; + case Uop_IdxInd_Stage6_READ_SBC: IdxInd_Stage6_READ_SBC(); break; + case Uop_IdxInd_Stage6_WRITE_STA: IdxInd_Stage6_WRITE_STA(); break; + case Uop_IdxInd_Stage6_WRITE_SAX: IdxInd_Stage6_WRITE_SAX(); break; + case Uop_IdxInd_Stage6_RMW: IdxInd_Stage6_RMW(); break; + case Uop_IdxInd_Stage7_RMW_SLO: IdxInd_Stage7_RMW_SLO(); break; + case Uop_IdxInd_Stage7_RMW_ISC: IdxInd_Stage7_RMW_ISC(); break; + case Uop_IdxInd_Stage7_RMW_DCP: IdxInd_Stage7_RMW_DCP(); break; + case Uop_IdxInd_Stage7_RMW_SRE: IdxInd_Stage7_RMW_SRE(); break; + case Uop_IdxInd_Stage7_RMW_RRA: IdxInd_Stage7_RMW_RRA(); break; + case Uop_IdxInd_Stage7_RMW_RLA: IdxInd_Stage7_RMW_RLA(); break; + case Uop_IdxInd_Stage8_RMW: IdxInd_Stage8_RMW(); break; + case Uop_PushP: PushP(); break; + case Uop_PushA: PushA(); break; + case Uop_PullA_NoInc: PullA_NoInc(); break; + case Uop_PullP_NoInc: PullP_NoInc(); break; + case Uop_Imp_ASL_A: Imp_ASL_A(); break; + case Uop_Imp_ROL_A: Imp_ROL_A(); break; + case Uop_Imp_ROR_A: Imp_ROR_A(); break; + case Uop_Imp_LSR_A: Imp_LSR_A(); break; + case Uop_JMP_abs: JMP_abs(); break; + case Uop_IncPC: IncPC(); break; + case Uop_ZP_RMW_Stage3: ZP_RMW_Stage3(); break; + case Uop_ZP_RMW_Stage5: ZP_RMW_Stage5(); break; + case Uop_ZP_RMW_INC: ZP_RMW_INC(); break; + case Uop_ZP_RMW_DEC: ZP_RMW_DEC(); break; + case Uop_ZP_RMW_ASL: ZP_RMW_ASL(); break; + case Uop_ZP_RMW_SRE: ZP_RMW_SRE(); break; + case Uop_ZP_RMW_RRA: ZP_RMW_RRA(); break; + case Uop_ZP_RMW_DCP: ZP_RMW_DCP(); break; + case Uop_ZP_RMW_LSR: ZP_RMW_LSR(); break; + case Uop_ZP_RMW_ROR: ZP_RMW_ROR(); break; + case Uop_ZP_RMW_ROL: ZP_RMW_ROL(); break; + case Uop_ZP_RMW_SLO: ZP_RMW_SLO(); break; + case Uop_ZP_RMW_ISC: ZP_RMW_ISC(); break; + case Uop_ZP_RMW_RLA: ZP_RMW_RLA(); break; + case Uop_AbsIdx_Stage3_Y: AbsIdx_Stage3_Y(); break; + case Uop_AbsIdx_Stage3_X: AbsIdx_Stage3_X(); break; + case Uop_AbsIdx_READ_Stage4: AbsIdx_READ_Stage4(); break; + case Uop_AbsIdx_Stage4: AbsIdx_Stage4(); break; + case Uop_AbsIdx_WRITE_Stage5_STA: AbsIdx_WRITE_Stage5_STA(); break; + case Uop_AbsIdx_WRITE_Stage5_SHY: AbsIdx_WRITE_Stage5_SHY(); break; + case Uop_AbsIdx_WRITE_Stage5_SHX: AbsIdx_WRITE_Stage5_SHX(); break; + case Uop_AbsIdx_WRITE_Stage5_ERROR: AbsIdx_WRITE_Stage5_ERROR(); break; + case Uop_AbsIdx_RMW_Stage5: AbsIdx_RMW_Stage5(); break; + case Uop_AbsIdx_RMW_Stage7: AbsIdx_RMW_Stage7(); break; + case Uop_AbsIdx_RMW_Stage6_DEC: AbsIdx_RMW_Stage6_DEC(); break; + case Uop_AbsIdx_RMW_Stage6_DCP: AbsIdx_RMW_Stage6_DCP(); break; + case Uop_AbsIdx_RMW_Stage6_ISC: AbsIdx_RMW_Stage6_ISC(); break; + case Uop_AbsIdx_RMW_Stage6_INC: AbsIdx_RMW_Stage6_INC(); break; + case Uop_AbsIdx_RMW_Stage6_ROL: AbsIdx_RMW_Stage6_ROL(); break; + case Uop_AbsIdx_RMW_Stage6_LSR: AbsIdx_RMW_Stage6_LSR(); break; + case Uop_AbsIdx_RMW_Stage6_SLO: AbsIdx_RMW_Stage6_SLO(); break; + case Uop_AbsIdx_RMW_Stage6_SRE: AbsIdx_RMW_Stage6_SRE(); break; + case Uop_AbsIdx_RMW_Stage6_RRA: AbsIdx_RMW_Stage6_RRA(); break; + case Uop_AbsIdx_RMW_Stage6_RLA: AbsIdx_RMW_Stage6_RLA(); break; + case Uop_AbsIdx_RMW_Stage6_ASL: AbsIdx_RMW_Stage6_ASL(); break; + case Uop_AbsIdx_RMW_Stage6_ROR: AbsIdx_RMW_Stage6_ROR(); break; + case Uop_AbsIdx_READ_Stage5_LDA: AbsIdx_READ_Stage5_LDA(); break; + case Uop_AbsIdx_READ_Stage5_LDX: AbsIdx_READ_Stage5_LDX(); break; + case Uop_AbsIdx_READ_Stage5_LAX: AbsIdx_READ_Stage5_LAX(); break; + case Uop_AbsIdx_READ_Stage5_LDY: AbsIdx_READ_Stage5_LDY(); break; + case Uop_AbsIdx_READ_Stage5_ORA: AbsIdx_READ_Stage5_ORA(); break; + case Uop_AbsIdx_READ_Stage5_NOP: AbsIdx_READ_Stage5_NOP(); break; + case Uop_AbsIdx_READ_Stage5_CMP: AbsIdx_READ_Stage5_CMP(); break; + case Uop_AbsIdx_READ_Stage5_SBC: AbsIdx_READ_Stage5_SBC(); break; + case Uop_AbsIdx_READ_Stage5_ADC: AbsIdx_READ_Stage5_ADC(); break; + case Uop_AbsIdx_READ_Stage5_EOR: AbsIdx_READ_Stage5_EOR(); break; + case Uop_AbsIdx_READ_Stage5_AND: AbsIdx_READ_Stage5_AND(); break; + case Uop_AbsIdx_READ_Stage5_ERROR: AbsIdx_READ_Stage5_ERROR(); break; + case Uop_AbsInd_JMP_Stage4: AbsInd_JMP_Stage4(); break; + case Uop_AbsInd_JMP_Stage5: AbsInd_JMP_Stage5(); break; + case Uop_Abs_RMW_Stage4: Abs_RMW_Stage4(); break; + case Uop_Abs_RMW_Stage5_INC: Abs_RMW_Stage5_INC(); break; + case Uop_Abs_RMW_Stage5_DEC: Abs_RMW_Stage5_DEC(); break; + case Uop_Abs_RMW_Stage5_DCP: Abs_RMW_Stage5_DCP(); break; + case Uop_Abs_RMW_Stage5_ISC: Abs_RMW_Stage5_ISC(); break; + case Uop_Abs_RMW_Stage5_ASL: Abs_RMW_Stage5_ASL(); break; + case Uop_Abs_RMW_Stage5_ROR: Abs_RMW_Stage5_ROR(); break; + case Uop_Abs_RMW_Stage5_SLO: Abs_RMW_Stage5_SLO(); break; + case Uop_Abs_RMW_Stage5_RLA: Abs_RMW_Stage5_RLA(); break; + case Uop_Abs_RMW_Stage5_SRE: Abs_RMW_Stage5_SRE(); break; + case Uop_Abs_RMW_Stage5_RRA: Abs_RMW_Stage5_RRA(); break; + case Uop_Abs_RMW_Stage5_ROL: Abs_RMW_Stage5_ROL(); break; + case Uop_Abs_RMW_Stage5_LSR: Abs_RMW_Stage5_LSR(); break; + case Uop_Abs_RMW_Stage6: Abs_RMW_Stage6(); break; + case Uop_End_ISpecial: End_ISpecial(); break; + case Uop_End_SuppressInterrupt: End_SuppressInterrupt(); break; + case Uop_End: End(); break; + case Uop_End_BranchSpecial: End_BranchSpecial(); break; + } + } + + __declspec(dllexport) void ExecuteOne() + { + if (!rdy_freeze) + { + TotalExecutedCycles++; + + interrupt_pending |= NMI || (IRQ && !FlagI); + } + rdy_freeze = false; + + //i tried making ExecuteOneRetry not re-entrant by having it set a flag instead, then exit from the call below, check the flag, and GOTO if it was flagged, but it wasnt faster + ExecuteOneRetry(); + + if (!rdy_freeze) + mi++; + } //ExecuteOne + +}; // struct CPU diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/Old Managed Stuff/Execute.cs b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/Old Managed Stuff/Execute.cs new file mode 100644 index 0000000000..98dac152b9 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/Old Managed Stuff/Execute.cs @@ -0,0 +1,2912 @@ +//http://nesdev.parodius.com/6502_cpu.txt + +using System; +using BizHawk.Common; +using BizHawk.Common.NumberExtensions; + +namespace BizHawk.Emulation.Cores.Components.M6502 +{ + public partial class MOS6502X + { + //dont know whether this system is any faster. hard to get benchmarks someone else try it? + //static ShortBuffer CompiledMicrocode; + //static ShortBuffer MicrocodeIndex; + //static MOS6502X() + //{ + // int index = 0; + // MicrocodeIndex = new ShortBuffer(VOP_NUM); + // List temp = new List(); + // for (int i = 0; i < VOP_NUM; i++) + // { + // MicrocodeIndex[i] = (short)index; + // int numUops = Microcode[i].Length; + // for (int j = 0; j < numUops; j++) + // temp.Add(Microcode[i][j]); + // index += numUops; + // } + // CompiledMicrocode = new ShortBuffer(temp.Count); + // for (int i = 0; i < temp.Count; i++) + // CompiledMicrocode[i] = (short)temp[i]; + //} + + static Uop[][] Microcode = new Uop[][] + { + //0x00 + /*BRK [implied]*/ new Uop[] { Uop.Fetch2, Uop.PushPCH, Uop.PushPCL, Uop.PushP_BRK, Uop.FetchPCLVector, Uop.FetchPCHVector, Uop.End_SuppressInterrupt }, + /*ORA (addr,X) [indexed indirect READ]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_READ_ORA, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*SLO* (addr,X) [indexed indirect RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_RMW, Uop.IdxInd_Stage7_RMW_SLO, Uop.IdxInd_Stage8_RMW, Uop.End }, + /*NOP zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_NOP, Uop.End }, + /*ORA zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_ORA, Uop.End }, + /*ASL zp [zero page RMW]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_ASL, Uop.ZP_RMW_Stage5, Uop.End }, + /*SLO* zp [zero page RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_SLO, Uop.ZP_RMW_Stage5, Uop.End }, + /*PHP [implied]*/ new Uop[] { Uop.FetchDummy, Uop.PushP, Uop.End }, + /*ORA #nn [immediate]*/ new Uop[] { Uop.Imm_ORA, Uop.End }, + /*ASL A [accumulator]*/ new Uop[] { Uop.Imp_ASL_A, Uop.End }, + /*ANC** [immediate] [unofficial]*/ new Uop[] { Uop.Imm_ANC, Uop.End }, + /*NOP addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_NOP, Uop.End }, + /*ORA addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_ORA, Uop.End }, + /*ASL addr [absolute RMW]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_ASL, Uop.Abs_RMW_Stage6, Uop.End }, + /*SLO* addr [absolute RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_SLO, Uop.Abs_RMW_Stage6, Uop.End }, + //0x10 + /*BPL +/-rel*/ new Uop[] { Uop.RelBranch_Stage2_BPL, Uop.End }, + /*ORA (addr),Y* [indirect indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_READ_Stage5, Uop.IndIdx_READ_Stage6_ORA, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*SLO (addr),Y* [indirect indexed RMW] [unofficial] */ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_RMW_Stage5, Uop.IndIdx_RMW_Stage6, Uop.IndIdx_RMW_Stage7_SLO, Uop.IndIdx_RMW_Stage8, Uop.End }, + /*NOP zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_NOP, Uop.End }, + /*ORA zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_ORA, Uop.End }, + /*ASL zp,X [zero page indexed RMW]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_ASL, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*SLO* zp,X [zero page indexed RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_SLO, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*CLC [implied]*/ new Uop[] { Uop.Imp_CLC, Uop.End }, + /*ORA addr,Y* [absolute indexed READ Y]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_ORA, Uop.End }, + /*NOP 1A*/ new Uop[] { Uop.FetchDummy, Uop.End }, + /*SLO* addr,Y [absolute indexed RMW Y] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_SLO, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*NOP addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_NOP, Uop.End }, + /*ORA addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_ORA, Uop.End }, + /*ASL addr,X [absolute indexed RMW X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_ASL, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*SLO* addr,X [absolute indexed RMW X] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_SLO, Uop.AbsIdx_RMW_Stage7, Uop.End }, + //0x20 + /*JSR*/ new Uop[] { Uop.Fetch2, Uop.NOP, Uop.PushPCH, Uop.PushPCL, Uop.JSR, Uop.End }, + /*AND (addr,X) [indexed indirect READ]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_READ_AND, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*RLA* (addr,X) [indexed indirect RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_RMW, Uop.IdxInd_Stage7_RMW_RLA, Uop.IdxInd_Stage8_RMW, Uop.End }, + /*BIT zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_BIT, Uop.End }, + /*AND zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_AND, Uop.End }, + /*ROL zp [zero page RMW]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_ROL, Uop.ZP_RMW_Stage5, Uop.End }, + /*RLA* zp [zero page RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_RLA, Uop.ZP_RMW_Stage5, Uop.End }, + /*PLP [implied] */ new Uop[] { Uop.FetchDummy, Uop.IncS, Uop.PullP_NoInc, Uop.End_ISpecial }, + /*AND #nn [immediate]*/ new Uop[] { Uop.Imm_AND, Uop.End }, + /*ROL A [accumulator]*/ new Uop[] { Uop.Imp_ROL_A, Uop.End }, + /*ANC** [immediate] [unofficial]*/ new Uop[] { Uop.Imm_ANC, Uop.End }, + /*BIT addr [absolute]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_BIT, Uop.End }, + /*AND addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_AND, Uop.End }, + /*ROL addr [absolute RMW]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_ROL, Uop.Abs_RMW_Stage6, Uop.End }, + /*RLA* addr [absolute RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_RLA, Uop.Abs_RMW_Stage6, Uop.End }, + //0x30 + /*BMI +/-rel [relative]*/ new Uop[] { Uop.RelBranch_Stage2_BMI, Uop.End }, + /*AND (addr),Y* [indirect indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_READ_Stage5, Uop.IndIdx_READ_Stage6_AND, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*RLA* (addr),Y* [indirect indexed RMW] [unofficial] */ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_RMW_Stage5, Uop.IndIdx_RMW_Stage6, Uop.IndIdx_RMW_Stage7_RLA, Uop.IndIdx_RMW_Stage8, Uop.End }, + /*NOP zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_NOP, Uop.End }, + /*AND zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_AND, Uop.End }, + /*ROL zp,X [zero page indexed RMW]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_ROL, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*RLA* zp,X [zero page indexed RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_RLA, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*SEC [implied]*/ new Uop[] { Uop.Imp_SEC, Uop.End }, + /*AND addr,Y* [absolute indexed READ Y]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_AND, Uop.End }, + /*NOP 3A [implied]*/ new Uop[] { Uop.FetchDummy, Uop.End }, + /*RLA* addr,Y [absolute indexed RMW Y] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_RLA, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*NOP addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_NOP, Uop.End }, + /*AND addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_AND, Uop.End }, + /*ROL addr,X [absolute indexed RMW X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_ROL, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*RLA* addr,X [absolute indexed RMW X] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_RLA, Uop.AbsIdx_RMW_Stage7, Uop.End }, + //0x40 + /*RTI*/ new Uop[] { Uop.FetchDummy, Uop.IncS, Uop.PullP, Uop.PullPCL, Uop.PullPCH_NoInc, Uop.End }, + /*EOR (addr,X) [indexed indirect READ]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_READ_EOR, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*SRE* (addr,X) [indexed indirect RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_RMW, Uop.IdxInd_Stage7_RMW_SRE, Uop.IdxInd_Stage8_RMW, Uop.End }, + /*NOP zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_NOP, Uop.End }, + /*EOR zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_EOR, Uop.End }, + /*LSR zp [zero page RMW]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_LSR, Uop.ZP_RMW_Stage5, Uop.End }, + /*SRE* zp [zero page RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_SRE, Uop.ZP_RMW_Stage5, Uop.End }, + /*PHA [implied]*/ new Uop[] { Uop.FetchDummy, Uop.PushA, Uop.End }, + /*EOR #nn [immediate]*/ new Uop[] { Uop.Imm_EOR, Uop.End }, + /*LSR A [accumulator]*/ new Uop[] { Uop.Imp_LSR_A, Uop.End }, + /*ASR** [immediate] [unofficial]*/ new Uop[] { Uop.Imm_ASR, Uop.End }, + /*JMP addr [absolute]*/ new Uop[] { Uop.Fetch2, Uop.JMP_abs, Uop.End }, + /*EOR addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_EOR, Uop.End }, + /*LSR addr [absolute RMW]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_LSR, Uop.Abs_RMW_Stage6, Uop.End }, + /*SRE* addr [absolute RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_SRE, Uop.Abs_RMW_Stage6, Uop.End }, + //0x50 + /*BVC +/-rel [relative]*/ new Uop[] { Uop.RelBranch_Stage2_BVC, Uop.End }, + /*EOR (addr),Y* [indirect indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_READ_Stage5, Uop.IndIdx_READ_Stage6_EOR, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*SRE* (addr),Y* [indirect indexed RMW] [unofficial] */ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_RMW_Stage5, Uop.IndIdx_RMW_Stage6, Uop.IndIdx_RMW_Stage7_SRE, Uop.IndIdx_RMW_Stage8, Uop.End }, + /*NOP zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_NOP, Uop.End }, + /*EOR zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_EOR, Uop.End }, + /*LSR zp,X [zero page indexed RMW]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_LSR, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*SRE* zp,X [zero page indexed RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_SRE, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*CLI [implied]*/ new Uop[] { Uop.Imp_CLI, Uop.End_ISpecial }, + /*EOR addr,Y* [absolute indexed READ Y]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_EOR, Uop.End }, + /*NOP 5A [implied]*/ new Uop[] { Uop.FetchDummy, Uop.End }, + /*SRE* addr,Y [absolute indexed RMW Y] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_SRE, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*NOP addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_NOP, Uop.End }, + /*EOR addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_EOR, Uop.End }, + /*LSR addr,X [absolute indexed RMW X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_LSR, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*SRE* addr,X [absolute indexed RMW X] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_SRE, Uop.AbsIdx_RMW_Stage7, Uop.End }, + //0x60 + /*RTS*/ new Uop[] { Uop.FetchDummy, Uop.IncS, Uop.PullPCL, Uop.PullPCH_NoInc, Uop.IncPC, Uop.End }, //can't fetch here because the PC isnt ready until the end of the last clock + /*ADC (addr,X) [indexed indirect READ]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_READ_ADC, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*RRA* (addr,X) [indexed indirect RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_RMW, Uop.IdxInd_Stage7_RMW_RRA, Uop.IdxInd_Stage8_RMW, Uop.End }, + /*NOP zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_NOP, Uop.End }, + /*ADC zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_ADC, Uop.End }, + /*ROR zp [zero page RMW]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_ROR, Uop.ZP_RMW_Stage5, Uop.End }, + /*RRA* zp [zero page RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_RRA, Uop.ZP_RMW_Stage5, Uop.End }, + /*PLA [implied]*/ new Uop[] { Uop.FetchDummy, Uop.IncS, Uop.PullA_NoInc, Uop.End }, + /*ADC #nn [immediate]*/ new Uop[] { Uop.Imm_ADC, Uop.End }, + /*ROR A [accumulator]*/ new Uop[] { Uop.Imp_ROR_A, Uop.End }, + /*ARR** [immediate] [unofficial]*/ new Uop[] { Uop.Imm_ARR, Uop.End }, + /*JMP (addr) [absolute indirect JMP]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.AbsInd_JMP_Stage4, Uop.AbsInd_JMP_Stage5, Uop.End }, + /*ADC addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_ADC, Uop.End }, + /*ROR addr [absolute RMW]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_ROR, Uop.Abs_RMW_Stage6, Uop.End }, + /*RRA* addr [absolute RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_RRA, Uop.Abs_RMW_Stage6, Uop.End }, + //0x70 + /*BVS +/-rel [relative]*/ new Uop[] { Uop.RelBranch_Stage2_BVS, Uop.End }, + /*ADC (addr),Y [indirect indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_READ_Stage5, Uop.IndIdx_READ_Stage6_ADC, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*RRA* (addr),Y [indirect indexed RMW Y] [unofficial] */ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_RMW_Stage5, Uop.IndIdx_RMW_Stage6, Uop.IndIdx_RMW_Stage7_RRA, Uop.IndIdx_RMW_Stage8, Uop.End }, + /*NOP zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_NOP, Uop.End }, + /*ADC zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_ADC, Uop.End }, + /*ROR zp,X [zero page indexed RMW]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_ROR, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*RRA* zp,X [zero page indexed RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_RRA, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*SEI [implied]*/ new Uop[] { Uop.Imp_SEI, Uop.End_ISpecial }, + /*ADC addr,Y* [absolute indexed READ Y]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_ADC, Uop.End }, + /*NOP 7A [implied]*/ new Uop[] { Uop.FetchDummy, Uop.End }, + /*RRA* addr,Y [absolute indexed RMW Y] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_RRA, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*NOP addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_NOP, Uop.End }, + /*ADC addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_ADC, Uop.End }, + /*ROR addr,X [absolute indexed RMW X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_ROR, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*RRA* addr,X [absolute indexed RMW X] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_RRA, Uop.AbsIdx_RMW_Stage7, Uop.End }, + //0x80 + /*NOP #nn [immediate]*/ new Uop[] { Uop.Imm_Unsupported, Uop.End }, + /*STA (addr,X) [indexed indirect WRITE]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_WRITE_STA, Uop.End }, + /*NOP #nn [immediate]*/ new Uop[] { Uop.Imm_Unsupported, Uop.End }, //jams very rarely + /*SAX* (addr,X) [indexed indirect WRITE] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_WRITE_SAX, Uop.End }, + /*STY zp [zero page WRITE]*/ new Uop[] { Uop.Fetch2, Uop.ZP_WRITE_STY, Uop.End }, + /*STA zp [zero page WRITE]*/ new Uop[] { Uop.Fetch2, Uop.ZP_WRITE_STA, Uop.End }, + /*STX zp [zero page WRITE]*/ new Uop[] { Uop.Fetch2, Uop.ZP_WRITE_STX, Uop.End }, + /*SAX* zp [zero page WRITE] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZP_WRITE_SAX, Uop.End }, + /*DEY [implied]*/ new Uop[] { Uop.Imp_DEY, Uop.End }, + /*NOP #nn [immediate]*/ new Uop[] { Uop.Imm_Unsupported, Uop.End }, + /*TXA [implied]*/ new Uop[] { Uop.Imp_TXA, Uop.End }, + /*ANE** [immediate] [unofficial]*/ new Uop[] { Uop.Imm_Unsupported, Uop.End }, + /*STY addr [absolute WRITE]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_WRITE_STY, Uop.End }, + /*STA addr [absolute WRITE]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_WRITE_STA, Uop.End }, + /*STX addr [absolute WRITE]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_WRITE_STX, Uop.End }, + /*SAX* addr [absolute WRITE] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_WRITE_SAX, Uop.End }, + //0x90 + /*BCC +/-rel [relative]*/ new Uop[] { Uop.RelBranch_Stage2_BCC, Uop.End }, + /*STA (addr),Y [indirect indexed WRITE]*/ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_WRITE_Stage5, Uop.IndIdx_WRITE_Stage6_STA, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*SHA** [indirect indexed WRITE] [unofficial] [not tested by blargg's instruction tests]*/ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_WRITE_Stage5, Uop.IndIdx_WRITE_Stage6_SHA, Uop.End }, + /*STY zp,X [zero page indexed WRITE X]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_WRITE_STY, Uop.End }, + /*STA zp,X [zero page indexed WRITE X]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_WRITE_STA, Uop.End }, + /*STX zp,Y [zero page indexed WRITE Y]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_Y, Uop.ZP_WRITE_STX, Uop.End }, + /*SAX* zp,Y [zero page indexed WRITE Y] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_Y, Uop.ZP_WRITE_SAX, Uop.End }, + /*TYA [implied]*/ new Uop[] { Uop.Imp_TYA, Uop.End }, + /*STA addr,Y [absolute indexed WRITE]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_WRITE_Stage5_STA, Uop.End }, + /*TXS [implied]*/ new Uop[] { Uop.Imp_TXS, Uop.End }, + /*SHS* addr,X [absolute indexed WRITE X] [unofficial] [NOT IMPLEMENTED - TRICKY, AND NO TEST]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_WRITE_Stage5_ERROR, Uop.End }, + /*SHY** [absolute indexed WRITE] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_WRITE_Stage5_SHY, Uop.End }, + /*STA addr,X [absolute indexed WRITE]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_WRITE_Stage5_STA, Uop.End }, + /*SHX* addr,Y [absolute indexed WRITE Y] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_WRITE_Stage5_SHX, Uop.End }, + /*SHA* addr,Y [absolute indexed WRITE Y] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_WRITE_Stage5_SHY, Uop.End }, + //0xA0 + /*LDY #nn [immediate]*/ new Uop[] { Uop.Imm_LDY, Uop.End }, + /*LDA (addr,X) [indexed indirect READ]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_READ_LDA, Uop.End }, + /*LDX #nn [immediate]*/ new Uop[] { Uop.Imm_LDX, Uop.End }, + /*LAX* (addr,X) [indexed indirect READ] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_READ_LAX, Uop.End }, + /*LDY zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_LDY, Uop.End }, + /*LDA zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_LDA, Uop.End }, + /*LDX zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_LDX, Uop.End }, + /*LAX* zp [zero page READ] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_LAX, Uop.End }, + /*TAY [implied]*/ new Uop[] { Uop.Imp_TAY, Uop.End }, + /*LDA #nn [immediate]*/ new Uop[] { Uop.Imm_LDA, Uop.End }, + /*TAX [implied]*/ new Uop[] { Uop.Imp_TAX, Uop.End }, + /*LXA** (ATX) [immediate] [unofficial]*/ new Uop[] { Uop.Imm_LXA, Uop.End }, + /*LDY addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_LDY, Uop.End }, + /*LDA addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_LDA, Uop.End }, + /*LDX addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_LDX, Uop.End }, + /*LAX* addr [absolute READ] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_LAX, Uop.End }, + //0xB0 + /*BCS +/-rel [relative]*/ new Uop[] { Uop.RelBranch_Stage2_BCS, Uop.End }, + /*LDA (addr),Y* [indirect indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_READ_Stage5, Uop.IndIdx_READ_Stage6_LDA, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*LAX* (addr),Y* [indirect indexed READ] [unofficial] */ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_READ_Stage5, Uop.IndIdx_READ_Stage6_LAX, Uop.End }, + /*LDY zp,X [zero page indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_LDY, Uop.End }, + /*LDA zp,X [zero page indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_LDA, Uop.End }, + /*LDX zp,Y [zero page indexed READ Y]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_Y, Uop.ZP_READ_LDX, Uop.End }, + /*LAX* zp,Y [zero page indexed READ] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_Y, Uop.ZP_READ_LAX, Uop.End }, + /*CLV [implied]*/ new Uop[] { Uop.Imp_CLV, Uop.End }, + /*LDA addr,Y* [absolute indexed READ Y]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_LDA, Uop.End }, + /*TSX [implied]*/ new Uop[] { Uop.Imp_TSX, Uop.End }, + /*LAS* addr,X [absolute indexed READ X] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_ERROR, Uop.End }, + /*LDY addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_LDY, Uop.End }, + /*LDA addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_LDA, Uop.End }, + /*LDX addr,Y* [absolute indexed READ Y]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_LDX, Uop.End }, + /*LAX* addr,Y [absolute indexed READ Y] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_LAX, Uop.End }, + //0xC0 + /*CPY #nn [immediate]*/ new Uop[] { Uop.Imm_CPY, Uop.End }, + /*CMP (addr,X) [indexed indirect READ]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_READ_CMP, Uop.End }, + /*NOP #nn [immediate]*/ new Uop[] { Uop.Imm_Unsupported, Uop.End }, //jams very rarely + /*DCP* (addr,X) [indexed indirect RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_RMW, Uop.IdxInd_Stage7_RMW_DCP, Uop.IdxInd_Stage8_RMW, Uop.End }, + /*CPY zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_CPY, Uop.End }, + /*CMP zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_CMP, Uop.End }, + /*DEC zp [zero page RMW]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_DEC, Uop.ZP_RMW_Stage5, Uop.End }, + /*DCP* zp [zero page RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_DCP, Uop.ZP_RMW_Stage5, Uop.End }, + /*INY [implied]*/ new Uop[] { Uop.Imp_INY, Uop.End }, + /*CMP #nn [immediate]*/ new Uop[] { Uop.Imm_CMP, Uop.End }, + /*DEX [implied]*/ new Uop[] { Uop.Imp_DEX, Uop.End }, + /*AXS** [immediate] [unofficial]*/ new Uop[] { Uop.Imm_AXS, Uop.End }, + /*CPY addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_CPY, Uop.End }, + /*CMP addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_CMP, Uop.End }, + /*DEC addr [absolute RMW]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_DEC, Uop.Abs_RMW_Stage6, Uop.End }, + /*DCP* addr [absolute RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_DCP, Uop.Abs_RMW_Stage6, Uop.End }, + //0xD0 + /*BNE +/-rel [relative]*/ new Uop[] { Uop.RelBranch_Stage2_BNE, Uop.End }, + /*CMP (addr),Y* [indirect indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_READ_Stage5, Uop.IndIdx_READ_Stage6_CMP, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*DCP* (addr),Y* [indirect indexed RMW Y] [unofficial] */ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_RMW_Stage5, Uop.IndIdx_RMW_Stage6, Uop.IndIdx_RMW_Stage7_DCP, Uop.IndIdx_RMW_Stage8, Uop.End }, + /*NOP zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_NOP, Uop.End }, + /*CMP zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_CMP, Uop.End }, + /*DEC zp,X [zero page indexed RMW X]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_DEC, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*DCP* zp,X [zero page indexed RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_DCP, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*CLD [implied]*/ new Uop[] { Uop.Imp_CLD, Uop.End }, + /*CMP addr,Y* [absolute indexed READ Y]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_CMP, Uop.End }, + /*NOP DA [implied]*/ new Uop[] { Uop.FetchDummy, Uop.End }, + /*DCP* addr,Y [absolute indexed RMW Y] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_DCP, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*NOP addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_NOP, Uop.End }, + /*CMP addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_CMP, Uop.End }, + /*DEC addr,X [absolute indexed RMW X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_DEC, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*DCP* addr,X [absolute indexed RMW X] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_DCP, Uop.AbsIdx_RMW_Stage7, Uop.End }, + //0xE0 + /*CPX #nn [immediate]*/ new Uop[] { Uop.Imm_CPX, Uop.End }, + /*SBC (addr,X) [indirect indexed]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_READ_SBC, Uop.End }, + /*NOP #nn [immediate]*/ new Uop[] { Uop.Imm_Unsupported, Uop.End }, //jams very rarely + /*ISC* (addr,X) [indexed indirect RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.IdxInd_Stage3, Uop.IdxInd_Stage4, Uop.IdxInd_Stage5, Uop.IdxInd_Stage6_RMW, Uop.IdxInd_Stage7_RMW_ISC, Uop.IdxInd_Stage8_RMW, Uop.End }, + /*CPX zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_CPX, Uop.End }, + /*SBC zp [zero page READ]*/ new Uop[] { Uop.Fetch2, Uop.ZP_READ_SBC, Uop.End }, + /*INC zp [zero page RMW]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_INC, Uop.ZP_RMW_Stage5, Uop.End }, + /*ISB* zp [zero page RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZP_RMW_Stage3, Uop.ZP_RMW_ISC, Uop.ZP_RMW_Stage5, Uop.End }, + /*INX [implied]*/ new Uop[] { Uop.Imp_INX, Uop.End }, + /*SBC #nn [immediate READ]*/ new Uop[] { Uop.Imm_SBC, Uop.End }, + /*NOP EA [implied]*/ new Uop[] { Uop.FetchDummy, Uop.End }, //nothing happened here.. but the last thing to happen was a fetch, so we can't pipeline the next fetch + /*ISB #nn [immediate READ]*/ new Uop[] { Uop.Imm_SBC, Uop.End }, + /*CPX addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_CPX, Uop.End }, + /*SBC addr [absolute READ]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_READ_SBC, Uop.End }, + /*INC addr [absolute RMW]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_INC, Uop.Abs_RMW_Stage6, Uop.End }, + /*ISC* addr [absolute RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.Fetch3, Uop.Abs_RMW_Stage4, Uop.Abs_RMW_Stage5_ISC, Uop.Abs_RMW_Stage6, Uop.End }, + //0xF0 + /*BEQ +/-rel [relative]*/ new Uop[] { Uop.RelBranch_Stage2_BEQ, Uop.End }, + /*SBC (addr),Y* [indirect indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_READ_Stage5, Uop.IndIdx_READ_Stage6_SBC, Uop.End }, + /*JAM*/ new Uop[] { Uop.End }, + /*ISC* (addr),Y* [indirect indexed RMW Y] [unofficial] */ new Uop[] { Uop.Fetch2, Uop.IndIdx_Stage3, Uop.IndIdx_Stage4, Uop.IndIdx_RMW_Stage5, Uop.IndIdx_RMW_Stage6, Uop.IndIdx_RMW_Stage7_ISC, Uop.IndIdx_RMW_Stage8, Uop.End }, + /*NOP zp,X [zero page indexed READ]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_NOP, Uop.End }, + /*SBC zp,X [zero page indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZP_READ_SBC, Uop.End }, + /*INC zp,X [zero page indexed RMW X]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_INC, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*ISC* zp,X [zero page indexed RMW] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.ZpIdx_Stage3_X, Uop.ZpIdx_RMW_Stage4, Uop.ZP_RMW_ISC, Uop.ZpIdx_RMW_Stage6, Uop.End }, + /*SED [implied]*/ new Uop[] { Uop.Imp_SED, Uop.End }, + /*SBC addr,Y* [absolute indexed READ Y]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_SBC, Uop.End }, + /*NOP FA [implied]*/ new Uop[] { Uop.FetchDummy, Uop.End }, + /*ISC* addr,Y [absolute indexed RMW Y] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_ISC, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*NOP addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_NOP, Uop.End }, + /*SBC addr,X* [absolute indexed READ X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_READ_Stage4, Uop.AbsIdx_READ_Stage5_SBC, Uop.End }, + /*INC addr,X [absolute indexed RMW X]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_INC, Uop.AbsIdx_RMW_Stage7, Uop.End }, + /*ISC* addr,X [absolute indexed RMW X] [unofficial]*/ new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_X, Uop.AbsIdx_Stage4, Uop.AbsIdx_RMW_Stage5, Uop.AbsIdx_RMW_Stage6_ISC, Uop.AbsIdx_RMW_Stage7, Uop.End }, + //0x100 + /*VOP_Fetch1*/ new Uop[] { Uop.Fetch1 }, + /*VOP_RelativeStuff*/ new Uop[] { Uop.RelBranch_Stage3, Uop.End_BranchSpecial }, + /*VOP_RelativeStuff2*/ new Uop[] { Uop.RelBranch_Stage4, Uop.End }, + /*VOP_RelativeStuff2*/ new Uop[] { Uop.End_SuppressInterrupt }, + //i assume these are dummy fetches.... maybe theyre just nops? supposedly these take 7 cycles so thats the only way i can make sense of it + //one of them might be the next instruction's fetch, and whatever fetch follows it. + //the interrupt would then take place if necessary, using a cached PC. but im not so sure about that. + /*VOP_NMI*/ new Uop[] { Uop.FetchDummy, Uop.FetchDummy, Uop.PushPCH, Uop.PushPCL, Uop.PushP_NMI, Uop.FetchPCLVector, Uop.FetchPCHVector, Uop.End_SuppressInterrupt }, + /*VOP_IRQ*/ new Uop[] { Uop.FetchDummy, Uop.FetchDummy, Uop.PushPCH, Uop.PushPCL, Uop.PushP_IRQ, Uop.FetchPCLVector, Uop.FetchPCHVector, Uop.End_SuppressInterrupt }, + /*VOP_RESET*/ new Uop[] { Uop.FetchDummy, Uop.FetchDummy, Uop.PushDummy, Uop.PushDummy, Uop.PushP_Reset, Uop.FetchPCLVector, Uop.FetchPCHVector, Uop.End_SuppressInterrupt }, + /*VOP_Fetch1_NoInterrupt*/ new Uop[] { Uop.Fetch1_Real }, + }; + + + static MOS6502X() + { + using (System.IO.StreamWriter sw = new System.IO.StreamWriter("UopEnum.h")) + { + sw.WriteLine("// AUTOGENERATED"); + sw.WriteLine("#ifndef UOPENUM_H"); + sw.WriteLine("#define UOPENUM_H"); + sw.WriteLine("enum Uop {"); + foreach (var v in Enum.GetValues(typeof(Uop))) + { + //sw.WriteLine("#define Uop_{0} {1}", (Uop)v, (int)v); + sw.WriteLine("\tUop_{0}, ", (Uop)v); + } + sw.WriteLine("};"); + sw.WriteLine("#endif // UOPENUM_H"); + } + using (System.IO.StreamWriter sw = new System.IO.StreamWriter("UopTable.cpp")) + { + sw.WriteLine("// AUTOGENERATED"); + sw.WriteLine("#include \"UopEnum.h\""); + + int max = 0; + foreach (var a in Microcode) + if (a.Length > max) + max = a.Length; + + sw.WriteLine("const Uop Microcode[{0}][{1}] = {{", Microcode.Length, max); + for (int i = 0; i < Microcode.Length; i++) + { + sw.Write("\t{"); + for (int j = 0; j < Microcode[i].Length; j++) + { + sw.Write("Uop_{0}", Microcode[i][j]); + if (j < Microcode[i].Length - 1) + sw.Write(", "); + } + sw.WriteLine("},"); + } + sw.WriteLine("};"); + } + } + + + enum Uop + { + //sometimes i used this as a marker for unsupported instructions, but it is very inconsistent + Unsupported, + + Fetch1, Fetch1_Real, Fetch2, Fetch3, + //used by instructions with no second opcode byte (6502 fetches a byte anyway but won't increment PC for these) + FetchDummy, + + NOP, + + JSR, + IncPC, //from RTS + + //[absolute WRITE] + Abs_WRITE_STA, Abs_WRITE_STX, Abs_WRITE_STY, + Abs_WRITE_SAX, //unofficials + //[absolute READ] + Abs_READ_BIT, Abs_READ_LDA, Abs_READ_LDY, Abs_READ_ORA, Abs_READ_LDX, Abs_READ_CMP, Abs_READ_ADC, Abs_READ_CPX, Abs_READ_SBC, Abs_READ_AND, Abs_READ_EOR, Abs_READ_CPY, Abs_READ_NOP, + Abs_READ_LAX, //unofficials + //[absolute RMW] + Abs_RMW_Stage4, Abs_RMW_Stage6, + Abs_RMW_Stage5_INC, Abs_RMW_Stage5_DEC, Abs_RMW_Stage5_LSR, Abs_RMW_Stage5_ROL, Abs_RMW_Stage5_ASL, Abs_RMW_Stage5_ROR, + Abs_RMW_Stage5_SLO, Abs_RMW_Stage5_RLA, Abs_RMW_Stage5_SRE, Abs_RMW_Stage5_RRA, Abs_RMW_Stage5_DCP, Abs_RMW_Stage5_ISC, //unofficials + + //[absolute JUMP] + JMP_abs, + + //[zero page misc] + ZpIdx_Stage3_X, ZpIdx_Stage3_Y, + ZpIdx_RMW_Stage4, ZpIdx_RMW_Stage6, + //[zero page WRITE] + ZP_WRITE_STA, ZP_WRITE_STX, ZP_WRITE_STY, ZP_WRITE_SAX, + //[zero page RMW] + ZP_RMW_Stage3, ZP_RMW_Stage5, + ZP_RMW_DEC, ZP_RMW_INC, ZP_RMW_ASL, ZP_RMW_LSR, ZP_RMW_ROR, ZP_RMW_ROL, + ZP_RMW_SLO, ZP_RMW_RLA, ZP_RMW_SRE, ZP_RMW_RRA, ZP_RMW_DCP, ZP_RMW_ISC, + //[zero page READ] + ZP_READ_EOR, ZP_READ_BIT, ZP_READ_ORA, ZP_READ_LDA, ZP_READ_LDY, ZP_READ_LDX, ZP_READ_CPX, ZP_READ_SBC, ZP_READ_CPY, ZP_READ_NOP, ZP_READ_ADC, ZP_READ_AND, ZP_READ_CMP, ZP_READ_LAX, + + //[indexed indirect READ] (addr,X) + //[indexed indirect WRITE] (addr,X) + IdxInd_Stage3, IdxInd_Stage4, IdxInd_Stage5, + IdxInd_Stage6_READ_ORA, IdxInd_Stage6_READ_SBC, IdxInd_Stage6_READ_LDA, IdxInd_Stage6_READ_EOR, IdxInd_Stage6_READ_CMP, IdxInd_Stage6_READ_ADC, IdxInd_Stage6_READ_AND, + IdxInd_Stage6_READ_LAX, + IdxInd_Stage6_WRITE_STA, IdxInd_Stage6_WRITE_SAX, + IdxInd_Stage6_RMW, //work happens in stage 7 + IdxInd_Stage7_RMW_SLO, IdxInd_Stage7_RMW_RLA, IdxInd_Stage7_RMW_SRE, IdxInd_Stage7_RMW_RRA, IdxInd_Stage7_RMW_ISC, IdxInd_Stage7_RMW_DCP, //unofficials + IdxInd_Stage8_RMW, + + //[absolute indexed] + AbsIdx_Stage3_X, AbsIdx_Stage3_Y, AbsIdx_Stage4, + //[absolute indexed WRITE] + AbsIdx_WRITE_Stage5_STA, + AbsIdx_WRITE_Stage5_SHY, AbsIdx_WRITE_Stage5_SHX, //unofficials + AbsIdx_WRITE_Stage5_ERROR, + //[absolute indexed READ] + AbsIdx_READ_Stage4, + AbsIdx_READ_Stage5_LDA, AbsIdx_READ_Stage5_CMP, AbsIdx_READ_Stage5_SBC, AbsIdx_READ_Stage5_ADC, AbsIdx_READ_Stage5_EOR, AbsIdx_READ_Stage5_LDX, AbsIdx_READ_Stage5_AND, AbsIdx_READ_Stage5_ORA, AbsIdx_READ_Stage5_LDY, AbsIdx_READ_Stage5_NOP, + AbsIdx_READ_Stage5_LAX, //unofficials + AbsIdx_READ_Stage5_ERROR, + //[absolute indexed RMW] + AbsIdx_RMW_Stage5, AbsIdx_RMW_Stage7, + AbsIdx_RMW_Stage6_ROR, AbsIdx_RMW_Stage6_DEC, AbsIdx_RMW_Stage6_INC, AbsIdx_RMW_Stage6_ASL, AbsIdx_RMW_Stage6_LSR, AbsIdx_RMW_Stage6_ROL, + AbsIdx_RMW_Stage6_SLO, AbsIdx_RMW_Stage6_RLA, AbsIdx_RMW_Stage6_SRE, AbsIdx_RMW_Stage6_RRA, AbsIdx_RMW_Stage6_DCP, AbsIdx_RMW_Stage6_ISC, //unofficials + + IncS, DecS, + PushPCL, PushPCH, PushP, PullP, PullPCL, PullPCH_NoInc, PushA, PullA_NoInc, PullP_NoInc, + PushP_BRK, PushP_NMI, PushP_IRQ, PushP_Reset, PushDummy, + FetchPCLVector, FetchPCHVector, //todo - may not need these ?? can reuse fetch2 and fetch3? + + //[implied] and [accumulator] + Imp_ASL_A, Imp_ROL_A, Imp_ROR_A, Imp_LSR_A, + Imp_SEC, Imp_CLI, Imp_SEI, Imp_CLD, Imp_CLC, Imp_CLV, Imp_SED, + Imp_INY, Imp_DEY, Imp_INX, Imp_DEX, + Imp_TSX, Imp_TXS, Imp_TAX, Imp_TAY, Imp_TYA, Imp_TXA, + + //[immediate] + Imm_CMP, Imm_ADC, Imm_AND, Imm_SBC, Imm_ORA, Imm_EOR, Imm_CPY, Imm_CPX, Imm_ANC, Imm_ASR, Imm_ARR, Imm_LXA, Imm_AXS, + Imm_LDA, Imm_LDX, Imm_LDY, + Imm_Unsupported, + + //sub-ops + NZ_X, NZ_Y, NZ_A, + RelBranch_Stage2_BNE, RelBranch_Stage2_BPL, RelBranch_Stage2_BCC, RelBranch_Stage2_BCS, RelBranch_Stage2_BEQ, RelBranch_Stage2_BMI, RelBranch_Stage2_BVC, RelBranch_Stage2_BVS, + RelBranch_Stage2, RelBranch_Stage3, RelBranch_Stage4, + _Eor, _Bit, _Cpx, _Cpy, _Cmp, _Adc, _Sbc, _Ora, _And, _Anc, _Asr, _Arr, _Lxa, _Axs, //alu-related sub-ops + + //JMP (addr) 0x6C + AbsInd_JMP_Stage4, AbsInd_JMP_Stage5, + + //[indirect indexed] (i.e. LDA (addr),Y ) + IndIdx_Stage3, IndIdx_Stage4, IndIdx_READ_Stage5, IndIdx_WRITE_Stage5, + IndIdx_WRITE_Stage6_STA, IndIdx_WRITE_Stage6_SHA, + IndIdx_READ_Stage6_LDA, IndIdx_READ_Stage6_CMP, IndIdx_READ_Stage6_ORA, IndIdx_READ_Stage6_SBC, IndIdx_READ_Stage6_ADC, IndIdx_READ_Stage6_AND, IndIdx_READ_Stage6_EOR, + IndIdx_READ_Stage6_LAX, + IndIdx_RMW_Stage5, + IndIdx_RMW_Stage6, //just reads from effective address + IndIdx_RMW_Stage7_SLO, IndIdx_RMW_Stage7_RLA, IndIdx_RMW_Stage7_SRE, IndIdx_RMW_Stage7_RRA, IndIdx_RMW_Stage7_ISC, IndIdx_RMW_Stage7_DCP, //unofficials + IndIdx_RMW_Stage8, + + End, + End_ISpecial, //same as end, but preserves the iflag set by the instruction + End_BranchSpecial, + End_SuppressInterrupt, + } + + void InitOpcodeHandlers() + { + //delegates arent faster than the switch. pretty sure. dont use it. + //opcodeHandlers = new Action[] { + // Unsupported,Fetch1, Fetch1_Real, Fetch2, Fetch3,FetchDummy, + // NOP,JSR,IncPC, + // Abs_WRITE_STA, Abs_WRITE_STX, Abs_WRITE_STY,Abs_WRITE_SAX,Abs_READ_BIT, Abs_READ_LDA, Abs_READ_LDY, Abs_READ_ORA, Abs_READ_LDX, Abs_READ_CMP, Abs_READ_ADC, Abs_READ_CPX, Abs_READ_SBC, Abs_READ_AND, Abs_READ_EOR, Abs_READ_CPY, Abs_READ_NOP, + // Abs_READ_LAX,Abs_RMW_Stage4, Abs_RMW_Stage6,Abs_RMW_Stage5_INC, Abs_RMW_Stage5_DEC, Abs_RMW_Stage5_LSR, Abs_RMW_Stage5_ROL, Abs_RMW_Stage5_ASL, Abs_RMW_Stage5_ROR,Abs_RMW_Stage5_SLO, Abs_RMW_Stage5_RLA, Abs_RMW_Stage5_SRE, Abs_RMW_Stage5_RRA, Abs_RMW_Stage5_DCP, Abs_RMW_Stage5_ISC, + // JMP_abs,ZpIdx_Stage3_X, ZpIdx_Stage3_Y,ZpIdx_RMW_Stage4, ZpIdx_RMW_Stage6,ZP_WRITE_STA, ZP_WRITE_STX, ZP_WRITE_STY, ZP_WRITE_SAX,ZP_RMW_Stage3, ZP_RMW_Stage5, + // ZP_RMW_DEC, ZP_RMW_INC, ZP_RMW_ASL, ZP_RMW_LSR, ZP_RMW_ROR, ZP_RMW_ROL,ZP_RMW_SLO, ZP_RMW_RLA, ZP_RMW_SRE, ZP_RMW_RRA, ZP_RMW_DCP, ZP_RMW_ISC, + // ZP_READ_EOR, ZP_READ_BIT, ZP_READ_ORA, ZP_READ_LDA, ZP_READ_LDY, ZP_READ_LDX, ZP_READ_CPX, ZP_READ_SBC, ZP_READ_CPY, ZP_READ_NOP, ZP_READ_ADC, ZP_READ_AND, ZP_READ_CMP, ZP_READ_LAX, + // IdxInd_Stage3, IdxInd_Stage4, IdxInd_Stage5,IdxInd_Stage6_READ_ORA, IdxInd_Stage6_READ_SBC, IdxInd_Stage6_READ_LDA, IdxInd_Stage6_READ_EOR, IdxInd_Stage6_READ_CMP, IdxInd_Stage6_READ_ADC, IdxInd_Stage6_READ_AND, + // IdxInd_Stage6_READ_LAX,IdxInd_Stage6_WRITE_STA, IdxInd_Stage6_WRITE_SAX,IdxInd_Stage6_RMW,IdxInd_Stage7_RMW_SLO, IdxInd_Stage7_RMW_RLA, IdxInd_Stage7_RMW_SRE, IdxInd_Stage7_RMW_RRA, IdxInd_Stage7_RMW_ISC, IdxInd_Stage7_RMW_DCP, + // IdxInd_Stage8_RMW,AbsIdx_Stage3_X, AbsIdx_Stage3_Y, AbsIdx_Stage4,AbsIdx_WRITE_Stage5_STA,AbsIdx_WRITE_Stage5_SHY, AbsIdx_WRITE_Stage5_SHX,AbsIdx_WRITE_Stage5_ERROR,AbsIdx_READ_Stage4, + // AbsIdx_READ_Stage5_LDA, AbsIdx_READ_Stage5_CMP, AbsIdx_READ_Stage5_SBC, AbsIdx_READ_Stage5_ADC, AbsIdx_READ_Stage5_EOR, AbsIdx_READ_Stage5_LDX, AbsIdx_READ_Stage5_AND, AbsIdx_READ_Stage5_ORA, AbsIdx_READ_Stage5_LDY, AbsIdx_READ_Stage5_NOP, + // AbsIdx_READ_Stage5_LAX,AbsIdx_READ_Stage5_ERROR,AbsIdx_RMW_Stage5, AbsIdx_RMW_Stage7,AbsIdx_RMW_Stage6_ROR, AbsIdx_RMW_Stage6_DEC, AbsIdx_RMW_Stage6_INC, AbsIdx_RMW_Stage6_ASL, AbsIdx_RMW_Stage6_LSR, AbsIdx_RMW_Stage6_ROL, + // AbsIdx_RMW_Stage6_SLO, AbsIdx_RMW_Stage6_RLA, AbsIdx_RMW_Stage6_SRE, AbsIdx_RMW_Stage6_RRA, AbsIdx_RMW_Stage6_DCP, AbsIdx_RMW_Stage6_ISC,IncS, DecS, + // PushPCL, PushPCH, PushP, PullP, PullPCL, PullPCH_NoInc, PushA, PullA_NoInc, PullP_NoInc,PushP_BRK, PushP_NMI, PushP_IRQ, PushP_Reset, PushDummy,FetchPCLVector, FetchPCHVector, + // Imp_ASL_A, Imp_ROL_A, Imp_ROR_A, Imp_LSR_A,Imp_SEC, Imp_CLI, Imp_SEI, Imp_CLD, Imp_CLC, Imp_CLV, Imp_SED,Imp_INY, Imp_DEY, Imp_INX, Imp_DEX,Imp_TSX, Imp_TXS, Imp_TAX, Imp_TAY, Imp_TYA, Imp_TXA, + // Imm_CMP, Imm_ADC, Imm_AND, Imm_SBC, Imm_ORA, Imm_EOR, Imm_CPY, Imm_CPX, Imm_ANC, Imm_ASR, Imm_ARR, Imm_LXA, Imm_AXS,Imm_LDA, Imm_LDX, Imm_LDY, + // Imm_Unsupported,NZ_X, NZ_Y, NZ_A,RelBranch_Stage2_BNE, RelBranch_Stage2_BPL, RelBranch_Stage2_BCC, RelBranch_Stage2_BCS, RelBranch_Stage2_BEQ, RelBranch_Stage2_BMI, RelBranch_Stage2_BVC, RelBranch_Stage2_BVS, + // RelBranch_Stage2, RelBranch_Stage3, RelBranch_Stage4,_Eor, _Bit, _Cpx, _Cpy, _Cmp, _Adc, _Sbc, _Ora, _And, _Anc, _Asr, _Arr, _Lxa, _Axs, + // AbsInd_JMP_Stage4, AbsInd_JMP_Stage5,IndIdx_Stage3, IndIdx_Stage4, IndIdx_READ_Stage5, IndIdx_WRITE_Stage5, + // IndIdx_WRITE_Stage6_STA, IndIdx_WRITE_Stage6_SHA,IndIdx_READ_Stage6_LDA, IndIdx_READ_Stage6_CMP, IndIdx_READ_Stage6_ORA, IndIdx_READ_Stage6_SBC, IndIdx_READ_Stage6_ADC, IndIdx_READ_Stage6_AND, IndIdx_READ_Stage6_EOR, + // IndIdx_READ_Stage6_LAX,IndIdx_RMW_Stage5,IndIdx_RMW_Stage6, IndIdx_RMW_Stage7_SLO, IndIdx_RMW_Stage7_RLA, IndIdx_RMW_Stage7_SRE, IndIdx_RMW_Stage7_RRA, IndIdx_RMW_Stage7_ISC, IndIdx_RMW_Stage7_DCP,IndIdx_RMW_Stage8, + // End,End_ISpecial,End_BranchSpecial,End_SuppressInterrupt, + //}; + } + + const int VOP_Fetch1 = 256; + const int VOP_RelativeStuff = 257; + const int VOP_RelativeStuff2 = 258; + const int VOP_RelativeStuff3 = 259; + const int VOP_NMI = 260; + const int VOP_IRQ = 261; + const int VOP_RESET = 262; + const int VOP_Fetch1_NoInterrupt = 263; + const int VOP_NUM = 264; + + bool Interrupted + { + get + { + return NMI || (IRQ && !FlagI); + } + } + + void FetchDummy() + { + DummyReadMemory(PC); + } + + public void Execute(int cycles) + { + for (int i = 0; i < cycles; i++) + { + ExecuteOne(); + } + } + + void Fetch1() + { + my_iflag = FlagI; + FlagI = iflag_pending; + if (!branch_irq_hack) + { + interrupt_pending = false; + if (NMI) + { + if (TraceCallback != null) + TraceCallback("====NMI===="); + ea = NMIVector; + opcode = VOP_NMI; + NMI = false; + mi = 0; + ExecuteOneRetry(); + return; + } + else if (IRQ && !my_iflag) + { + if (TraceCallback != null) + TraceCallback("====IRQ===="); + ea = IRQVector; + opcode = VOP_IRQ; + mi = 0; + ExecuteOneRetry(); + return; + } + } + Fetch1_Real(); + } + + void Fetch1_Real() + { + rdy_freeze = !RDY; + if (RDY) + { + if (debug) Console.WriteLine(State()); + branch_irq_hack = false; + if (OnExecFetch != null) OnExecFetch(PC); + if (TraceCallback != null) + TraceCallback(State()); + opcode = ReadMemory(PC++); + mi = -1; + } + } + void Fetch2() + { + rdy_freeze = !RDY; + if (RDY) + { + opcode2 = ReadMemory(PC++); + } + } + void Fetch3() + { + rdy_freeze = !RDY; + if (RDY) + { + opcode3 = ReadMemory(PC++); + } + } + void PushPCH() + { + WriteMemory((ushort)(S-- + 0x100), (byte)(PC >> 8)); + } + void PushPCL() + { + WriteMemory((ushort)(S-- + 0x100), (byte)PC); + } + void PushP_BRK() + { + FlagB = true; + WriteMemory((ushort)(S-- + 0x100), P); + FlagI = true; + ea = BRKVector; + + } + void PushP_IRQ() + { + FlagB = false; + WriteMemory((ushort)(S-- + 0x100), P); + FlagI = true; + ea = IRQVector; + + } + void PushP_NMI() + { + FlagB = false; + WriteMemory((ushort)(S-- + 0x100), P); + FlagI = true; //is this right? + ea = NMIVector; + + } + void PushP_Reset() + { + ea = ResetVector; + S--; + FlagI = true; + + } + void PushDummy() + { + S--; + + } + void FetchPCLVector() + { + rdy_freeze = !RDY; + if (RDY) + { + if (ea == BRKVector && FlagB && NMI) + { + NMI = false; + ea = NMIVector; + } + if (ea == IRQVector && !FlagB && NMI) + { + NMI = false; + ea = NMIVector; + } + alu_temp = ReadMemory((ushort)ea); + } + + } + void FetchPCHVector() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp += ReadMemory((ushort)(ea + 1)) << 8; + PC = (ushort)alu_temp; + } + + } + void Imp_INY() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); Y++; NZ_Y(); + } + } + void Imp_DEY() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); Y--; NZ_Y(); + } + } + void Imp_INX() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); X++; NZ_X(); + } + } + void Imp_DEX() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); X--; NZ_X(); + } + } + void NZ_A() + { + P = (byte)((P & 0x7D) | TableNZ[A]); + } + void NZ_X() + { + P = (byte)((P & 0x7D) | TableNZ[X]); + } + void NZ_Y() + { + P = (byte)((P & 0x7D) | TableNZ[Y]); + + } + void Imp_TSX() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); X = S; NZ_X(); + } + } + void Imp_TXS() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); S = X; + } + } + void Imp_TAX() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); X = A; NZ_X(); + } + } + void Imp_TAY() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); Y = A; NZ_Y(); + } + } + void Imp_TYA() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); A = Y; NZ_A(); + } + } + void Imp_TXA() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); A = X; NZ_A(); + } + + } + void Imp_SEI() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); iflag_pending = true; + } + } + void Imp_CLI() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); iflag_pending = false; + } + } + void Imp_SEC() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); FlagC = true; + } + } + void Imp_CLC() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); FlagC = false; + } + } + void Imp_SED() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); FlagD = true; + } + } + void Imp_CLD() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); FlagD = false; + } + } + void Imp_CLV() + { + rdy_freeze = !RDY; + if (RDY) + { + FetchDummy(); FlagV = false; + } + + } + void Abs_WRITE_STA() + { + WriteMemory((ushort)((opcode3 << 8) + opcode2), A); + } + void Abs_WRITE_STX() + { + WriteMemory((ushort)((opcode3 << 8) + opcode2), X); + } + void Abs_WRITE_STY() + { + WriteMemory((ushort)((opcode3 << 8) + opcode2), Y); + } + void Abs_WRITE_SAX() + { + WriteMemory((ushort)((opcode3 << 8) + opcode2), (byte)(X & A)); + + } + void ZP_WRITE_STA() + { + WriteMemory(opcode2, A); + } + void ZP_WRITE_STY() + { + WriteMemory(opcode2, Y); + } + void ZP_WRITE_STX() + { + WriteMemory(opcode2, X); + } + void ZP_WRITE_SAX() + { + WriteMemory(opcode2, (byte)(X & A)); + + } + void IndIdx_Stage3() + { + rdy_freeze = !RDY; + if (RDY) + { + ea = ReadMemory(opcode2); + } + + } + void IndIdx_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ea + Y; + ea = (ReadMemory((byte)(opcode2 + 1)) << 8) + | ((alu_temp & 0xFF)); + } + + } + void IndIdx_WRITE_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory((ushort)ea); + ea += (alu_temp >> 8) << 8; + } + + } + void IndIdx_READ_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + if (!alu_temp.Bit(8)) + { + mi++; + ExecuteOneRetry(); + return; + } + else + { + ReadMemory((ushort)ea); + ea = (ushort)(ea + 0x100); + } + } + } + void IndIdx_RMW_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + if (alu_temp.Bit(8)) + ea = (ushort)(ea + 0x100); + ReadMemory((ushort)ea); + } + + } + void IndIdx_WRITE_Stage6_STA() + { + WriteMemory((ushort)ea, A); + + } + void IndIdx_WRITE_Stage6_SHA() + { + WriteMemory((ushort)ea, (byte)(A & X & 7)); + + } + void IndIdx_READ_Stage6_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory((ushort)ea); + NZ_A(); + } + } + void IndIdx_READ_Stage6_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Cmp(); + } + } + void IndIdx_READ_Stage6_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _And(); + } + } + void IndIdx_READ_Stage6_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Eor(); + } + } + void IndIdx_READ_Stage6_LAX() + { + rdy_freeze = !RDY; + if (RDY) + { + A = X = ReadMemory((ushort)ea); + NZ_A(); + } + } + void IndIdx_READ_Stage6_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Adc(); + } + } + void IndIdx_READ_Stage6_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Sbc(); + } + } + void IndIdx_READ_Stage6_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Ora(); + } + } + void IndIdx_RMW_Stage6() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + } + + } + void IndIdx_RMW_Stage7_SLO() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)((value8 << 1)); + A |= value8; + NZ_A(); + } + void IndIdx_RMW_Stage7_SRE() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + A ^= value8; + NZ_A(); + } + void IndIdx_RMW_Stage7_RRA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); + FlagC = (temp8 & 1) != 0; + _Adc(); + } + void IndIdx_RMW_Stage7_ISC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 + 1); + _Sbc(); + } + void IndIdx_RMW_Stage7_DCP() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 - 1); + FlagC = (temp8 & 1) != 0; + _Cmp(); + } + void IndIdx_RMW_Stage7_RLA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + A &= value8; + NZ_A(); + } + void IndIdx_RMW_Stage8() + { + WriteMemory((ushort)ea, (byte)alu_temp); + + + } + void RelBranch_Stage2_BVS() + { + branch_taken = FlagV == true; + RelBranch_Stage2(); + } + void RelBranch_Stage2_BVC() + { + branch_taken = FlagV == false; + RelBranch_Stage2(); + } + void RelBranch_Stage2_BMI() + { + branch_taken = FlagN == true; + RelBranch_Stage2(); + } + void RelBranch_Stage2_BPL() + { + branch_taken = FlagN == false; + RelBranch_Stage2(); + } + void RelBranch_Stage2_BCS() + { + branch_taken = FlagC == true; + RelBranch_Stage2(); + } + void RelBranch_Stage2_BCC() + { + branch_taken = FlagC == false; + RelBranch_Stage2(); + } + void RelBranch_Stage2_BEQ() + { + branch_taken = FlagZ == true; + RelBranch_Stage2(); + } + void RelBranch_Stage2_BNE() + { + branch_taken = FlagZ == false; + RelBranch_Stage2(); + + } + void RelBranch_Stage2() + { + rdy_freeze = !RDY; + if (RDY) + { + opcode2 = ReadMemory(PC++); + if (branch_taken) + { + branch_taken = false; + //if the branch is taken, we enter a different bit of microcode to calculate the PC and complete the branch + opcode = VOP_RelativeStuff; + mi = -1; + } + } + + } + void RelBranch_Stage3() + { + FetchDummy(); + alu_temp = (byte)PC + (int)(sbyte)opcode2; + PC &= 0xFF00; + PC |= (ushort)((alu_temp & 0xFF)); + if (alu_temp.Bit(8)) + { + //we need to carry the add, and then we'll be ready to fetch the next instruction + opcode = VOP_RelativeStuff2; + mi = -1; + } + else + { + //to pass cpu_interrupts_v2/5-branch_delays_irq we need to handle a quirk here + //if we decide to interrupt in the next cycle, this condition will cause it to get deferred by one instruction + if (!interrupt_pending) + branch_irq_hack = true; + } + + } + void RelBranch_Stage4() + { + FetchDummy(); + if (alu_temp.Bit(31)) + PC = (ushort)(PC - 0x100); + else PC = (ushort)(PC + 0x100); + + + } + void NOP() + { + } + void DecS() + { + S--; + } + void IncS() + { + S++; + } + void JSR() + { + rdy_freeze = !RDY; + if (RDY) + { + PC = (ushort)((ReadMemory((ushort)(PC)) << 8) + opcode2); + } + } + void PullP() + { + rdy_freeze = !RDY; + if (RDY) + { + P = ReadMemory((ushort)(S++ + 0x100)); + FlagT = true; //force T always to remain true + } + + } + void PullPCL() + { + rdy_freeze = !RDY; + if (RDY) + { + PC &= 0xFF00; + PC |= ReadMemory((ushort)(S++ + 0x100)); + } + + } + void PullPCH_NoInc() + { + rdy_freeze = !RDY; + if (RDY) + { + PC &= 0xFF; + PC |= (ushort)(ReadMemory((ushort)(S + 0x100)) << 8); + } + + } + void Abs_READ_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + NZ_A(); + } + } + void Abs_READ_LDY() + { + rdy_freeze = !RDY; + if (RDY) + { + Y = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + NZ_Y(); + } + } + void Abs_READ_LDX() + { + rdy_freeze = !RDY; + if (RDY) + { + X = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + NZ_X(); + } + } + void Abs_READ_BIT() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Bit(); + } + } + void Abs_READ_LAX() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + A = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + X = A; + NZ_A(); + } + } + void Abs_READ_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _And(); + } + } + void Abs_READ_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Eor(); + } + } + void Abs_READ_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Ora(); + } + } + void Abs_READ_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Adc(); + } + } + void Abs_READ_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Cmp(); + } + } + void Abs_READ_CPY() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Cpy(); + } + } + void Abs_READ_NOP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + } + + } + void Abs_READ_CPX() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Cpx(); + } + } + void Abs_READ_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); + _Sbc(); + } + + } + void ZpIdx_Stage3_X() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory(opcode2); + opcode2 = (byte)(opcode2 + X); //a bit sneaky to shove this into opcode2... but we can reuse all the zero page uops if we do that + } + + } + void ZpIdx_Stage3_Y() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory(opcode2); + opcode2 = (byte)(opcode2 + Y); //a bit sneaky to shove this into opcode2... but we can reuse all the zero page uops if we do that + } + + } + void ZpIdx_RMW_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + } + + } + void ZpIdx_RMW_Stage6() + { + WriteMemory(opcode2, (byte)alu_temp); + + + } + void ZP_READ_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Eor(); + } + } + void ZP_READ_BIT() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Bit(); + } + } + void ZP_READ_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory(opcode2); + NZ_A(); + } + } + void ZP_READ_LDY() + { + rdy_freeze = !RDY; + if (RDY) + { + Y = ReadMemory(opcode2); + NZ_Y(); + } + } + void ZP_READ_LDX() + { + rdy_freeze = !RDY; + if (RDY) + { + X = ReadMemory(opcode2); + NZ_X(); + } + } + void ZP_READ_LAX() + { + rdy_freeze = !RDY; + if (RDY) + { + //?? is this right?? + X = ReadMemory(opcode2); + A = X; + NZ_A(); + } + } + void ZP_READ_CPY() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Cpy(); + } + } + void ZP_READ_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Cmp(); + } + } + void ZP_READ_CPX() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Cpx(); + } + } + void ZP_READ_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Ora(); + } + } + void ZP_READ_NOP() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory(opcode2); //just a dummy + } + + } + void ZP_READ_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Sbc(); + } + } + void ZP_READ_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _Adc(); + } + } + void ZP_READ_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + _And(); + } + + } + void _Cpx() + { + value8 = (byte)alu_temp; + value16 = (ushort)(X - value8); + FlagC = (X >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + + } + void _Cpy() + { + value8 = (byte)alu_temp; + value16 = (ushort)(Y - value8); + FlagC = (Y >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + + } + void _Cmp() + { + value8 = (byte)alu_temp; + value16 = (ushort)(A - value8); + FlagC = (A >= value8); + P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); + + } + void _Bit() + { + FlagN = (alu_temp & 0x80) != 0; + FlagV = (alu_temp & 0x40) != 0; + FlagZ = (A & alu_temp) == 0; + + } + void _Eor() + { + A ^= (byte)alu_temp; + NZ_A(); + } + void _And() + { + A &= (byte)alu_temp; + NZ_A(); + } + void _Ora() + { + A |= (byte)alu_temp; + NZ_A(); + } + void _Anc() + { + A &= (byte)alu_temp; + FlagC = A.Bit(7); + NZ_A(); + } + void _Asr() + { + A &= (byte)alu_temp; + FlagC = A.Bit(0); + A >>= 1; + NZ_A(); + } + void _Axs() + { + X &= A; + alu_temp = X - (byte)alu_temp; + X = (byte)alu_temp; + FlagC = !alu_temp.Bit(8); + NZ_X(); + } + void _Arr() + { + { + A &= (byte)alu_temp; + booltemp = A.Bit(0); + A = (byte)((A >> 1) | (FlagC ? 0x80 : 0x00)); + FlagC = booltemp; + if (A.Bit(5)) + if (A.Bit(6)) + { FlagC = true; FlagV = false; } + else { FlagV = true; FlagC = false; } + else if (A.Bit(6)) + { FlagV = true; FlagC = true; } + else { FlagV = false; FlagC = false; } + FlagZ = (A == 0); + + } + } + void _Lxa() + { + A |= 0xFF; //there is some debate about what this should be. it may depend on the 6502 variant. this is suggested by qeed's doc for the nes and passes blargg's instruction test + A &= (byte)alu_temp; + X = A; + NZ_A(); + } + void _Sbc() + { + { + value8 = (byte)alu_temp; + tempint = A - value8 - (FlagC ? 0 : 1); + if (FlagD && BCD_Enabled) + { + lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1); + hi = (A & 0xF0) - (value8 & 0xF0); + if ((lo & 0xF0) != 0) lo -= 0x06; + if ((lo & 0x80) != 0) hi -= 0x10; + if ((hi & 0x0F00) != 0) hi -= 0x60; + FlagV = ((A ^ value8) & (A ^ tempint) & 0x80) != 0; + FlagC = (hi & 0xFF00) == 0; + A = (byte)((lo & 0x0F) | (hi & 0xF0)); + } + else + { + FlagV = ((A ^ value8) & (A ^ tempint) & 0x80) != 0; + FlagC = tempint >= 0; + A = (byte)tempint; + } + NZ_A(); + } + } + void _Adc() + { + { + //TODO - an extra cycle penalty? + value8 = (byte)alu_temp; + if (FlagD && BCD_Enabled) + { + lo = (A & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0); + hi = (A & 0xF0) + (value8 & 0xF0); + if (lo > 0x09) + { + hi += 0x10; + lo += 0x06; + } + if (hi > 0x90) hi += 0x60; + FlagV = (~(A ^ value8) & (A ^ hi) & 0x80) != 0; + FlagC = hi > 0xFF; + A = (byte)((lo & 0x0F) | (hi & 0xF0)); + } + else + { + tempint = value8 + A + (FlagC ? 1 : 0); + FlagV = (~(A ^ value8) & (A ^ tempint) & 0x80) != 0; + FlagC = tempint > 0xFF; + A = (byte)tempint; + } + NZ_A(); + } + + } + void Unsupported() + { + + + } + void Imm_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Eor(); + } + } + void Imm_ANC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Anc(); + } + } + void Imm_ASR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Asr(); + } + } + void Imm_AXS() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Axs(); + } + } + void Imm_ARR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Arr(); + } + } + void Imm_LXA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Lxa(); + } + } + void Imm_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Ora(); + } + } + void Imm_CPY() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Cpy(); + } + } + void Imm_CPX() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Cpx(); + } + } + void Imm_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Cmp(); + } + } + void Imm_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Sbc(); + } + } + void Imm_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _And(); + } + } + void Imm_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(PC++); + _Adc(); + } + } + void Imm_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory(PC++); + NZ_A(); + } + } + void Imm_LDX() + { + rdy_freeze = !RDY; + if (RDY) + { + X = ReadMemory(PC++); + NZ_X(); + } + } + void Imm_LDY() + { + rdy_freeze = !RDY; + if (RDY) + { + Y = ReadMemory(PC++); + NZ_Y(); + } + } + void Imm_Unsupported() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory(PC++); + } + + } + void IdxInd_Stage3() + { + rdy_freeze = !RDY; + if (RDY) + { + ReadMemory(opcode2); //dummy? + alu_temp = (opcode2 + X) & 0xFF; + } + + } + void IdxInd_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + ea = ReadMemory((ushort)alu_temp); + } + + } + void IdxInd_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + ea += (ReadMemory((byte)(alu_temp + 1)) << 8); + } + + } + void IdxInd_Stage6_READ_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + //TODO make uniform with others + A = ReadMemory((ushort)ea); + NZ_A(); + } + } + void IdxInd_Stage6_READ_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Ora(); + } + } + void IdxInd_Stage6_READ_LAX() + { + rdy_freeze = !RDY; + if (RDY) + { + A = X = ReadMemory((ushort)ea); + NZ_A(); + } + } + void IdxInd_Stage6_READ_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Cmp(); + } + } + void IdxInd_Stage6_READ_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Adc(); + } + } + void IdxInd_Stage6_READ_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _And(); + } + } + void IdxInd_Stage6_READ_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Eor(); + } + } + void IdxInd_Stage6_READ_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Sbc(); + } + } + void IdxInd_Stage6_WRITE_STA() + { + WriteMemory((ushort)ea, A); + + } + void IdxInd_Stage6_WRITE_SAX() + { + alu_temp = A & X; + WriteMemory((ushort)ea, (byte)alu_temp); + //flag writing skipped on purpose + + } + void IdxInd_Stage6_RMW() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + } + + } + void IdxInd_Stage7_RMW_SLO() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)((value8 << 1)); + A |= value8; + NZ_A(); + } + void IdxInd_Stage7_RMW_ISC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 + 1); + _Sbc(); + } + void IdxInd_Stage7_RMW_DCP() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 - 1); + FlagC = (temp8 & 1) != 0; + _Cmp(); + } + void IdxInd_Stage7_RMW_SRE() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + A ^= value8; + NZ_A(); + } + void IdxInd_Stage7_RMW_RRA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); + FlagC = (temp8 & 1) != 0; + _Adc(); + } + void IdxInd_Stage7_RMW_RLA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + A &= value8; + NZ_A(); + } + void IdxInd_Stage8_RMW() + { + WriteMemory((ushort)ea, (byte)alu_temp); + + + } + void PushP() + { + FlagB = true; + WriteMemory((ushort)(S-- + 0x100), P); + + } + void PushA() + { + WriteMemory((ushort)(S-- + 0x100), A); + } + void PullA_NoInc() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory((ushort)(S + 0x100)); + NZ_A(); + } + } + void PullP_NoInc() + { + rdy_freeze = !RDY; + if (RDY) + { + my_iflag = FlagI; + P = ReadMemory((ushort)(S + 0x100)); + iflag_pending = FlagI; + FlagI = my_iflag; + FlagT = true; //force T always to remain true + + } + + } + void Imp_ASL_A() + { + FetchDummy(); + FlagC = (A & 0x80) != 0; + A = (byte)(A << 1); + NZ_A(); + } + void Imp_ROL_A() + { + FetchDummy(); + temp8 = A; + A = (byte)((A << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + NZ_A(); + } + void Imp_ROR_A() + { + FetchDummy(); + temp8 = A; + A = (byte)((A >> 1) | ((P & 1) << 7)); + FlagC = (temp8 & 1) != 0; + NZ_A(); + } + void Imp_LSR_A() + { + FetchDummy(); + FlagC = (A & 1) != 0; + A = (byte)(A >> 1); + NZ_A(); + + } + void JMP_abs() + { + rdy_freeze = !RDY; + if (RDY) + { + PC = (ushort)((ReadMemory(PC) << 8) + opcode2); + } + + } + void IncPC() + { + PC++; + + + } + void ZP_RMW_Stage3() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory(opcode2); + } + + } + void ZP_RMW_Stage5() + { + WriteMemory(opcode2, (byte)alu_temp); + + } + void ZP_RMW_INC() + { + WriteMemory(opcode2, (byte)alu_temp); + alu_temp = (byte)((alu_temp + 1) & 0xFF); + P = (byte)((P & 0x7D) | TableNZ[alu_temp]); + + } + void ZP_RMW_DEC() + { + WriteMemory(opcode2, (byte)alu_temp); + alu_temp = (byte)((alu_temp - 1) & 0xFF); + P = (byte)((P & 0x7D) | TableNZ[alu_temp]); + + } + void ZP_RMW_ASL() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)(value8 << 1); + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void ZP_RMW_SRE() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + A ^= value8; + NZ_A(); + } + void ZP_RMW_RRA() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); + FlagC = (temp8 & 1) != 0; + _Adc(); + } + void ZP_RMW_DCP() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 - 1); + FlagC = (temp8 & 1) != 0; + _Cmp(); + } + void ZP_RMW_LSR() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void ZP_RMW_ROR() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void ZP_RMW_ROL() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void ZP_RMW_SLO() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)((value8 << 1)); + A |= value8; + NZ_A(); + } + void ZP_RMW_ISC() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = (byte)alu_temp; + alu_temp = value8 = (byte)(value8 + 1); + _Sbc(); + } + void ZP_RMW_RLA() + { + WriteMemory(opcode2, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + A &= value8; + NZ_A(); + + } + void AbsIdx_Stage3_Y() + { + rdy_freeze = !RDY; + if (RDY) + { + opcode3 = ReadMemory(PC++); + alu_temp = opcode2 + Y; + ea = (opcode3 << 8) + (alu_temp & 0xFF); + + //new Uop[] { Uop.Fetch2, Uop.AbsIdx_Stage3_Y, Uop.AbsIdx_Stage4, Uop.AbsIdx_WRITE_Stage5_STA, Uop.End }, + } + } + void AbsIdx_Stage3_X() + { + rdy_freeze = !RDY; + if (RDY) + { + opcode3 = ReadMemory(PC++); + alu_temp = opcode2 + X; + ea = (opcode3 << 8) + (alu_temp & 0xFF); + } + + } + void AbsIdx_READ_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + if (!alu_temp.Bit(8)) + { + mi++; + ExecuteOneRetry(); + return; + } + else + { + alu_temp = ReadMemory((ushort)ea); + ea = (ushort)(ea + 0x100); + } + } + + } + void AbsIdx_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + //bleh.. redundant code to make sure we dont clobber alu_temp before using it to decide whether to change ea + if (alu_temp.Bit(8)) + { + alu_temp = ReadMemory((ushort)ea); + ea = (ushort)(ea + 0x100); + } + else alu_temp = ReadMemory((ushort)ea); + } + + } + void AbsIdx_WRITE_Stage5_STA() + { + WriteMemory((ushort)ea, A); + + } + void AbsIdx_WRITE_Stage5_SHY() + { + alu_temp = Y & (ea >> 8); + ea = (ea & 0xFF) | (alu_temp << 8); //"(the bank where the value is stored may be equal to the value stored)" -- more like IS. + WriteMemory((ushort)ea, (byte)alu_temp); + + } + void AbsIdx_WRITE_Stage5_SHX() + { + alu_temp = X & (ea >> 8); + ea = (ea & 0xFF) | (alu_temp << 8); //"(the bank where the value is stored may be equal to the value stored)" -- more like IS. + WriteMemory((ushort)ea, (byte)alu_temp); + + } + void AbsIdx_WRITE_Stage5_ERROR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + //throw new InvalidOperationException("UNSUPPORTED OPCODE [probably SHS] PLEASE REPORT"); + } + + } + void AbsIdx_RMW_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + } + + } + void AbsIdx_RMW_Stage7() + { + WriteMemory((ushort)ea, (byte)alu_temp); + + } + void AbsIdx_RMW_Stage6_DEC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + alu_temp = value8 = (byte)(alu_temp - 1); + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void AbsIdx_RMW_Stage6_DCP() + { + WriteMemory((ushort)ea, (byte)alu_temp); + alu_temp = value8 = (byte)(alu_temp - 1); + _Cmp(); + } + void AbsIdx_RMW_Stage6_ISC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + alu_temp = value8 = (byte)(alu_temp + 1); + _Sbc(); + } + void AbsIdx_RMW_Stage6_INC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + alu_temp = value8 = (byte)(alu_temp + 1); + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void AbsIdx_RMW_Stage6_ROL() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void AbsIdx_RMW_Stage6_LSR() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void AbsIdx_RMW_Stage6_SLO() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)(value8 << 1); + A |= value8; + NZ_A(); + } + void AbsIdx_RMW_Stage6_SRE() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + A ^= value8; + NZ_A(); + } + void AbsIdx_RMW_Stage6_RRA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); + FlagC = (temp8 & 1) != 0; + _Adc(); + } + void AbsIdx_RMW_Stage6_RLA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + A &= value8; + NZ_A(); + } + void AbsIdx_RMW_Stage6_ASL() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)(value8 << 1); + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void AbsIdx_RMW_Stage6_ROR() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + + + } + void AbsIdx_READ_Stage5_LDA() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory((ushort)ea); + NZ_A(); + } + } + void AbsIdx_READ_Stage5_LDX() + { + rdy_freeze = !RDY; + if (RDY) + { + X = ReadMemory((ushort)ea); + NZ_X(); + } + } + void AbsIdx_READ_Stage5_LAX() + { + rdy_freeze = !RDY; + if (RDY) + { + A = ReadMemory((ushort)ea); + X = A; + NZ_A(); + } + } + void AbsIdx_READ_Stage5_LDY() + { + rdy_freeze = !RDY; + if (RDY) + { + Y = ReadMemory((ushort)ea); + NZ_Y(); + } + } + void AbsIdx_READ_Stage5_ORA() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Ora(); + } + } + void AbsIdx_READ_Stage5_NOP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + } + + } + void AbsIdx_READ_Stage5_CMP() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Cmp(); + } + } + void AbsIdx_READ_Stage5_SBC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Sbc(); + } + } + void AbsIdx_READ_Stage5_ADC() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Adc(); + } + } + void AbsIdx_READ_Stage5_EOR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _Eor(); + } + } + void AbsIdx_READ_Stage5_AND() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + _And(); + } + } + void AbsIdx_READ_Stage5_ERROR() + { + rdy_freeze = !RDY; + if (RDY) + { + alu_temp = ReadMemory((ushort)ea); + //throw new InvalidOperationException("UNSUPPORTED OPCODE [probably LAS] PLEASE REPORT"); + } + + } + void AbsInd_JMP_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + ea = (opcode3 << 8) + opcode2; + alu_temp = ReadMemory((ushort)ea); + } + } + void AbsInd_JMP_Stage5() + { + rdy_freeze = !RDY; + if (RDY) + { + ea = (opcode3 << 8) + (byte)(opcode2 + 1); + alu_temp += ReadMemory((ushort)ea) << 8; + PC = (ushort)alu_temp; + } + + } + void Abs_RMW_Stage4() + { + rdy_freeze = !RDY; + if (RDY) + { + ea = (opcode3 << 8) + opcode2; + alu_temp = ReadMemory((ushort)ea); + } + + } + void Abs_RMW_Stage5_INC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)(alu_temp + 1); + alu_temp = value8; + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void Abs_RMW_Stage5_DEC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)(alu_temp - 1); + alu_temp = value8; + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void Abs_RMW_Stage5_DCP() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)(alu_temp - 1); + alu_temp = value8; + _Cmp(); + } + void Abs_RMW_Stage5_ISC() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)(alu_temp + 1); + alu_temp = value8; + _Sbc(); + } + void Abs_RMW_Stage5_ASL() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)(value8 << 1); + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void Abs_RMW_Stage5_ROR() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); + FlagC = (temp8 & 1) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void Abs_RMW_Stage5_SLO() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 0x80) != 0; + alu_temp = value8 = (byte)(value8 << 1); + A |= value8; + NZ_A(); + } + void Abs_RMW_Stage5_RLA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + A &= value8; + NZ_A(); + } + void Abs_RMW_Stage5_SRE() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + A ^= value8; + NZ_A(); + } + void Abs_RMW_Stage5_RRA() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); + FlagC = (temp8 & 1) != 0; + _Adc(); + } + void Abs_RMW_Stage5_ROL() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = temp8 = (byte)alu_temp; + alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); + FlagC = (temp8 & 0x80) != 0; + P = (byte)((P & 0x7D) | TableNZ[value8]); + + } + void Abs_RMW_Stage5_LSR() + { + WriteMemory((ushort)ea, (byte)alu_temp); + value8 = (byte)alu_temp; + FlagC = (value8 & 1) != 0; + alu_temp = value8 = (byte)(value8 >> 1); + P = (byte)((P & 0x7D) | TableNZ[value8]); + + + } + void Abs_RMW_Stage6() + { + WriteMemory((ushort)ea, (byte)alu_temp); + + + } + void End_ISpecial() + { + opcode = VOP_Fetch1; + mi = 0; + ExecuteOneRetry(); + return; + + } + void End_SuppressInterrupt() + { + opcode = VOP_Fetch1_NoInterrupt; + mi = 0; + ExecuteOneRetry(); + return; + + } + void End() + { + opcode = VOP_Fetch1; + mi = 0; + iflag_pending = FlagI; + ExecuteOneRetry(); + return; + } + void End_BranchSpecial() + { + End(); + } + + void ExecuteOneRetry() + { + //dont know whether this system is any faster. hard to get benchmarks someone else try it? + //Uop uop = (Uop)CompiledMicrocode[MicrocodeIndex[opcode] + mi]; + Uop uop = Microcode[opcode][mi]; + switch (uop) + { + default: throw new InvalidOperationException(); + case Uop.Fetch1: Fetch1(); break; + case Uop.Fetch1_Real: Fetch1_Real(); break; + case Uop.Fetch2: Fetch2(); break; + case Uop.Fetch3: Fetch3(); break; + case Uop.FetchDummy: FetchDummy(); break; + case Uop.PushPCH: PushPCH(); break; + case Uop.PushPCL: PushPCL(); break; + case Uop.PushP_BRK: PushP_BRK(); break; + case Uop.PushP_IRQ: PushP_IRQ(); break; + case Uop.PushP_NMI: PushP_NMI(); break; + case Uop.PushP_Reset: PushP_Reset(); break; + case Uop.PushDummy: PushDummy(); break; + case Uop.FetchPCLVector: FetchPCLVector(); break; + case Uop.FetchPCHVector: FetchPCHVector(); break; + case Uop.Imp_INY: Imp_INY(); break; + case Uop.Imp_DEY: Imp_DEY(); break; + case Uop.Imp_INX: Imp_INX(); break; + case Uop.Imp_DEX: Imp_DEX(); break; + case Uop.NZ_A: NZ_A(); break; + case Uop.NZ_X: NZ_X(); break; + case Uop.NZ_Y: NZ_Y(); break; + case Uop.Imp_TSX: Imp_TSX(); break; + case Uop.Imp_TXS: Imp_TXS(); break; + case Uop.Imp_TAX: Imp_TAX(); break; + case Uop.Imp_TAY: Imp_TAY(); break; + case Uop.Imp_TYA: Imp_TYA(); break; + case Uop.Imp_TXA: Imp_TXA(); break; + case Uop.Imp_SEI: Imp_SEI(); break; + case Uop.Imp_CLI: Imp_CLI(); break; + case Uop.Imp_SEC: Imp_SEC(); break; + case Uop.Imp_CLC: Imp_CLC(); break; + case Uop.Imp_SED: Imp_SED(); break; + case Uop.Imp_CLD: Imp_CLD(); break; + case Uop.Imp_CLV: Imp_CLV(); break; + case Uop.Abs_WRITE_STA: Abs_WRITE_STA(); break; + case Uop.Abs_WRITE_STX: Abs_WRITE_STX(); break; + case Uop.Abs_WRITE_STY: Abs_WRITE_STY(); break; + case Uop.Abs_WRITE_SAX: Abs_WRITE_SAX(); break; + case Uop.ZP_WRITE_STA: ZP_WRITE_STA(); break; + case Uop.ZP_WRITE_STY: ZP_WRITE_STY(); break; + case Uop.ZP_WRITE_STX: ZP_WRITE_STX(); break; + case Uop.ZP_WRITE_SAX: ZP_WRITE_SAX(); break; + case Uop.IndIdx_Stage3: IndIdx_Stage3(); break; + case Uop.IndIdx_Stage4: IndIdx_Stage4(); break; + case Uop.IndIdx_WRITE_Stage5: IndIdx_WRITE_Stage5(); break; + case Uop.IndIdx_READ_Stage5: IndIdx_READ_Stage5(); break; + case Uop.IndIdx_RMW_Stage5: IndIdx_RMW_Stage5(); break; + case Uop.IndIdx_WRITE_Stage6_STA: IndIdx_WRITE_Stage6_STA(); break; + case Uop.IndIdx_WRITE_Stage6_SHA: IndIdx_WRITE_Stage6_SHA(); break; + case Uop.IndIdx_READ_Stage6_LDA: IndIdx_READ_Stage6_LDA(); break; + case Uop.IndIdx_READ_Stage6_CMP: IndIdx_READ_Stage6_CMP(); break; + case Uop.IndIdx_READ_Stage6_AND: IndIdx_READ_Stage6_AND(); break; + case Uop.IndIdx_READ_Stage6_EOR: IndIdx_READ_Stage6_EOR(); break; + case Uop.IndIdx_READ_Stage6_LAX: IndIdx_READ_Stage6_LAX(); break; + case Uop.IndIdx_READ_Stage6_ADC: IndIdx_READ_Stage6_ADC(); break; + case Uop.IndIdx_READ_Stage6_SBC: IndIdx_READ_Stage6_SBC(); break; + case Uop.IndIdx_READ_Stage6_ORA: IndIdx_READ_Stage6_ORA(); break; + case Uop.IndIdx_RMW_Stage6: IndIdx_RMW_Stage6(); break; + case Uop.IndIdx_RMW_Stage7_SLO: IndIdx_RMW_Stage7_SLO(); break; + case Uop.IndIdx_RMW_Stage7_SRE: IndIdx_RMW_Stage7_SRE(); break; + case Uop.IndIdx_RMW_Stage7_RRA: IndIdx_RMW_Stage7_RRA(); break; + case Uop.IndIdx_RMW_Stage7_ISC: IndIdx_RMW_Stage7_ISC(); break; + case Uop.IndIdx_RMW_Stage7_DCP: IndIdx_RMW_Stage7_DCP(); break; + case Uop.IndIdx_RMW_Stage7_RLA: IndIdx_RMW_Stage7_RLA(); break; + case Uop.IndIdx_RMW_Stage8: IndIdx_RMW_Stage8(); break; + case Uop.RelBranch_Stage2_BVS: RelBranch_Stage2_BVS(); break; + case Uop.RelBranch_Stage2_BVC: RelBranch_Stage2_BVC(); break; + case Uop.RelBranch_Stage2_BMI: RelBranch_Stage2_BMI(); break; + case Uop.RelBranch_Stage2_BPL: RelBranch_Stage2_BPL(); break; + case Uop.RelBranch_Stage2_BCS: RelBranch_Stage2_BCS(); break; + case Uop.RelBranch_Stage2_BCC: RelBranch_Stage2_BCC(); break; + case Uop.RelBranch_Stage2_BEQ: RelBranch_Stage2_BEQ(); break; + case Uop.RelBranch_Stage2_BNE: RelBranch_Stage2_BNE(); break; + case Uop.RelBranch_Stage2: RelBranch_Stage2(); break; + case Uop.RelBranch_Stage3: RelBranch_Stage3(); break; + case Uop.RelBranch_Stage4: RelBranch_Stage4(); break; + case Uop.NOP: NOP(); break; + case Uop.DecS: DecS(); break; + case Uop.IncS: IncS(); break; + case Uop.JSR: JSR(); break; + case Uop.PullP: PullP(); break; + case Uop.PullPCL: PullPCL(); break; + case Uop.PullPCH_NoInc: PullPCH_NoInc(); break; + case Uop.Abs_READ_LDA: Abs_READ_LDA(); break; + case Uop.Abs_READ_LDY: Abs_READ_LDY(); break; + case Uop.Abs_READ_LDX: Abs_READ_LDX(); break; + case Uop.Abs_READ_BIT: Abs_READ_BIT(); break; + case Uop.Abs_READ_LAX: Abs_READ_LAX(); break; + case Uop.Abs_READ_AND: Abs_READ_AND(); break; + case Uop.Abs_READ_EOR: Abs_READ_EOR(); break; + case Uop.Abs_READ_ORA: Abs_READ_ORA(); break; + case Uop.Abs_READ_ADC: Abs_READ_ADC(); break; + case Uop.Abs_READ_CMP: Abs_READ_CMP(); break; + case Uop.Abs_READ_CPY: Abs_READ_CPY(); break; + case Uop.Abs_READ_NOP: Abs_READ_NOP(); break; + case Uop.Abs_READ_CPX: Abs_READ_CPX(); break; + case Uop.Abs_READ_SBC: Abs_READ_SBC(); break; + case Uop.ZpIdx_Stage3_X: ZpIdx_Stage3_X(); break; + case Uop.ZpIdx_Stage3_Y: ZpIdx_Stage3_Y(); break; + case Uop.ZpIdx_RMW_Stage4: ZpIdx_RMW_Stage4(); break; + case Uop.ZpIdx_RMW_Stage6: ZpIdx_RMW_Stage6(); break; + case Uop.ZP_READ_EOR: ZP_READ_EOR(); break; + case Uop.ZP_READ_BIT: ZP_READ_BIT(); break; + case Uop.ZP_READ_LDA: ZP_READ_LDA(); break; + case Uop.ZP_READ_LDY: ZP_READ_LDY(); break; + case Uop.ZP_READ_LDX: ZP_READ_LDX(); break; + case Uop.ZP_READ_LAX: ZP_READ_LAX(); break; + case Uop.ZP_READ_CPY: ZP_READ_CPY(); break; + case Uop.ZP_READ_CMP: ZP_READ_CMP(); break; + case Uop.ZP_READ_CPX: ZP_READ_CPX(); break; + case Uop.ZP_READ_ORA: ZP_READ_ORA(); break; + case Uop.ZP_READ_NOP: ZP_READ_NOP(); break; + case Uop.ZP_READ_SBC: ZP_READ_SBC(); break; + case Uop.ZP_READ_ADC: ZP_READ_ADC(); break; + case Uop.ZP_READ_AND: ZP_READ_AND(); break; + case Uop._Cpx: _Cpx(); break; + case Uop._Cpy: _Cpy(); break; + case Uop._Cmp: _Cmp(); break; + case Uop._Eor: _Eor(); break; + case Uop._And: _And(); break; + case Uop._Ora: _Ora(); break; + case Uop._Anc: _Anc(); break; + case Uop._Asr: _Asr(); break; + case Uop._Axs: _Axs(); break; + case Uop._Arr: _Arr(); break; + case Uop._Lxa: _Lxa(); break; + case Uop._Sbc: _Sbc(); break; + case Uop._Adc: _Adc(); break; + case Uop.Unsupported: Unsupported(); break; + case Uop.Imm_EOR: Imm_EOR(); break; + case Uop.Imm_ANC: Imm_ANC(); break; + case Uop.Imm_ASR: Imm_ASR(); break; + case Uop.Imm_AXS: Imm_AXS(); break; + case Uop.Imm_ARR: Imm_ARR(); break; + case Uop.Imm_LXA: Imm_LXA(); break; + case Uop.Imm_ORA: Imm_ORA(); break; + case Uop.Imm_CPY: Imm_CPY(); break; + case Uop.Imm_CPX: Imm_CPX(); break; + case Uop.Imm_CMP: Imm_CMP(); break; + case Uop.Imm_SBC: Imm_SBC(); break; + case Uop.Imm_AND: Imm_AND(); break; + case Uop.Imm_ADC: Imm_ADC(); break; + case Uop.Imm_LDA: Imm_LDA(); break; + case Uop.Imm_LDX: Imm_LDX(); break; + case Uop.Imm_LDY: Imm_LDY(); break; + case Uop.Imm_Unsupported: Imm_Unsupported(); break; + case Uop.IdxInd_Stage3: IdxInd_Stage3(); break; + case Uop.IdxInd_Stage4: IdxInd_Stage4(); break; + case Uop.IdxInd_Stage5: IdxInd_Stage5(); break; + case Uop.IdxInd_Stage6_READ_LDA: IdxInd_Stage6_READ_LDA(); break; + case Uop.IdxInd_Stage6_READ_ORA: IdxInd_Stage6_READ_ORA(); break; + case Uop.IdxInd_Stage6_READ_LAX: IdxInd_Stage6_READ_LAX(); break; + case Uop.IdxInd_Stage6_READ_CMP: IdxInd_Stage6_READ_CMP(); break; + case Uop.IdxInd_Stage6_READ_ADC: IdxInd_Stage6_READ_ADC(); break; + case Uop.IdxInd_Stage6_READ_AND: IdxInd_Stage6_READ_AND(); break; + case Uop.IdxInd_Stage6_READ_EOR: IdxInd_Stage6_READ_EOR(); break; + case Uop.IdxInd_Stage6_READ_SBC: IdxInd_Stage6_READ_SBC(); break; + case Uop.IdxInd_Stage6_WRITE_STA: IdxInd_Stage6_WRITE_STA(); break; + case Uop.IdxInd_Stage6_WRITE_SAX: IdxInd_Stage6_WRITE_SAX(); break; + case Uop.IdxInd_Stage6_RMW: IdxInd_Stage6_RMW(); break; + case Uop.IdxInd_Stage7_RMW_SLO: IdxInd_Stage7_RMW_SLO(); break; + case Uop.IdxInd_Stage7_RMW_ISC: IdxInd_Stage7_RMW_ISC(); break; + case Uop.IdxInd_Stage7_RMW_DCP: IdxInd_Stage7_RMW_DCP(); break; + case Uop.IdxInd_Stage7_RMW_SRE: IdxInd_Stage7_RMW_SRE(); break; + case Uop.IdxInd_Stage7_RMW_RRA: IdxInd_Stage7_RMW_RRA(); break; + case Uop.IdxInd_Stage7_RMW_RLA: IdxInd_Stage7_RMW_RLA(); break; + case Uop.IdxInd_Stage8_RMW: IdxInd_Stage8_RMW(); break; + case Uop.PushP: PushP(); break; + case Uop.PushA: PushA(); break; + case Uop.PullA_NoInc: PullA_NoInc(); break; + case Uop.PullP_NoInc: PullP_NoInc(); break; + case Uop.Imp_ASL_A: Imp_ASL_A(); break; + case Uop.Imp_ROL_A: Imp_ROL_A(); break; + case Uop.Imp_ROR_A: Imp_ROR_A(); break; + case Uop.Imp_LSR_A: Imp_LSR_A(); break; + case Uop.JMP_abs: JMP_abs(); break; + case Uop.IncPC: IncPC(); break; + case Uop.ZP_RMW_Stage3: ZP_RMW_Stage3(); break; + case Uop.ZP_RMW_Stage5: ZP_RMW_Stage5(); break; + case Uop.ZP_RMW_INC: ZP_RMW_INC(); break; + case Uop.ZP_RMW_DEC: ZP_RMW_DEC(); break; + case Uop.ZP_RMW_ASL: ZP_RMW_ASL(); break; + case Uop.ZP_RMW_SRE: ZP_RMW_SRE(); break; + case Uop.ZP_RMW_RRA: ZP_RMW_RRA(); break; + case Uop.ZP_RMW_DCP: ZP_RMW_DCP(); break; + case Uop.ZP_RMW_LSR: ZP_RMW_LSR(); break; + case Uop.ZP_RMW_ROR: ZP_RMW_ROR(); break; + case Uop.ZP_RMW_ROL: ZP_RMW_ROL(); break; + case Uop.ZP_RMW_SLO: ZP_RMW_SLO(); break; + case Uop.ZP_RMW_ISC: ZP_RMW_ISC(); break; + case Uop.ZP_RMW_RLA: ZP_RMW_RLA(); break; + case Uop.AbsIdx_Stage3_Y: AbsIdx_Stage3_Y(); break; + case Uop.AbsIdx_Stage3_X: AbsIdx_Stage3_X(); break; + case Uop.AbsIdx_READ_Stage4: AbsIdx_READ_Stage4(); break; + case Uop.AbsIdx_Stage4: AbsIdx_Stage4(); break; + case Uop.AbsIdx_WRITE_Stage5_STA: AbsIdx_WRITE_Stage5_STA(); break; + case Uop.AbsIdx_WRITE_Stage5_SHY: AbsIdx_WRITE_Stage5_SHY(); break; + case Uop.AbsIdx_WRITE_Stage5_SHX: AbsIdx_WRITE_Stage5_SHX(); break; + case Uop.AbsIdx_WRITE_Stage5_ERROR: AbsIdx_WRITE_Stage5_ERROR(); break; + case Uop.AbsIdx_RMW_Stage5: AbsIdx_RMW_Stage5(); break; + case Uop.AbsIdx_RMW_Stage7: AbsIdx_RMW_Stage7(); break; + case Uop.AbsIdx_RMW_Stage6_DEC: AbsIdx_RMW_Stage6_DEC(); break; + case Uop.AbsIdx_RMW_Stage6_DCP: AbsIdx_RMW_Stage6_DCP(); break; + case Uop.AbsIdx_RMW_Stage6_ISC: AbsIdx_RMW_Stage6_ISC(); break; + case Uop.AbsIdx_RMW_Stage6_INC: AbsIdx_RMW_Stage6_INC(); break; + case Uop.AbsIdx_RMW_Stage6_ROL: AbsIdx_RMW_Stage6_ROL(); break; + case Uop.AbsIdx_RMW_Stage6_LSR: AbsIdx_RMW_Stage6_LSR(); break; + case Uop.AbsIdx_RMW_Stage6_SLO: AbsIdx_RMW_Stage6_SLO(); break; + case Uop.AbsIdx_RMW_Stage6_SRE: AbsIdx_RMW_Stage6_SRE(); break; + case Uop.AbsIdx_RMW_Stage6_RRA: AbsIdx_RMW_Stage6_RRA(); break; + case Uop.AbsIdx_RMW_Stage6_RLA: AbsIdx_RMW_Stage6_RLA(); break; + case Uop.AbsIdx_RMW_Stage6_ASL: AbsIdx_RMW_Stage6_ASL(); break; + case Uop.AbsIdx_RMW_Stage6_ROR: AbsIdx_RMW_Stage6_ROR(); break; + case Uop.AbsIdx_READ_Stage5_LDA: AbsIdx_READ_Stage5_LDA(); break; + case Uop.AbsIdx_READ_Stage5_LDX: AbsIdx_READ_Stage5_LDX(); break; + case Uop.AbsIdx_READ_Stage5_LAX: AbsIdx_READ_Stage5_LAX(); break; + case Uop.AbsIdx_READ_Stage5_LDY: AbsIdx_READ_Stage5_LDY(); break; + case Uop.AbsIdx_READ_Stage5_ORA: AbsIdx_READ_Stage5_ORA(); break; + case Uop.AbsIdx_READ_Stage5_NOP: AbsIdx_READ_Stage5_NOP(); break; + case Uop.AbsIdx_READ_Stage5_CMP: AbsIdx_READ_Stage5_CMP(); break; + case Uop.AbsIdx_READ_Stage5_SBC: AbsIdx_READ_Stage5_SBC(); break; + case Uop.AbsIdx_READ_Stage5_ADC: AbsIdx_READ_Stage5_ADC(); break; + case Uop.AbsIdx_READ_Stage5_EOR: AbsIdx_READ_Stage5_EOR(); break; + case Uop.AbsIdx_READ_Stage5_AND: AbsIdx_READ_Stage5_AND(); break; + case Uop.AbsIdx_READ_Stage5_ERROR: AbsIdx_READ_Stage5_ERROR(); break; + case Uop.AbsInd_JMP_Stage4: AbsInd_JMP_Stage4(); break; + case Uop.AbsInd_JMP_Stage5: AbsInd_JMP_Stage5(); break; + case Uop.Abs_RMW_Stage4: Abs_RMW_Stage4(); break; + case Uop.Abs_RMW_Stage5_INC: Abs_RMW_Stage5_INC(); break; + case Uop.Abs_RMW_Stage5_DEC: Abs_RMW_Stage5_DEC(); break; + case Uop.Abs_RMW_Stage5_DCP: Abs_RMW_Stage5_DCP(); break; + case Uop.Abs_RMW_Stage5_ISC: Abs_RMW_Stage5_ISC(); break; + case Uop.Abs_RMW_Stage5_ASL: Abs_RMW_Stage5_ASL(); break; + case Uop.Abs_RMW_Stage5_ROR: Abs_RMW_Stage5_ROR(); break; + case Uop.Abs_RMW_Stage5_SLO: Abs_RMW_Stage5_SLO(); break; + case Uop.Abs_RMW_Stage5_RLA: Abs_RMW_Stage5_RLA(); break; + case Uop.Abs_RMW_Stage5_SRE: Abs_RMW_Stage5_SRE(); break; + case Uop.Abs_RMW_Stage5_RRA: Abs_RMW_Stage5_RRA(); break; + case Uop.Abs_RMW_Stage5_ROL: Abs_RMW_Stage5_ROL(); break; + case Uop.Abs_RMW_Stage5_LSR: Abs_RMW_Stage5_LSR(); break; + case Uop.Abs_RMW_Stage6: Abs_RMW_Stage6(); break; + case Uop.End_ISpecial: End_ISpecial(); break; + case Uop.End_SuppressInterrupt: End_SuppressInterrupt(); break; + case Uop.End: End(); break; + case Uop.End_BranchSpecial: End_BranchSpecial(); break; + } + } + + public void ExecuteOne() + { + if (!rdy_freeze) + { + TotalExecutedCycles++; + + interrupt_pending |= Interrupted; + } + rdy_freeze = false; + + //i tried making ExecuteOneRetry not re-entrant by having it set a flag instead, then exit from the call below, check the flag, and GOTO if it was flagged, but it wasnt faster + ExecuteOneRetry(); + + if (!rdy_freeze) + mi++; + } //ExecuteOne + } +} diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/Old Managed Stuff/MOS6502X.cs b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/Old Managed Stuff/MOS6502X.cs new file mode 100644 index 0000000000..2b34116abe --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/Old Managed Stuff/MOS6502X.cs @@ -0,0 +1,327 @@ +using System; + + +using BizHawk.Common; + +using System.Runtime.InteropServices; +using System.Security; + +using System.Reflection; +using System.Reflection.Emit; + +namespace BizHawk.Emulation.Cores.Components.M6502 +{ + [StructLayout(LayoutKind.Explicit)] // LayoutKind.Sequential doesn't work right on the managed form of non-blittable structs + public sealed partial class MOS6502X + { + [FieldOffset(0)] + private int _anchor; + + [SuppressUnmanagedCodeSecurity] + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate byte ReadDel(ushort addr); + [SuppressUnmanagedCodeSecurity] + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void WriteDel(ushort addr, byte val); + [SuppressUnmanagedCodeSecurity] + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void AddrDel(ushort addr); + + // interface + [FieldOffset(16)]private ReadDel _ReadMemory; + [FieldOffset(20)]private ReadDel _DummyReadMemory; + [FieldOffset(24)]private ReadDel _PeekMemory; + [FieldOffset(28)]private WriteDel _WriteMemory; + [FieldOffset(32)]private AddrDel _OnExecFetch; // this only calls when the first byte of an instruction is fetched. + + public ReadDel ReadMemory + { + set { _rmp = Marshal.GetFunctionPointerForDelegate(value); _ReadMemory = value; } + get { return _ReadMemory; } + } + public ReadDel DummyReadMemory + { + set { _dmp = Marshal.GetFunctionPointerForDelegate(value); _DummyReadMemory = value; } + get { return _DummyReadMemory; } + } + public ReadDel PeekMemory + { + set { _pmp = Marshal.GetFunctionPointerForDelegate(value); _PeekMemory = value; } + get { return _PeekMemory; } + } + public WriteDel WriteMemory + { + set { _wmp = Marshal.GetFunctionPointerForDelegate(value); _WriteMemory = value; } + get { return _WriteMemory; } + } + public AddrDel OnExecFetch + { + set { _exp = IntPtr.Zero; /* Marshal.GetFunctionPointerForDelegate(value); */ _OnExecFetch = value; } + get { return _OnExecFetch; } + } + + [FieldOffset(36)]public Action TraceCallback; // TODOOO + + [FieldOffset(40)]private IntPtr _rmp; + [FieldOffset(44)]private IntPtr _dmp; + [FieldOffset(48)]private IntPtr _pmp; + [FieldOffset(52)]private IntPtr _wmp; + [FieldOffset(56)]private IntPtr _exp; + + // config + [FieldOffset(60)]public bool BCD_Enabled = true; + [FieldOffset(61)]public bool debug = false; + + // state + [FieldOffset(62)]public byte A; + [FieldOffset(63)]public byte X; + [FieldOffset(64)]public byte Y; + //public byte P; + /// Carry Flag + [FieldOffset(65)]public bool FlagC; + /// Zero Flag + [FieldOffset(66)]public bool FlagZ; + /// Interrupt Disable Flag + [FieldOffset(67)]public bool FlagI; + /// Decimal Mode Flag + [FieldOffset(68)]public bool FlagD; + /// Break Flag + [FieldOffset(69)]public bool FlagB; + /// T... Flag + [FieldOffset(70)]public bool FlagT; + /// Overflow Flag + [FieldOffset(71)]public bool FlagV; + /// Negative Flag + [FieldOffset(72)]public bool FlagN; + + [FieldOffset(74)]public ushort PC; + [FieldOffset(76)]public byte S; + + [FieldOffset(77)]public bool IRQ; + [FieldOffset(78)]public bool NMI; + [FieldOffset(79)]public bool RDY; + + [FieldOffset(80)]public int TotalExecutedCycles; + + //opcode bytes.. theoretically redundant with the temp variables? who knows. + [FieldOffset(84)]int opcode; + [FieldOffset(88)]byte opcode2; + [FieldOffset(89)]byte opcode3; + + [FieldOffset(92)]int ea; + [FieldOffset(96)]int alu_temp; //cpu internal temp variables + [FieldOffset(100)]int mi; //microcode index + [FieldOffset(104)]bool iflag_pending; //iflag must be stored after it is checked in some cases (CLI and SEI). + [FieldOffset(105)]bool rdy_freeze; //true if the CPU must be frozen + + //tracks whether an interrupt condition has popped up recently. + //not sure if this is real or not but it helps with the branch_irq_hack + [FieldOffset(106)]bool interrupt_pending; + [FieldOffset(107)]bool branch_irq_hack; //see Uop.RelBranch_Stage3 for more details + + // transient state + [FieldOffset(108)]byte value8; + [FieldOffset(109)]byte temp8; + [FieldOffset(110)]ushort value16; + [FieldOffset(112)]bool branch_taken = false; + [FieldOffset(113)]bool my_iflag; + [FieldOffset(114)]bool booltemp; + [FieldOffset(116)]int tempint; + [FieldOffset(120)]int lo; + [FieldOffset(124)]int hi; + + public byte P + { + // NVTB DIZC + get + { + byte ret = 0; + if (FlagC) ret |= 1; + if (FlagZ) ret |= 2; + if (FlagI) ret |= 4; + if (FlagD) ret |= 8; + if (FlagB) ret |= 16; + if (FlagT) ret |= 32; + if (FlagV) ret |= 64; + if (FlagN) ret |= 128; + return ret; + } + set + { + FlagC = (value & 1) != 0; + FlagZ = (value & 2) != 0; + FlagI = (value & 4) != 0; + FlagD = (value & 8) != 0; + FlagB = (value & 16) != 0; + FlagT = (value & 32) != 0; + FlagV = (value & 64) != 0; + FlagN = (value & 128) != 0; + } + } + + public MOS6502X() + { + InitOpcodeHandlers(); + InitNative(); + Reset(); + } + + public void SyncState(Serializer ser) + { + ser.BeginSection("MOS6502X"); + ser.Sync("A", ref A); + ser.Sync("X", ref X); + ser.Sync("Y", ref Y); + { + byte tmp = P; + ser.Sync("P", ref tmp); + P = tmp; + } + ser.Sync("PC", ref PC); + ser.Sync("S", ref S); + ser.Sync("NMI", ref NMI); + ser.Sync("IRQ", ref IRQ); + ser.Sync("RDY", ref RDY); + ser.Sync("TotalExecutedCycles", ref TotalExecutedCycles); + ser.Sync("opcode", ref opcode); + ser.Sync("opcode2", ref opcode2); + ser.Sync("opcode3", ref opcode3); + ser.Sync("ea", ref ea); + ser.Sync("alu_temp", ref alu_temp); + ser.Sync("mi", ref mi); + ser.Sync("iflag_pending", ref iflag_pending); + ser.Sync("rdy_freeze", ref rdy_freeze); + ser.Sync("interrupt_pending", ref interrupt_pending); + ser.Sync("branch_irq_hack", ref branch_irq_hack); + ser.EndSection(); + } + + + public void Reset() + { + A = 0; + X = 0; + Y = 0; + P = 0; + S = 0; + PC = 0; + TotalExecutedCycles = 0; + mi = 0; + opcode = 256; + iflag_pending = true; + RDY = true; + } + + public void NESSoftReset() + { + opcode = VOP_RESET; + mi = 0; + iflag_pending = true; + FlagI = true; + } + + public string State(bool disassemble = true) + { + int notused; + string a = string.Format("{0:X4} {1:X2} {2} ", PC, _PeekMemory(PC), disassemble ? Disassemble(PC, out notused) : "---").PadRight(30); + string b = string.Format("A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5}", A, X, Y, P, S, TotalExecutedCycles); + string val = a + b + " "; + if (FlagN) val = val + "N"; + if (FlagV) val = val + "V"; + if (FlagT) val = val + "T"; + if (FlagB) val = val + "B"; + if (FlagD) val = val + "D"; + if (FlagI) val = val + "I"; + if (FlagZ) val = val + "Z"; + if (FlagC) val = val + "C"; + return val; + } + + public string TraceState() + { + // only disassemble when we're at the beginning of an opcode + return State(opcode == VOP_Fetch1 || Microcode[opcode][mi] >= Uop.End); + } + + public const ushort NMIVector = 0xFFFA; + public const ushort ResetVector = 0xFFFC; + public const ushort BRKVector = 0xFFFE; + public const ushort IRQVector = 0xFFFE; + + enum ExceptionType + { + BRK, NMI, IRQ + } + + + #region native interop + + + private void InitNative() + { + } + + [SuppressUnmanagedCodeSecurity] + [DllImport("6502XXX.dll", CallingConvention = CallingConvention.ThisCall, EntryPoint="_ZN3CPU10ExecuteOneEv")] + //[DllImport("6502XXX.dll", CallingConvention = CallingConvention.ThisCall, EntryPoint="?ExecuteOne@CPU@@QAEXXZ")] + private static extern void ExecuteOneNativeInternal(IntPtr o); + + public unsafe void ExecuteOneNative() + { + fixed (int* p = &_anchor) + { + ExecuteOneNativeInternal((IntPtr)p); + } + } + + #endregion + + public void SetCallbacks + ( + ReadDel ReadMemory, + ReadDel DummyReadMemory, + ReadDel PeekMemory, + WriteDel WriteMemory + ) + { + this.ReadMemory = ReadMemory; + this.DummyReadMemory = DummyReadMemory; + this.PeekMemory = PeekMemory; + this.WriteMemory = WriteMemory; + } + + public ushort ReadWord(ushort address) + { + byte l = _ReadMemory(address); + byte h = _ReadMemory(++address); + return (ushort)((h << 8) | l); + } + + public ushort PeekWord(ushort address) + { + byte l = _PeekMemory(address); + byte h = _PeekMemory(++address); + return (ushort)((h << 8) | l); + } + + private static readonly byte[] TableNZ = + { + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 + }; + } +} diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/TableNZ.h b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/TableNZ.h new file mode 100644 index 0000000000..18cc3d1e97 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/TableNZ.h @@ -0,0 +1,19 @@ +const byte TableNZ[] = + { + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 + }; \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/UopEnum.h b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/UopEnum.h similarity index 94% rename from BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/UopEnum.h rename to BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/UopEnum.h index 5d51cc3c15..53a44d4b19 100644 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/UopEnum.h +++ b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/UopEnum.h @@ -139,7 +139,6 @@ enum Uop { Uop_DecS, Uop_PushPCL, Uop_PushPCH, - Uop_PushPCH_B, Uop_PushP, Uop_PullP, Uop_PullPCL, @@ -250,5 +249,4 @@ enum Uop { Uop_End_BranchSpecial, Uop_End_SuppressInterrupt, }; -extern const Uop Microcode[264][8]; #endif // UOPENUM_H diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/UopTable.cpp b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/UopTable.cpp similarity index 100% rename from BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/UopTable.cpp rename to BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/UopTable.cpp diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/mingw/Makefile b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/mingw/Makefile new file mode 100644 index 0000000000..05a27cbc7b --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/6502XXX/mingw/Makefile @@ -0,0 +1,26 @@ +CXX = g++ +CXXFLAGS = -Wall -I.. -O3 -fno-exceptions -fomit-frame-pointer -std=c++11 +TARGET = 6502XXX.dll +LDFLAGS = -shared -static-libgcc -static-libstdc++ $(CXXFLAGS) +RM = rm +CP = cp + +SRCS = \ + ../execute.cpp + +OBJS = $(SRCS:.cpp=.o) + +all: $(TARGET) + +%.o: %.cpp + $(CXX) -c -o $@ $< $(CXXFLAGS) + +$(TARGET) : $(OBJS) + $(CXX) -o $@ $(LDFLAGS) $(OBJS) + +clean: + $(RM) $(OBJS) + $(RM) $(TARGET) + +install: + $(CP) $(TARGET) ../../../../../output/dll diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XDouble.cs b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XDouble.cs deleted file mode 100644 index 6cd560c402..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XDouble.cs +++ /dev/null @@ -1,242 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -using BizHawk.Common; - -namespace BizHawk.Emulation.Cores.Components.M6502 -{ - /// - /// maintains a managed 6502X and an unmanaged 6502X, running them alongside and ensuring consistency - /// by taking savestates every cycle (!). slow. - /// - /* - public class MOS6502XDouble - { - readonly MOS6502X m; - readonly MOS6502X_CPP n; - - public MOS6502XDouble() - { - m = new MOS6502X(DisposeBuilder); - n = new MOS6502X_CPP(DisposeBuilder); - BCD_Enabled = true; - m.SetCallbacks( - delegate(ushort addr) - { - byte ret = ReadMemory(addr); - reads.Enqueue(ret); - return ret; - }, - delegate(ushort addr) - { - byte ret = DummyReadMemory(addr); - reads.Enqueue(ret); - return ret; - }, - delegate(ushort addr) - { - byte ret = PeekMemory(addr); - reads.Enqueue(ret); - return ret; - }, - delegate(ushort addr, byte value) - { - writes.Enqueue(value); - WriteMemory(addr, value); - }); - n.SetCallbacks( - delegate(ushort addr) - { - if (reads.Count > 0) - return reads.Dequeue(); - else - { - PreCrash(); - throw new Exception("native did extra read!"); - } - }, - delegate(ushort addr) - { - if (reads.Count > 0) - return reads.Dequeue(); - else - { - PreCrash(); - throw new Exception("native did extra read!"); - } - }, - delegate(ushort addr, byte value) - { - if (writes.Count > 0) - { - byte test = writes.Dequeue(); - if (test != value) - { - PreCrash(); - throw new Exception(string.Format("writes were different! managed {0} native {1}", test, value)); - } - // ignore because the write already happened - } - else - { - PreCrash(); - throw new Exception("native did extra write!"); - } - }, DisposeBuilder); - - SyncUp(); - } - Queue reads = new Queue(); - Queue writes = new Queue(); - - private bool _BCD_Enabled; - public bool BCD_Enabled { get { return _BCD_Enabled; } set { _BCD_Enabled = value; m.BCD_Enabled = value; n.BCD_Enabled = value; } } - public bool debug { get; private set; } - public bool throw_unhandled { get; private set; } - - public byte A { get; private set; } - public byte X { get; private set; } - public byte Y { get; private set; } - byte _P; - public byte P { get { return _P; } set { _P = value; m.P = value; n.P = value; SyncUp(); } } - ushort _PC; - public ushort PC { get { return _PC; } set { _PC = value; m.PC = value; n.PC = value; SyncUp(); } } - byte _S; - public byte S { get { return _S; } set { _S = value; m.S = value; n.S = value; SyncUp(); } } - - bool _IRQ; - public bool IRQ { get { return _IRQ; } set { _IRQ = value; m.IRQ = value; n.IRQ = value; } } - bool _NMI; - public bool NMI { get { return _NMI; } set { _NMI = value; m.NMI = value; n.NMI = value; } } - - public int TotalExecutedCycles { get; private set; } - - public Func ReadMemory; //{ set { m.ReadMemory = value; n.ReadMemory = value; } } - public Func DummyReadMemory; //{ set { m.DummyReadMemory = value; n.DummyReadMemory = value; } } - public Func PeekMemory; //{ set { m.ReadMemory = value; n.ReadMemory = value; } } - public Action WriteMemory; //{ set { m.WriteMemory = value; n.WriteMemory = value; } } - - public void SetCallbacks - ( - Func ReadMemory, - Func DummyReadMemory, - Func PeekMemory, - Action WriteMemory, - Action DisposeBuilder - ) - { - this.ReadMemory = ReadMemory; - this.DummyReadMemory = DummyReadMemory; - this.PeekMemory = PeekMemory; - this.WriteMemory = WriteMemory; - } - - - string oldleft = ""; - string oldright = ""; - void PreCrash() - { - Console.WriteLine(String.Format("about to crash! cached:\n==managed==\n{0}\n==native==\n{1}\n", oldleft, oldright)); - } - void TestQueue() - { - if (reads.Count > 0) - { - PreCrash(); - throw new Exception("managed did extra read!"); - } - if (writes.Count > 0) - { - PreCrash(); - throw new Exception("managed did extra write!"); - } - } - - void SyncUp() - { - TestQueue(); - StringWriter sm = new StringWriter(); - Serializer ssm = new Serializer(sm); - m.SyncState(ssm); - sm.Flush(); - - StringWriter sn = new StringWriter(); - Serializer ssn = new Serializer(sn); - n.SyncState(ssn); - sn.Flush(); - - string sssm = sm.ToString(); - string sssn = sn.ToString(); - - if (sssm != sssn) - { - PreCrash(); - throw new Exception(string.Format("save mismatch!\n==managed==\n{0}\n==native==\n{1}\n", sssm, sssn)); - } - A = m.A; - X = m.X; - Y = m.Y; - _P = m.P; - _PC = m.PC; - _S = m.S; - _IRQ = m.IRQ; - _NMI = m.NMI; - oldleft = sssm; - oldright = sssn; - } - - void MtoN() - { - StringWriter sm = new StringWriter(); - Serializer ssm = new Serializer(sm); - m.SyncState(ssm); - sm.Flush(); - StringReader sn = new StringReader(sm.ToString()); - Serializer ssn = new Serializer(sn); - n.SyncState(ssn); - } - - public string State() - { - SyncUp(); - return m.State(); - } - - public void NESSoftReset() - { - m.NESSoftReset(); - n.NESSoftReset(); - SyncUp(); - } - - public void ExecuteOne() - { - m.ExecuteOne(); - n.ExecuteOne(); - SyncUp(); - } - - public void SyncState(Serializer ser) - { - // doesn't work quite as expected because you can't rewind a ser - SyncUp(); - if (ser.IsWriter) - { - // since SyncUp() guarantees that states are the same, we only need write one - m.SyncState(ser); - } - else - { - // daisy chain the state - m.SyncState(ser); - MtoN(); - } - SyncUp(); - } - - public string Disassemble(ushort pc, out int bytesToAdvance) { bytesToAdvance = 1; return "FOOBAR"; } - - } - */ -} diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative.cs b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative.cs deleted file mode 100644 index e66012de60..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative.cs +++ /dev/null @@ -1,218 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -using BizHawk.Common; - -namespace BizHawk.Emulation.Cores.Components.M6502 -{ - public static class MOS6502X_DLL - { - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate byte ReadMemoryD(ushort addr); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void WriteMemoryD(ushort addr, byte value); - - [DllImport("MOS6502XNative.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr Create(); - [DllImport("MOS6502XNative.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern void Destroy(IntPtr ptr); - - [DllImport("MOS6502XNative.dll", CallingConvention = CallingConvention.ThisCall, EntryPoint = "?Reset@MOS6502X@@QAEXXZ")] - internal static extern void Reset(IntPtr ptr); - - [DllImport("MOS6502XNative.dll", CallingConvention = CallingConvention.ThisCall, EntryPoint = "?NESSoftReset@MOS6502X@@QAEXXZ")] - internal static extern void NESSoftReset(IntPtr ptr); - - [DllImport("MOS6502XNative.dll", CallingConvention = CallingConvention.ThisCall, EntryPoint = "?ExecuteOne@MOS6502X@@QAEXXZ")] - internal static extern void ExecuteOne(IntPtr ptr); - - [DllImport("MOS6502XNative.dll", CallingConvention = CallingConvention.ThisCall, EntryPoint = "?SetTrampolines@MOS6502X@@QAEXP6AEG@Z0P6AXGE@Z@Z")] - internal static extern void SetTrampolines(IntPtr ptr, ReadMemoryD Read, ReadMemoryD DummyRead, WriteMemoryD Write); - } - - /// - /// MOS6502X core in unmanaged code - /// - [StructLayout(LayoutKind.Explicit)] - public class MOS6502X_CPP - { - /* - * In order to get anywhere near usable performance, the class is cleared of all unblittable types, - * set up with identical memory order to a C++ class, and then GC pinned for the duration. A - * naive pinvoke attempt will produce 1/7th the performance of this. - */ - - // these are aliased to a C++ class, so don't move them - #region c++ alias - - // C# bool is not blittable! - [FieldOffset(0x00), MarshalAs(UnmanagedType.U1)] - byte _BCD_Enabled; - [FieldOffset(0x01), MarshalAs(UnmanagedType.U1)] - public byte debug; - [FieldOffset(0x02), MarshalAs(UnmanagedType.U1)] - public byte throw_unhandled; - - [FieldOffset(0x03)] - public byte A; - [FieldOffset(0x04)] - public byte X; - [FieldOffset(0x05)] - public byte Y; - [FieldOffset(0x06)] - public byte P; - [FieldOffset(0x08)] - public ushort PC; - [FieldOffset(0x0a)] - public byte S; - - [FieldOffset(0x0b), MarshalAs(UnmanagedType.U1)] - byte _IRQ; - [FieldOffset(0x0c), MarshalAs(UnmanagedType.U1)] - byte _NMI; - - [FieldOffset(0x10)] - public int TotalExecutedCycles; - - // delegates are not blittable, so pretend they aren't there - [FieldOffset(0x14)] - IntPtr ZZZ000; - //public MOS6502X_DLL.ReadMemoryD ReadMemory; - [FieldOffset(0x18)] - IntPtr ZZZ001; - //public MOS6502X_DLL.ReadMemoryD DummyReadMemory; - [FieldOffset(0x1c)] - IntPtr ZZZ002; - //public MOS6502X_DLL.WriteMemoryD WriteMemory; - - //opcode bytes.. theoretically redundant with the temp variables? who knows. - [FieldOffset(0x20)] - public int opcode; - [FieldOffset(0x24)] - public byte opcode2; - [FieldOffset(0x25)] - public byte opcode3; - - [FieldOffset(0x28)] - public int ea; - [FieldOffset(0x2c)] - public int alu_temp; //cpu internal temp variables - [FieldOffset(0x30)] - public int mi; //microcode index - [FieldOffset(0x34), MarshalAs(UnmanagedType.U1)] - public byte iflag_pending; //iflag must be stored after it is checked in some cases (CLI and SEI). - - //tracks whether an interrupt condition has popped up recently. - //not sure if this is real or not but it helps with the branch_irq_hack - [FieldOffset(0x35), MarshalAs(UnmanagedType.U1)] - public byte interrupt_pending; - [FieldOffset(0x36), MarshalAs(UnmanagedType.U1)] - public byte branch_irq_hack; //see Uop.RelBranch_Stage3 for more details - - #endregion - - [FieldOffset(0x48)] - IntPtr pthis; - - // for fields which were converted from bool to byte, use props for backwards compatibility - public bool IRQ { get { return _IRQ != 0; } set { _IRQ = (byte)(value ? 1 : 0); } } - public bool NMI { get { return _NMI != 0; } set { _NMI = (byte)(value ? 1 : 0); } } - public bool BCD_Enabled { get { return _BCD_Enabled != 0; } set { _BCD_Enabled = (byte)(value ? 1 : 0); } } - - public MOS6502X_CPP(Action DisposeBuilder) - { - // this bit of foolery is only needed if you actually need to run the native-side constructor - //IntPtr native = MOS6502X_DLL.Create(); - //if (native == null) - // throw new Exception("Native constructor returned null!"); - - var h = GCHandle.Alloc(this, GCHandleType.Pinned); - pthis = h.AddrOfPinnedObject(); - - // bad - use memcpy instead - //Marshal.PtrToStructure(native, this); - - //MOS6502X_DLL.Destroy(native); - - BCD_Enabled = true; - - MOS6502X_DLL.Reset(pthis); - - DisposeBuilder(h); - } - - public void Reset() { MOS6502X_DLL.Reset(pthis); } - public void NESSoftReset() { MOS6502X_DLL.NESSoftReset(pthis); } - public void ExecuteOne() { MOS6502X_DLL.ExecuteOne(pthis); } - - public string State() { return "FOOBAR"; } /* - { - int notused; - string a = string.Format("{0:X4} {1:X2} {2} ", PC, ReadMemory(PC), Disassemble(PC, out notused)).PadRight(30); - string b = string.Format("A:{0:X2} X:{1:X2} Y:{2:X2} P:{3:X2} SP:{4:X2} Cy:{5}", A, X, Y, P, S, TotalExecutedCycles); - string val = a + b + " "; - if (FlagN) val = val + "N"; - if (FlagV) val = val + "V"; - if (FlagT) val = val + "T"; - if (FlagB) val = val + "B"; - if (FlagD) val = val + "D"; - if (FlagI) val = val + "I"; - if (FlagZ) val = val + "Z"; - if (FlagC) val = val + "C"; - return val; - }*/ - - // to maintain savestate compatibility, we have bytes that we serialize as bool - static void SyncByteFakeBool(Serializer ser, string name, ref byte loc) - { - bool tmp = loc != 0; - ser.Sync(name, ref tmp); - loc = (byte)(tmp ? 1 : 0); - } - - public void SyncState(Serializer ser) - { - ser.BeginSection("MOS6502X"); - ser.Sync("A", ref A); - ser.Sync("X", ref X); - ser.Sync("Y", ref Y); - ser.Sync("P", ref P); - ser.Sync("PC", ref PC); - ser.Sync("S", ref S); - SyncByteFakeBool(ser, "NMI", ref _NMI);//ser.Sync("NMI", ref _NMI); - SyncByteFakeBool(ser, "IRQ", ref _IRQ);//ser.Sync("IRQ", ref _IRQ); - ser.Sync("TotalExecutedCycles", ref TotalExecutedCycles); - ser.Sync("opcode", ref opcode); - ser.Sync("opcode2", ref opcode2); - ser.Sync("opcode3", ref opcode3); - ser.Sync("ea", ref ea); - ser.Sync("alu_temp", ref alu_temp); - ser.Sync("mi", ref mi); - SyncByteFakeBool(ser, "iflag_pending", ref iflag_pending); //ser.Sync("iflag_pending", ref iflag_pending); - SyncByteFakeBool(ser, "interrupt_pending", ref interrupt_pending); //ser.Sync("interrupt_pending", ref interrupt_pending); - SyncByteFakeBool(ser, "branch_irq_hack", ref branch_irq_hack); //ser.Sync("branch_irq_hack", ref branch_irq_hack); - ser.EndSection(); - } - - public string Disassemble(ushort pc, out int bytesToAdvance) { bytesToAdvance = 1; return "FOOBAR"; } - - public void SetCallbacks - (Func ReadMemory, - Func DummyReadMemory, - Action WriteMemory, Action DisposeBuilder) - { - var d1 = new MOS6502X_DLL.ReadMemoryD(ReadMemory); - var h1 = GCHandle.Alloc(d1); - var d2 = new MOS6502X_DLL.ReadMemoryD(DummyReadMemory); - var h2 = GCHandle.Alloc(d2); - var d3 = new MOS6502X_DLL.WriteMemoryD(WriteMemory); - var h3 = GCHandle.Alloc(d3); - - MOS6502X_DLL.SetTrampolines(pthis, d1, d2, d3); - DisposeBuilder(h1); - DisposeBuilder(h2); - DisposeBuilder(h3); - } - } - -} diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/Execute.cpp b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/Execute.cpp deleted file mode 100644 index 0bea96b118..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/Execute.cpp +++ /dev/null @@ -1,1170 +0,0 @@ -#include "MOS6502X.h" -#include "UopEnum.h" - -const int VOP_Fetch1 = 256; -const int VOP_RelativeStuff = 257; -const int VOP_RelativeStuff2 = 258; -const int VOP_RelativeStuff3 = 259; -const int VOP_NMI = 260; -const int VOP_IRQ = 261; -const int VOP_RESET = 262; -const int VOP_Fetch1_NoInterrupt = 263; - -const ushort NMIVector = 0xFFFA; -const ushort ResetVector = 0xFFFC; -const ushort BRKVector = 0xFFFE; -const ushort IRQVector = 0xFFFE; - -const byte TableNZ[] = -{ - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 -}; - - - -#define BIT(x,b) (((x) & (1 << (b))) != 0) - -#define GetFlagC (((P) & 0x01) != 0) -#define GetFlagZ (((P) & 0x02) != 0) -#define GetFlagI (((P) & 0x04) != 0) -#define GetFlagD (((P) & 0x08) != 0) -#define GetFlagB (((P) & 0x10) != 0) -#define GetFlagT (((P) & 0x20) != 0) -#define GetFlagV (((P) & 0x40) != 0) -#define GetFlagN (((P) & 0x80) != 0) - -#define SetFlagC(value) {P = (P & ~0x01) | (value ? 0x01 : 0x00);} -#define SetFlagZ(value) {P = (P & ~0x02) | (value ? 0x02 : 0x00);} -#define SetFlagI(value) {P = (P & ~0x04) | (value ? 0x04 : 0x00);} -#define SetFlagD(value) {P = (P & ~0x08) | (value ? 0x08 : 0x00);} -#define SetFlagB(value) {P = (P & ~0x10) | (value ? 0x10 : 0x00);} -#define SetFlagT(value) {P = (P & ~0x20) | (value ? 0x20 : 0x00);} -#define SetFlagV(value) {P = (P & ~0x40) | (value ? 0x40 : 0x00);} -#define SetFlagN(value) {P = (P & ~0x80) | (value ? 0x80 : 0x00);} - -void MOS6502X::NESSoftReset() -{ - opcode = VOP_RESET; - mi = 0; - iflag_pending = true; - SetFlagI(true); -} - -void MOS6502X::ExecuteOne() -{ - byte value8, temp8; - ushort value16; - bool branch_taken = false; - - TotalExecutedCycles++; - - interrupt_pending |= NMI || (IRQ && !GetFlagI); - -RETRY: - Uop uop = Microcode[opcode][mi]; - switch (uop) - { - //default: throw new InvalidOperationException(); - case Uop_Fetch1: - { - bool my_iflag = GetFlagI; - SetFlagI(iflag_pending); - if (!branch_irq_hack) - { - interrupt_pending = false; - if (NMI) - { - ea = NMIVector; - opcode = VOP_NMI; - NMI = false; - mi = 0; - goto RETRY; - } - else if (IRQ && !my_iflag) - { - ea = IRQVector; - opcode = VOP_IRQ; - mi = 0; - goto RETRY; - } - } - goto case_Uop_Fetch1_Real; - } - -case_Uop_Fetch1_Real: case Uop_Fetch1_Real: - //if (debug) Console.WriteLine(State()); - branch_irq_hack = false; - opcode = ReadMemory(PC++); - mi = -1; - break; - -case Uop_Fetch2: opcode2 = ReadMemory(PC++); break; -case Uop_Fetch3: opcode3 = ReadMemory(PC++); break; -case Uop_FetchDummy: FetchDummy(); break; - -case Uop_PushPCH: WriteMemory((ushort)(S-- + 0x100), (byte)(PC >> 8)); break; -case Uop_PushPCL: WriteMemory((ushort)(S-- + 0x100), (byte)PC); break; -case Uop_PushP_BRK: - SetFlagB(true); - WriteMemory((ushort)(S-- + 0x100), P); - SetFlagI(true); - ea = BRKVector; - break; -case Uop_PushP_IRQ: - SetFlagB(false); - WriteMemory((ushort)(S-- + 0x100), P); - SetFlagI(true); - ea = IRQVector; - break; -case Uop_PushP_NMI: - SetFlagB(false); - WriteMemory((ushort)(S-- + 0x100), P); - SetFlagI(true); //is this right? - ea = NMIVector; - break; -case Uop_PushP_Reset: - ea = ResetVector; - S--; - SetFlagI(true); - break; -case Uop_PushDummy: - S--; - break; -case Uop_FetchPCLVector: - if (ea == BRKVector && GetFlagB && NMI) - { - NMI = false; - ea = NMIVector; - } - if(ea == IRQVector && !GetFlagB && NMI) - { - NMI = false; - ea = NMIVector; - } - alu_temp = ReadMemory((ushort)ea); - break; -case Uop_FetchPCHVector: - alu_temp += ReadMemory((ushort)(ea + 1)) << 8; - PC = (ushort)alu_temp; - break; - - -case Uop_Imp_INY: FetchDummy(); Y++; goto case_Uop_NZ_Y; -case Uop_Imp_DEY: FetchDummy(); Y--; goto case_Uop_NZ_Y; -case Uop_Imp_INX: FetchDummy(); X++; goto case_Uop_NZ_X; -case Uop_Imp_DEX: FetchDummy(); X--; goto case_Uop_NZ_X; - -case_Uop_NZ_A: case Uop_NZ_A: P = (byte)((P & 0x7D) | TableNZ[A]); break; -case_Uop_NZ_X: case Uop_NZ_X: P = (byte)((P & 0x7D) | TableNZ[X]); break; -case_Uop_NZ_Y: case Uop_NZ_Y: P = (byte)((P & 0x7D) | TableNZ[Y]); break; - -case Uop_Imp_TSX: FetchDummy(); X = S; goto case_Uop_NZ_X; -case Uop_Imp_TXS: FetchDummy(); S = X; break; -case Uop_Imp_TAX: FetchDummy(); X = A; goto case_Uop_NZ_X; -case Uop_Imp_TAY: FetchDummy(); Y = A; goto case_Uop_NZ_Y; -case Uop_Imp_TYA: FetchDummy(); A = Y; goto case_Uop_NZ_A; -case Uop_Imp_TXA: FetchDummy(); A = X; goto case_Uop_NZ_A; - -case Uop_Imp_SEI: FetchDummy(); iflag_pending = true; break; -case Uop_Imp_CLI: FetchDummy(); iflag_pending = false; break; -case Uop_Imp_SEC: FetchDummy(); SetFlagC(true); break; -case Uop_Imp_CLC: FetchDummy(); SetFlagC(false); break; -case Uop_Imp_SED: FetchDummy(); SetFlagD(true); break; -case Uop_Imp_CLD: FetchDummy(); SetFlagD(false); break; -case Uop_Imp_CLV: FetchDummy(); SetFlagV(false); break; - -case Uop_Abs_WRITE_STA: WriteMemory((ushort)((opcode3 << 8) + opcode2), A); break; -case Uop_Abs_WRITE_STX: WriteMemory((ushort)((opcode3 << 8) + opcode2), X); break; -case Uop_Abs_WRITE_STY: WriteMemory((ushort)((opcode3 << 8) + opcode2), Y); break; -case Uop_Abs_WRITE_SAX: WriteMemory((ushort)((opcode3 << 8) + opcode2), (byte)(X & A)); break; - -case Uop_ZP_WRITE_STA: WriteMemory(opcode2, A); break; -case Uop_ZP_WRITE_STY: WriteMemory(opcode2, Y); break; -case Uop_ZP_WRITE_STX: WriteMemory(opcode2, X); break; -case Uop_ZP_WRITE_SAX: WriteMemory(opcode2, (byte)(X & A)); break; - -case Uop_IndIdx_Stage3: - ea = ReadMemory(opcode2); - break; -case Uop_IndIdx_Stage4: - alu_temp = ea + Y; - ea = (ReadMemory((byte)(opcode2+1))<<8) - | ((alu_temp&0xFF)); - break; -case Uop_IndIdx_WRITE_Stage5: - ReadMemory((ushort)ea); - ea += (alu_temp >> 8) << 8; - break; -case Uop_IndIdx_READ_Stage5: - if (!BIT(alu_temp,8)) - { - mi++; - goto RETRY; - } - else - { - ReadMemory((ushort)ea); - ea = (ushort)(ea + 0x100); - } - break; -case Uop_IndIdx_RMW_Stage5: - if (BIT(alu_temp,8)) - ea = (ushort)(ea + 0x100); - ReadMemory((ushort)ea); - break; -case Uop_IndIdx_WRITE_Stage6_STA: - WriteMemory((ushort)ea, A); - break; -case Uop_IndIdx_WRITE_Stage6_SHA: - WriteMemory((ushort)ea, (byte)(A&X&7)); - break; -case Uop_IndIdx_READ_Stage6_LDA: - A = ReadMemory((ushort)ea); - goto case_Uop_NZ_A; -case Uop_IndIdx_READ_Stage6_CMP: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Cmp; -case Uop_IndIdx_READ_Stage6_AND: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__And; -case Uop_IndIdx_READ_Stage6_EOR: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Eor; -case Uop_IndIdx_READ_Stage6_LAX: - A = X = ReadMemory((ushort)ea); - goto case_Uop_NZ_A; -case Uop_IndIdx_READ_Stage6_ADC: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Adc; -case Uop_IndIdx_READ_Stage6_SBC: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Sbc; -case Uop_IndIdx_READ_Stage6_ORA: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Ora; -case Uop_IndIdx_RMW_Stage6: - alu_temp = ReadMemory((ushort)ea); - break; -case Uop_IndIdx_RMW_Stage7_SLO: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 0x80) != 0); - alu_temp = value8 = (byte)((value8 << 1)); - A |= value8; - goto case_Uop_NZ_A; -case Uop_IndIdx_RMW_Stage7_SRE: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 1) != 0); - alu_temp = value8 = (byte)(value8 >> 1); - A ^= value8; - goto case_Uop_NZ_A; -case Uop_IndIdx_RMW_Stage7_RRA: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); - SetFlagC((temp8 & 1) != 0); - goto case_Uop__Adc; -case Uop_IndIdx_RMW_Stage7_ISC: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)(value8 + 1); - goto case_Uop__Sbc; -case Uop_IndIdx_RMW_Stage7_DCP: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)(value8 - 1); - SetFlagC((temp8 & 1) != 0); - goto case_Uop__Cmp; -case Uop_IndIdx_RMW_Stage7_RLA: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); - SetFlagC((temp8 & 0x80) != 0); - A &= value8; - goto case_Uop_NZ_A; -case Uop_IndIdx_RMW_Stage8: - WriteMemory((ushort)ea, (byte)alu_temp); - break; - -case Uop_RelBranch_Stage2_BVS: - branch_taken = GetFlagV == true; - goto case_Uop_RelBranch_Stage2; -case Uop_RelBranch_Stage2_BVC: - branch_taken = GetFlagV == false; - goto case_Uop_RelBranch_Stage2; -case Uop_RelBranch_Stage2_BMI: - branch_taken = GetFlagN == true; - goto case_Uop_RelBranch_Stage2; -case Uop_RelBranch_Stage2_BPL: - branch_taken = GetFlagN == false; - goto case_Uop_RelBranch_Stage2; -case Uop_RelBranch_Stage2_BCS: - branch_taken = GetFlagC == true; - goto case_Uop_RelBranch_Stage2; -case Uop_RelBranch_Stage2_BCC: - branch_taken = GetFlagC == false; - goto case_Uop_RelBranch_Stage2; -case Uop_RelBranch_Stage2_BEQ: - branch_taken = GetFlagZ == true; - goto case_Uop_RelBranch_Stage2; -case Uop_RelBranch_Stage2_BNE: - branch_taken = GetFlagZ == false; - goto case_Uop_RelBranch_Stage2; - -case_Uop_RelBranch_Stage2: case Uop_RelBranch_Stage2: - opcode2 = ReadMemory(PC++); - if (branch_taken) - { - //if the branch is taken, we enter a different bit of microcode to calculate the PC and complete the branch - opcode = VOP_RelativeStuff; - mi = -1; - } - - break; -case Uop_RelBranch_Stage3: - FetchDummy(); - alu_temp = (byte)PC + (int)(sbyte)opcode2; - PC &= 0xFF00; - PC |= (ushort)((alu_temp&0xFF)); - if (BIT(alu_temp,8)) - { - //we need to carry the add, and then we'll be ready to fetch the next instruction - opcode = VOP_RelativeStuff2; - mi = -1; - } - else - { - //to pass cpu_interrupts_v2/5-branch_delays_irq we need to handle a quirk here - //if we decide to interrupt in the next cycle, this condition will cause it to get deferred by one instruction - if(!interrupt_pending) - branch_irq_hack = true; - } - break; -case Uop_RelBranch_Stage4: - FetchDummy(); - if (BIT(alu_temp,31)) - PC = (ushort)(PC - 0x100); - else PC = (ushort)(PC + 0x100); - break; - -case Uop_NOP: break; -case Uop_DecS: S--; break; -case Uop_IncS: S++; break; -case Uop_JSR: PC = (ushort)((ReadMemory((ushort)(PC)) << 8) + opcode2); break; -case Uop_PullP: - P = ReadMemory((ushort)(S++ + 0x100)); - SetFlagT(true); //force T always to remain true - break; -case Uop_PullPCL: - PC &= 0xFF00; - PC |= ReadMemory((ushort)(S++ + 0x100)); - break; -case Uop_PullPCH_NoInc: - PC &= 0xFF; - PC |= (ushort)(ReadMemory((ushort)(S + 0x100)) << 8); - break; - -case Uop_Abs_READ_LDA: - A = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop_NZ_A; -case Uop_Abs_READ_LDY: - Y = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop_NZ_Y; -case Uop_Abs_READ_LDX: - X = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop_NZ_X; -case Uop_Abs_READ_BIT: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop__Bit; -case Uop_Abs_READ_LAX: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - A = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - X = A; - goto case_Uop_NZ_A; -case Uop_Abs_READ_AND: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop__And; -case Uop_Abs_READ_EOR: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop__Eor; -case Uop_Abs_READ_ORA: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop__Ora; -case Uop_Abs_READ_ADC: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop__Adc; -case Uop_Abs_READ_CMP: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop__Cmp; -case Uop_Abs_READ_CPY: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop__Cpy; -case Uop_Abs_READ_NOP: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - break; -case Uop_Abs_READ_CPX: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop__Cpx; -case Uop_Abs_READ_SBC: - alu_temp = ReadMemory((ushort)((opcode3 << 8) + opcode2)); - goto case_Uop__Sbc; - -case Uop_ZpIdx_Stage3_X: - ReadMemory(opcode2); - opcode2 = (byte)(opcode2 + X); //a bit sneaky to shove this into opcode2... but we can reuse all the zero page uops if we do that - break; -case Uop_ZpIdx_Stage3_Y: - ReadMemory(opcode2); - opcode2 = (byte)(opcode2 + Y); //a bit sneaky to shove this into opcode2... but we can reuse all the zero page uops if we do that - break; -case Uop_ZpIdx_RMW_Stage4: - alu_temp = ReadMemory(opcode2); - break; -case Uop_ZpIdx_RMW_Stage6: - WriteMemory(opcode2, (byte)alu_temp); - break; - -case Uop_ZP_READ_EOR: - alu_temp = ReadMemory(opcode2); - goto case_Uop__Eor; -case Uop_ZP_READ_BIT: - alu_temp = ReadMemory(opcode2); - goto case_Uop__Bit; -case Uop_ZP_READ_LDA: - A = ReadMemory(opcode2); - goto case_Uop_NZ_A; -case Uop_ZP_READ_LDY: - Y = ReadMemory(opcode2); - goto case_Uop_NZ_Y; -case Uop_ZP_READ_LDX: - X = ReadMemory(opcode2); - goto case_Uop_NZ_X; -case Uop_ZP_READ_LAX: - //?? is this right?? - X = ReadMemory(opcode2); - A = X; - goto case_Uop_NZ_A; -case Uop_ZP_READ_CPY: - alu_temp = ReadMemory(opcode2); - goto case_Uop__Cpy; -case Uop_ZP_READ_CMP: - alu_temp = ReadMemory(opcode2); - goto case_Uop__Cmp; -case Uop_ZP_READ_CPX: - alu_temp = ReadMemory(opcode2); - goto case_Uop__Cpx; -case Uop_ZP_READ_ORA: - alu_temp = ReadMemory(opcode2); - goto case_Uop__Ora; -case Uop_ZP_READ_NOP: - ReadMemory(opcode2); //just a dummy - break; -case Uop_ZP_READ_SBC: - alu_temp = ReadMemory(opcode2); - goto case_Uop__Sbc; -case Uop_ZP_READ_ADC: - alu_temp = ReadMemory(opcode2); - goto case_Uop__Adc; -case Uop_ZP_READ_AND: - alu_temp = ReadMemory(opcode2); - goto case_Uop__And; - -case_Uop__Cpx: case Uop__Cpx: - value8 = (byte)alu_temp; - value16 = (ushort)(X - value8); - SetFlagC(X >= value8); - P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); - break; -case_Uop__Cpy: case Uop__Cpy: - value8 = (byte)alu_temp; - value16 = (ushort)(Y - value8); - SetFlagC(Y >= value8); - P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); - break; -case_Uop__Cmp: case Uop__Cmp: - value8 = (byte)alu_temp; - value16 = (ushort)(A - value8); - SetFlagC(A >= value8); - P = (byte)((P & 0x7D) | TableNZ[(byte)value16]); - break; -case_Uop__Bit: case Uop__Bit: - SetFlagN((alu_temp & 0x80) != 0); - SetFlagV((alu_temp & 0x40) != 0); - SetFlagZ((A & alu_temp) == 0); - break; -case_Uop__Eor: case Uop__Eor: - A ^= (byte)alu_temp; - goto case_Uop_NZ_A; -case_Uop__And: case Uop__And: - A &= (byte)alu_temp; - goto case_Uop_NZ_A; -case_Uop__Ora: case Uop__Ora: - A |= (byte)alu_temp; - goto case_Uop_NZ_A; -case_Uop__Anc: case Uop__Anc: - A &= (byte)alu_temp; - SetFlagC(BIT(A,7)); - goto case_Uop_NZ_A; -case_Uop__Asr: case Uop__Asr: - A &= (byte)alu_temp; - SetFlagC(BIT(A,0)); - A >>= 1; - goto case_Uop_NZ_A; -case_Uop__Axs: case Uop__Axs: - X &= A; - alu_temp = X - (byte)alu_temp; - X = (byte)alu_temp; - SetFlagC(!BIT(alu_temp,8)); - goto case_Uop_NZ_X; -case_Uop__Arr: case Uop__Arr: - { - A &= (byte)alu_temp; - bool temp = BIT(A,0); - A = (byte)((A >> 1) | (GetFlagC ? 0x80 : 0x00)); - SetFlagC(temp); - if (BIT(A,5)) - if (BIT(A,6)) - { SetFlagC(true); SetFlagV(false); } - else { SetFlagV(true); SetFlagC(false); } - else if (BIT(A,6)) - { SetFlagV(true); SetFlagC(true); } - else { SetFlagV(false); SetFlagC(false); } - SetFlagZ(A == 0); - break; - } -case_Uop__Lxa: case Uop__Lxa: - A |= 0xFF; //there is some debate about what this should be. it may depend on the 6502 variant. this is suggested by qeed's doc for the nes and passes blargg's instruction test - A &= (byte)alu_temp; - X = A; - goto case_Uop_NZ_A; -case_Uop__Sbc: case Uop__Sbc: - { - value8 = (byte)alu_temp; - int temp = A - value8 - (GetFlagC ? 0 : 1); - if (GetFlagD && BCD_Enabled) - { - int lo = (A & 0x0F) - (value8 & 0x0F) - (GetFlagC ? 0 : 1); - int hi = (A & 0xF0) - (value8 & 0xF0); - if ((lo & 0xF0) != 0) lo -= 0x06; - if ((lo & 0x80) != 0) hi -= 0x10; - if ((hi & 0x0F00) != 0) hi -= 0x60; - SetFlagV(((A ^ value8) & (A ^ temp) & 0x80) != 0); - SetFlagC((hi & 0xFF00) == 0); - A = (byte)((lo & 0x0F) | (hi & 0xF0)); - } - else - { - SetFlagV(((A ^ value8) & (A ^ temp) & 0x80) != 0); - SetFlagC(temp >= 0); - A = (byte)temp; - } - goto case_Uop_NZ_A; - } -case_Uop__Adc: case Uop__Adc: - { - //TODO - an extra cycle penalty? - value8 = (byte)alu_temp; - if (GetFlagD && BCD_Enabled) - { - int lo = (A & 0x0F) + (value8 & 0x0F) + (GetFlagC ? 1 : 0); - int hi = (A & 0xF0) + (value8 & 0xF0); - if (lo > 0x09) - { - hi += 0x10; - lo += 0x06; - } - if (hi > 0x90) hi += 0x60; - SetFlagV((~(A ^ value8) & (A ^ hi) & 0x80) != 0); - SetFlagC(hi > 0xFF); - A = (byte)((lo & 0x0F) | (hi & 0xF0)); - } - else - { - int temp = value8 + A + (GetFlagC ? 1 : 0); - SetFlagV((~(A ^ value8) & (A ^ temp) & 0x80) != 0); - SetFlagC(temp > 0xFF); - A = (byte)temp; - } - goto case_Uop_NZ_A; - } - -case Uop_Unsupported: - break; - -case Uop_Imm_EOR: - alu_temp = ReadMemory(PC++); - goto case_Uop__Eor; -case Uop_Imm_ANC: - alu_temp = ReadMemory(PC++); - goto case_Uop__Anc; -case Uop_Imm_ASR: - alu_temp = ReadMemory(PC++); - goto case_Uop__Asr; -case Uop_Imm_AXS: - alu_temp = ReadMemory(PC++); - goto case_Uop__Axs; -case Uop_Imm_ARR: - alu_temp = ReadMemory(PC++); - goto case_Uop__Arr; -case Uop_Imm_LXA: - alu_temp = ReadMemory(PC++); - goto case_Uop__Lxa; -case Uop_Imm_ORA: - alu_temp = ReadMemory(PC++); - goto case_Uop__Ora; -case Uop_Imm_CPY: - alu_temp = ReadMemory(PC++); - goto case_Uop__Cpy; -case Uop_Imm_CPX: - alu_temp = ReadMemory(PC++); - goto case_Uop__Cpx; -case Uop_Imm_CMP: - alu_temp = ReadMemory(PC++); - goto case_Uop__Cmp; -case Uop_Imm_SBC: - alu_temp = ReadMemory(PC++); - goto case_Uop__Sbc; -case Uop_Imm_AND: - alu_temp = ReadMemory(PC++); - goto case_Uop__And; -case Uop_Imm_ADC: - alu_temp = ReadMemory(PC++); - goto case_Uop__Adc; -case Uop_Imm_LDA: - A = ReadMemory(PC++); - goto case_Uop_NZ_A; -case Uop_Imm_LDX: - X = ReadMemory(PC++); - goto case_Uop_NZ_X; -case Uop_Imm_LDY: - Y = ReadMemory(PC++); - goto case_Uop_NZ_Y; -case Uop_Imm_Unsupported: - ReadMemory(PC++); - break; - -case Uop_IdxInd_Stage3: - ReadMemory(opcode2); //dummy? - alu_temp = (opcode2 + X) & 0xFF; - break; -case Uop_IdxInd_Stage4: - ea = ReadMemory((ushort)alu_temp); - break; -case Uop_IdxInd_Stage5: - ea += (ReadMemory((byte)(alu_temp + 1)) << 8); - break; -case Uop_IdxInd_Stage6_READ_LDA: - //TODO make uniform with others - A = ReadMemory((ushort)ea); - goto case_Uop_NZ_A; -case Uop_IdxInd_Stage6_READ_ORA: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Ora; -case Uop_IdxInd_Stage6_READ_LAX: - A = X = ReadMemory((ushort)ea); - goto case_Uop_NZ_A; -case Uop_IdxInd_Stage6_READ_CMP: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Cmp; -case Uop_IdxInd_Stage6_READ_ADC: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Adc; -case Uop_IdxInd_Stage6_READ_AND: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__And; -case Uop_IdxInd_Stage6_READ_EOR: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Eor; -case Uop_IdxInd_Stage6_READ_SBC: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Sbc; -case Uop_IdxInd_Stage6_WRITE_STA: - WriteMemory((ushort)ea, A); - break; -case Uop_IdxInd_Stage6_WRITE_SAX: - alu_temp = A & X; - WriteMemory((ushort)ea, (byte)alu_temp); - //flag writing skipped on purpose - break; -case Uop_IdxInd_Stage6_RMW: - alu_temp = ReadMemory((ushort)ea); - break; -case Uop_IdxInd_Stage7_RMW_SLO: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 0x80) != 0); - alu_temp = value8 = (byte)((value8 << 1)); - A |= value8; - goto case_Uop_NZ_A; -case Uop_IdxInd_Stage7_RMW_ISC: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - alu_temp = value8 = (byte)(value8 + 1); - goto case_Uop__Sbc; -case Uop_IdxInd_Stage7_RMW_DCP: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)(value8 - 1); - SetFlagC((temp8 & 1) != 0); - goto case_Uop__Cmp; -case Uop_IdxInd_Stage7_RMW_SRE: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 1) != 0); - alu_temp = value8 = (byte)(value8 >> 1); - A ^= value8; - goto case_Uop_NZ_A; -case Uop_IdxInd_Stage7_RMW_RRA: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); - SetFlagC((temp8 & 1) != 0); - goto case_Uop__Adc; -case Uop_IdxInd_Stage7_RMW_RLA: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); - SetFlagC((temp8 & 0x80) != 0); - A &= value8; - goto case_Uop_NZ_A; -case Uop_IdxInd_Stage8_RMW: - WriteMemory((ushort)ea, (byte)alu_temp); - break; - -case Uop_PushP: - SetFlagB(true); - WriteMemory((ushort)(S-- + 0x100), P); - break; -case Uop_PushA: WriteMemory((ushort)(S-- + 0x100), A); break; -case Uop_PullA_NoInc: - A = ReadMemory((ushort)(S + 0x100)); - goto case_Uop_NZ_A; -case Uop_PullP_NoInc: - { - bool my_iflag = GetFlagI; - P = ReadMemory((ushort)(S + 0x100)); - iflag_pending = GetFlagI; - SetFlagI(my_iflag); - SetFlagT(true); //force T always to remain true - break; - } - -case Uop_Imp_ASL_A: - FetchDummy(); - SetFlagC((A & 0x80) != 0); - A = (byte)(A << 1); - goto case_Uop_NZ_A; -case Uop_Imp_ROL_A: - FetchDummy(); - temp8 = A; - A = (byte)((A << 1) | (P & 1)); - SetFlagC((temp8 & 0x80) != 0); - goto case_Uop_NZ_A; -case Uop_Imp_ROR_A: - FetchDummy(); - temp8 = A; - A = (byte)((A >> 1) | ((P & 1) << 7)); - SetFlagC((temp8 & 1) != 0); - goto case_Uop_NZ_A; -case Uop_Imp_LSR_A: - FetchDummy(); - SetFlagC((A & 1) != 0); - A = (byte)(A >> 1); - goto case_Uop_NZ_A; - -case Uop_JMP_abs: - PC = (ushort)((ReadMemory(PC) << 8) + opcode2); - break; -case Uop_IncPC: - PC++; - break; - -case Uop_ZP_RMW_Stage3: - alu_temp = ReadMemory(opcode2); - break; -case Uop_ZP_RMW_Stage5: - WriteMemory(opcode2,(byte)alu_temp); - break; -case Uop_ZP_RMW_INC: - WriteMemory(opcode2, (byte)alu_temp); - alu_temp = (byte)((alu_temp+1)&0xFF); - P = (byte)((P & 0x7D) | TableNZ[alu_temp]); - break; -case Uop_ZP_RMW_DEC: - WriteMemory(opcode2, (byte)alu_temp); - alu_temp = (byte)((alu_temp - 1) & 0xFF); - P = (byte)((P & 0x7D) | TableNZ[alu_temp]); - break; -case Uop_ZP_RMW_ASL: - WriteMemory(opcode2, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 0x80) != 0); - alu_temp = value8 = (byte)(value8 << 1); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_ZP_RMW_SRE: - WriteMemory(opcode2, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 1) != 0); - alu_temp = value8 = (byte)(value8 >> 1); - A ^= value8; - goto case_Uop_NZ_A; -case Uop_ZP_RMW_RRA: - WriteMemory(opcode2, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); - SetFlagC((temp8 & 1) != 0); - goto case_Uop__Adc; -case Uop_ZP_RMW_DCP: - WriteMemory(opcode2, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)(value8 - 1); - SetFlagC((temp8 & 1) != 0); - goto case_Uop__Cmp; -case Uop_ZP_RMW_LSR: - WriteMemory(opcode2, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 1) != 0); - alu_temp = value8 = (byte)(value8 >> 1); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_ZP_RMW_ROR: - WriteMemory(opcode2, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); - SetFlagC((temp8 & 1) != 0); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_ZP_RMW_ROL: - WriteMemory(opcode2, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); - SetFlagC((temp8 & 0x80) != 0); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_ZP_RMW_SLO: - WriteMemory(opcode2, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 0x80) != 0); - alu_temp = value8 = (byte)((value8 << 1)); - A |= value8; - goto case_Uop_NZ_A; -case Uop_ZP_RMW_ISC: - WriteMemory(opcode2, (byte)alu_temp); - value8 = (byte)alu_temp; - alu_temp = value8 = (byte)(value8 + 1); - goto case_Uop__Sbc; -case Uop_ZP_RMW_RLA: - WriteMemory(opcode2, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); - SetFlagC((temp8 & 0x80) != 0); - A &= value8; - goto case_Uop_NZ_A; - -case Uop_AbsIdx_Stage3_Y: - opcode3 = ReadMemory(PC++); - alu_temp = opcode2 + Y; - ea = (opcode3 << 8) + (alu_temp & 0xFF); - break; - //new Uop[] { Uop_Fetch2, Uop_AbsIdx_Stage3_Y, Uop_AbsIdx_Stage4, Uop_AbsIdx_WRITE_Stage5_STA, Uop_End }, -case Uop_AbsIdx_Stage3_X: - opcode3 = ReadMemory(PC++); - alu_temp = opcode2 + X; - ea = (opcode3 << 8) + (alu_temp & 0xFF); - break; -case Uop_AbsIdx_READ_Stage4: - if (!BIT(alu_temp,8)) - { - mi++; - goto RETRY; - } - else - { - alu_temp = ReadMemory((ushort)ea); - ea = (ushort)(ea + 0x100); - } - break; -case Uop_AbsIdx_Stage4: - //bleh.. redundant code to make sure we dont clobber alu_temp before using it to decide whether to change ea - if (BIT(alu_temp,8)) - { - alu_temp = ReadMemory((ushort)ea); - ea = (ushort)(ea + 0x100); - } - else alu_temp = ReadMemory((ushort)ea); - break; - -case Uop_AbsIdx_WRITE_Stage5_STA: - WriteMemory((ushort)ea, A); - break; -case Uop_AbsIdx_WRITE_Stage5_SHY: - alu_temp = Y & (ea>>8); - ea = (ea & 0xFF) | (alu_temp << 8); //"(the bank where the value is stored may be equal to the value stored)" -- more like IS. - WriteMemory((ushort)ea, (byte)alu_temp); - break; -case Uop_AbsIdx_WRITE_Stage5_SHX: - alu_temp = X & (ea >> 8); - ea = (ea & 0xFF) | (alu_temp << 8); //"(the bank where the value is stored may be equal to the value stored)" -- more like IS. - WriteMemory((ushort)ea, (byte)alu_temp); - break; -case Uop_AbsIdx_WRITE_Stage5_ERROR: - alu_temp = ReadMemory((ushort)ea); - //throw new InvalidOperationException("UNSUPPORTED OPCODE [probably SHS] PLEASE REPORT"); - break; - -case Uop_AbsIdx_RMW_Stage5: - alu_temp = ReadMemory((ushort)ea); - break; -case Uop_AbsIdx_RMW_Stage7: - WriteMemory((ushort)ea, (byte)alu_temp); - break; -case Uop_AbsIdx_RMW_Stage6_DEC: - WriteMemory((ushort)ea, (byte)alu_temp); - alu_temp = value8 = (byte)(alu_temp - 1); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_AbsIdx_RMW_Stage6_DCP: - WriteMemory((ushort)ea, (byte)alu_temp); - alu_temp = value8 = (byte)(alu_temp - 1); - goto case_Uop__Cmp; -case Uop_AbsIdx_RMW_Stage6_ISC: - WriteMemory((ushort)ea, (byte)alu_temp); - alu_temp = value8 = (byte)(alu_temp + 1); - goto case_Uop__Sbc; -case Uop_AbsIdx_RMW_Stage6_INC: - WriteMemory((ushort)ea, (byte)alu_temp); - alu_temp = value8 = (byte)(alu_temp + 1); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_AbsIdx_RMW_Stage6_ROL: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); - SetFlagC((temp8 & 0x80) != 0); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_AbsIdx_RMW_Stage6_LSR: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 1) != 0); - alu_temp = value8 = (byte)(value8 >> 1); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_AbsIdx_RMW_Stage6_SLO: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 0x80) != 0); - alu_temp = value8 = (byte)(value8 << 1); - A |= value8; - goto case_Uop_NZ_A; -case Uop_AbsIdx_RMW_Stage6_SRE: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 1) != 0); - alu_temp = value8 = (byte)(value8 >> 1); - A ^= value8; - goto case_Uop_NZ_A; -case Uop_AbsIdx_RMW_Stage6_RRA: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); - SetFlagC((temp8 & 1) != 0); - goto case_Uop__Adc; -case Uop_AbsIdx_RMW_Stage6_RLA: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); - SetFlagC((temp8 & 0x80) != 0); - A &= value8; - goto case_Uop_NZ_A; -case Uop_AbsIdx_RMW_Stage6_ASL: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 0x80) != 0); - alu_temp = value8 = (byte)(value8 << 1); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_AbsIdx_RMW_Stage6_ROR: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); - SetFlagC((temp8 & 1) != 0); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; - -case Uop_AbsIdx_READ_Stage5_LDA: - A = ReadMemory((ushort)ea); - goto case_Uop_NZ_A; -case Uop_AbsIdx_READ_Stage5_LDX: - X = ReadMemory((ushort)ea); - goto case_Uop_NZ_X; -case Uop_AbsIdx_READ_Stage5_LAX: - A = ReadMemory((ushort)ea); - X = A; - goto case_Uop_NZ_A; -case Uop_AbsIdx_READ_Stage5_LDY: - Y = ReadMemory((ushort)ea); - goto case_Uop_NZ_Y; -case Uop_AbsIdx_READ_Stage5_ORA: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Ora; -case Uop_AbsIdx_READ_Stage5_NOP: - alu_temp = ReadMemory((ushort)ea); - break; -case Uop_AbsIdx_READ_Stage5_CMP: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Cmp; -case Uop_AbsIdx_READ_Stage5_SBC: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Sbc; -case Uop_AbsIdx_READ_Stage5_ADC: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Adc; -case Uop_AbsIdx_READ_Stage5_EOR: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__Eor; -case Uop_AbsIdx_READ_Stage5_AND: - alu_temp = ReadMemory((ushort)ea); - goto case_Uop__And; -case Uop_AbsIdx_READ_Stage5_ERROR: - alu_temp = ReadMemory((ushort)ea); - //throw new InvalidOperationException("UNSUPPORTED OPCODE [probably LAS] PLEASE REPORT"); - break; - -case Uop_AbsInd_JMP_Stage4: - ea = (opcode3<<8)+opcode2; - alu_temp = ReadMemory((ushort)ea); - break; -case Uop_AbsInd_JMP_Stage5: - ea = (opcode3<<8)+(byte)(opcode2+1); - alu_temp += ReadMemory((ushort)ea) << 8; - PC = (ushort)alu_temp; - break; - -case Uop_Abs_RMW_Stage4: - ea = (opcode3<<8)+opcode2; - alu_temp = ReadMemory((ushort)ea); - break; -case Uop_Abs_RMW_Stage5_INC: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)(alu_temp + 1); - alu_temp = value8; - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_Abs_RMW_Stage5_DEC: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)(alu_temp - 1); - alu_temp = value8; - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_Abs_RMW_Stage5_DCP: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)(alu_temp - 1); - alu_temp = value8; - goto case_Uop__Cmp; -case Uop_Abs_RMW_Stage5_ISC: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)(alu_temp + 1); - alu_temp = value8; - goto case_Uop__Sbc; -case Uop_Abs_RMW_Stage5_ASL: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 0x80) != 0); - alu_temp = value8 = (byte)(value8 << 1); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_Abs_RMW_Stage5_ROR: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); - SetFlagC((temp8 & 1) != 0); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_Abs_RMW_Stage5_SLO: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 0x80) != 0); - alu_temp = value8 = (byte)(value8 << 1); - A |= value8; - goto case_Uop_NZ_A; -case Uop_Abs_RMW_Stage5_RLA: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); - SetFlagC((temp8 & 0x80) != 0); - A &= value8; - goto case_Uop_NZ_A; -case Uop_Abs_RMW_Stage5_SRE: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 1) != 0); - alu_temp = value8 = (byte)(value8 >> 1); - A ^= value8; - goto case_Uop_NZ_A; -case Uop_Abs_RMW_Stage5_RRA: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 >> 1) | ((P & 1) << 7)); - SetFlagC((temp8 & 1) != 0); - goto case_Uop__Adc; -case Uop_Abs_RMW_Stage5_ROL: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = temp8 = (byte)alu_temp; - alu_temp = value8 = (byte)((value8 << 1) | (P & 1)); - SetFlagC((temp8 & 0x80) != 0); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; -case Uop_Abs_RMW_Stage5_LSR: - WriteMemory((ushort)ea, (byte)alu_temp); - value8 = (byte)alu_temp; - SetFlagC((value8 & 1) != 0); - alu_temp = value8 = (byte)(value8 >> 1); - P = (byte)((P & 0x7D) | TableNZ[value8]); - break; - -case Uop_Abs_RMW_Stage6: - WriteMemory((ushort)ea, (byte)alu_temp); - break; - -case Uop_End_ISpecial: - opcode = VOP_Fetch1; - mi = 0; - goto RETRY; - -case Uop_End_SuppressInterrupt: - opcode = VOP_Fetch1_NoInterrupt; - mi = 0; - goto RETRY; - -case_Uop_End: case Uop_End: - opcode = VOP_Fetch1; - mi = 0; - iflag_pending = GetFlagI; - goto RETRY; -case Uop_End_BranchSpecial: - goto case_Uop_End; - } - - mi++; - -} - diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502X.cpp b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502X.cpp deleted file mode 100644 index 37c2dec8ca..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502X.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "MOS6502X.h" - -void MOS6502X::FetchDummy() -{ - DummyReadMemory(PC); -} - -void MOS6502X::Reset() -{ - A = 0; - X = 0; - Y = 0; - P = 0; - S = 0; - PC = 0; - TotalExecutedCycles = 0; - mi = 0; - opcode = 256; - //MessageBox(NULL,L"Opcode set to 256", NULL, 0); - iflag_pending = true; -} - -void MOS6502X::SetTrampolines(byte (__cdecl *ReadMemory)(ushort), byte (__cdecl *DummyReadMemory)(ushort), void (__cdecl *WriteMemory)(ushort, byte)) -{ - this->ReadMemory = ReadMemory; - this->DummyReadMemory = DummyReadMemory; - this->WriteMemory = WriteMemory; -} - -/* -#include -#define SHOWRA(a) SHOWGA((int)(void *)(a) - ((int)(void *)cpu), #a) - -void SHOWGA(int diff, const char *nom) -{ - char buffra[24]; - std::sprintf(buffra, "%08xi", diff); - MessageBoxA(NULL, buffra, nom, 0); -}*/ - -void* Create() -{ - MOS6502X* cpu = new MOS6502X(); - /* - SHOWRA(&cpu->BCD_Enabled); - SHOWRA(&cpu->debug); - SHOWRA(&cpu->throw_unhandled); - SHOWRA(&cpu->A); - SHOWRA(&cpu->X); - SHOWRA(&cpu->Y); - SHOWRA(&cpu->P); - SHOWRA(&cpu->PC); - SHOWRA(&cpu->S); - SHOWRA(&cpu->IRQ); - SHOWRA(&cpu->NMI); - SHOWRA(&cpu->TotalExecutedCycles); - SHOWRA(&cpu->ReadMemory); - SHOWRA(&cpu->DummyReadMemory); - SHOWRA(&cpu->WriteMemory); - SHOWRA(&cpu->opcode); - SHOWRA(&cpu->opcode2); - SHOWRA(&cpu->opcode3); - SHOWRA(&cpu->ea); - SHOWRA(&cpu->alu_temp); - SHOWRA(&cpu->mi); - SHOWRA(&cpu->iflag_pending); - SHOWRA(&cpu->interrupt_pending); - SHOWRA(&cpu->branch_irq_hack); - */ - - return (void *)cpu; -} - -void Destroy(void *ptr) -{ - MOS6502X* cpu = (MOS6502X*) ptr; - delete cpu; -} - - diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502X.h b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502X.h deleted file mode 100644 index b0a30355d8..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502X.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef MOS6502X_H -#define MOS6502X_H - -#include "ints.h" - -class MOS6502X -{ -public: - bool BCD_Enabled; - bool debug; - bool throw_unhandled; - - byte A; - byte X; - byte Y; - byte P; - ushort PC; - byte S; - - bool IRQ; - bool NMI; - - int TotalExecutedCycles; - - byte (__cdecl *ReadMemory)(ushort); - byte (__cdecl *DummyReadMemory)(ushort); - void (__cdecl *WriteMemory)(ushort, byte); - - //opcode bytes.. theoretically redundant with the temp variables? who knows. - int opcode; - byte opcode2, opcode3; - - int ea, alu_temp; //cpu internal temp variables - int mi; //microcode index - bool iflag_pending; //iflag must be stored after it is checked in some cases (CLI and SEI). - - //tracks whether an interrupt condition has popped up recently. - //not sure if this is real or not but it helps with the branch_irq_hack - bool interrupt_pending; - bool branch_irq_hack; //see Uop.RelBranch_Stage3 for more details - - - __declspec(dllexport) void ExecuteOne(); - void FetchDummy(); - __declspec(dllexport) void Reset(); - __declspec(dllexport) void NESSoftReset(); - __declspec(dllexport) void SetTrampolines(byte (__cdecl *ReadMemory)(ushort), byte (__cdecl *DummyReadMemory)(ushort), void (__cdecl *WriteMemory)(ushort, byte)); -}; - -extern "C" __declspec(dllexport) void* __cdecl Create(); -extern "C" __declspec(dllexport) void __cdecl Destroy(void *); - -#endif // MOS6502X_H diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.vcxproj.user b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.vcxproj.user deleted file mode 100644 index 695b5c78b9..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/MOS6502XNative.vcxproj.user +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/ints.h b/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/ints.h deleted file mode 100644 index 7155b64e75..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/ints.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef INTS_H -#define INTS_H - -typedef unsigned char byte; -typedef unsigned short ushort; -typedef signed char sbyte; - -#endif