diff --git a/CpuCoreGenerator/MOS 6502/CoreGenerator.cs b/CpuCoreGenerator/MOS 6502/CoreGenerator.cs index 5363dca6bd..13b1f2ec18 100644 --- a/CpuCoreGenerator/MOS 6502/CoreGenerator.cs +++ b/CpuCoreGenerator/MOS 6502/CoreGenerator.cs @@ -13,10 +13,13 @@ namespace M6502 ZeroPageY, Absolute, AbsoluteX, + AbsoluteX_P, //* page-crossing penalty AbsoluteY, + AbsoluteY_P,//* page-crossing penalty Indirect, IndirectX, IndirectY, + IndirectY_P, Relative } @@ -40,10 +43,13 @@ namespace M6502 case AddrMode.ZeroPageY: return 2; case AddrMode.Absolute: return 3; case AddrMode.AbsoluteX: return 3; + case AddrMode.AbsoluteX_P: return 3; case AddrMode.AbsoluteY: return 3; + case AddrMode.AbsoluteY_P: return 3; case AddrMode.Indirect: return 3; case AddrMode.IndirectX: return 2; case AddrMode.IndirectY: return 2; + case AddrMode.IndirectY_P: return 2; case AddrMode.Relative: return 2; default: return -1; @@ -55,19 +61,22 @@ namespace M6502 { switch (AddressMode) { - case AddrMode.Implicit: return Instruction; - case AddrMode.Accumulator: return Instruction+" A"; - case AddrMode.Immediate: return Instruction+" #nn"; - case AddrMode.ZeroPage: return Instruction+" zp"; - case AddrMode.ZeroPageX: return Instruction + " zp,X"; - case AddrMode.ZeroPageY: return Instruction + " zp,Y"; - case AddrMode.Absolute: return Instruction + " addr"; - case AddrMode.AbsoluteX: return Instruction + " addr,X"; - case AddrMode.AbsoluteY: return Instruction + " addr,Y"; - case AddrMode.Indirect: return Instruction + " (addr)"; - case AddrMode.IndirectX: return Instruction + " (addr,X)"; - case AddrMode.IndirectY: return Instruction + " (addr),Y"; - case AddrMode.Relative: return Instruction + " +/-rel"; + case AddrMode.Implicit: return Instruction; + case AddrMode.Accumulator: return Instruction+" A"; + case AddrMode.Immediate: return Instruction+" #nn"; + case AddrMode.ZeroPage: return Instruction+" zp"; + case AddrMode.ZeroPageX: return Instruction + " zp,X"; + case AddrMode.ZeroPageY: return Instruction + " zp,Y"; + case AddrMode.Absolute: return Instruction + " addr"; + case AddrMode.AbsoluteX: return Instruction + " addr,X"; + case AddrMode.AbsoluteX_P: return Instruction + " addr,X*"; + case AddrMode.AbsoluteY: return Instruction + " addr,Y"; + case AddrMode.AbsoluteY_P: return Instruction + " addr,Y*"; + case AddrMode.Indirect: return Instruction + " (addr)"; + case AddrMode.IndirectX: return Instruction + " (addr,X)"; + case AddrMode.IndirectY: return Instruction + " (addr),Y"; + case AddrMode.IndirectY_P: return Instruction + " (addr),Y*"; + case AddrMode.Relative: return Instruction + " +/-rel"; default: return Instruction; } } @@ -86,20 +95,20 @@ namespace M6502 Set(0x65, "ADC", AddrMode.ZeroPage , 3); Set(0x75, "ADC", AddrMode.ZeroPageX, 4); Set(0x6D, "ADC", AddrMode.Absolute , 4); - Set(0x7D, "ADC", AddrMode.AbsoluteX, 4);//+ - Set(0x79, "ADC", AddrMode.AbsoluteY, 4);//+ + Set(0x7D, "ADC", AddrMode.AbsoluteX_P, 4);//+ + Set(0x79, "ADC", AddrMode.AbsoluteY_P, 4);//+ Set(0x61, "ADC", AddrMode.IndirectX, 6); - Set(0x71, "ADC", AddrMode.IndirectY, 5);//+ + Set(0x71, "ADC", AddrMode.IndirectY_P, 5);//+ // AND Set(0x29, "AND", AddrMode.Immediate, 2); - Set(0x25, "AND", AddrMode.ZeroPage , 2); - Set(0x35, "AND", AddrMode.ZeroPageX, 3); + Set(0x25, "AND", AddrMode.ZeroPage , 3); + Set(0x35, "AND", AddrMode.ZeroPageX, 4); Set(0x2D, "AND", AddrMode.Absolute , 4); - Set(0x3D, "AND", AddrMode.AbsoluteX, 4);//+ - Set(0x39, "AND", AddrMode.AbsoluteY, 4);//+ + Set(0x3D, "AND", AddrMode.AbsoluteX_P, 4);//+ + Set(0x39, "AND", AddrMode.AbsoluteY_P, 4);//+ Set(0x21, "AND", AddrMode.IndirectX, 6); - Set(0x31, "AND", AddrMode.IndirectY, 5);//+ + Set(0x31, "AND", AddrMode.IndirectY_P, 5);//+ // Arithmatic Shift Left Set(0x0A, "ASL", AddrMode.Accumulator, 2); @@ -130,19 +139,19 @@ namespace M6502 Set(0xC5, "CMP", AddrMode.ZeroPage , 3); Set(0xD5, "CMP", AddrMode.ZeroPageX, 4); Set(0xCD, "CMP", AddrMode.Absolute , 4); - Set(0xDD, "CMP", AddrMode.AbsoluteX, 4);//+ - Set(0xD9, "CMP", AddrMode.AbsoluteY, 4);//+ + Set(0xDD, "CMP", AddrMode.AbsoluteX_P, 4);//+ + Set(0xD9, "CMP", AddrMode.AbsoluteY_P, 4);//+ Set(0xC1, "CMP", AddrMode.IndirectX, 6); - Set(0xD1, "CMP", AddrMode.IndirectY, 5);//+ + Set(0xD1, "CMP", AddrMode.IndirectY_P, 5);//+ // Compare X register Set(0xE0, "CPX", AddrMode.Immediate, 2); - Set(0xE4, "CPX", AddrMode.ZeroPage , 2); + Set(0xE4, "CPX", AddrMode.ZeroPage , 3); Set(0xEC, "CPX", AddrMode.Absolute , 4); // Compare Y register Set(0xC0, "CPY", AddrMode.Immediate, 2); - Set(0xC4, "CPY", AddrMode.ZeroPage , 2); + Set(0xC4, "CPY", AddrMode.ZeroPage , 3); Set(0xCC, "CPY", AddrMode.Absolute , 4); // DEC @@ -156,10 +165,10 @@ namespace M6502 Set(0x45, "EOR", AddrMode.ZeroPage , 3); Set(0x55, "EOR", AddrMode.ZeroPageX, 4); Set(0x4D, "EOR", AddrMode.Absolute , 4); - Set(0x5D, "EOR", AddrMode.AbsoluteX, 4);//+ - Set(0x59, "EOR", AddrMode.AbsoluteY, 4);//+ + Set(0x5D, "EOR", AddrMode.AbsoluteX_P, 4);//+ + Set(0x59, "EOR", AddrMode.AbsoluteY_P, 4);//+ Set(0x41, "EOR", AddrMode.IndirectX, 6); - Set(0x51, "EOR", AddrMode.IndirectY, 5);//+ + Set(0x51, "EOR", AddrMode.IndirectY_P, 5);//+ // Flag Instructions Set(0x18, "CLC", AddrMode.Implicit, 2); // Clear Carry @@ -188,24 +197,24 @@ namespace M6502 Set(0xA5, "LDA", AddrMode.ZeroPage , 3); Set(0xB5, "LDA", AddrMode.ZeroPageX, 4); Set(0xAD, "LDA", AddrMode.Absolute , 4); - Set(0xBD, "LDA", AddrMode.AbsoluteX, 4);//+ - Set(0xB9, "LDA", AddrMode.AbsoluteY, 4);//+ + Set(0xBD, "LDA", AddrMode.AbsoluteX_P, 4);//+ + Set(0xB9, "LDA", AddrMode.AbsoluteY_P, 4);//+ Set(0xA1, "LDA", AddrMode.IndirectX, 6); - Set(0xB1, "LDA", AddrMode.IndirectY, 5);//+ + Set(0xB1, "LDA", AddrMode.IndirectY_P, 5);//+ // Load X register Set(0xA2, "LDX", AddrMode.Immediate, 2); Set(0xA6, "LDX", AddrMode.ZeroPage , 3); Set(0xB6, "LDX", AddrMode.ZeroPageY, 4); Set(0xAE, "LDX", AddrMode.Absolute , 4); - Set(0xBE, "LDX", AddrMode.AbsoluteY, 4);//+ + Set(0xBE, "LDX", AddrMode.AbsoluteY_P, 4);//+ // Load Y register Set(0xA0, "LDY", AddrMode.Immediate, 2); Set(0xA4, "LDY", AddrMode.ZeroPage , 3); Set(0xB4, "LDY", AddrMode.ZeroPageX, 4); Set(0xAC, "LDY", AddrMode.Absolute , 4); - Set(0xBC, "LDY", AddrMode.AbsoluteX, 4);//+ + Set(0xBC, "LDY", AddrMode.AbsoluteX_P, 4);//+ // Logical Shift Right Set(0x4A, "LSR", AddrMode.Accumulator, 2); @@ -253,13 +262,13 @@ namespace M6502 // Bitwise OR with Accumulator Set(0x09, "ORA", AddrMode.Immediate, 2); - Set(0x05, "ORA", AddrMode.ZeroPage , 2); - Set(0x15, "ORA", AddrMode.ZeroPageX, 3); + Set(0x05, "ORA", AddrMode.ZeroPage , 3); + Set(0x15, "ORA", AddrMode.ZeroPageX, 4); Set(0x0D, "ORA", AddrMode.Absolute , 4); - Set(0x1D, "ORA", AddrMode.AbsoluteX, 4);//+ - Set(0x19, "ORA", AddrMode.AbsoluteY, 4);//+ + Set(0x1D, "ORA", AddrMode.AbsoluteX_P, 4);//+ + Set(0x19, "ORA", AddrMode.AbsoluteY_P, 4);//+ Set(0x01, "ORA", AddrMode.IndirectX, 6); - Set(0x11, "ORA", AddrMode.IndirectY, 5);//+ + Set(0x11, "ORA", AddrMode.IndirectY_P, 5);//+ // Register instructions Set(0xAA, "TAX", AddrMode.Implicit, 2); // Transfer A to X @@ -296,10 +305,10 @@ namespace M6502 Set(0xE5, "SBC", AddrMode.ZeroPage , 3); Set(0xF5, "SBC", AddrMode.ZeroPageX, 4); Set(0xED, "SBC", AddrMode.Absolute , 4); - Set(0xFD, "SBC", AddrMode.AbsoluteX, 4);//+ - Set(0xF9, "SBC", AddrMode.AbsoluteY, 4);//+ + Set(0xFD, "SBC", AddrMode.AbsoluteX_P, 4);//+ + Set(0xF9, "SBC", AddrMode.AbsoluteY_P, 4);//+ Set(0xE1, "SBC", AddrMode.IndirectX, 6); - Set(0xF1, "SBC", AddrMode.IndirectY, 5);//+ + Set(0xF1, "SBC", AddrMode.IndirectY_P, 5);//+ // Store Accumulator Set(0x85, "STA", AddrMode.ZeroPage , 3); @@ -395,7 +404,13 @@ namespace M6502 for (int i = 0; i < 256; i++) { if (Opcodes[i] != null) + { + if (i == 0x91) + { + int zzz = 9; + } EmulateOpcode(w, i); + } } w.WriteLine(" default:"); @@ -480,8 +495,6 @@ namespace M6502 private void GetValue8(OpcodeInfo op, TextWriter w, string dest) { - // TODO it APPEARS that the +1 opcode penalty applies to all AbsoluteX, AbsoluteY, and IndirectY - // but this is not completely clear. the doc has some exceptions, but are they real? switch (op.AddressMode) { case AddrMode.Immediate: @@ -494,21 +507,33 @@ namespace M6502 w.WriteLine(Spaces + dest + " = ReadMemory((byte)(ReadMemory(PC++)+Y));"); break; case AddrMode.Absolute: w.WriteLine(Spaces + dest + " = ReadMemory(ReadWord(PC)); PC += 2;"); break; + case AddrMode.AbsoluteX_P: + w.WriteLine(Spaces + "temp16 = ReadWord(PC);"); + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(temp16+X));"); + w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) "); + w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }"); + w.WriteLine(Spaces + "PC += 2;"); + break; case AddrMode.AbsoluteX: w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadWord(PC)+X));"); - w.WriteLine(Spaces + "if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) "); + w.WriteLine(Spaces + "PC += 2;"); + break; + case AddrMode.AbsoluteY_P: + w.WriteLine(Spaces + "temp16 = ReadWord(PC);"); + w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(temp16+Y));"); + w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) "); w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }"); w.WriteLine(Spaces + "PC += 2;"); break; case AddrMode.AbsoluteY: w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadWord(PC)+Y));"); - w.WriteLine(Spaces + "if ((PC & 0xFF00) != ((PC+Y) & 0xFF00)) "); - w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }"); w.WriteLine(Spaces + "PC += 2;"); break; case AddrMode.IndirectX: w.WriteLine(Spaces + dest + " = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X)));"); break; case AddrMode.IndirectY: + w.WriteLine(Spaces + dest + " = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+Y)));"); break; + case AddrMode.IndirectY_P: w.WriteLine(Spaces + "temp16 = ReadWordPageWrap(ReadMemory(PC++));"); w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(temp16+Y));"); w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) "); @@ -546,6 +571,8 @@ namespace M6502 case AddrMode.IndirectX: w.WriteLine(Spaces + dest + " = ReadWordPageWrap((byte)(ReadMemory(PC++)+X));"); break; case AddrMode.IndirectY: + w.WriteLine(Spaces + dest + " = ReadWordPageWrap((byte)(ReadMemory(PC++)+Y));"); break; + case AddrMode.IndirectY_P: w.WriteLine(Spaces + "temp16 = ReadWordPageWrap(ReadMemory(PC++));"); w.WriteLine(Spaces + dest + " = (ushort)(temp16+Y);"); w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) ");