BizHawk/BizHawk.Emulation.Cores/CPUs/MOS 6502X/MOS6502XNative/Execute.cpp

1171 lines
34 KiB
C++
Raw Normal View History

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