From 1f9051a60d39e105e41f73b37c20cddb0ca922bd Mon Sep 17 00:00:00 2001 From: PalindromicBreadLoaf Date: Wed, 23 Jul 2025 20:23:33 -0400 Subject: [PATCH] Implement Exclusive OR Instructions --- src/cpu.cpp | 323 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/cpu.h | 16 +++ 2 files changed, 338 insertions(+), 1 deletion(-) diff --git a/src/cpu.cpp b/src/cpu.cpp index 822ba02..c396131 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -142,7 +142,7 @@ uint16_t CPU::PopWord() { return (high << 8) | low; } -void CPU::DoADC(uint16_t value) { +void CPU::DoADC(const uint16_t value) { uint32_t result; if (P & FLAG_M) { @@ -389,6 +389,23 @@ void CPU::ExecuteInstruction() { case 0xC6: DEC_DirectPage(); break; // DEC $nn case 0xD6: DEC_DirectPageX(); break; // DEC $nn,X + // EOR - Exclusive OR + case 0x49: EOR_Immediate(); break; // EOR #$nn or #$nnnn + case 0x4D: EOR_Absolute(); break; // EOR $nnnn + case 0x5D: EOR_AbsoluteX(); break; // EOR $nnnn,X + case 0x59: EOR_AbsoluteY(); break; // EOR $nnnn,Y + case 0x45: EOR_DirectPage(); break; // EOR $nn + case 0x55: EOR_DirectPageX(); break; // EOR $nn,X + case 0x52: EOR_IndirectDirectPage(); break; // EOR ($nn) + case 0x47: EOR_IndirectDirectPageLong(); break; // EOR [$nn] + case 0x41: EOR_IndexedIndirectDirectPageX(); break; // EOR ($nn,X) + case 0x51: EOR_IndirectDirectPageY(); break; // EOR ($nn),Y + case 0x57: EOR_IndirectDirectPageLongY(); break; // EOR [$nn],Y + case 0x4F: EOR_AbsoluteLong(); break; // EOR $nnnnnn + case 0x5F: EOR_AbsoluteLongX(); break; // EOR $nnnnnn,X + case 0x43: EOR_StackRelative(); break; // EOR $nn,S + case 0x53: EOR_StackRelativeIndirectY(); break; // EOR ($nn,S),Y + // JMP - Jump to an Address case 0x4C: JMP_Absolute(); break; // JMP $nnnn case 0x6C: JMP_AbsoluteIndirect(); break; // JMP ($nnnn) @@ -2902,4 +2919,308 @@ void CPU::CMP_IndirectDirectPageLongY() { cycles += 7; if (D & 0xFF) cycles++; } +} + +void CPU::EOR_Immediate() { + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(PC++); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 2; + } else { // 16-bit mode + const uint16_t operand = ReadWord(PC); + PC += 2; + A ^= operand; + UpdateNZ16(A); + cycles += 3; + } +} + +void CPU::EOR_Absolute() { + const uint16_t address = ReadWord(PC); + PC += 2; + const uint32_t full_address = (DB << 16) | address; + + if (P & FLAG_M) { // 8-bit mode + uint8_t operand = ReadByte(full_address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 4; + } else { // 16-bit mode + uint16_t operand = ReadWord(full_address); + A ^= operand; + UpdateNZ16(A); + cycles += 5; + } +} + +void CPU::EOR_AbsoluteX() { + const uint16_t base_address = ReadWord(PC); + PC += 2; + const uint32_t full_address = (DB << 16) | (base_address + X); + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(full_address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 4; + if ((base_address & 0xFF00) != ((base_address + X) & 0xFF00)) { + cycles++; + } + } else { // 16-bit mode + const uint16_t operand = ReadWord(full_address); + A ^= operand; + UpdateNZ16(A); + cycles += 5; + if ((base_address & 0xFF00) != ((base_address + X) & 0xFF00)) { + cycles++; + } + } +} + +void CPU::EOR_AbsoluteY() { + const uint16_t base_address = ReadWord(PC); + PC += 2; + const uint32_t full_address = (DB << 16) | (base_address + Y); + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(full_address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 4; + if ((base_address & 0xFF00) != ((base_address + Y) & 0xFF00)) { + cycles++; + } + } else { // 16-bit mode + const uint16_t operand = ReadWord(full_address); + A ^= operand; + UpdateNZ16(A); + cycles += 5; + if ((base_address & 0xFF00) != ((base_address + Y) & 0xFF00)) { + cycles++; + } + } +} + +void CPU::EOR_DirectPage() { + const uint8_t offset = ReadByte(PC++); + const uint32_t address = D + offset; + + if (P & FLAG_M) { // 8-bit mode + uint8_t operand = ReadByte(address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 3; + if (D & 0xFF) cycles++; + } else { // 16-bit mode + const uint16_t operand = ReadWord(address); + A ^= operand; + UpdateNZ16(A); + cycles += 4; + if (D & 0xFF) cycles++; + } +} + +void CPU::EOR_DirectPageX() { + const uint8_t offset = ReadByte(PC++); + const uint32_t address = D + offset + X; + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 4; + if (D & 0xFF) cycles++; + } else { // 16-bit mode + const uint16_t operand = ReadWord(address); + A ^= operand; + UpdateNZ16(A); + cycles += 5; + if (D & 0xFF) cycles++; + } +} + +void CPU::EOR_IndirectDirectPage() { + const uint8_t offset = ReadByte(PC++); + const uint32_t pointer_address = D + offset; + const uint16_t indirect_address = ReadWord(pointer_address); + const uint32_t full_address = (DB << 16) | indirect_address; + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(full_address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 5; + if (D & 0xFF) cycles++; + } else { // 16-bit mode + const uint16_t operand = ReadWord(full_address); + A ^= operand; + UpdateNZ16(A); + cycles += 6; + if (D & 0xFF) cycles++; + } +} + +void CPU::EOR_IndirectDirectPageLong() { + const uint8_t offset = ReadByte(PC++); + const uint32_t pointer_address = D + offset; + const uint32_t full_address = ReadByte(pointer_address) | + (ReadByte(pointer_address + 1) << 8) | + (ReadByte(pointer_address + 2) << 16); + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(full_address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 6; + if (D & 0xFF) cycles++; + } else { // 16-bit mode + const uint16_t operand = ReadWord(full_address); + A ^= operand; + UpdateNZ16(A); + cycles += 7; + if (D & 0xFF) cycles++; + } +} + +void CPU::EOR_IndexedIndirectDirectPageX() { + const uint8_t offset = ReadByte(PC++); + const uint32_t pointer_address = D + offset + X; + const uint16_t indirect_address = ReadWord(pointer_address); + const uint32_t full_address = (DB << 16) | indirect_address; + + if (P & FLAG_M) { // 8-bit mode + uint8_t operand = ReadByte(full_address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 6; + if (D & 0xFF) cycles++; + } else { // 16-bit mode + const uint16_t operand = ReadWord(full_address); + A ^= operand; + UpdateNZ16(A); + cycles += 7; + if (D & 0xFF) cycles++; + } +} + +void CPU::EOR_IndirectDirectPageY() { + const uint8_t offset = ReadByte(PC++); + const uint32_t pointer_address = D + offset; + const uint16_t base_address = ReadWord(pointer_address); + const uint32_t full_address = (DB << 16) | (base_address + Y); + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(full_address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 5; + if (D & 0xFF) cycles++; + if ((base_address & 0xFF00) != ((base_address + Y) & 0xFF00)) { + cycles++; + } + } else { // 16-bit mode + const uint16_t operand = ReadWord(full_address); + A ^= operand; + UpdateNZ16(A); + cycles += 6; + if (D & 0xFF) cycles++; + if ((base_address & 0xFF00) != ((base_address + Y) & 0xFF00)) { + cycles++; + } + } +} + +void CPU::EOR_IndirectDirectPageLongY() { + const uint8_t offset = ReadByte(PC++); + const uint32_t pointer_address = D + offset; + const uint32_t base_address = ReadByte(pointer_address) | + (ReadByte(pointer_address + 1) << 8) | + (ReadByte(pointer_address + 2) << 16); + const uint32_t full_address = base_address + Y; + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(full_address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 6; + if (D & 0xFF) cycles++; + } else { // 16-bit mode + const uint16_t operand = ReadWord(full_address); + A ^= operand; + UpdateNZ16(A); + cycles += 7; + if (D & 0xFF) cycles++; + } +} + +void CPU::EOR_AbsoluteLong() { + const uint32_t address = ReadByte(PC) | (ReadByte(PC + 1) << 8) | (ReadByte(PC + 2) << 16); + PC += 3; + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 5; + } else { // 16-bit mode + const uint16_t operand = ReadWord(address); + A ^= operand; + UpdateNZ16(A); + cycles += 6; + } +} + +void CPU::EOR_AbsoluteLongX() { + const uint32_t base_address = ReadByte(PC) | (ReadByte(PC + 1) << 8) | (ReadByte(PC + 2) << 16); + PC += 3; + const uint32_t full_address = base_address + X; + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(full_address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 5; + } else { // 16-bit mode + const uint16_t operand = ReadWord(full_address); + A ^= operand; + UpdateNZ16(A); + cycles += 6; + } +} + +void CPU::EOR_StackRelative() { + const uint8_t offset = ReadByte(PC++); + const uint32_t address = SP + offset; + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 4; + } else { // 16-bit mode + const uint16_t operand = ReadWord(address); + A ^= operand; + UpdateNZ16(A); + cycles += 5; + } +} + +void CPU::EOR_StackRelativeIndirectY() { + const uint8_t offset = ReadByte(PC++); + const uint32_t pointer_address = SP + offset; + const uint16_t base_address = ReadWord(pointer_address); + const uint32_t full_address = (DB << 16) | (base_address + Y); + + if (P & FLAG_M) { // 8-bit mode + const uint8_t operand = ReadByte(full_address); + A = (A & 0xFF00) | ((A & 0xFF) ^ operand); + UpdateNZ8(A & 0xFF); + cycles += 7; + } else { // 16-bit mode + const uint16_t operand = ReadWord(full_address); + A ^= operand; + UpdateNZ16(A); + cycles += 8; + } } \ No newline at end of file diff --git a/src/cpu.h b/src/cpu.h index a06b39e..69c00ad 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -260,6 +260,22 @@ public: void CMP_IndirectDirectPageLong(); void CMP_StackRelativeIndirectY(); void CMP_IndirectDirectPageLongY(); + + void EOR_Immediate(); + void EOR_Absolute(); + void EOR_AbsoluteX(); + void EOR_AbsoluteY(); + void EOR_DirectPage(); + void EOR_DirectPageX(); + void EOR_IndirectDirectPage(); + void EOR_IndirectDirectPageLong(); + void EOR_IndexedIndirectDirectPageX(); + void EOR_IndirectDirectPageY(); + void EOR_IndirectDirectPageLongY(); + void EOR_AbsoluteLong(); + void EOR_AbsoluteLongX(); + void EOR_StackRelative(); + void EOR_StackRelativeIndirectY(); }; #endif //CPU_H