Implementing ROR

This commit is contained in:
Anonymus Raccoon
2020-05-13 16:35:13 +02:00
parent deab98dac0
commit 4c4cc6b655
3 changed files with 103 additions and 5 deletions
+7 -5
View File
@@ -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;
}
}
+54
View File
@@ -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.");
}