Implement BIT Instructions
This commit is contained in:
155
src/cpu.cpp
155
src/cpu.cpp
@@ -220,6 +220,69 @@ void CPU::UpdateASLFlags16(const uint16_t original_value, const uint16_t result)
|
|||||||
UpdateNZ16(result);
|
UpdateNZ16(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to update flags after BIT operation (non-immediate modes)
|
||||||
|
void CPU::UpdateBITFlags8(uint8_t memory_value, uint8_t acc_value) {
|
||||||
|
// Z flag: set if (A & memory) == 0
|
||||||
|
if (const uint8_t result = acc_value & memory_value; result == 0) {
|
||||||
|
P |= FLAG_Z;
|
||||||
|
} else {
|
||||||
|
P &= ~FLAG_Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// N flag: copy bit 7 of memory
|
||||||
|
if (memory_value & 0x80) {
|
||||||
|
P |= FLAG_N;
|
||||||
|
} else {
|
||||||
|
P &= ~FLAG_N;
|
||||||
|
}
|
||||||
|
|
||||||
|
// V flag: copy bit 6 of memory
|
||||||
|
if (memory_value & 0x40) {
|
||||||
|
P |= FLAG_V;
|
||||||
|
} else {
|
||||||
|
P &= ~FLAG_V;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::UpdateBITFlags16(const uint16_t memory_value, const uint16_t acc_value) {
|
||||||
|
if (const uint16_t result = acc_value & memory_value; result == 0) {
|
||||||
|
P |= FLAG_Z;
|
||||||
|
} else {
|
||||||
|
P &= ~FLAG_Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// N flag: copy bit 15 of memory
|
||||||
|
if (memory_value & 0x8000) {
|
||||||
|
P |= FLAG_N;
|
||||||
|
} else {
|
||||||
|
P &= ~FLAG_N;
|
||||||
|
}
|
||||||
|
|
||||||
|
// V flag: copy bit 14 of memory
|
||||||
|
if (memory_value & 0x4000) {
|
||||||
|
P |= FLAG_V;
|
||||||
|
} else {
|
||||||
|
P &= ~FLAG_V;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function for immediate mode BIT
|
||||||
|
void CPU::UpdateBITImmediateFlags8(const uint8_t memory_value, const uint8_t acc_value) {
|
||||||
|
if (const uint8_t result = acc_value & memory_value; result == 0) {
|
||||||
|
P |= FLAG_Z;
|
||||||
|
} else {
|
||||||
|
P &= ~FLAG_Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::UpdateBITImmediateFlags16(const uint16_t memory_value, const uint16_t acc_value) {
|
||||||
|
if (const uint16_t result = acc_value & memory_value; result == 0) {
|
||||||
|
P |= FLAG_Z;
|
||||||
|
} else {
|
||||||
|
P &= ~FLAG_Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CPU::ExecuteInstruction() {
|
void CPU::ExecuteInstruction() {
|
||||||
// TODO: Actual Opcode decoding
|
// TODO: Actual Opcode decoding
|
||||||
switch (const uint8_t opcode = bus->Read(PC++)) {
|
switch (const uint8_t opcode = bus->Read(PC++)) {
|
||||||
@@ -272,6 +335,13 @@ void CPU::ExecuteInstruction() {
|
|||||||
case 0x30: BMI_Relative(); break; // BMI $nn
|
case 0x30: BMI_Relative(); break; // BMI $nn
|
||||||
case 0x10: BPL_Relative(); break; // BPL $nn
|
case 0x10: BPL_Relative(); break; // BPL $nn
|
||||||
|
|
||||||
|
// BIT - Test Bits Instructions
|
||||||
|
case 0x89: BIT_Immediate(); break; // BIT #$nn or #$nnnn
|
||||||
|
case 0x2C: BIT_Absolute(); break; // BIT $nnnn
|
||||||
|
case 0x3C: BIT_AbsoluteX(); break; // BIT $nnnn,X
|
||||||
|
case 0x24: BIT_DirectPage(); break; // BIT $nn
|
||||||
|
case 0x34: BIT_DirectPageX(); break; // BIT $nn,X
|
||||||
|
|
||||||
// CMP - Compare Accumulator
|
// CMP - Compare Accumulator
|
||||||
case 0xC9: CMP_Immediate(); break; // CMP #$nn or #$nnnn
|
case 0xC9: CMP_Immediate(); break; // CMP #$nn or #$nnnn
|
||||||
case 0xCD: CMP_Absolute(); break; // CMP $nnnn
|
case 0xCD: CMP_Absolute(); break; // CMP $nnnn
|
||||||
@@ -2570,4 +2640,89 @@ void CPU::ASL_DirectPageX() {
|
|||||||
cycles += 8;
|
cycles += 8;
|
||||||
if (D & 0xFF) cycles++;
|
if (D & 0xFF) cycles++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::BIT_Immediate() {
|
||||||
|
if (P & FLAG_M) { // 8-bit mode
|
||||||
|
const uint8_t operand = ReadByte(PC++);
|
||||||
|
UpdateBITImmediateFlags8(operand, A & 0xFF);
|
||||||
|
cycles += 2;
|
||||||
|
} else { // 16-bit mode
|
||||||
|
const uint16_t operand = ReadWord(PC);
|
||||||
|
PC += 2;
|
||||||
|
UpdateBITImmediateFlags16(operand, A);
|
||||||
|
cycles += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::BIT_Absolute() {
|
||||||
|
const uint16_t address = ReadWord(PC);
|
||||||
|
PC += 2;
|
||||||
|
const uint32_t full_address = (DB << 16) | address;
|
||||||
|
|
||||||
|
if (P & FLAG_M) { // 8-bit mode
|
||||||
|
const uint8_t operand = ReadByte(full_address);
|
||||||
|
UpdateBITFlags8(operand, A & 0xFF);
|
||||||
|
cycles += 4;
|
||||||
|
} else { // 16-bit mode
|
||||||
|
const uint16_t operand = ReadWord(full_address);
|
||||||
|
UpdateBITFlags16(operand, A);
|
||||||
|
cycles += 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::BIT_AbsoluteX() {
|
||||||
|
const uint16_t base_address = ReadWord(PC);
|
||||||
|
PC += 2;
|
||||||
|
const uint32_t full_address = (DB << 16) | (base_address + X);
|
||||||
|
|
||||||
|
if (P & FLAG_M) { // 8-bit mode
|
||||||
|
const uint8_t operand = ReadByte(full_address);
|
||||||
|
UpdateBITFlags8(operand, A & 0xFF);
|
||||||
|
cycles += 4;
|
||||||
|
if ((base_address & 0xFF00) != ((base_address + X) & 0xFF00)) {
|
||||||
|
cycles++;
|
||||||
|
}
|
||||||
|
} else { // 16-bit mode
|
||||||
|
const uint16_t operand = ReadWord(full_address);
|
||||||
|
UpdateBITFlags16(operand, A);
|
||||||
|
cycles += 5;
|
||||||
|
if ((base_address & 0xFF00) != ((base_address + X) & 0xFF00)) {
|
||||||
|
cycles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::BIT_DirectPage() {
|
||||||
|
const uint8_t offset = ReadByte(PC++);
|
||||||
|
const uint32_t address = D + offset;
|
||||||
|
|
||||||
|
if (P & FLAG_M) { // 8-bit mode
|
||||||
|
const uint8_t operand = ReadByte(address);
|
||||||
|
UpdateBITFlags8(operand, A & 0xFF);
|
||||||
|
cycles += 3;
|
||||||
|
if (D & 0xFF) cycles++;
|
||||||
|
} else { // 16-bit mode
|
||||||
|
const uint16_t operand = ReadWord(address);
|
||||||
|
UpdateBITFlags16(operand, A);
|
||||||
|
cycles += 4;
|
||||||
|
if (D & 0xFF) cycles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::BIT_DirectPageX() {
|
||||||
|
const uint8_t offset = ReadByte(PC++);
|
||||||
|
const uint32_t address = D + offset + X;
|
||||||
|
|
||||||
|
if (P & FLAG_M) { // 8-bit mode
|
||||||
|
const uint8_t operand = ReadByte(address);
|
||||||
|
UpdateBITFlags8(operand, A & 0xFF);
|
||||||
|
cycles += 4;
|
||||||
|
if (D & 0xFF) cycles++;
|
||||||
|
} else { // 16-bit mode
|
||||||
|
const uint16_t operand = ReadWord(address);
|
||||||
|
UpdateBITFlags16(operand, A);
|
||||||
|
cycles += 5;
|
||||||
|
if (D & 0xFF) cycles++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
12
src/cpu.h
12
src/cpu.h
@@ -79,6 +79,12 @@ public:
|
|||||||
void UpdateASLFlags8(uint8_t original_value, uint8_t result);
|
void UpdateASLFlags8(uint8_t original_value, uint8_t result);
|
||||||
void UpdateASLFlags16(uint16_t original_value, uint16_t result);
|
void UpdateASLFlags16(uint16_t original_value, uint16_t result);
|
||||||
|
|
||||||
|
// Helper methods for BIT
|
||||||
|
void UpdateBITFlags8(uint8_t memory_value, uint8_t acc_value);
|
||||||
|
void UpdateBITFlags16(uint16_t memory_value, uint16_t acc_value);
|
||||||
|
void UpdateBITImmediateFlags8(uint8_t memory_value, uint8_t acc_value);
|
||||||
|
void UpdateBITImmediateFlags16(uint16_t memory_value, uint16_t acc_value);
|
||||||
|
|
||||||
// Instruction implementations
|
// Instruction implementations
|
||||||
// TODO: Implement remaining instructions
|
// TODO: Implement remaining instructions
|
||||||
void CMP_Immediate();
|
void CMP_Immediate();
|
||||||
@@ -232,6 +238,12 @@ public:
|
|||||||
void ASL_AbsoluteX();
|
void ASL_AbsoluteX();
|
||||||
void ASL_DirectPage();
|
void ASL_DirectPage();
|
||||||
void ASL_DirectPageX();
|
void ASL_DirectPageX();
|
||||||
|
|
||||||
|
void BIT_Immediate();
|
||||||
|
void BIT_Absolute();
|
||||||
|
void BIT_AbsoluteX();
|
||||||
|
void BIT_DirectPage();
|
||||||
|
void BIT_DirectPageX();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //CPU_H
|
#endif //CPU_H
|
||||||
|
|||||||
Reference in New Issue
Block a user