mirror of
https://github.com/zoriya/ComSquare.git
synced 2026-05-29 17:02:21 +00:00
Implementing ROR
This commit is contained in:
+7
-5
@@ -427,6 +427,8 @@ namespace ComSquare::CPU
|
||||
int LSR(uint24_t, AddressingMode);
|
||||
// !@brief Rotate Left
|
||||
int ROL(uint24_t, AddressingMode);
|
||||
// !@brief Rotate Right
|
||||
int ROR(uint24_t, AddressingMode);
|
||||
|
||||
//! @brief All the instructions of the CPU.
|
||||
//! @info Instructions are indexed by their opcode
|
||||
@@ -533,15 +535,15 @@ namespace ComSquare::CPU
|
||||
{&CPU::ADC, 4, "adc", AddressingMode::StackRelative, 2}, // 63
|
||||
{&CPU::STZ, 3, "stz", AddressingMode::DirectPage, 2}, // 64
|
||||
{&CPU::ADC, 3, "adc", AddressingMode::DirectPage, 2}, // 65
|
||||
{&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 66
|
||||
{&CPU::ROR, 5, "ror", AddressingMode::DirectPage, 2}, // 66
|
||||
{&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectLong, 2}, // 67
|
||||
{&CPU::PLA, 4, "pla", AddressingMode::Implied, 1}, // 68
|
||||
{&CPU::ADC, 2, "adc", AddressingMode::ImmediateForA, 2}, // 69
|
||||
{&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 6A
|
||||
{&CPU::ROR, 2, "ror", AddressingMode::Implied, 1}, // 6A
|
||||
{&CPU::RTS, 6, "rts", AddressingMode::Implied, 1}, // 6B
|
||||
{&CPU::JMP, 5, "jmp", AddressingMode::AbsoluteIndirect, 3}, // 6C
|
||||
{&CPU::ADC, 4, "adc", AddressingMode::Absolute, 3}, // 6D
|
||||
{&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 6E
|
||||
{&CPU::ROR, 6, "ror", AddressingMode::Absolute, 3}, // 6E
|
||||
{&CPU::ADC, 5, "adc", AddressingMode::AbsoluteLong, 4}, // 6F
|
||||
{&CPU::BVS, 2, "bvs", AddressingMode::Immediate8bits, 2}, // 70
|
||||
{&CPU::ADC, 5, "adc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 71
|
||||
@@ -549,7 +551,7 @@ namespace ComSquare::CPU
|
||||
{&CPU::ADC, 7, "adc", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 73
|
||||
{&CPU::STZ, 4, "stz", AddressingMode::DirectPageIndexedByX, 2}, // 74
|
||||
{&CPU::ADC, 4, "adc", AddressingMode::DirectPageIndexedByX, 2}, // 75
|
||||
{&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 76
|
||||
{&CPU::ROR, 6, "ror", AddressingMode::DirectPageIndexedByX, 2}, // 76
|
||||
{&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 77
|
||||
{&CPU::SEI, 2, "sei", AddressingMode::Implied, 1}, // 78
|
||||
{&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByY, 2}, // 79
|
||||
@@ -557,7 +559,7 @@ namespace ComSquare::CPU
|
||||
{&CPU::TDC, 2, "tdc", AddressingMode::Implied, 1}, // 7B
|
||||
{&CPU::JMP, 6, "jmp", AddressingMode::AbsoluteIndirectIndexedByX, 3}, // 7C
|
||||
{&CPU::ADC, 4, "adc", AddressingMode::AbsoluteIndexedByX, 3}, // 7D
|
||||
{&CPU::BRK, 7, "ror #-#", AddressingMode::Implied, 2}, // 7E
|
||||
{&CPU::ROR, 7, "ror", AddressingMode::AbsoluteIndexedByX, 3}, // 7E
|
||||
{&CPU::ADC, 5, "adc", AddressingMode::AbsoluteIndexedByXLong, 4}, // 7F
|
||||
{&CPU::BRA, 3, "bra", AddressingMode::Immediate8bits, 2}, // 80
|
||||
{&CPU::STA, 6, "sta", AddressingMode::DirectPageIndexedByX, 2}, // 81
|
||||
|
||||
@@ -176,4 +176,46 @@ namespace ComSquare::CPU
|
||||
}
|
||||
return cycles;
|
||||
}
|
||||
|
||||
int CPU::ROR(uint24_t valueAddr, AddressingMode mode)
|
||||
{
|
||||
this->_registers.p.n = false;
|
||||
bool oldCarry = this->_registers.p.c;
|
||||
unsigned highByteIndex = this->_registers.p.m ? 7 : 15;
|
||||
|
||||
if (mode == Implied) {
|
||||
this->_registers.p.c = this->_registers.a & 1u;
|
||||
this->_registers.a >>= 1u;
|
||||
this->_registers.a |= oldCarry << highByteIndex;
|
||||
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 & 1u;
|
||||
value >>= 1u;
|
||||
value |= oldCarry << highByteIndex;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -243,4 +243,58 @@ Test(ROL, 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(ROR, emulationTestWithtoutCarry)
|
||||
{
|
||||
Init()
|
||||
snes.wram->_data[0] = 0b01100110;
|
||||
snes.cpu->_registers.p.m = true;
|
||||
snes.cpu->_registers.p.c = false;
|
||||
snes.cpu->ROR(0x0, ComSquare::CPU::AddressingMode::Absolute);
|
||||
cr_assert_eq(snes.wram->_data[0], 0b00110011, "The data in ram should be 0b00110011 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, false, "The carry flag should not be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
|
||||
}
|
||||
|
||||
Test(ROR, emulationTest)
|
||||
{
|
||||
Init()
|
||||
snes.wram->_data[0] = 0b01100110;
|
||||
snes.cpu->_registers.p.m = true;
|
||||
snes.cpu->_registers.p.c = true;
|
||||
snes.cpu->ROR(0x0, ComSquare::CPU::AddressingMode::Absolute);
|
||||
cr_assert_eq(snes.wram->_data[0], 0b10110011, "The data in ram should be 0b10110011 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, false, "The carry flag should not be set.");
|
||||
cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
|
||||
}
|
||||
|
||||
Test(ROR, 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->ROR(0x0, ComSquare::CPU::AddressingMode::Absolute);
|
||||
cr_assert_eq(snes.wram->_data[0], 0b11011001, "The data in ram should be 0b11011001 but it was %x", snes.wram->_data[0]);
|
||||
cr_assert_eq(snes.wram->_data[1], 0b11000001, "The data in ram should be 0b11000001 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(ROR, accumulator)
|
||||
{
|
||||
Init()
|
||||
snes.cpu->_registers.a = 0b10110011;
|
||||
snes.cpu->_registers.p.m = true;
|
||||
snes.cpu->_registers.p.c = true;
|
||||
snes.cpu->ROR(0x0, ComSquare::CPU::AddressingMode::Implied);
|
||||
cr_assert_eq(snes.cpu->_registers.al, 0b11011001, "The accumulator should be 0b11011001 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