BizHawk/BizHawk.Emulation/CPUs/MOS 6502X/Execute.cs

1593 lines
74 KiB
C#
Raw Normal View History

//http://nesdev.parodius.com/6502_cpu.txt
using System;
namespace BizHawk.Emulation.CPUs.M6502
{
public partial class MOS6502X
{
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, PushPCH_B, 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,
}
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;
//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
bool Interrupted
{
get
{
return NMI || (IRQ && !FlagI);
}
}
void FetchDummy()
{
DummyReadMemory(PC);
}
public void Execute(int cycles)
{
for (int i = 0; i < cycles; i++)
{
ExecuteOne();
}
}
public void ExecuteOne()
{
byte value8, temp8;
ushort value16;
bool branch_taken = false;
TotalExecutedCycles++;
interrupt_pending |= Interrupted;
RETRY:
Uop uop = Microcode[opcode][mi];
switch (uop)
{
default: throw new InvalidOperationException();
case Uop.Fetch1:
{
bool my_iflag = FlagI;
FlagI = 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:
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:
FlagB = true;
WriteMemory((ushort)(S-- + 0x100), P);
FlagI = true;
ea = BRKVector;
break;
case Uop.PushP_IRQ:
FlagB = false;
WriteMemory((ushort)(S-- + 0x100), P);
FlagI = true;
ea = IRQVector;
break;
case Uop.PushP_NMI:
FlagB = false;
WriteMemory((ushort)(S-- + 0x100), P);
FlagI = true; //is this right?
ea = NMIVector;
break;
case Uop.PushP_Reset:
ea = ResetVector;
S--;
FlagI = true;
break;
case Uop.PushDummy:
S--;
break;
case Uop.FetchPCLVector:
if (ea == BRKVector && FlagB && NMI)
{
NMI = false;
ea = NMIVector;
}
if(ea == IRQVector && !FlagB && 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: P = (byte)((P & 0x7D) | TableNZ[A]); break;
case Uop.NZ_X: P = (byte)((P & 0x7D) | TableNZ[X]); break;
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(); FlagC = true; break;
case Uop.Imp_CLC: FetchDummy(); FlagC = false; break;
case Uop.Imp_SED: FetchDummy(); FlagD = true; break;
case Uop.Imp_CLD: FetchDummy(); FlagD = false; break;
case Uop.Imp_CLV: FetchDummy(); FlagV = 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 (!alu_temp.Bit(8))
{
mi++;
goto RETRY;
}
else
{
ReadMemory((ushort)ea);
ea = (ushort)(ea + 0x100);
}
break;
case Uop.IndIdx_RMW_Stage5:
if (alu_temp.Bit(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;
FlagC = (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;
FlagC = (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));
FlagC = (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);
FlagC = (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));
FlagC = (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 = FlagV == true;
goto case Uop.RelBranch_Stage2;
case Uop.RelBranch_Stage2_BVC:
branch_taken = FlagV == false;
goto case Uop.RelBranch_Stage2;
case Uop.RelBranch_Stage2_BMI:
branch_taken = FlagN == true;
goto case Uop.RelBranch_Stage2;
case Uop.RelBranch_Stage2_BPL:
branch_taken = FlagN == false;
goto case Uop.RelBranch_Stage2;
case Uop.RelBranch_Stage2_BCS:
branch_taken = FlagC == true;
goto case Uop.RelBranch_Stage2;
case Uop.RelBranch_Stage2_BCC:
branch_taken = FlagC == false;
goto case Uop.RelBranch_Stage2;
case Uop.RelBranch_Stage2_BEQ:
branch_taken = FlagZ == true;
goto case Uop.RelBranch_Stage2;
case Uop.RelBranch_Stage2_BNE:
branch_taken = FlagZ == false;
goto 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 (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;
}
break;
case Uop.RelBranch_Stage4:
FetchDummy();
if (alu_temp.Bit(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));
FlagT = 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:
value8 = (byte)alu_temp;
value16 = (ushort)(X - value8);
FlagC = (X >= value8);
P = (byte)((P & 0x7D) | TableNZ[(byte)value16]);
break;
case Uop._Cpy:
value8 = (byte)alu_temp;
value16 = (ushort)(Y - value8);
FlagC = (Y >= value8);
P = (byte)((P & 0x7D) | TableNZ[(byte)value16]);
break;
case Uop._Cmp:
value8 = (byte)alu_temp;
value16 = (ushort)(A - value8);
FlagC = (A >= value8);
P = (byte)((P & 0x7D) | TableNZ[(byte)value16]);
break;
case Uop._Bit:
FlagN = (alu_temp & 0x80) != 0;
FlagV = (alu_temp & 0x40) != 0;
FlagZ = (A & alu_temp) == 0;
break;
case Uop._Eor:
A ^= (byte)alu_temp;
goto case Uop.NZ_A;
case Uop._And:
A &= (byte)alu_temp;
goto case Uop.NZ_A;
case Uop._Ora:
A |= (byte)alu_temp;
goto case Uop.NZ_A;
case Uop._Anc:
A &= (byte)alu_temp;
FlagC = A.Bit(7);
goto case Uop.NZ_A;
case Uop._Asr:
A &= (byte)alu_temp;
FlagC = A.Bit(0);
A >>= 1;
goto case Uop.NZ_A;
case Uop._Axs:
X &= A;
alu_temp = X - (byte)alu_temp;
X = (byte)alu_temp;
FlagC = !alu_temp.Bit(8);
goto case Uop.NZ_X;
case Uop._Arr:
{
A &= (byte)alu_temp;
bool temp = A.Bit(0);
A = (byte)((A >> 1) | (FlagC ? 0x80 : 0x00));
FlagC = temp;
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);
break;
}
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:
{
value8 = (byte)alu_temp;
int temp = A - value8 - (FlagC ? 0 : 1);
if (FlagD && BCD_Enabled)
{
int lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 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;
FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0;
FlagC = (hi & 0xFF00) == 0;
A = (byte)((lo & 0x0F) | (hi & 0xF0));
}
else
{
FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0;
FlagC = temp >= 0;
A = (byte)temp;
}
goto case Uop.NZ_A;
}
case Uop._Adc:
{
//TODO - an extra cycle penalty?
value8 = (byte)alu_temp;
if (FlagD && BCD_Enabled)
{
int lo = (A & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0);
int 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
{
int temp = value8 + A + (FlagC ? 1 : 0);
FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0;
FlagC = 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;
FlagC = (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);
FlagC = (temp8 & 1) != 0;
goto case Uop._Cmp;
case Uop.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;
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));
FlagC = (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));
FlagC = (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:
FlagB = 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 = FlagI;
P = ReadMemory((ushort)(S + 0x100));
iflag_pending = FlagI;
FlagI = my_iflag;
FlagT = true; //force T always to remain true
break;
}
case Uop.Imp_ASL_A:
FetchDummy();
FlagC = (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));
FlagC = (temp8 & 0x80) != 0;
goto case Uop.NZ_A;
case Uop.Imp_ROR_A:
FetchDummy();
temp8 = A;
A = (byte)((A >> 1) | ((P & 1) << 7));
FlagC = (temp8 & 1) != 0;
goto case Uop.NZ_A;
case Uop.Imp_LSR_A:
FetchDummy();
FlagC = (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;
FlagC = (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;
FlagC = (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));
FlagC = (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);
FlagC = (temp8 & 1) != 0;
goto case Uop._Cmp;
case Uop.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]);
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));
FlagC = (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));
FlagC = (temp8 & 0x80) != 0;
P = (byte)((P & 0x7D) | TableNZ[value8]);
break;
case Uop.ZP_RMW_SLO:
WriteMemory(opcode2, (byte)alu_temp);
value8 = (byte)alu_temp;
FlagC = (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));
FlagC = (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 (!alu_temp.Bit(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 (alu_temp.Bit(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));
FlagC = (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;
FlagC = (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;
FlagC = (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;
FlagC = (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));
FlagC = (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));
FlagC = (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;
FlagC = (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));
FlagC = (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;
FlagC = (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));
FlagC = (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;
FlagC = (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));
FlagC = (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;
FlagC = (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));
FlagC = (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));
FlagC = (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;
FlagC = (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:
opcode = VOP_Fetch1;
mi = 0;
iflag_pending = FlagI;
goto RETRY;
case Uop.End_BranchSpecial:
goto case Uop.End;
}
mi++;
} //ExecuteOne
}
}