ADC, AND with tests for various addressing modes
This commit is contained in:
@@ -2,6 +2,7 @@ set(
|
||||
YAZE_APP_CORE_SRC
|
||||
app/core/common.cc
|
||||
app/core/controller.cc
|
||||
app/core/emulator.cc
|
||||
app/core/pipeline.cc
|
||||
)
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@ add_executable(
|
||||
yaze
|
||||
app/yaze.cc
|
||||
app/rom.cc
|
||||
app/emu/apu.cc
|
||||
app/emu/cpu.cc
|
||||
app/emu/ppu.cc
|
||||
app/emu/snes.cc
|
||||
${YAZE_APP_CORE_SRC}
|
||||
${YAZE_APP_EDITOR_SRC}
|
||||
${YAZE_APP_GFX_SRC}
|
||||
|
||||
@@ -8,25 +8,28 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
|
||||
uint8_t CPU::ReadByte(uint16_t addr) const {
|
||||
return memory.at(addr); // Read a byte from memory at the specified address
|
||||
uint8_t CPU::ReadByte(uint16_t address) const {
|
||||
return memory.ReadByte(address);
|
||||
}
|
||||
|
||||
uint16_t CPU::ReadWord(uint16_t address) const {
|
||||
uint8_t low = ReadByte(address);
|
||||
uint8_t high = ReadByte(address + 1);
|
||||
return (high << 8) | low;
|
||||
return memory.ReadWord(address);
|
||||
}
|
||||
|
||||
uint32_t CPU::ReadWordLong(uint16_t address) const {
|
||||
uint8_t low = ReadByte(address);
|
||||
uint8_t mid = ReadByte(address + 1);
|
||||
uint8_t high = ReadByte(address + 2);
|
||||
return (high << 16) | (mid << 8) | low;
|
||||
return memory.ReadWordLong(address);
|
||||
}
|
||||
|
||||
void CPU::WriteByte(uint32_t address, uint8_t value) {
|
||||
memory.WriteByte(address, value);
|
||||
}
|
||||
|
||||
void CPU::WriteWord(uint32_t address, uint16_t value) {
|
||||
memory.WriteWord(address, value);
|
||||
}
|
||||
|
||||
uint8_t CPU::FetchByte() {
|
||||
uint8_t byte = memory.ReadWord(PC); // Read a byte from memory at PC
|
||||
uint8_t byte = memory.ReadByte(PC); // Read a byte from memory at PC
|
||||
PC++; // Increment the Program Counter
|
||||
return byte;
|
||||
}
|
||||
@@ -64,7 +67,7 @@ uint8_t CPU::FetchByteDirectPage(uint8_t operand) {
|
||||
|
||||
uint16_t CPU::DirectPageIndexedIndirectX() {
|
||||
uint8_t dp = FetchByte();
|
||||
return ReadWord((dp + X) & 0xFF);
|
||||
return memory.ReadWord((dp + X) & 0xFF);
|
||||
}
|
||||
|
||||
uint16_t CPU::StackRelative() {
|
||||
@@ -76,7 +79,7 @@ uint16_t CPU::DirectPage() { return FetchByte(); }
|
||||
|
||||
uint16_t CPU::DirectPageIndirectLong() {
|
||||
uint8_t dp = FetchByte();
|
||||
return ReadWordLong(dp);
|
||||
return memory.ReadWordLong(dp);
|
||||
}
|
||||
|
||||
uint16_t CPU::Immediate() { return PC++; }
|
||||
@@ -87,17 +90,17 @@ uint16_t CPU::AbsoluteLong() { return FetchLong(); }
|
||||
|
||||
uint16_t CPU::DirectPageIndirectIndexedY() {
|
||||
uint8_t dp = FetchByte();
|
||||
return ReadWord(dp) + Y;
|
||||
return memory.ReadWord(dp) + Y;
|
||||
}
|
||||
|
||||
uint16_t CPU::DirectPageIndirect() {
|
||||
uint8_t dp = FetchByte();
|
||||
return ReadWord(dp);
|
||||
return memory.ReadWord(dp);
|
||||
}
|
||||
|
||||
uint16_t CPU::StackRelativeIndirectIndexedY() {
|
||||
uint8_t sr = FetchByte();
|
||||
return ReadWord(SP + sr) + Y;
|
||||
return memory.ReadWord(SP + sr) + Y;
|
||||
}
|
||||
|
||||
uint16_t CPU::DirectPageIndexedX() {
|
||||
@@ -107,7 +110,7 @@ uint16_t CPU::DirectPageIndexedX() {
|
||||
|
||||
uint16_t CPU::DirectPageIndirectLongIndexedY() {
|
||||
uint8_t dp = FetchByte();
|
||||
return ReadWordLong(dp) + Y;
|
||||
return memory.ReadWordLong(dp) + Y;
|
||||
}
|
||||
|
||||
uint16_t CPU::AbsoluteIndexedY() { return FetchWord() + Y; }
|
||||
@@ -141,7 +144,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
|
||||
ADC(operand);
|
||||
break;
|
||||
case 0x6D: // ADC Absolute
|
||||
operand = memory.ReadByte(Absolute());
|
||||
operand = memory.ReadWord(Absolute());
|
||||
ADC(operand);
|
||||
break;
|
||||
case 0x6F: // ADC Absolute Long
|
||||
@@ -182,49 +185,62 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
|
||||
break;
|
||||
|
||||
case 0x21: // AND DP Indexed Indirect, X
|
||||
// AND();
|
||||
operand = memory.ReadByte(DirectPageIndexedIndirectX());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x23: // AND Stack Relative
|
||||
// AND();
|
||||
operand = memory.ReadByte(StackRelative());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x25: // AND Direct Page
|
||||
// AND();
|
||||
operand = FetchByteDirectPage(PC);
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x27: // AND DP Indirect Long
|
||||
// AND();
|
||||
operand = memory.ReadByte(DirectPageIndirectLong());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x29: // AND Immediate
|
||||
// AND();
|
||||
AND(Immediate());
|
||||
break;
|
||||
case 0x2D: // AND Absolute
|
||||
// AND();
|
||||
AND(Absolute());
|
||||
break;
|
||||
case 0x2F: // AND Absolute Long
|
||||
// AND();
|
||||
operand = memory.ReadByte(AbsoluteLong());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x31: // AND DP Indirect Indexed, Y
|
||||
// AND();
|
||||
operand = memory.ReadByte(DirectPageIndirectIndexedY());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x32: // AND DP Indirect
|
||||
// AND();
|
||||
operand = memory.ReadByte(DirectPageIndirect());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x33: // AND SR Indirect Indexed, Y
|
||||
// AND();
|
||||
operand = memory.ReadByte(StackRelativeIndirectIndexedY());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x35: // AND DP Indexed, X
|
||||
// AND();
|
||||
operand = memory.ReadByte(DirectPageIndexedX());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x37: // AND DP Indirect Long Indexed, Y
|
||||
// AND();
|
||||
operand = memory.ReadByte(DirectPageIndirectLongIndexedY());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x39: // AND Absolute Indexed, Y
|
||||
// AND();
|
||||
operand = memory.ReadByte(AbsoluteIndexedY());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x3D: // AND Absolute Indexed, X
|
||||
// AND();
|
||||
operand = memory.ReadByte(AbsoluteIndexedX());
|
||||
AND(operand);
|
||||
break;
|
||||
case 0x3F: // AND Absolute Long Indexed, X
|
||||
// AND();
|
||||
operand = memory.ReadByte(AbsoluteLongIndexedX());
|
||||
AND(operand);
|
||||
break;
|
||||
|
||||
case 0x06: // ASL Direct Page
|
||||
@@ -999,7 +1015,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
|
||||
}
|
||||
|
||||
void CPU::ADC(uint8_t operand) {
|
||||
auto C = (bool)GetCarryFlag();
|
||||
auto C = GetCarryFlag();
|
||||
if (GetAccumulatorSize()) { // 8-bit mode
|
||||
uint16_t result = (A & 0xFF) + (operand & 0xFF); // + (C ? 1 : 0);
|
||||
SetCarryFlag(!(result > 0xFF)); // Update the carry flag
|
||||
@@ -1033,6 +1049,21 @@ void CPU::ADC(uint8_t operand) {
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::AND(uint16_t address) {
|
||||
uint8_t operand;
|
||||
if (GetAccumulatorSize() == 0) { // 16-bit mode
|
||||
uint16_t operand16 = memory.ReadWord(address);
|
||||
A &= operand16;
|
||||
SetZeroFlag(A == 0);
|
||||
SetNegativeFlag(A & 0x8000);
|
||||
} else { // 8-bit mode
|
||||
operand = memory.ReadByte(address);
|
||||
A &= operand;
|
||||
SetZeroFlag(A == 0);
|
||||
SetNegativeFlag(A & 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
@@ -1,8 +1,11 @@
|
||||
#ifndef YAZE_APP_EMU_CPU_H_
|
||||
#define YAZE_APP_EMU_CPU_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "mem.h"
|
||||
#include "app/emu/mem.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
@@ -91,9 +94,15 @@ class CPU : public Memory {
|
||||
public:
|
||||
explicit CPU(Memory& mem) : memory(mem) {}
|
||||
|
||||
void Init() {}
|
||||
|
||||
uint8_t ReadByte(uint16_t address) const override;
|
||||
uint16_t ReadWord(uint16_t address) const override;
|
||||
uint32_t ReadWordLong(uint16_t address) const override;
|
||||
|
||||
void WriteByte(uint32_t address, uint8_t value) override;
|
||||
void WriteWord(uint32_t address, uint16_t value) override;
|
||||
|
||||
void SetMemory(const std::vector<uint8_t>& data) override {
|
||||
memory.SetMemory(data);
|
||||
}
|
||||
@@ -156,48 +165,30 @@ class CPU : public Memory {
|
||||
// B #$10 00010000 Break (emulation mode only)
|
||||
|
||||
// Setting flags in the status register
|
||||
void SetZeroFlag(bool condition) {
|
||||
if (condition) {
|
||||
status |= 0x02;
|
||||
} else {
|
||||
status &= ~0x02;
|
||||
}
|
||||
}
|
||||
|
||||
void SetNegativeFlag(bool condition) {
|
||||
if (condition) {
|
||||
status |= 0x80;
|
||||
} else {
|
||||
status &= ~0x80;
|
||||
}
|
||||
}
|
||||
|
||||
void SetOverflowFlag(bool condition) {
|
||||
if (condition) {
|
||||
status |= 0x40;
|
||||
} else {
|
||||
status &= ~0x40;
|
||||
}
|
||||
}
|
||||
|
||||
void SetCarryFlag(bool condition) {
|
||||
if (condition) {
|
||||
status |= 0x01;
|
||||
} else {
|
||||
status &= ~0x01;
|
||||
}
|
||||
}
|
||||
|
||||
int GetCarryFlag() { return status & 0x01; }
|
||||
int GetZeroFlag() { return status & 0x02; }
|
||||
|
||||
int GetAccumulatorSize() { return status & 0x20; }
|
||||
int GetIndexSize() { return status & 0x10; }
|
||||
|
||||
int GetEmulationMode() { return status & 0x04; }
|
||||
// Set individual flags
|
||||
void SetNegativeFlag(bool set) { SetFlag(0x80, set); }
|
||||
void SetOverflowFlag(bool set) { SetFlag(0x40, set); }
|
||||
void SetBreakFlag(bool set) { SetFlag(0x10, set); }
|
||||
void SetDecimalFlag(bool set) { SetFlag(0x08, set); }
|
||||
void SetInterruptFlag(bool set) { SetFlag(0x04, set); }
|
||||
void SetZeroFlag(bool set) { SetFlag(0x02, set); }
|
||||
void SetCarryFlag(bool set) { SetFlag(0x01, set); }
|
||||
|
||||
// Get individual flags
|
||||
bool GetNegativeFlag() const { return GetFlag(0x80); }
|
||||
bool GetOverflowFlag() const { return GetFlag(0x40); }
|
||||
bool GetBreakFlag() const { return GetFlag(0x10); }
|
||||
bool GetDecimalFlag() const { return GetFlag(0x08); }
|
||||
bool GetInterruptFlag() const { return GetFlag(0x04); }
|
||||
bool GetZeroFlag() const { return GetFlag(0x02); }
|
||||
bool GetCarryFlag() const { return GetFlag(0x01); }
|
||||
|
||||
// Instructions
|
||||
void ADC(uint8_t operand);
|
||||
void AND(uint16_t address);
|
||||
|
||||
void BEQ(int8_t offset) {
|
||||
if (GetZeroFlag()) { // If the zero flag is set
|
||||
@@ -324,6 +315,19 @@ class CPU : public Memory {
|
||||
SetNegativeFlag(Y & 0x80);
|
||||
}
|
||||
|
||||
private:
|
||||
// Helper function to set or clear a specific flag bit
|
||||
void SetFlag(uint8_t mask, bool set) {
|
||||
if (set) {
|
||||
status |= mask; // Set the bit
|
||||
} else {
|
||||
status &= ~mask; // Clear the bit
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to get the value of a specific flag bit
|
||||
bool GetFlag(uint8_t mask) const { return (status & mask) != 0; }
|
||||
|
||||
// Appease the C++ Gods...
|
||||
uint8_t operator[](int i) const override { return 0; }
|
||||
uint8_t at(int i) const override { return 0; }
|
||||
@@ -331,4 +335,6 @@ class CPU : public Memory {
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EMU_CPU_H_
|
||||
181
test/cpu_test.cc
181
test/cpu_test.cc
@@ -14,6 +14,10 @@ class MockMemory : public Memory {
|
||||
MOCK_CONST_METHOD1(ReadByte, uint8_t(uint16_t address));
|
||||
MOCK_CONST_METHOD1(ReadWord, uint16_t(uint16_t address));
|
||||
MOCK_CONST_METHOD1(ReadWordLong, uint32_t(uint16_t address));
|
||||
|
||||
MOCK_METHOD2(WriteByte, void(uint32_t address, uint8_t value));
|
||||
MOCK_METHOD2(WriteWord, void(uint32_t address, uint16_t value));
|
||||
|
||||
MOCK_CONST_METHOD1(at, uint8_t(int i));
|
||||
uint8_t operator[](int i) const override { return at(i); }
|
||||
|
||||
@@ -29,6 +33,12 @@ class MockMemory : public Memory {
|
||||
return static_cast<uint16_t>(memory_.at(address)) |
|
||||
(static_cast<uint16_t>(memory_.at(address + 1)) << 8);
|
||||
});
|
||||
ON_CALL(*this, ReadWordLong(::testing::_))
|
||||
.WillByDefault([this](uint16_t address) {
|
||||
return static_cast<uint32_t>(memory_.at(address)) |
|
||||
(static_cast<uint32_t>(memory_.at(address + 1)) << 8) |
|
||||
(static_cast<uint32_t>(memory_.at(address + 2)) << 16);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -75,6 +85,118 @@ TEST(CPUTest, AddPositiveAndNegativeNumbers) {
|
||||
EXPECT_EQ(cpu.A, static_cast<uint8_t>(-10));
|
||||
}
|
||||
|
||||
TEST(CPUTest, ADCDirectPage) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.A = 0x01;
|
||||
cpu.D = 0x0001;
|
||||
std::vector<uint8_t> data = {0x65, 0x01, 0x05};
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(0x01));
|
||||
|
||||
cpu.ExecuteInstruction(0x65); // ADC Direct Page
|
||||
EXPECT_EQ(cpu.A, 0x06);
|
||||
}
|
||||
|
||||
TEST(CPUTest, ADCAbsolute) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.A = 0x01;
|
||||
cpu.PC = 1; // PC register
|
||||
cpu.status = 0x00; // 16-bit mode
|
||||
std::vector<uint8_t> data = {0x6D, 0x03, 0x00, 0x05, 0x00};
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0003));
|
||||
|
||||
EXPECT_CALL(mock_memory, ReadWord(0x0003)).WillOnce(Return(0x0005));
|
||||
|
||||
cpu.ExecuteInstruction(0x6D); // ADC Absolute
|
||||
EXPECT_EQ(cpu.A, 0x06);
|
||||
}
|
||||
|
||||
TEST(CPUTest, ADCIndirectX) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.A = 0x01; // A register
|
||||
cpu.X = 0x02; // X register
|
||||
cpu.PC = 0; // PC register
|
||||
cpu.status = 0x00; // 16-bit mode
|
||||
std::vector<uint8_t> data = {0x72, 0x04, 0x00, 0x00, 0x20, 0x05, 0xFF};
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
// Get the absolute address
|
||||
EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0004));
|
||||
|
||||
cpu.ExecuteInstruction(0x72); // ADC Indirect Indexed with X
|
||||
EXPECT_EQ(cpu.A, 0x06);
|
||||
}
|
||||
|
||||
TEST(CPUTest, ADCIndexedIndirect) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.A = 0x01;
|
||||
cpu.X = 0x02;
|
||||
cpu.PC = 1;
|
||||
cpu.status = 0x00; // 16-bit mode
|
||||
std::vector<uint8_t> data = {/*ADC=*/0x61, /*DP=*/0x01, 0x18, 0x20, 0x05};
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0003));
|
||||
|
||||
cpu.ExecuteInstruction(0x61); // ADC Indexed Indirect
|
||||
EXPECT_EQ(cpu.A, 0x06);
|
||||
}
|
||||
|
||||
TEST(CPUTest, ANDImmediate) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.PC = 0;
|
||||
cpu.status = 0xFF; // 8-bit mode
|
||||
cpu.A = 0b11110000; // A register
|
||||
std::vector<uint8_t> data = {0x29, 0b10101010}; // AND #0b10101010
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(0b10101010));
|
||||
|
||||
cpu.ExecuteInstruction(0x29); // AND Immediate
|
||||
EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
|
||||
}
|
||||
|
||||
TEST(CPUTest, ANDAbsolute) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.A = 0b11111111; // A register
|
||||
cpu.status = 0x00; // 16-bit mode
|
||||
cpu.PC = 1; // PC register
|
||||
std::vector<uint8_t> data = {0x2D, 0x03, 0x00, 0b10101010, 0x01, 0x02};
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
// Get the absolute address
|
||||
EXPECT_CALL(mock_memory, ReadWord(0x0001)).WillOnce(Return(0x0003));
|
||||
|
||||
// Get the value at the absolute address
|
||||
EXPECT_CALL(mock_memory, ReadWord(0x0003)).WillOnce(Return(0b10101010));
|
||||
|
||||
cpu.ExecuteInstruction(0x2D); // AND Absolute
|
||||
|
||||
EXPECT_THAT(cpu.PC, testing::Eq(0x03));
|
||||
EXPECT_EQ(cpu.A, 0b10101010); // A register should now be 0b10101010
|
||||
}
|
||||
|
||||
TEST(CPUTest, ANDIndexedIndirect) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.A = 0b10101010; // A register
|
||||
cpu.X = 0x02; // X register
|
||||
std::vector<uint8_t> data = {0x21, 0x10, 0x18, 0x20, 0b01010101};
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
cpu.ExecuteInstruction(0x21); // AND Indexed Indirect
|
||||
EXPECT_EQ(cpu.A, 0b00000000); // A register should now be 0b00000000
|
||||
}
|
||||
|
||||
TEST(CPUTest, CheckCarryFlag) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
@@ -136,8 +258,9 @@ TEST(CPUTest, BranchLongAlways) {
|
||||
TEST(CPUTest, REP) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.status = 0xFF; // All flags set
|
||||
std::vector<uint8_t> data = {0xC2, 0x30, 0x00}; // REP #0x30 (clear N & Z flags)
|
||||
cpu.status = 0xFF; // All flags set
|
||||
std::vector<uint8_t> data = {0xC2, 0x30,
|
||||
0x00}; // REP #0x30 (clear N & Z flags)
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
cpu.ExecuteInstruction(0xC2); // REP
|
||||
@@ -147,8 +270,9 @@ TEST(CPUTest, REP) {
|
||||
TEST(CPUTest, SEP) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.status = 0x00; // All flags cleared
|
||||
std::vector<uint8_t> data = {0xE2, 0x30, 0x00}; // SEP #0x30 (set N & Z flags)
|
||||
cpu.status = 0x00; // All flags cleared
|
||||
std::vector<uint8_t> data = {0xE2, 0x30,
|
||||
0x00}; // SEP #0x30 (set N & Z flags)
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
cpu.ExecuteInstruction(0xE2); // SEP
|
||||
@@ -199,55 +323,6 @@ TEST(CPUTest, TAY) {
|
||||
EXPECT_EQ(cpu.Y, 0xDE); // Y register should now be equal to A
|
||||
}
|
||||
|
||||
TEST(CPUTest, ADCDirectPage) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.A = 0x01;
|
||||
cpu.D = 0x0000;
|
||||
std::vector<uint8_t> data = {0x65, 0x01, 0x05};
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
EXPECT_CALL(mock_memory, ReadByte(_)).WillOnce(Return(0x01));
|
||||
|
||||
cpu.ExecuteInstruction(0x65); // ADC Direct Page
|
||||
EXPECT_EQ(cpu.A, 0x06);
|
||||
}
|
||||
|
||||
TEST(CPUTest, ADCAbsolute) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.A = 0x01;
|
||||
std::vector<uint8_t> data = {0x6D, 0x10, 0x00, 0x05};
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
cpu.ExecuteInstruction(0x6D); // ADC Absolute
|
||||
EXPECT_EQ(cpu.A, 0x06);
|
||||
}
|
||||
|
||||
TEST(CPUTest, ADCIndirectX) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.A = 0x01;
|
||||
cpu.X = 0x02;
|
||||
std::vector<uint8_t> data = {0x72, 0x10, 0x00, 0x00, 0x20, 0x05};
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
cpu.ExecuteInstruction(0x72); // ADC Indirect Indexed with X
|
||||
EXPECT_EQ(cpu.A, 0x06);
|
||||
}
|
||||
|
||||
TEST(CPUTest, ADCIndexedIndirect) {
|
||||
MockMemory mock_memory;
|
||||
CPU cpu(mock_memory);
|
||||
cpu.A = 0x01;
|
||||
cpu.X = 0x02;
|
||||
std::vector<uint8_t> data = {0x61, 0x10, 0x18, 0x20, 0x05};
|
||||
mock_memory.SetMemoryContents(data);
|
||||
|
||||
cpu.ExecuteInstruction(0x61); // ADC Indexed Indirect
|
||||
EXPECT_EQ(cpu.A, 0x06);
|
||||
}
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
Reference in New Issue
Block a user