From 574d3e1312fa4461dbafb56a5ffb9f9cee9a0692 Mon Sep 17 00:00:00 2001 From: PalindromicBreadLoaf Date: Wed, 23 Jul 2025 09:44:52 -0400 Subject: [PATCH] Implement AND Instructions --- src/cpu.cpp | 321 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cpu.h | 16 +++ 2 files changed, 337 insertions(+) diff --git a/src/cpu.cpp b/src/cpu.cpp index d6bc2eb..dfad8be 100644 --- a/src/cpu.cpp +++ b/src/cpu.cpp @@ -205,6 +205,23 @@ uint16_t CPU::AdjustDecimal(const uint16_t binary_result, const bool is_16bit) { void CPU::ExecuteInstruction() { // TODO: Actual Opcode decoding switch (const uint8_t opcode = bus->Read(PC++)) { + // Bitwise AND Instructions + case 0x29: AND_Immediate(); break; // AND #$nn or #$nnnn + case 0x2D: AND_Absolute(); break; // AND $nnnn + case 0x3D: AND_AbsoluteX(); break; // AND $nnnn,X + case 0x39: AND_AbsoluteY(); break; // AND $nnnn,Y + case 0x25: AND_DirectPage(); break; // AND $nn + case 0x35: AND_DirectPageX(); break; // AND $nn,X + case 0x32: AND_IndirectDirectPage(); break; // AND ($nn) + case 0x27: AND_IndirectDirectPageLong(); break; // AND [$nn] + case 0x21: AND_IndexedIndirectDirectPageX(); break; // AND ($nn,X) + case 0x31: AND_IndirectDirectPageY(); break; // AND ($nn),Y + case 0x37: AND_IndirectDirectPageLongY(); break; // AND [$nn],Y + case 0x2F: AND_AbsoluteLong(); break; // AND $nnnnnn + case 0x3F: AND_AbsoluteLongX(); break; // AND $nnnnnn,X + case 0x23: AND_StackRelative(); break; // AND $nn,S + case 0x33: AND_StackRelativeIndirectY(); break; // AND ($nn,S),Y + // ADC - Add with Carry case 0x69: ADC_Immediate(); break; // ADC #$nn/#$nnnn case 0x6D: ADC_Absolute(); break; // ADC $nnnn @@ -2126,4 +2143,308 @@ void CPU::ADC_StackRelativeIndirectY() { DoADC(value); cycles += 8; } +} + +void CPU::AND_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::AND_Absolute() { + const uint16_t address = ReadWord(PC); + PC += 2; + const uint32_t full_address = (DB << 16) | 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 += 4; + } else { // 16-bit mode + const uint16_t operand = ReadWord(full_address); + A &= operand; + UpdateNZ16(A); + cycles += 5; + } +} + +void CPU::AND_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::AND_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::AND_DirectPage() { + const uint8_t offset = ReadByte(PC++); + const uint32_t address = D + offset; + + if (P & FLAG_M) { // 8-bit mode + const 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::AND_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::AND_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::AND_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::AND_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 + 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::AND_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::AND_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 + 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 + uint16_t operand = ReadWord(full_address); + A &= operand; + UpdateNZ16(A); + cycles += 7; + if (D & 0xFF) cycles++; + } +} + +void CPU::AND_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::AND_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::AND_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::AND_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 afbc2d4..761b6b2 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -206,6 +206,22 @@ public: void ADC_DirectPageIndirectLongY(); void ADC_StackRelative(); void ADC_StackRelativeIndirectY(); + + void AND_Immediate(); + void AND_Absolute(); + void AND_AbsoluteX(); + void AND_AbsoluteY(); + void AND_DirectPage(); + void AND_DirectPageX(); + void AND_IndirectDirectPage(); + void AND_IndirectDirectPageLong(); + void AND_IndexedIndirectDirectPageX(); + void AND_IndirectDirectPageY(); + void AND_IndirectDirectPageLongY(); + void AND_AbsoluteLong(); + void AND_AbsoluteLongX(); + void AND_StackRelative(); + void AND_StackRelativeIndirectY(); }; #endif //CPU_H