mirror of
https://github.com/zoriya/ComSquare.git
synced 2025-12-20 14:15:11 +00:00
Implementing CPX and CPY
This commit is contained in:
@@ -351,6 +351,14 @@ namespace ComSquare::CPU
|
|||||||
case Instructions::INX: this->INX(); return 2;
|
case Instructions::INX: this->INX(); return 2;
|
||||||
case Instructions::INY: this->INY(); return 2;
|
case Instructions::INY: this->INY(); return 2;
|
||||||
|
|
||||||
|
case Instructions::CPX_IM: this->CPX(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
|
||||||
|
case Instructions::CPX_ABS: this->CPX(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
|
||||||
|
case Instructions::CPX_DP: this->CPX(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
|
||||||
|
|
||||||
|
case Instructions::CPY_IM: this->CPY(this->_getImmediateAddrForX()); return 2 + !this->_registers.p.m;
|
||||||
|
case Instructions::CPY_ABS: this->CPY(this->_getAbsoluteAddr()); return 4 + !this->_registers.p.m;
|
||||||
|
case Instructions::CPY_DP: this->CPY(this->_getDirectAddr()); return 3 + !this->_registers.p.m + this->_registers.dl != 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw InvalidOpcode("CPU", opcode);
|
throw InvalidOpcode("CPU", opcode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -333,7 +333,15 @@ namespace ComSquare::CPU
|
|||||||
TXS = 0x9A,
|
TXS = 0x9A,
|
||||||
|
|
||||||
INX = 0xE8,
|
INX = 0xE8,
|
||||||
INY = 0xC8
|
INY = 0xC8,
|
||||||
|
|
||||||
|
CPX_IM = 0xE0,
|
||||||
|
CPX_ABS = 0xEC,
|
||||||
|
CPX_DP = 0xE4,
|
||||||
|
|
||||||
|
CPY_IM = 0xC0,
|
||||||
|
CPY_ABS = 0xCC,
|
||||||
|
CPY_DP = 0xC4
|
||||||
};
|
};
|
||||||
|
|
||||||
//! @brief The main CPU
|
//! @brief The main CPU
|
||||||
@@ -497,6 +505,10 @@ namespace ComSquare::CPU
|
|||||||
void INX();
|
void INX();
|
||||||
//! @brief Increment the Y register
|
//! @brief Increment the Y register
|
||||||
void INY();
|
void INY();
|
||||||
|
//! @brief Compare the X register with the memory
|
||||||
|
void CPX(uint24_t valueAddr);
|
||||||
|
//! @brief Compare the Y register with the memory
|
||||||
|
void CPY(uint24_t valueAddr);
|
||||||
public:
|
public:
|
||||||
explicit CPU(std::shared_ptr<Memory::MemoryBus> bus, Cartridge::Header &cartridgeHeader);
|
explicit CPU(std::shared_ptr<Memory::MemoryBus> bus, Cartridge::Header &cartridgeHeader);
|
||||||
CPU(const CPU &) = default;
|
CPU(const CPU &) = default;
|
||||||
|
|||||||
@@ -188,4 +188,42 @@ namespace ComSquare::CPU
|
|||||||
this->_registers.p.z = this->_registers.y == 0;
|
this->_registers.p.z = this->_registers.y == 0;
|
||||||
this->_registers.p.n = this->_registers.y & negativeFlag;
|
this->_registers.p.n = this->_registers.y & negativeFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPU::CPX(uint24_t valueAddr)
|
||||||
|
{
|
||||||
|
unsigned value = this->_bus->read(valueAddr++);
|
||||||
|
|
||||||
|
if (this->_registers.p.x_b) {
|
||||||
|
uint8_t x = this->_registers.x;
|
||||||
|
x -= value;
|
||||||
|
this->_registers.p.z = x == 0;
|
||||||
|
this->_registers.p.n = x & 0x80u;
|
||||||
|
} else {
|
||||||
|
value += this->_bus->read(valueAddr) << 8u;
|
||||||
|
uint16_t x = this->_registers.x;
|
||||||
|
x -= value;
|
||||||
|
this->_registers.p.z = x == 0;
|
||||||
|
this->_registers.p.n = x & 0x8000u;
|
||||||
|
}
|
||||||
|
this->_registers.p.c = this->_registers.x >= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::CPY(uint24_t valueAddr)
|
||||||
|
{
|
||||||
|
unsigned value = this->_bus->read(valueAddr++);
|
||||||
|
|
||||||
|
this->_registers.p.c = this->_registers.y >= value;
|
||||||
|
if (this->_registers.p.x_b) {
|
||||||
|
uint8_t y = this->_registers.y;
|
||||||
|
y -= value;
|
||||||
|
this->_registers.p.z = y == 0;
|
||||||
|
this->_registers.p.n = y & 0x80u;
|
||||||
|
} else {
|
||||||
|
value += this->_bus->read(valueAddr) << 8u;
|
||||||
|
uint16_t y = this->_registers.y;
|
||||||
|
y -= value;
|
||||||
|
this->_registers.p.z = y == 0;
|
||||||
|
this->_registers.p.n = y & 0x8000u;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -337,6 +337,14 @@ namespace ComSquare::Debugger
|
|||||||
case Instructions::INX: return "INX";
|
case Instructions::INX: return "INX";
|
||||||
case Instructions::INY: return "INY";
|
case Instructions::INY: return "INY";
|
||||||
|
|
||||||
|
case Instructions::CPX_IM: return "CPX " + this->_getImmediateValueForX(pc);
|
||||||
|
case Instructions::CPX_ABS: return "CPX " + this->_getAbsoluteValue(pc);
|
||||||
|
case Instructions::CPX_DP: return "CPX";
|
||||||
|
|
||||||
|
case Instructions::CPY_IM: return "CPY " + this->_getImmediateValueForX(pc);
|
||||||
|
case Instructions::CPY_ABS: return "CPY " + this->_getAbsoluteValue(pc);
|
||||||
|
case Instructions::CPY_DP: return "CPY";
|
||||||
|
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -539,3 +539,69 @@ Test(INY, 8bits)
|
|||||||
cr_assert_eq(pair.second.cpu->_registers.p.z, true, "The zero flag should be set");
|
cr_assert_eq(pair.second.cpu->_registers.p.z, true, "The zero flag should be set");
|
||||||
cr_assert_eq(pair.second.cpu->_registers.p.n, false, "The negative flag should not be set");
|
cr_assert_eq(pair.second.cpu->_registers.p.n, false, "The negative flag should not be set");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Test(CPX, basic)
|
||||||
|
{
|
||||||
|
auto pair = Init();
|
||||||
|
pair.second.cpu->_registers.p.x_b = true;
|
||||||
|
pair.second.cpu->_registers.p.flags = 0;
|
||||||
|
pair.second.cpu->_registers.x = 0xFF;
|
||||||
|
pair.second.wram->_data[0] = 0xFF;
|
||||||
|
pair.second.cpu->CPX(0x0);
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.z, true, "The zero flag should be set");
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.n, false, "The negative flag should not be set");
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.c, true, "The carry flag should be set");
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(CPX, negative)
|
||||||
|
{
|
||||||
|
auto pair = Init();
|
||||||
|
pair.second.cpu->_registers.p.x_b = true;
|
||||||
|
pair.second.cpu->_registers.p.flags = 0;
|
||||||
|
pair.second.cpu->_registers.x = 0x80;
|
||||||
|
pair.second.wram->_data[0] = 0xFF;
|
||||||
|
pair.second.cpu->CPX(0x0);
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.z, false, "The zero flag should not be set");
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.n, true, "The negative flag should be set");
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.c, false, "The carry flag should not be set");
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(CPX, 16bits)
|
||||||
|
{
|
||||||
|
auto pair = Init();
|
||||||
|
pair.second.cpu->_registers.p.flags = 0;
|
||||||
|
pair.second.cpu->_registers.p.x_b = false;
|
||||||
|
pair.second.cpu->_registers.x = 0x8888;
|
||||||
|
pair.second.wram->_data[0] = 0x88;
|
||||||
|
pair.second.wram->_data[1] = 0x98;
|
||||||
|
pair.second.cpu->CPX(0x0);
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.z, false, "The zero flag should not be set");
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.n, true, "The negative flag should be set");
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.c, false, "The carry flag should not be set");
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(CPY, basic)
|
||||||
|
{
|
||||||
|
auto pair = Init();
|
||||||
|
pair.second.cpu->_registers.p.x_b = true;
|
||||||
|
pair.second.cpu->_registers.p.flags = 0;
|
||||||
|
pair.second.cpu->_registers.y = 0xFF;
|
||||||
|
pair.second.wram->_data[0] = 0xFF;
|
||||||
|
pair.second.cpu->CPY(0x0);
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.z, true, "The zero flag should be set");
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.n, false, "The negative flag should not be set");
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.c, true, "The carry flag should be set");
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(CPY, negative)
|
||||||
|
{
|
||||||
|
auto pair = Init();
|
||||||
|
pair.second.cpu->_registers.p.x_b = true;
|
||||||
|
pair.second.cpu->_registers.p.flags = 0;
|
||||||
|
pair.second.cpu->_registers.y = 0x80;
|
||||||
|
pair.second.wram->_data[0] = 0xFF;
|
||||||
|
pair.second.cpu->CPY(0x0);
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.z, false, "The zero flag should not be set");
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.n, true, "The negative flag should be set");
|
||||||
|
cr_assert_eq(pair.second.cpu->_registers.p.c, false, "The carry flag should not be set");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user