mirror of
https://github.com/zoriya/ComSquare.git
synced 2026-05-25 23:48:29 +00:00
Implementing ROL
This commit is contained in:
+7
-5
@@ -425,6 +425,8 @@ namespace ComSquare::CPU
|
||||
int ASL(uint24_t, AddressingMode);
|
||||
// !@brief Logical Shift Right
|
||||
int LSR(uint24_t, AddressingMode);
|
||||
// !@brief Rotate Left
|
||||
int ROL(uint24_t, AddressingMode);
|
||||
|
||||
//! @brief All the instructions of the CPU.
|
||||
//! @info Instructions are indexed by their opcode
|
||||
@@ -467,15 +469,15 @@ namespace ComSquare::CPU
|
||||
{&CPU::AND, 4, "and", AddressingMode::StackRelative, 2}, // 23
|
||||
{&CPU::BIT, 3, "bit", AddressingMode::DirectPage, 2}, // 24
|
||||
{&CPU::AND, 3, "and", AddressingMode::DirectPage, 2}, // 25
|
||||
{&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 26
|
||||
{&CPU::ROL, 5, "rol", AddressingMode::DirectPage, 2}, // 26
|
||||
{&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectLong, 2}, // 27
|
||||
{&CPU::PLP, 4, "plp", AddressingMode::Implied, 1}, // 28
|
||||
{&CPU::AND, 2, "and", AddressingMode::ImmediateForA, 2}, // 29
|
||||
{&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 2A
|
||||
{&CPU::ROL, 2, "rol", AddressingMode::Implied, 1}, // 2A
|
||||
{&CPU::PLD, 5, "pld", AddressingMode::Implied, 1}, // 2B
|
||||
{&CPU::BIT, 4, "bit", AddressingMode::Absolute, 3}, // 2C
|
||||
{&CPU::AND, 4, "and", AddressingMode::Absolute, 3}, // 2D
|
||||
{&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 2E
|
||||
{&CPU::ROL, 6, "rol", AddressingMode::Absolute, 3}, // 2E
|
||||
{&CPU::AND, 5, "and", AddressingMode::AbsoluteLong, 4}, // 2F
|
||||
{&CPU::BMI, 2, "bmi", AddressingMode::Immediate8bits, 2}, // 30
|
||||
{&CPU::AND, 5, "and", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 31
|
||||
@@ -483,7 +485,7 @@ namespace ComSquare::CPU
|
||||
{&CPU::AND, 7, "and", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 33
|
||||
{&CPU::BIT, 4, "bit", AddressingMode::DirectPageIndexedByX, 2}, // 34
|
||||
{&CPU::AND, 4, "and", AddressingMode::DirectPageIndexedByX, 2}, // 35
|
||||
{&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 36
|
||||
{&CPU::ROL, 6, "rol", AddressingMode::DirectPageIndexedByX, 2}, // 36
|
||||
{&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 37
|
||||
{&CPU::SEC, 2, "sec", AddressingMode::Implied, 1}, // 38
|
||||
{&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByY, 3}, // 39
|
||||
@@ -491,7 +493,7 @@ namespace ComSquare::CPU
|
||||
{&CPU::TSC, 2, "tsc", AddressingMode::Implied, 1}, // 3B
|
||||
{&CPU::BIT, 4, "bit", AddressingMode::AbsoluteIndexedByX, 3}, // 3C
|
||||
{&CPU::AND, 4, "and", AddressingMode::AbsoluteIndexedByX, 3}, // 3D
|
||||
{&CPU::BRK, 7, "rol #-#", AddressingMode::Implied, 2}, // 3E
|
||||
{&CPU::ROL, 7, "rol", AddressingMode::AbsoluteIndexedByX, 3}, // 3E
|
||||
{&CPU::AND, 5, "and", AddressingMode::AbsoluteIndexedByXLong, 4}, // 3F
|
||||
{&CPU::RTI, 6, "rti", AddressingMode::Implied, 1}, // 40
|
||||
{&CPU::EOR, 6, "eor", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 41
|
||||
|
||||
@@ -133,4 +133,47 @@ namespace ComSquare::CPU
|
||||
}
|
||||
return cycles;
|
||||
}
|
||||
|
||||
int CPU::ROL(uint24_t valueAddr, AddressingMode mode)
|
||||
{
|
||||
unsigned highByte = this->_registers.p.m ? 0x80u : 0x8000u;
|
||||
bool oldCarry = this->_registers.p.c;
|
||||
|
||||
if (mode == Implied) {
|
||||
this->_registers.p.c = this->_registers.a & highByte;
|
||||
this->_registers.a <<= 1u;
|
||||
this->_registers.a |= oldCarry;
|
||||
this->_registers.p.n = this->_registers.a & highByte;
|
||||
this->_registers.p.z = this->_registers.a == 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t value = this->_bus->read(valueAddr);
|
||||
if (!this->_registers.p.m)
|
||||
value += this->_bus->read(valueAddr + 1) << 8u;
|
||||
|
||||
this->_registers.p.c = value & highByte;
|
||||
value <<= 1u;
|
||||
value |= oldCarry;
|
||||
this->_registers.p.n = value & highByte;
|
||||
this->_registers.p.z = value == 0;
|
||||
|
||||
this->_bus->write(valueAddr, value);
|
||||
if (!this->_registers.p.m)
|
||||
this->_bus->write(valueAddr + 1, value >> 8u);
|
||||
|
||||
int cycles = 2 * !this->_registers.p.m;
|
||||
switch (mode) {
|
||||
case DirectPage:
|
||||
case DirectPageIndexedByX:
|
||||
cycles += this->_registers.dl != 0;
|
||||
break;
|
||||
case AbsoluteIndexedByX:
|
||||
cycles += this->_hasIndexCrossedPageBoundary;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return cycles;
|
||||
}
|
||||
}
|
||||
@@ -190,4 +190,57 @@ Test(LSR, accumulator)
|
||||
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
|
||||
}
|
||||
|
||||
Test(ROL, emulationTest)
|
||||
{
|
||||
Init()
|
||||
snes.wram->_data[0] = 0b10110011;
|
||||
snes.cpu->_registers.p.m = true;
|
||||
snes.cpu->ROL(0x0, ComSquare::CPU::AddressingMode::Absolute);
|
||||
cr_assert_eq(snes.wram->_data[0], 0b01100110, "The data in ram should be 0b01100110 but it was %x", snes.wram->_data[0]);
|
||||
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
|
||||
}
|
||||
|
||||
Test(ROL, emulationTestWithCarry)
|
||||
{
|
||||
Init()
|
||||
snes.wram->_data[0] = 0b10110011;
|
||||
snes.cpu->_registers.p.m = true;
|
||||
snes.cpu->_registers.p.c = true;
|
||||
snes.cpu->ROL(0x0, ComSquare::CPU::AddressingMode::Absolute);
|
||||
cr_assert_eq(snes.wram->_data[0], 0b01100111, "The data in ram should be 0b01100111 but it was %x", snes.wram->_data[0]);
|
||||
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
|
||||
}
|
||||
|
||||
Test(ROL, nativeTest)
|
||||
{
|
||||
Init()
|
||||
snes.wram->_data[0] = 0b10110011;
|
||||
snes.wram->_data[1] = 0b10000011;
|
||||
snes.cpu->_registers.p.m = false;
|
||||
snes.cpu->_registers.p.c = true;
|
||||
snes.cpu->ROL(0x0, ComSquare::CPU::AddressingMode::Absolute);
|
||||
cr_assert_eq(snes.wram->_data[0], 0b01100111, "The data in ram should be 0b01100111 but it was %x", snes.wram->_data[0]);
|
||||
cr_assert_eq(snes.wram->_data[1], 0b00000111, "The data in ram should be 0b00000111 but it was %x", snes.wram->_data[1]);
|
||||
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
|
||||
}
|
||||
|
||||
Test(ROL, accumulator)
|
||||
{
|
||||
Init()
|
||||
snes.cpu->_registers.a = 0b10110011;
|
||||
snes.cpu->_registers.p.m = true;
|
||||
snes.cpu->_registers.p.c = true;
|
||||
snes.cpu->ROL(0x0, ComSquare::CPU::AddressingMode::Implied);
|
||||
cr_assert_eq(snes.cpu->_registers.al, 0b01100111, "The accumulator should be 0b01100111 but it was %x", snes.cpu->_registers.al);
|
||||
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
|
||||
}
|
||||
Reference in New Issue
Block a user