#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++;

}

