Implement Some Subroutine instructions

This commit is contained in:
2025-07-22 11:41:06 -04:00
parent 268b45b062
commit a863b36f82
2 changed files with 112 additions and 1 deletions

View File

@@ -100,8 +100,9 @@ void CPU::UpdateCompareFlags16(const uint16_t reg_value, const uint16_t compare_
}
}
// General Branching Code
void CPU::DoBranch(const bool condition) {
int8_t displacement = static_cast<int8_t>(ReadByte(PC));
const int8_t displacement = static_cast<int8_t>(ReadByte(PC));
PC++;
if (condition) {
@@ -116,6 +117,32 @@ void CPU::DoBranch(const bool condition) {
}
}
// Stack helper methods:
void CPU::PushByte(const uint8_t value) {
WriteByte(SP, value);
SP--;
cycles++;
}
void CPU::PushWord(const uint16_t value) {
// Push high then low
PushByte(value >> 8); // High byte
PushByte(value & 0xFF); // Low byte
}
uint8_t CPU::PopByte() {
SP++;
cycles++;
return ReadByte(SP);
}
uint16_t CPU::PopWord() {
// Pop low then high
const uint8_t low = PopByte();
const uint8_t high = PopByte();
return (high << 8) | low;
}
void CPU::ExecuteInstruction() {
// TODO: Actual Opcode decoding
switch (const uint8_t opcode = bus->Read(PC++)) {
@@ -163,6 +190,11 @@ void CPU::ExecuteInstruction() {
case 0x5C: JMP_AbsoluteLong(); break; // JMP $nnnnnn
case 0x7C: JMP_AbsoluteIndirectX(); break; // JMP ($nnnn,X)
// Subroutine instructions
case 0x20: JSR_Absolute(); break; // JSR $nnnn
case 0x22: JSR_AbsoluteLong(); break; // JSR $nnnnnn
case 0xFC: JSR_AbsoluteIndirectX(); break; // JSR ($nnnn,X)
// Single Register Decrement
case 0xCA: DEX(); break; // DEX - Decrement X Register
case 0x88: DEY(); break; // DEY - Decrement Y Register
@@ -208,6 +240,10 @@ void CPU::ExecuteInstruction() {
case 0xA4: LDY_DirectPage(); break; // LDY $nn
case 0xB4: LDY_DirectPageX(); break; // LDY $nn,X
// More Subroutines
case 0x60: RTS(); break; // RTS
case 0x6B: RTL(); break; // RTL
//SDA - Store Accumulator
case 0x8D: STA_Absolute(); break; // STA $nnnn
case 0x9D: STA_AbsoluteX(); break; // STA $nnnn,X
@@ -1516,3 +1552,66 @@ void CPU::BMI_Relative() {
void CPU::BPL_Relative() {
DoBranch(!(P & FLAG_N));
}
void CPU::JSR_Absolute() {
const uint16_t target_addr = ReadWord(PC);
PC += 2;
const uint16_t return_addr = (PC - 1) & 0xFFFF;
PushWord(return_addr);
PC = (static_cast<uint32_t>(PB) << 16) | target_addr;
cycles += 6;
}
void CPU::JSR_AbsoluteLong() {
const uint16_t addr_low = ReadWord(PC);
PC += 2;
const uint8_t addr_high = ReadByte(PC);
PC++;
PushByte(PB);
const uint16_t return_addr = (PC - 1) & 0xFFFF;
PushWord(return_addr);
PB = addr_high;
PC = (static_cast<uint32_t>(addr_high) << 16) | addr_low;
cycles += 8;
}
void CPU::JSR_AbsoluteIndirectX() {
const uint16_t base_addr = ReadWord(PC);
PC += 2;
const uint32_t indirect_addr = (static_cast<uint32_t>(PB) << 16) | ((base_addr + X) & 0xFFFF);
const uint16_t target_addr = ReadWord(indirect_addr);
const uint16_t return_addr = (PC - 1) & 0xFFFF;
PushWord(return_addr);
PC = (static_cast<uint32_t>(PB) << 16) | target_addr;
cycles += 8;
}
void CPU::RTS() {
const uint16_t return_addr = PopWord();
PC = (static_cast<uint32_t>(PB) << 16) | ((return_addr + 1) & 0xFFFF);
cycles += 6;
}
void CPU::RTL() {
const uint16_t return_addr = PopWord();
PB = PopByte();
PC = (static_cast<uint32_t>(PB) << 16) | ((return_addr + 1) & 0xFFFF);
cycles += 6;
}

View File

@@ -63,6 +63,12 @@ public:
// Branching helper method
void DoBranch(bool condition);
// Helper methods for stack operations
void PushByte(uint8_t value);
void PushWord(uint16_t value);
uint8_t PopByte();
uint16_t PopWord();
// Instruction implementations
// TODO: Implement remaining instructions
void CMP_Immediate();
@@ -158,6 +164,12 @@ public:
void BCS_Relative();
void BMI_Relative();
void BPL_Relative();
void JSR_Absolute();
void JSR_AbsoluteLong();
void JSR_AbsoluteIndirectX();
void RTS();
void RTL();
};
#endif //CPU_H