Implement Store Instructions
This commit is contained in:
290
src/cpu.cpp
290
src/cpu.cpp
@@ -22,33 +22,40 @@ void CPU::Step() {
|
||||
}
|
||||
|
||||
// CPU Helper Methods
|
||||
uint8_t CPU::ReadByte(uint32_t address) {
|
||||
uint8_t CPU::ReadByte(const uint32_t address) {
|
||||
cycles++;
|
||||
return bus->Read(address);
|
||||
}
|
||||
|
||||
uint16_t CPU::ReadWord(uint32_t address) {
|
||||
uint16_t CPU::ReadWord(const uint32_t address) {
|
||||
uint8_t low = ReadByte(address);
|
||||
uint8_t high = ReadByte(address + 1);
|
||||
return (high << 8) | low;
|
||||
}
|
||||
|
||||
void CPU::UpdateNZ8(uint8_t value) {
|
||||
void CPU::UpdateNZ8(const uint8_t value) {
|
||||
P = (P & ~FLAG_N) | (value & 0x80); // Set N flag if bit 7 is set
|
||||
P = (P & ~FLAG_Z) | (value == 0 ? FLAG_Z : 0); // Set Z flag if value is zero
|
||||
}
|
||||
|
||||
void CPU::UpdateNZ16(uint16_t value) {
|
||||
void CPU::UpdateNZ16(const uint16_t value) {
|
||||
P = (P & ~FLAG_N) | ((value & 0x8000) ? FLAG_N : 0); // Set N flag if bit 15 is set
|
||||
P = (P & ~FLAG_Z) | (value == 0 ? FLAG_Z : 0); // Set Z flag if value is zero
|
||||
}
|
||||
|
||||
// Helper method to write bytes/words to memory
|
||||
void CPU::WriteByte(const uint32_t address, const uint8_t value) const {
|
||||
bus->Write(address, value);
|
||||
}
|
||||
|
||||
void CPU::WriteWord(const uint32_t address, const uint16_t value) const {
|
||||
bus->Write(address, value & 0xFF); // Low byte
|
||||
bus->Write(address + 1, (value >> 8) & 0xFF); // High byte
|
||||
}
|
||||
|
||||
void CPU::ExecuteInstruction() {
|
||||
uint8_t opcode = bus->Read(PC++);
|
||||
|
||||
// TODO: Actual Opcode decoding
|
||||
switch (opcode) {
|
||||
switch (const uint8_t opcode = bus->Read(PC++)) {
|
||||
case 0xEA: NOP(); break;
|
||||
|
||||
// LDA - Load Accumulator
|
||||
@@ -78,12 +85,32 @@ void CPU::ExecuteInstruction() {
|
||||
case 0xA4: LDY_DirectPage(); break; // LDY $nn
|
||||
case 0xB4: LDY_DirectPageX(); break; // LDY $nn,X
|
||||
|
||||
//SDA - Store Accumulator
|
||||
case 0x8D: STA_Absolute(); break;
|
||||
case 0x9D: STA_AbsoluteX(); break;
|
||||
case 0x99: STA_AbsoluteY(); break;
|
||||
case 0x85: STA_DirectPage(); break;
|
||||
case 0x95: STA_DirectPageX(); break;
|
||||
case 0x92: STA_IndirectDirectPage(); break;
|
||||
case 0x91: STA_IndirectDirectPageY(); break;
|
||||
case 0x81: STA_DirectPageIndirectX(); break;
|
||||
case 0x8F: STA_Long(); break;
|
||||
case 0x9F: STA_LongX(); break;
|
||||
|
||||
//SDX - Store X Register
|
||||
case 0x8E: STX_Absolute(); break;
|
||||
case 0x86: STX_DirectPage(); break;
|
||||
case 0x96: STX_DirectPageY(); break;
|
||||
|
||||
// SDY - Store Y Register
|
||||
case 0x8C: STY_Absolute(); break;
|
||||
case 0x84: STY_DirectPage(); break;
|
||||
case 0x94: STY_DirectPageX(); break;
|
||||
|
||||
default:
|
||||
std::cout << "Unknown opcode: 0x" << std::hex << static_cast<int>(opcode) << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
cycles++;
|
||||
}
|
||||
|
||||
void CPU::NOP() {
|
||||
@@ -513,3 +540,248 @@ void CPU::LDY_DirectPageX() {
|
||||
// Extra cycle if D register is not page-aligned
|
||||
if (D & 0xFF) cycles++;
|
||||
}
|
||||
|
||||
//Store operations implementation
|
||||
void CPU::STA_Absolute() {
|
||||
uint32_t address = ReadWord(PC + 1) | (DB << 16);
|
||||
PC += 3;
|
||||
|
||||
if (P & FLAG_M) { // 8-bit mode
|
||||
WriteByte(address, A & 0xFF);
|
||||
cycles += 4;
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, A);
|
||||
cycles += 5;
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STA_AbsoluteX() {
|
||||
uint32_t base = ReadWord(PC + 1) | (DB << 16);
|
||||
uint32_t address = base + X;
|
||||
PC += 3;
|
||||
|
||||
if (P & FLAG_M) { // 8-bit mode
|
||||
WriteByte(address, A & 0xFF);
|
||||
cycles += 5;
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, A);
|
||||
cycles += 6;
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STA_AbsoluteY() {
|
||||
uint32_t base = ReadWord(PC + 1) | (DB << 16);
|
||||
uint32_t address = base + Y;
|
||||
PC += 3;
|
||||
|
||||
if (P & FLAG_M) { // 8-bit mode
|
||||
WriteByte(address, A & 0xFF);
|
||||
cycles += 5;
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, A);
|
||||
cycles += 6;
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STA_DirectPage() {
|
||||
uint8_t offset = ReadByte(PC + 1);
|
||||
uint32_t address = (D + offset) & 0xFFFF;
|
||||
PC += 2;
|
||||
|
||||
if (P & FLAG_M) { // 8-bit mode
|
||||
WriteByte(address, A & 0xFF);
|
||||
cycles += 3;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, A);
|
||||
cycles += 4;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STA_DirectPageX() {
|
||||
uint8_t offset = ReadByte(PC + 1);
|
||||
uint32_t address = (D + offset + X) & 0xFFFF;
|
||||
PC += 2;
|
||||
|
||||
if (P & FLAG_M) { // 8-bit mode
|
||||
WriteByte(address, A & 0xFF);
|
||||
cycles += 4;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, A);
|
||||
cycles += 5;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STA_IndirectDirectPage() {
|
||||
uint8_t offset = ReadByte(PC + 1);
|
||||
uint32_t pointer = (D + offset) & 0xFFFF;
|
||||
uint32_t address = ReadWord(pointer) | (DB << 16);
|
||||
PC += 2;
|
||||
|
||||
if (P & FLAG_M) { // 8-bit mode
|
||||
WriteByte(address, A & 0xFF);
|
||||
cycles += 5;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, A);
|
||||
cycles += 6;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STA_IndirectDirectPageY() {
|
||||
uint8_t offset = ReadByte(PC + 1);
|
||||
uint32_t pointer = (D + offset) & 0xFFFF;
|
||||
uint32_t base = ReadWord(pointer) | (DB << 16);
|
||||
uint32_t address = base + Y;
|
||||
PC += 2;
|
||||
|
||||
if (P & FLAG_M) { // 8-bit mode
|
||||
WriteByte(address, A & 0xFF);
|
||||
cycles += 6;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, A);
|
||||
cycles += 7;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STA_DirectPageIndirectX() {
|
||||
uint8_t offset = ReadByte(PC + 1);
|
||||
uint32_t pointer = (D + offset + X) & 0xFFFF;
|
||||
uint32_t address = ReadWord(pointer) | (DB << 16);
|
||||
PC += 2;
|
||||
|
||||
if (P & FLAG_M) { // 8-bit mode
|
||||
WriteByte(address, A & 0xFF);
|
||||
cycles += 6;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, A);
|
||||
cycles += 7;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STA_Long() {
|
||||
uint32_t address = ReadByte(PC + 1) | (ReadByte(PC + 2) << 8) | (ReadByte(PC + 3) << 16);
|
||||
PC += 4;
|
||||
|
||||
if (P & FLAG_M) { // 8-bit mode
|
||||
WriteByte(address, A & 0xFF);
|
||||
cycles += 5;
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, A);
|
||||
cycles += 6;
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STA_LongX() {
|
||||
uint32_t base = ReadByte(PC + 1) | (ReadByte(PC + 2) << 8) | (ReadByte(PC + 3) << 16);
|
||||
uint32_t address = base + X;
|
||||
PC += 4;
|
||||
|
||||
if (P & FLAG_M) { // 8-bit mode
|
||||
WriteByte(address, A & 0xFF);
|
||||
cycles += 6;
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, A);
|
||||
cycles += 7;
|
||||
}
|
||||
}
|
||||
|
||||
// STX - Store X Register
|
||||
void CPU::STX_Absolute() {
|
||||
uint32_t address = ReadWord(PC + 1) | (DB << 16);
|
||||
PC += 3;
|
||||
|
||||
if (P & FLAG_X) { // 8-bit mode
|
||||
WriteByte(address, X & 0xFF);
|
||||
cycles += 4;
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, X);
|
||||
cycles += 5;
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STX_DirectPage() {
|
||||
uint8_t offset = ReadByte(PC + 1);
|
||||
uint32_t address = (D + offset) & 0xFFFF;
|
||||
PC += 2;
|
||||
|
||||
if (P & FLAG_X) { // 8-bit mode
|
||||
WriteByte(address, X & 0xFF);
|
||||
cycles += 3;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, X);
|
||||
cycles += 4;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STX_DirectPageY() {
|
||||
uint8_t offset = ReadByte(PC + 1);
|
||||
uint32_t address = (D + offset + Y) & 0xFFFF;
|
||||
PC += 2;
|
||||
|
||||
if (P & FLAG_X) { // 8-bit mode
|
||||
WriteByte(address, X & 0xFF);
|
||||
cycles += 4;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, X);
|
||||
cycles += 5;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
}
|
||||
}
|
||||
|
||||
// STY - Store Y Register
|
||||
void CPU::STY_Absolute() {
|
||||
uint32_t address = ReadWord(PC + 1) | (DB << 16);
|
||||
PC += 3;
|
||||
|
||||
if (P & FLAG_X) { // 8-bit mode
|
||||
WriteByte(address, Y & 0xFF);
|
||||
cycles += 4;
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, Y);
|
||||
cycles += 5;
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STY_DirectPage() {
|
||||
uint8_t offset = ReadByte(PC + 1);
|
||||
uint32_t address = (D + offset) & 0xFFFF;
|
||||
PC += 2;
|
||||
|
||||
if (P & FLAG_X) { // 8-bit mode
|
||||
WriteByte(address, Y & 0xFF);
|
||||
cycles += 3;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, Y);
|
||||
cycles += 4;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
}
|
||||
}
|
||||
|
||||
void CPU::STY_DirectPageX() {
|
||||
uint8_t offset = ReadByte(PC + 1);
|
||||
uint32_t address = (D + offset + X) & 0xFFFF;
|
||||
PC += 2;
|
||||
|
||||
if (P & FLAG_X) { // 8-bit mode
|
||||
WriteByte(address, Y & 0xFF);
|
||||
cycles += 4;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
} else { // 16-bit mode
|
||||
WriteWord(address, Y);
|
||||
cycles += 5;
|
||||
if (D & 0xFF) cycles++; // Extra cycle if D register low byte != 0
|
||||
}
|
||||
}
|
||||
28
src/cpu.h
28
src/cpu.h
@@ -53,6 +53,11 @@ public:
|
||||
void UpdateNZ8(uint8_t value);
|
||||
void UpdateNZ16(uint16_t value);
|
||||
|
||||
// Memory write helpers
|
||||
void WriteByte(uint32_t address, uint8_t value) const;
|
||||
void WriteWord(uint32_t address, uint16_t value) const;
|
||||
|
||||
|
||||
// Instruction implementations
|
||||
// TODO: Implement remaining instructions
|
||||
void JMP();
|
||||
@@ -83,6 +88,29 @@ public:
|
||||
void LDY_DirectPage();
|
||||
void LDY_DirectPageX();
|
||||
|
||||
// STA - Store Accumulator operations
|
||||
void STA_Absolute();
|
||||
void STA_AbsoluteX();
|
||||
void STA_AbsoluteY();
|
||||
void STA_DirectPage();
|
||||
void STA_DirectPageX();
|
||||
void STA_IndirectDirectPage();
|
||||
void STA_IndirectDirectPageY();
|
||||
void STA_DirectPageIndirectX();
|
||||
void STA_Long();
|
||||
void STA_LongX();
|
||||
|
||||
// STX - Store X Register operations
|
||||
void STX_Absolute();
|
||||
void STX_DirectPage();
|
||||
void STX_DirectPageY();
|
||||
|
||||
// STY - Store Y Register operations
|
||||
void STY_Absolute();
|
||||
void STY_DirectPage();
|
||||
void STY_DirectPageX();
|
||||
|
||||
|
||||
void STA();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user