1171 lines
34 KiB
C++
1171 lines
34 KiB
C++
#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++;
|
|
|
|
}
|
|
|