Add PHX, PHY, PHB, PHD, PHK and PLX, PLY, PLB, PLD

This commit is contained in:
scawful
2023-08-19 16:18:45 -04:00
parent 76f40531f1
commit 8d0f4110e0
4 changed files with 200 additions and 104 deletions

View File

@@ -76,6 +76,12 @@ class MockMemory : public Memory {
uint16_t SP_ = 0x01FF;
};
class CPUTest : public ::testing::Test {
public:
MockMemory mock_memory;
CPU cpu{mock_memory};
};
using ::testing::_;
using ::testing::Return;
@@ -83,7 +89,7 @@ using ::testing::Return;
// Infrastructure
// ============================================================================
TEST(CPUTest, CheckMemoryContents) {
TEST_F(CPUTest, CheckMemoryContents) {
MockMemory memory;
std::vector<uint8_t> data = {0x00, 0x01, 0x02, 0x03, 0x04};
memory.SetMemoryContents(data);
@@ -106,9 +112,7 @@ TEST(CPUTest, CheckMemoryContents) {
// ============================================================================
// ADC - Add with Carry
TEST(CPUTest, ADC_Immediate_TwoPositiveNumbers) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, ADC_Immediate_TwoPositiveNumbers) {
cpu.A = 0x01;
std::vector<uint8_t> data = {0x69, 0x01};
mock_memory.SetMemoryContents(data);
@@ -119,9 +123,7 @@ TEST(CPUTest, ADC_Immediate_TwoPositiveNumbers) {
EXPECT_EQ(cpu.A, 0x02);
}
TEST(CPUTest, ADC_Immediate_PositiveAndNegativeNumbers) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, ADC_Immediate_PositiveAndNegativeNumbers) {
cpu.A = 10;
std::vector<uint8_t> data = {0x69, static_cast<uint8_t>(-20)};
mock_memory.SetMemoryContents(data);
@@ -132,9 +134,7 @@ TEST(CPUTest, ADC_Immediate_PositiveAndNegativeNumbers) {
EXPECT_EQ(cpu.A, static_cast<uint8_t>(-10));
}
TEST(CPUTest, ADC_Absolute) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, ADC_Absolute) {
cpu.A = 0x01;
cpu.PC = 1; // PC register
cpu.status = 0x00; // 16-bit mode
@@ -149,9 +149,7 @@ TEST(CPUTest, ADC_Absolute) {
EXPECT_EQ(cpu.A, 0x06);
}
TEST(CPUTest, ADC_AbsoluteLong) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, ADC_AbsoluteLong) {
cpu.A = 0x01;
cpu.PC = 1; // PC register
cpu.status = 0x00; // 16-bit mode
@@ -161,9 +159,9 @@ TEST(CPUTest, ADC_AbsoluteLong) {
/**
* Direct Page Unimplemented
*
TEST(CPUTest, ADC_DirectPage) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, ADC_DirectPage) {
cpu.A = 0x01;
cpu.D = 0x0001;
std::vector<uint8_t> data = {0x65, 0x01, 0x05};
@@ -175,9 +173,9 @@ TEST(CPUTest, ADC_DirectPage) {
EXPECT_EQ(cpu.A, 0x06);
}
TEST(CPUTest, ADC_DirectPageIndirect) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, ADC_DirectPageIndirect) {
cpu.A = 0x01; // A register
cpu.X = 0x02; // X register
cpu.PC = 0; // PC register
@@ -192,9 +190,9 @@ TEST(CPUTest, ADC_DirectPageIndirect) {
EXPECT_EQ(cpu.A, 0x06);
}
TEST(CPUTest, ADC_DirectPageIndexedIndirectX) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, ADC_DirectPageIndexedIndirectX) {
cpu.A = 0x01;
cpu.X = 0x02;
cpu.PC = 1;
@@ -211,9 +209,7 @@ TEST(CPUTest, ADC_DirectPageIndexedIndirectX) {
}
**/
TEST(CPUTest, ADC_CheckCarryFlag) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, ADC_CheckCarryFlag) {
cpu.A = 0xFF;
cpu.status = 0;
std::vector<uint8_t> data = {0x15, 0x01}; // Operand at address 0x15
@@ -230,9 +226,7 @@ TEST(CPUTest, ADC_CheckCarryFlag) {
// ============================================================================
// AND - Logical AND
TEST(CPUTest, AND_Immediate) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, AND_Immediate) {
cpu.PC = 0;
cpu.status = 0xFF; // 8-bit mode
cpu.A = 0b11110000; // A register
@@ -245,9 +239,7 @@ TEST(CPUTest, AND_Immediate) {
EXPECT_EQ(cpu.A, 0b10100000); // A register should now be 0b10100000
}
TEST(CPUTest, AND_Absolute) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, AND_Absolute) {
cpu.A = 0b11111111; // A register
cpu.status = 0x00; // 16-bit mode
cpu.PC = 1; // PC register
@@ -266,9 +258,7 @@ TEST(CPUTest, AND_Absolute) {
EXPECT_EQ(cpu.A, 0b10101010); // A register should now be 0b10101010
}
TEST(CPUTest, AND_IndexedIndirect) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, AND_IndexedIndirect) {
cpu.A = 0b10101010; // A register
cpu.X = 0x02; // X register
std::vector<uint8_t> data = {0x21, 0x10, 0x18, 0x20, 0b01010101};
@@ -281,9 +271,7 @@ TEST(CPUTest, AND_IndexedIndirect) {
// ============================================================================
// BCC - Branch if Carry Clear
TEST(CPUTest, BCC_WhenCarryFlagClear) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, BCC_WhenCarryFlagClear) {
cpu.SetCarryFlag(false);
cpu.PC = 0x1000;
std::vector<uint8_t> data(0x1001, 2); // Operand at address 0x1001
@@ -295,9 +283,7 @@ TEST(CPUTest, BCC_WhenCarryFlagClear) {
EXPECT_EQ(cpu.PC, 0x1002);
}
TEST(CPUTest, BCC_WhenCarryFlagSet) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, BCC_WhenCarryFlagSet) {
cpu.SetCarryFlag(true);
cpu.PC = 0x1000;
std::vector<uint8_t> data(0x1001, 2); // Operand at address 0x1001
@@ -313,9 +299,7 @@ TEST(CPUTest, BCC_WhenCarryFlagSet) {
// ============================================================================
// BRL - Branch Long
TEST(CPUTest, BRL) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, BRL) {
cpu.PC = 0x1000;
std::vector<uint8_t> data(0x1001, 2); // Operand at address 0x1001
mock_memory.SetMemoryContents(data);
@@ -329,51 +313,130 @@ TEST(CPUTest, BRL) {
// ============================================================================
// Stack Tests
class CPUTestKit : public ::testing::Test {
protected:
MockMemory memory_;
CPU cpu_{memory_};
};
TEST_F(CPUTestKit, PHA_PLA_Test) {
cpu_.A = 0x42;
EXPECT_CALL(memory_, PushByte(0x42)).WillOnce(Return());
cpu_.PHA();
cpu_.A = 0x00;
EXPECT_CALL(memory_, PopByte()).WillOnce(Return(0x42));
cpu_.PLA();
EXPECT_EQ(cpu_.A, 0x42);
TEST_F(CPUTest, PHA_PLA_Ok) {
cpu.A = 0x42;
EXPECT_CALL(mock_memory, PushByte(0x42)).WillOnce(Return());
cpu.PHA();
cpu.A = 0x00;
EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x42));
cpu.PLA();
EXPECT_EQ(cpu.A, 0x42);
}
TEST_F(CPUTestKit, PHP_PLP_Test) {
TEST_F(CPUTest, PHP_PLP_Ok) {
// Set some status flags
cpu_.SetNegativeFlag(true);
cpu_.SetZeroFlag(false);
EXPECT_TRUE(cpu_.GetNegativeFlag());
EXPECT_FALSE(cpu_.GetZeroFlag());
cpu.status = 0;
cpu.SetNegativeFlag(true);
cpu.SetZeroFlag(false);
EXPECT_TRUE(cpu.GetNegativeFlag());
EXPECT_FALSE(cpu.GetZeroFlag());
EXPECT_CALL(memory_, PushByte(0x80)).WillOnce(Return());
cpu_.PHP();
EXPECT_CALL(mock_memory, PushByte(0x80)).WillOnce(Return());
cpu.PHP();
// Clear status flags
cpu_.SetNegativeFlag(false);
cpu_.SetZeroFlag(true);
EXPECT_FALSE(cpu_.GetNegativeFlag());
EXPECT_TRUE(cpu_.GetZeroFlag());
cpu.SetNegativeFlag(false);
cpu.SetZeroFlag(true);
EXPECT_FALSE(cpu.GetNegativeFlag());
EXPECT_TRUE(cpu.GetZeroFlag());
EXPECT_CALL(memory_, PopByte()).WillOnce(Return(0x80));
cpu_.PLP();
EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x80));
cpu.PLP();
EXPECT_TRUE(cpu_.GetNegativeFlag());
EXPECT_FALSE(cpu_.GetZeroFlag());
EXPECT_TRUE(cpu.GetNegativeFlag());
EXPECT_FALSE(cpu.GetZeroFlag());
}
// ============================================================================
// PHA, PHP, PHX, PHY, PHB, PHD, PHK
// ============================================================================
TEST_F(CPUTest, PHA_PushAccumulator) {
cpu.A = 0x12;
EXPECT_CALL(mock_memory, PushByte(0x12));
cpu.ExecuteInstruction(0x48); // PHA
}
TEST_F(CPUTest, PHP_PushProcessorStatusRegister) {
cpu.status = 0x34;
EXPECT_CALL(mock_memory, PushByte(0x34));
cpu.ExecuteInstruction(0x08); // PHP
}
TEST_F(CPUTest, PHX_PushXRegister) {
cpu.X = 0x56;
EXPECT_CALL(mock_memory, PushByte(0x56));
cpu.ExecuteInstruction(0xDA); // PHX
}
TEST_F(CPUTest, PHY_PushYRegister) {
cpu.Y = 0x78;
EXPECT_CALL(mock_memory, PushByte(0x78));
cpu.ExecuteInstruction(0x5A); // PHY
}
TEST_F(CPUTest, PHB_PushDataBankRegister) {
cpu.DB = 0x9A;
EXPECT_CALL(mock_memory, PushByte(0x9A));
cpu.ExecuteInstruction(0x8B); // PHB
}
TEST_F(CPUTest, PHD_PushDirectPageRegister) {
cpu.D = 0xBC;
EXPECT_CALL(mock_memory, PushWord(0xBC));
cpu.ExecuteInstruction(0x0B); // PHD
}
TEST_F(CPUTest, PHK_PushProgramBankRegister) {
cpu.PB = 0xDE;
EXPECT_CALL(mock_memory, PushByte(0xDE));
cpu.ExecuteInstruction(0x4B); // PHK
}
// ============================================================================
// PLA, PLP, PLX, PLY, PLB, PLD
// ============================================================================
TEST_F(CPUTest, PLA_PullAccumulator) {
EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x12));
cpu.ExecuteInstruction(0x68); // PLA
EXPECT_EQ(cpu.A, 0x12);
}
TEST_F(CPUTest, PLP_PullProcessorStatusRegister) {
EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x34));
cpu.ExecuteInstruction(0x28); // PLP
EXPECT_EQ(cpu.status, 0x34);
}
TEST_F(CPUTest, PLX_PullXRegister) {
EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x56));
cpu.ExecuteInstruction(0xFA); // PLX
EXPECT_EQ(cpu.X, 0x56);
}
TEST_F(CPUTest, PLY_PullYRegister) {
EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x78));
cpu.ExecuteInstruction(0x7A); // PLY
EXPECT_EQ(cpu.Y, 0x78);
}
TEST_F(CPUTest, PLB_PullDataBankRegister) {
EXPECT_CALL(mock_memory, PopByte()).WillOnce(Return(0x9A));
cpu.ExecuteInstruction(0xAB); // PLB
EXPECT_EQ(cpu.DB, 0x9A);
}
TEST_F(CPUTest, PLD_PullDirectPageRegister) {
EXPECT_CALL(mock_memory, PopWord()).WillOnce(Return(0xBC));
cpu.ExecuteInstruction(0x2B); // PLD
EXPECT_EQ(cpu.D, 0xBC);
}
// ============================================================================
// REP - Reset Processor Status Bits
TEST(CPUTest, REP) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, REP) {
cpu.status = 0xFF; // All flags set
std::vector<uint8_t> data = {0xC2, 0x30,
0x00}; // REP #0x30 (clear N & Z flags)
@@ -386,9 +449,7 @@ TEST(CPUTest, REP) {
// ============================================================================
// SEP - Set Processor Status Bits
TEST(CPUTest, SEP) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, SEP) {
cpu.status = 0x00; // All flags cleared
std::vector<uint8_t> data = {0xE2, 0x30,
0x00}; // SEP #0x30 (set N & Z flags)
@@ -401,9 +462,7 @@ TEST(CPUTest, SEP) {
// ============================================================================
// TXA - Transfer Index X to Accumulator
TEST(CPUTest, TXA) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, TXA) {
cpu.X = 0xAB; // X register
std::vector<uint8_t> data = {0x8A}; // TXA
mock_memory.SetMemoryContents(data);
@@ -415,9 +474,7 @@ TEST(CPUTest, TXA) {
// ============================================================================
// TAX - Transfer Accumulator to Index X
TEST(CPUTest, TAX) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, TAX) {
cpu.A = 0xBC; // A register
std::vector<uint8_t> data = {0xAA}; // TAX
mock_memory.SetMemoryContents(data);
@@ -429,9 +486,7 @@ TEST(CPUTest, TAX) {
// ============================================================================
// TYA - Transfer Index Y to Accumulator
TEST(CPUTest, TYA) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, TYA) {
cpu.Y = 0xCD; // Y register
std::vector<uint8_t> data = {0x98}; // TYA
mock_memory.SetMemoryContents(data);
@@ -443,9 +498,7 @@ TEST(CPUTest, TYA) {
// ============================================================================
// TAY - Transfer Accumulator to Index Y
TEST(CPUTest, TAY) {
MockMemory mock_memory;
CPU cpu(mock_memory);
TEST_F(CPUTest, TAY) {
cpu.A = 0xDE; // A register
std::vector<uint8_t> data = {0xA8}; // TAY
mock_memory.SetMemoryContents(data);