Implementing ROL

This commit is contained in:
Anonymus Raccoon
2020-05-13 14:58:37 +02:00
parent 475986580d
commit deab98dac0
3 changed files with 103 additions and 5 deletions
+7 -5
View File
@@ -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;
}
}
+53
View File
@@ -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.");
}