Implementing instructions cycles

This commit is contained in:
AnonymusRaccoon
2020-02-11 17:39:06 +01:00
parent bc808bd424
commit 8addb29610
5 changed files with 65 additions and 29 deletions
+50 -18
View File
@@ -194,28 +194,30 @@ namespace ComSquare::CPU
return cycles;
}
int CPU::executeInstruction()
unsigned CPU::executeInstruction()
{
uint8_t opcode = this->_bus->read(this->_registers.pc);
switch (opcode) {
case Instructions::BRK: return this->BRK();
this->_extraMemoryCycles = 0;
case Instructions::ADC_DPXi: return this->ADC(this->_getDirectIndirectIndexedXAddr());
case Instructions::ADC_SR: return this->ADC(this->_getStackRelativeAddr());
case Instructions::ADC_DP: return this->ADC(this->_getDirectAddr());
case Instructions::ADC_DPil: return this->ADC(this->_getDirectIndirectLongAddr());
case Instructions::ADC_IM: return this->ADC(this->_getImmediateAddr());
case Instructions::ADC_ABS: return this->ADC(this->_getAbsoluteAddr());
case Instructions::ADC_ABSl: return this->ADC(this->_getAbsoluteLongAddr());
case Instructions::ADC_DPYi: return this->ADC(this->_getDirectIndirectIndexedYAddr());
case Instructions::ADC_DPi: return this->ADC(this->_getDirectIndirectAddr());
case Instructions::ADC_SRYi: return this->ADC(this->_getStackRelativeIndirectIndexedYAddr());
case Instructions::ADC_DPX: return this->ADC(this->_getDirectIndexedByXAddr());
case Instructions::ADC_DPYil:return this->ADC(this->_getDirectIndirectIndexedYLongAddr());
case Instructions::ADC_ABSY: return this->ADC(this->_getAbsoluteIndexedByYAddr());
case Instructions::ADC_ABSX: return this->ADC(this->_getAbsoluteIndexedByXAddr());
case Instructions::ADC_ABSXl:return this->ADC(this->_getAbsoluteIndexedByXLongAddr());
switch (opcode) {
case Instructions::BRK: return 7 + this->BRK();
case Instructions::ADC_IM: return 2 + this->ADC(this->_getImmediateAddr());
case Instructions::ADC_ABS: return 4 + this->ADC(this->_getAbsoluteAddr());
case Instructions::ADC_ABSl: return 5 + this->ADC(this->_getAbsoluteLongAddr());
case Instructions::ADC_DP: return 3 + this->ADC(this->_getDirectAddr());
case Instructions::ADC_DPi: return 5 + this->ADC(this->_getDirectIndirectAddr());
case Instructions::ADC_DPil: return 6 + this->ADC(this->_getDirectIndirectLongAddr());
case Instructions::ADC_ABSX: return 4 + this->ADC(this->_getAbsoluteIndexedByXAddr());
case Instructions::ADC_ABSXl:return 5 + this->ADC(this->_getAbsoluteIndexedByXLongAddr());
case Instructions::ADC_ABSY: return 4 + this->ADC(this->_getAbsoluteIndexedByYAddr());
case Instructions::ADC_DPX: return 4 + this->ADC(this->_getDirectIndexedByXAddr());
case Instructions::ADC_DPXi: return 6 + this->ADC(this->_getDirectIndirectIndexedXAddr());
case Instructions::ADC_DPYi: return 5 + this->ADC(this->_getDirectIndirectIndexedYAddr());
case Instructions::ADC_DPYil:return 6 + this->ADC(this->_getDirectIndirectIndexedYLongAddr());
case Instructions::ADC_SR: return 4 + this->ADC(this->_getStackRelativeAddr());
case Instructions::ADC_SRYi: return 7 + this->ADC(this->_getStackRelativeIndirectIndexedYAddr());
default:
return 0;
@@ -237,6 +239,9 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectAddr()
{
if (this->_registers.dl != 0)
this->_extraMemoryCycles++;
uint8_t addr = this->_bus->read(this->_registers.pac++);
return this->_registers.d + addr;
}
@@ -259,15 +264,23 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndirectIndexedYAddr()
{
if (this->_registers.dl != 0)
this->_extraMemoryCycles++;
uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
uint24_t base = this->_bus->read(dp);
base += this->_bus->read(dp + 1) << 8u;
base += this->_registers.dbr << 16u;
if ((base & 0xF0000000u) == (((base + this->_registers.y) & 0xF0000000u)))
this->_extraMemoryCycles++;
return base + this->_registers.y;
}
uint24_t CPU::_getDirectIndirectIndexedYLongAddr()
{
if (this->_registers.dl != 0)
this->_extraMemoryCycles++;
uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
uint24_t base = this->_bus->read(dp);
base += this->_bus->read(dp + 1) << 8u;
@@ -277,6 +290,9 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndirectIndexedXAddr()
{
if (this->_registers.dl != 0)
this->_extraMemoryCycles++;
uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
dp += this->_registers.x;
uint24_t base = this->_bus->read(dp);
@@ -287,6 +303,9 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndexedByXAddr()
{
if (this->_registers.dl != 0)
this->_extraMemoryCycles++;
uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
dp += this->_registers.x;
return dp;
@@ -294,6 +313,9 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndexedByYAddr()
{
if (this->_registers.dl != 0)
this->_extraMemoryCycles++;
uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
dp += this->_registers.y;
return dp;
@@ -304,6 +326,8 @@ namespace ComSquare::CPU
uint16_t abs = this->_bus->read(this->_registers.pac++);
abs += this->_bus->read(this->_registers.pac++) << 8u;
uint24_t effective = abs + (this->_registers.dbr << 16u);
if ((effective & 0xF0000000u) == (((effective + this->_registers.x) & 0xF0000000u)))
this->_extraMemoryCycles++;
return effective + this->_registers.x;
}
@@ -312,6 +336,8 @@ namespace ComSquare::CPU
uint16_t abs = this->_bus->read(this->_registers.pac++);
abs += this->_bus->read(this->_registers.pac++) << 8u;
uint24_t effective = abs + (this->_registers.dbr << 16u);
if ((effective & 0xF0000000u) == (((effective + this->_registers.y) & 0xF0000000u)))
this->_extraMemoryCycles++;
return effective + this->_registers.y;
}
@@ -360,6 +386,9 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndirectAddr()
{
if (this->_registers.dl != 0)
this->_extraMemoryCycles++;
uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
uint24_t effective = this->_bus->read(dp);
effective += this->_bus->read(dp + 1) << 8u;
@@ -369,6 +398,9 @@ namespace ComSquare::CPU
uint24_t CPU::_getDirectIndirectLongAddr()
{
if (this->_registers.dl != 0)
this->_extraMemoryCycles++;
uint16_t dp = this->_bus->read(this->_registers.pac++) + this->_registers.d;
uint24_t effective = this->_bus->read(dp);
effective += this->_bus->read(++dp) << 8u;
+9 -5
View File
@@ -25,7 +25,7 @@ namespace ComSquare::CPU
};
//! @brief The Data Bank Register;
uint8_t dbr;
//! @brief The Direct register;
//! @brief The Direct Page register;
union {
struct {
uint8_t dh;
@@ -202,7 +202,7 @@ namespace ComSquare::CPU
ADC_DPYil = 0x77,
ADC_ABSY = 0x79,
ADC_ABSX = 0x7D,
ADC_ABSXl = 0x7F,
ADC_ABSXl = 0x7F
};
//! @brief The main CPU
@@ -219,6 +219,9 @@ namespace ComSquare::CPU
//! @brief The cartridge header (stored for interrupt vectors..
Cartridge::Header &_cartridgeHeader;
//! @brief An additional number of cycles that the current running instruction took to run. (Used for address modes that take longer to run than others).
unsigned _extraMemoryCycles = 0;
//! @brief Immediate address mode is specified with a value. (This functions returns the 24bit space address of the value).
uint24_t _getImmediateAddr();
//! @brief The destination is formed by adding the direct page register with the 8-bit address to form an effective address. (This functions returns the 24bit space address of the value).
@@ -263,12 +266,13 @@ namespace ComSquare::CPU
//! @brief Execute a single instruction.
//! @return The number of CPU cycles that the instruction took.
int executeInstruction();
unsigned executeInstruction();
//! @brief Break instruction - Causes a software break. The PC is loaded from a vector table.
int BRK();
unsigned BRK();
//! @brief Add with carry - Adds operand to the Accumulator; adds an additional 1 if carry is set.
int ADC(uint24_t valueAddr);
//! @return The number of extra cycles that this operation took.
unsigned ADC(uint24_t valueAddr);
public:
explicit CPU(std::shared_ptr<Memory::MemoryBus> bus, Cartridge::Header &cartridgeHeader);
//! @brief This function continue to execute the Cartridge code.
+2 -2
View File
@@ -6,7 +6,7 @@
namespace ComSquare::CPU
{
int CPU::BRK()
unsigned CPU::BRK()
{
this->_registers.pc += 2;
@@ -16,6 +16,6 @@ namespace ComSquare::CPU
else
this->_registers.pc = this->_cartridgeHeader.nativeInterrupts.brk;
this->_registers.p.d = false;
return 7 + !this->_isEmulationMode;
return !this->_isEmulationMode;
}
}
@@ -7,7 +7,7 @@
namespace ComSquare::CPU
{
int CPU::ADC(uint24_t valueAddr)
unsigned CPU::ADC(uint24_t valueAddr)
{
unsigned value = this->_bus->read(valueAddr) + this->_registers.p.c;
if (this->_registers.p.m)
@@ -25,6 +25,6 @@ namespace ComSquare::CPU
this->_registers.a %= 0x100;
this->_registers.p.z = this->_registers.a == 0;
this->_registers.p.n = this->_registers.a & negativeMask;
return (0);
return this->_extraMemoryCycles + !this->_registers.p.m;
}
}
+2 -2
View File
@@ -16,7 +16,7 @@ Test(CPU_emulated, BRK)
pair.second.cartridge->header.emulationInterrupts.brk = 0x123u;
pair.second.cpu->_registers.p.d = true;
pair.second.cpu->_registers.pc = 0x156u;
cr_assert_eq(pair.second.cpu->BRK(), 7);
cr_assert_eq(pair.second.cpu->BRK(), 0);
cr_assert_eq(pair.second.cpu->_registers.pc, 0x123u);
cr_assert_eq(pair.second.cpu->_registers.p.i, 1, "pair.second.cpu->_registers.p.i mmust be equal to 1 but it was %d", pair.second.cpu->_registers.p.i);
cr_assert_eq(pair.second.cpu->_registers.p.d, false);
@@ -28,7 +28,7 @@ Test(CPU_native, BRK)
pair.second.cpu->_isEmulationMode = false;
pair.second.cartridge->header.nativeInterrupts.brk = 0x123u;
pair.second.cpu->_registers.pc = 0x156u;
cr_assert_eq(pair.second.cpu->BRK(), 8);
cr_assert_eq(pair.second.cpu->BRK(), 1);
cr_assert_eq(pair.second.cpu->_registers.pc, 0x123u);
cr_assert_eq(pair.second.cpu->_registers.p.i, true);
cr_assert_eq(pair.second.cpu->_registers.p.d, false);