Add JMP Absolute, JMP Indirect, JSR Absolute, JSL_AbsoluteLong
This commit is contained in:
@@ -448,13 +448,13 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x4C: // JMP Absolute
|
case 0x4C: // JMP Absolute
|
||||||
// JMP();
|
JMP(Absolute());
|
||||||
break;
|
break;
|
||||||
case 0x5C: // JMP Absolute Long
|
case 0x5C: // JMP Absolute Long
|
||||||
// JMP();
|
// JMP();
|
||||||
break;
|
break;
|
||||||
case 0x6C: // JMP Absolute Indirect
|
case 0x6C: // JMP Absolute Indirect
|
||||||
// JMP();
|
JMP(AbsoluteIndirect());
|
||||||
break;
|
break;
|
||||||
case 0x7C: // JMP Absolute Indexed Indirect, X
|
case 0x7C: // JMP Absolute Indexed Indirect, X
|
||||||
// JMP();
|
// JMP();
|
||||||
@@ -464,11 +464,11 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x20: // JSR Absolute
|
case 0x20: // JSR Absolute
|
||||||
// JSR();
|
JSR(Absolute());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x22: // JSL Absolute Long
|
case 0x22: // JSL Absolute Long
|
||||||
// JSL();
|
JSL(AbsoluteLong());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFC: // JSR Absolute Indexed Indirect, X
|
case 0xFC: // JSR Absolute Indexed Indirect, X
|
||||||
|
|||||||
@@ -344,7 +344,6 @@ class CPU : public Memory {
|
|||||||
// TSB: Test and set bits
|
// TSB: Test and set bits
|
||||||
// WAI: Wait for interrupt
|
// WAI: Wait for interrupt
|
||||||
// XBA: Exchange B and A accumulator
|
// XBA: Exchange B and A accumulator
|
||||||
// XCE: Exchange carry and emulation
|
|
||||||
|
|
||||||
void ADC(uint8_t operand);
|
void ADC(uint8_t operand);
|
||||||
void AND(uint16_t address);
|
void AND(uint16_t address);
|
||||||
@@ -452,6 +451,26 @@ class CPU : public Memory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JMP: Jump to new address
|
||||||
|
void JMP(uint16_t address) {
|
||||||
|
PC = address; // Set program counter to the new address
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSR: Jump to subroutine
|
||||||
|
void JSR(uint16_t address) {
|
||||||
|
PC -= 1; // Subtract 1 from program counter
|
||||||
|
memory.PushWord(PC); // Push the program counter onto the stack
|
||||||
|
PC = address; // Set program counter to the new address
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSL: Jump to subroutine long
|
||||||
|
void JSL(uint32_t address) {
|
||||||
|
PC -= 1; // Subtract 1 from program counter
|
||||||
|
memory.PushLong(PC); // Push the program counter onto the stack as a long
|
||||||
|
// value (24 bits)
|
||||||
|
PC = address; // Set program counter to the new address
|
||||||
|
}
|
||||||
|
|
||||||
// Push Accumulator on Stack
|
// Push Accumulator on Stack
|
||||||
void PHA() { memory.PushByte(A); }
|
void PHA() { memory.PushByte(A); }
|
||||||
|
|
||||||
@@ -620,6 +639,8 @@ class CPU : public Memory {
|
|||||||
void PushWord(uint16_t value) override { memory.PushWord(value); }
|
void PushWord(uint16_t value) override { memory.PushWord(value); }
|
||||||
uint8_t PopByte() override { return memory.PopByte(); }
|
uint8_t PopByte() override { return memory.PopByte(); }
|
||||||
uint16_t PopWord() override { return memory.PopWord(); }
|
uint16_t PopWord() override { return memory.PopWord(); }
|
||||||
|
void PushLong(uint32_t value) override { memory.PushLong(value); }
|
||||||
|
uint32_t PopLong() override { return memory.PopLong(); }
|
||||||
void ClearMemory() override { memory.ClearMemory(); }
|
void ClearMemory() override { memory.ClearMemory(); }
|
||||||
void LoadData(const std::vector<uint8_t>& data) override {
|
void LoadData(const std::vector<uint8_t>& data) override {
|
||||||
memory.LoadData(data);
|
memory.LoadData(data);
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ class Memory {
|
|||||||
virtual uint8_t PopByte() = 0;
|
virtual uint8_t PopByte() = 0;
|
||||||
virtual void PushWord(uint16_t value) = 0;
|
virtual void PushWord(uint16_t value) = 0;
|
||||||
virtual uint16_t PopWord() = 0;
|
virtual uint16_t PopWord() = 0;
|
||||||
|
virtual void PushLong(uint32_t value) = 0;
|
||||||
|
virtual uint32_t PopLong() = 0;
|
||||||
|
|
||||||
virtual int16_t SP() const = 0;
|
virtual int16_t SP() const = 0;
|
||||||
virtual void SetSP(int16_t value) = 0;
|
virtual void SetSP(int16_t value) = 0;
|
||||||
|
|
||||||
@@ -74,7 +77,7 @@ class MemoryImpl : public Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WriteByte(uint32_t address, uint8_t value) override {
|
void WriteByte(uint32_t address, uint8_t value) override {
|
||||||
// uint32_t mapped_address = GetMappedAddress(address);
|
// uint32_t mapped_address = GetMappedAddress(address);
|
||||||
memory_[address] = value;
|
memory_[address] = value;
|
||||||
}
|
}
|
||||||
void WriteWord(uint32_t address, uint16_t value) override {
|
void WriteWord(uint32_t address, uint16_t value) override {
|
||||||
@@ -114,6 +117,20 @@ class MemoryImpl : public Memory {
|
|||||||
return (static_cast<uint16_t>(high) << 8) | low;
|
return (static_cast<uint16_t>(high) << 8) | low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PushLong(uint32_t value) override {
|
||||||
|
PushByte(value >> 16);
|
||||||
|
PushByte(value >> 8);
|
||||||
|
PushByte(value & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PopLong() override {
|
||||||
|
uint8_t low = PopByte();
|
||||||
|
uint8_t mid = PopByte();
|
||||||
|
uint8_t high = PopByte();
|
||||||
|
return (static_cast<uint32_t>(high) << 16) |
|
||||||
|
(static_cast<uint32_t>(mid) << 8) | low;
|
||||||
|
}
|
||||||
|
|
||||||
int16_t SP() const override { return SP_; }
|
int16_t SP() const override { return SP_; }
|
||||||
void SetSP(int16_t value) override { SP_ = value; }
|
void SetSP(int16_t value) override { SP_ = value; }
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ class MockMemory : public Memory {
|
|||||||
MOCK_METHOD0(PopByte, uint8_t());
|
MOCK_METHOD0(PopByte, uint8_t());
|
||||||
MOCK_METHOD1(PushWord, void(uint16_t value));
|
MOCK_METHOD1(PushWord, void(uint16_t value));
|
||||||
MOCK_METHOD0(PopWord, uint16_t());
|
MOCK_METHOD0(PopWord, uint16_t());
|
||||||
|
MOCK_METHOD1(PushLong, void(uint32_t value));
|
||||||
|
MOCK_METHOD0(PopLong, uint32_t());
|
||||||
|
|
||||||
MOCK_CONST_METHOD0(SP, int16_t());
|
MOCK_CONST_METHOD0(SP, int16_t());
|
||||||
MOCK_METHOD1(SetSP, void(int16_t value));
|
MOCK_METHOD1(SetSP, void(int16_t value));
|
||||||
|
|
||||||
@@ -81,6 +84,19 @@ class MockMemory : public Memory {
|
|||||||
this->SetSP(SP_ + 2);
|
this->SetSP(SP_ + 2);
|
||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
|
ON_CALL(*this, PushLong(::testing::_))
|
||||||
|
.WillByDefault([this](uint32_t value) {
|
||||||
|
memory_.at(SP_) = value & 0xFF;
|
||||||
|
memory_.at(SP_ + 1) = (value >> 8) & 0xFF;
|
||||||
|
memory_.at(SP_ + 2) = (value >> 16) & 0xFF;
|
||||||
|
});
|
||||||
|
ON_CALL(*this, PopLong()).WillByDefault([this]() {
|
||||||
|
uint32_t value = static_cast<uint32_t>(memory_.at(SP_)) |
|
||||||
|
(static_cast<uint32_t>(memory_.at(SP_ + 1)) << 8) |
|
||||||
|
(static_cast<uint32_t>(memory_.at(SP_ + 2)) << 16);
|
||||||
|
this->SetSP(SP_ + 3);
|
||||||
|
return value;
|
||||||
|
});
|
||||||
ON_CALL(*this, ClearMemory()).WillByDefault([this]() {
|
ON_CALL(*this, ClearMemory()).WillByDefault([this]() {
|
||||||
memory_.resize(64000, 0x00);
|
memory_.resize(64000, 0x00);
|
||||||
});
|
});
|
||||||
@@ -467,6 +483,65 @@ TEST_F(CPUTest, INY) {
|
|||||||
EXPECT_TRUE(cpu.GetZeroFlag());
|
EXPECT_TRUE(cpu.GetZeroFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// JMP - Jump to new location
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
TEST_F(CPUTest, JMP_Absolute) {
|
||||||
|
cpu.PC = 0x1001;
|
||||||
|
std::vector<uint8_t> data = {0x4C, 0x05, 0x20}; // JMP $2005
|
||||||
|
mock_memory.SetMemoryContents(data);
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_memory, ReadWord(0x1001)).WillOnce(Return(0x2005));
|
||||||
|
|
||||||
|
cpu.ExecuteInstruction(0x4C); // JMP Absolute
|
||||||
|
EXPECT_EQ(cpu.PC, 0x2005);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CPUTest, JMP_Indirect) {
|
||||||
|
cpu.PC = 0x1001;
|
||||||
|
std::vector<uint8_t> data = {0x6C, 0x03, 0x20, 0x05, 0x30}; // JMP ($2003)
|
||||||
|
mock_memory.SetMemoryContents(data);
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_memory, ReadWord(0x1001)).WillOnce(Return(0x2003));
|
||||||
|
EXPECT_CALL(mock_memory, ReadWord(0x2003)).WillOnce(Return(0x3005));
|
||||||
|
|
||||||
|
cpu.ExecuteInstruction(0x6C); // JMP Indirect
|
||||||
|
EXPECT_EQ(cpu.PC, 0x3005);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// JSR - Jump to Subroutine
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
TEST_F(CPUTest, JSR_Absolute) {
|
||||||
|
cpu.PC = 0x1001;
|
||||||
|
std::vector<uint8_t> data = {0x20, 0x05, 0x20}; // JSR $2005
|
||||||
|
mock_memory.SetMemoryContents(data);
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_memory, ReadWord(0x1001)).WillOnce(Return(0x2005));
|
||||||
|
EXPECT_CALL(mock_memory, PushWord(0x1002)).Times(1);
|
||||||
|
|
||||||
|
cpu.ExecuteInstruction(0x20); // JSR Absolute
|
||||||
|
EXPECT_EQ(cpu.PC, 0x2005);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// JSL - Jump to Subroutine Long
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
TEST_F(CPUTest, JSL_AbsoluteLong) {
|
||||||
|
cpu.PC = 0x1001;
|
||||||
|
std::vector<uint8_t> data = {0x22, 0x05, 0x20, 0x00}; // JSL $002005
|
||||||
|
mock_memory.SetMemoryContents(data);
|
||||||
|
|
||||||
|
EXPECT_CALL(mock_memory, ReadWordLong(0x1001)).WillOnce(Return(0x002005));
|
||||||
|
EXPECT_CALL(mock_memory, PushLong(0x1003)).Times(1);
|
||||||
|
|
||||||
|
cpu.ExecuteInstruction(0x22); // JSL Absolute Long
|
||||||
|
EXPECT_EQ(cpu.PC, 0x002005);
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Stack Tests
|
// Stack Tests
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user