mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-01-03 09:29:50 +00:00
Tidy up memory event handling to make it a bit easier to verify read/write events.
Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
13725b7a3c
commit
017b2a6442
@ -40,6 +40,11 @@ namespace EightBit {
|
||||
CF = Bit0, // Carry
|
||||
};
|
||||
|
||||
enum BusDirection {
|
||||
Read,
|
||||
Write
|
||||
};
|
||||
|
||||
MOS6502(Memory& memory);
|
||||
virtual ~MOS6502();
|
||||
|
||||
@ -179,20 +184,20 @@ namespace EightBit {
|
||||
return m_memory.reference();
|
||||
}
|
||||
|
||||
uint8_t& AM_AbsoluteX(bool read = true) {
|
||||
uint8_t& AM_AbsoluteX(BusDirection direction = BusDirection::Read) {
|
||||
m_busRW = true;
|
||||
Address_AbsoluteX();
|
||||
m_memory.ADDRESS() = MEMPTR();
|
||||
if (read && (m_memory.ADDRESS().low == Mask8))
|
||||
if ((direction == BusDirection::Read) && (m_memory.ADDRESS().low == Mask8))
|
||||
++cycles;
|
||||
return m_memory.reference();
|
||||
}
|
||||
|
||||
uint8_t& AM_AbsoluteY(bool read = true) {
|
||||
uint8_t& AM_AbsoluteY(BusDirection direction = BusDirection::Read) {
|
||||
m_busRW = true;
|
||||
Address_AbsoluteY();
|
||||
m_memory.ADDRESS() = MEMPTR();
|
||||
if (read && (m_memory.ADDRESS().low == Mask8))
|
||||
if ((direction == BusDirection::Read) && (m_memory.ADDRESS().low == Mask8))
|
||||
++cycles;
|
||||
return m_memory.reference();
|
||||
}
|
||||
@ -218,11 +223,11 @@ namespace EightBit {
|
||||
return m_memory.reference();
|
||||
}
|
||||
|
||||
uint8_t& AM_IndirectIndexedY(bool read = true) {
|
||||
uint8_t& AM_IndirectIndexedY(BusDirection direction = BusDirection::Read) {
|
||||
m_busRW = true;
|
||||
Address_IndirectIndexedY();
|
||||
m_memory.ADDRESS() = MEMPTR();
|
||||
if (read && (m_memory.ADDRESS().low == Mask8))
|
||||
if ((direction == BusDirection::Read) && (m_memory.ADDRESS().low == Mask8))
|
||||
++cycles;
|
||||
return m_memory.reference();
|
||||
}
|
||||
@ -231,7 +236,7 @@ namespace EightBit {
|
||||
|
||||
#pragma region 6502 addressing mode switching
|
||||
|
||||
uint8_t& AM_00(int bbb, bool read = true) {
|
||||
uint8_t& AM_00(int bbb, BusDirection direction = BusDirection::Read) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
return AM_Immediate();
|
||||
@ -242,7 +247,7 @@ namespace EightBit {
|
||||
case 0b101:
|
||||
return AM_ZeroPageX();
|
||||
case 0b111:
|
||||
return AM_AbsoluteX(read);
|
||||
return AM_AbsoluteX(direction);
|
||||
case 0b010:
|
||||
case 0b100:
|
||||
case 0b110:
|
||||
@ -252,7 +257,7 @@ namespace EightBit {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t& AM_01(int bbb, bool read = true) {
|
||||
uint8_t& AM_01(int bbb, BusDirection direction = BusDirection::Read) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
return AM_IndexedIndirectX();
|
||||
@ -263,19 +268,19 @@ namespace EightBit {
|
||||
case 0b011:
|
||||
return AM_Absolute();
|
||||
case 0b100:
|
||||
return AM_IndirectIndexedY(read);
|
||||
return AM_IndirectIndexedY(direction);
|
||||
case 0b101:
|
||||
return AM_ZeroPageX();
|
||||
case 0b110:
|
||||
return AM_AbsoluteY(read);
|
||||
return AM_AbsoluteY(direction);
|
||||
case 0b111:
|
||||
return AM_AbsoluteX(read);
|
||||
return AM_AbsoluteX(direction);
|
||||
default:
|
||||
__assume(0);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t& AM_10(int bbb, bool read = true) {
|
||||
uint8_t& AM_10(int bbb, BusDirection direction = BusDirection::Read) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
return AM_Immediate();
|
||||
@ -288,7 +293,7 @@ namespace EightBit {
|
||||
case 0b101:
|
||||
return AM_ZeroPageX();
|
||||
case 0b111:
|
||||
return AM_AbsoluteX(read);
|
||||
return AM_AbsoluteX(direction);
|
||||
case 0b100:
|
||||
case 0b110:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
@ -297,7 +302,7 @@ namespace EightBit {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t& AM_10_x(int bbb, bool read = true) {
|
||||
uint8_t& AM_10_x(int bbb, BusDirection direction = BusDirection::Read) {
|
||||
switch (bbb) {
|
||||
case 0b000:
|
||||
return AM_Immediate();
|
||||
@ -310,7 +315,7 @@ namespace EightBit {
|
||||
case 0b101:
|
||||
return AM_ZeroPageY();
|
||||
case 0b111:
|
||||
return AM_AbsoluteY(read);
|
||||
return AM_AbsoluteY(direction);
|
||||
case 0b100:
|
||||
case 0b110:
|
||||
throw std::domain_error("Illegal addressing mode");
|
||||
@ -323,6 +328,61 @@ namespace EightBit {
|
||||
|
||||
#pragma endregion 6502 addressing modes
|
||||
|
||||
void firePendingBusEvents(BusDirection direction) {
|
||||
if (m_busRW) {
|
||||
switch (direction) {
|
||||
case BusDirection::Read:
|
||||
m_memory.fireReadBusEvent();
|
||||
break;
|
||||
case BusDirection::Write:
|
||||
m_memory.fireWriteBusEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ASL(int bbb) {
|
||||
auto& reference = AM_10(bbb, BusDirection::Write);
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
ASL(reference);
|
||||
firePendingBusEvents(BusDirection::Write);
|
||||
}
|
||||
|
||||
void ROL(int bbb) {
|
||||
auto& reference = AM_10(bbb, BusDirection::Write);
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
ROL(reference);
|
||||
firePendingBusEvents(BusDirection::Write);
|
||||
}
|
||||
|
||||
void LSR(int bbb) {
|
||||
auto& reference = AM_10(bbb, BusDirection::Write);
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
LSR(reference);
|
||||
firePendingBusEvents(BusDirection::Write);
|
||||
}
|
||||
|
||||
void ROR(int bbb) {
|
||||
auto& reference = AM_10(bbb, BusDirection::Write);
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
ROR(reference);
|
||||
firePendingBusEvents(BusDirection::Write);
|
||||
}
|
||||
|
||||
void DEC(int bbb) {
|
||||
auto& reference = AM_10(bbb, BusDirection::Write);
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
adjustNZ(--reference);
|
||||
firePendingBusEvents(BusDirection::Write);
|
||||
}
|
||||
|
||||
void INC(int bbb) {
|
||||
auto& reference = AM_10(bbb, BusDirection::Write);
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
adjustNZ(++reference);
|
||||
firePendingBusEvents(BusDirection::Write);
|
||||
}
|
||||
|
||||
void ROR(uint8_t& output);
|
||||
|
||||
void LSR(uint8_t& output);
|
||||
|
@ -135,8 +135,7 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
break;
|
||||
default: // BIT
|
||||
BIT(AM_00(decoded.bbb));
|
||||
assert(m_busRW);
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -194,9 +193,8 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
adjustNZ(A() = Y());
|
||||
break;
|
||||
default: // STY
|
||||
AM_00(decoded.bbb, false);
|
||||
assert(m_busRW);
|
||||
m_memory.write(Y());
|
||||
AM_00(decoded.bbb, BusDirection::Write) = Y();
|
||||
firePendingBusEvents(BusDirection::Write);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -213,8 +211,7 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
break;
|
||||
default: // LDY
|
||||
adjustNZ(Y() = AM_00(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -231,8 +228,7 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
break;
|
||||
default: // CPY
|
||||
CMP(Y(), AM_00(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -249,8 +245,7 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
break;
|
||||
default: // CPX
|
||||
CMP(X(), AM_00(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -260,43 +255,35 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
switch (decoded.aaa) {
|
||||
case 0b000: // ORA
|
||||
adjustNZ(A() |= AM_01(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
case 0b001: // AND
|
||||
adjustNZ(A() &= AM_01(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
case 0b010: // EOR
|
||||
adjustNZ(A() ^= AM_01(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
case 0b011: // ADC
|
||||
ADC(AM_01(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
case 0b100: // STA
|
||||
AM_01(decoded.bbb, false);
|
||||
assert(m_busRW);
|
||||
m_memory.write(A());
|
||||
AM_01(decoded.bbb, BusDirection::Write) = A();
|
||||
firePendingBusEvents(BusDirection::Write);
|
||||
break;
|
||||
case 0b101: // LDA
|
||||
adjustNZ(A() = AM_01(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
case 0b110: // CMP
|
||||
CMP(A(), AM_01(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
case 0b111: // SBC
|
||||
SBC(AM_01(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
default:
|
||||
__assume(0);
|
||||
@ -305,24 +292,16 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
case 0b10:
|
||||
switch (decoded.aaa) {
|
||||
case 0b000: // ASL
|
||||
ASL(AM_10(decoded.bbb, false));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
ASL(decoded.bbb);
|
||||
break;
|
||||
case 0b001: // ROL
|
||||
ROL(AM_10(decoded.bbb, false));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
ROL(decoded.bbb);
|
||||
break;
|
||||
case 0b010: // LSR
|
||||
LSR(AM_10(decoded.bbb, false));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
LSR(decoded.bbb);
|
||||
break;
|
||||
case 0b011: // ROR
|
||||
ROR(AM_10(decoded.bbb, false));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
ROR(decoded.bbb);
|
||||
break;
|
||||
case 0b100:
|
||||
switch (decoded.bbb) {
|
||||
@ -333,9 +312,8 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
S() = X();
|
||||
break;
|
||||
default: // STX
|
||||
AM_10_x(decoded.bbb, false);
|
||||
assert(m_busRW);
|
||||
m_memory.write(X());
|
||||
AM_10_x(decoded.bbb, BusDirection::Write) = X();
|
||||
firePendingBusEvents(BusDirection::Write);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -346,8 +324,7 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
break;
|
||||
default: // LDX
|
||||
adjustNZ(X() = AM_10_x(decoded.bbb));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
firePendingBusEvents(BusDirection::Read);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -357,9 +334,7 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
adjustNZ(--X());
|
||||
break;
|
||||
default: // DEC
|
||||
adjustNZ(--AM_10(decoded.bbb, false));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
DEC(decoded.bbb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -368,9 +343,7 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
||||
case 0b010: // NOP
|
||||
break;
|
||||
default: // INC
|
||||
adjustNZ(++AM_10(decoded.bbb, false));
|
||||
if (m_busRW)
|
||||
m_memory.read();
|
||||
INC(decoded.bbb);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -48,7 +48,6 @@ void Board::initialise() {
|
||||
m_cpu.ExecutedInstruction.connect(std::bind(&Board::Cpu_ExecutedInstruction_StopLoop, this, std::placeholders::_1));
|
||||
break;
|
||||
case Configuration::StopCondition::Halt:
|
||||
|
||||
break;
|
||||
default:
|
||||
throw std::domain_error("Unknown stop condition");
|
||||
|
12
inc/Memory.h
12
inc/Memory.h
@ -65,9 +65,13 @@ namespace EightBit {
|
||||
return address & m_addressMask;
|
||||
}
|
||||
|
||||
void fireReadBusEvent() {
|
||||
ReadByte.fire(AddressEventArgs(ADDRESS().word, DATA()));
|
||||
}
|
||||
|
||||
uint8_t read() {
|
||||
auto content = reference();
|
||||
ReadByte.fire(AddressEventArgs(ADDRESS().word, content));
|
||||
fireReadBusEvent();
|
||||
return content;
|
||||
}
|
||||
|
||||
@ -76,9 +80,13 @@ namespace EightBit {
|
||||
return read();
|
||||
}
|
||||
|
||||
void fireWriteBusEvent() {
|
||||
WrittenByte.fire(AddressEventArgs(ADDRESS().word, DATA()));
|
||||
}
|
||||
|
||||
void write(uint8_t value) {
|
||||
reference() = value;
|
||||
WrittenByte.fire(AddressEventArgs(ADDRESS().word, value));
|
||||
fireWriteBusEvent();
|
||||
}
|
||||
|
||||
void write(uint16_t offset, uint8_t value) {
|
||||
|
Loading…
Reference in New Issue
Block a user