diff --git a/Z80/HarteTest_Z80/HarteTest_Z80.vcxproj b/Z80/HarteTest_Z80/HarteTest_Z80.vcxproj
index 7b7ec5f..d5d4239 100644
--- a/Z80/HarteTest_Z80/HarteTest_Z80.vcxproj
+++ b/Z80/HarteTest_Z80/HarteTest_Z80.vcxproj
@@ -168,9 +168,6 @@
-
- {d8726a1b-bbfe-47ef-9860-26b90140ba66}
-
{a9c24bd9-0cb4-4c84-b09b-46b815f9da47}
diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h
index 72097c2..ad87314 100644
--- a/Z80/inc/Z80.h
+++ b/Z80/inc/Z80.h
@@ -135,16 +135,14 @@ namespace EightBit {
void handleRESET() noexcept final;
void handleINT() noexcept final;
- void pushWord(register16_t destination) noexcept final;
-
+ void memoryUpdate(int ticks) noexcept;
void memoryWrite() noexcept final;
uint8_t memoryRead() noexcept final;
+ void refreshMemory() noexcept;
- void busWrite() noexcept final;
- uint8_t busRead() noexcept final;
+ void jumpRelative(int8_t offset) noexcept final;
- void jr(int8_t offset) noexcept final;
- int jrConditional(int condition) noexcept final;
+ void call(register16_t destination) override;
private:
bool m_interruptPending = false;
@@ -189,17 +187,17 @@ namespace EightBit {
[[nodiscard]] constexpr auto displaced() const noexcept { return m_prefixDD || m_prefixFD; }
- [[nodiscard]] constexpr const register16_t& displacedAddress() noexcept {
+ [[nodiscard]] constexpr void displaceAddress() noexcept {
const auto& index_register = m_prefixDD ? IX() : IY();
const auto address = index_register.word + m_displacement;
MEMPTR().word = address;
- return MEMPTR();
+ BUS().ADDRESS() = MEMPTR();
}
void fetchDisplacement() noexcept;
- [[nodiscard]] uint8_t fetchInstruction() noexcept;
+ [[nodiscard]] uint8_t fetchInstruction() noexcept final;
- uint8_t readBusDataM1() noexcept;
+ uint8_t readDataUnderInterrupt();
typedef std::function addresser_t;
void loadAccumulatorIndirect(addresser_t addresser) noexcept;
@@ -212,8 +210,8 @@ namespace EightBit {
[[nodiscard]] register16_t& RP(int rp) noexcept;
[[nodiscard]] register16_t& RP2(int rp) noexcept;
- [[nodiscard]] uint8_t R(int r) noexcept;
- void R(int r, uint8_t value) noexcept;
+ [[nodiscard]] uint8_t& R(int r, MemoryMapping::AccessLevel access = MemoryMapping::AccessLevel::ReadOnly) noexcept;
+ void R(int r, uint8_t value, int ticks = 1) noexcept;
void R2(int r, uint8_t value) noexcept;
[[nodiscard]] static constexpr auto zeroTest(uint8_t data) noexcept { return data & ZF; }
@@ -341,7 +339,7 @@ namespace EightBit {
return adjustOverflowSub(input, signTest(before), signTest(value), signTest(calculation));
}
- [[nodiscard]] constexpr bool convertCondition(int flag) noexcept {
+ [[nodiscard]] bool convertCondition(int flag) noexcept override {
switch (flag) {
case 0:
return zero() == 0;
@@ -407,10 +405,7 @@ namespace EightBit {
void retn() noexcept;
void reti() noexcept;
- void returnConditionalFlag(int flag) noexcept;
- void jrConditionalFlag(int flag) noexcept;
- void callConditionalFlag(int flag) noexcept;
- void jumpConditionalFlag(int flag) noexcept;
+ void returnConditionalFlag(int flag) noexcept final;
[[nodiscard]] register16_t sbc(register16_t operand, register16_t value) noexcept;
[[nodiscard]] register16_t adc(register16_t operand, register16_t value) noexcept;
@@ -583,9 +578,10 @@ namespace EightBit {
adjustXY(((Q() ^ F()) | A()));
}
- void cpl() noexcept {
+ void cpl() noexcept final {
setBit(HC | NF);
- adjustXY(A() = ~A());
+ IntelProcessor::cpl();
+ adjustXY(A());
}
void xhtl(register16_t& exchange) noexcept;
diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp
index d85393a..c50ddff 100644
--- a/Z80/src/Z80.cpp
+++ b/Z80/src/Z80.cpp
@@ -141,76 +141,57 @@ const EightBit::register16_t& EightBit::Z80::HL() const noexcept {
return m_registers[m_registerSet][HL_IDX];
}
-void EightBit::Z80::pushWord(const register16_t destination) noexcept {
+void EightBit::Z80::memoryUpdate(int ticks) noexcept {
+ assert(ticks > 0 && "Ticks must be greater than zero");
+ WritingMemory.fire();
+ tick(ticks);
+ lowerMREQ();
+ lowerWR();
+ tick();
+ IntelProcessor::memoryWrite();
+ raiseWR();
+ raiseMREQ();
tick();
- IntelProcessor::pushWord(destination);
+ WrittenMemory.fire();
}
void EightBit::Z80::memoryWrite() noexcept {
+ memoryUpdate(1);
+}
- class _Writer final {
- Z80& m_parent;
- public:
- _Writer(Z80& parent) noexcept
- : m_parent(parent) {
- m_parent.WritingMemory.fire();
- m_parent.tick(2);
- m_parent.lowerMREQ();
- }
-
- ~_Writer() noexcept {
- m_parent.raiseMREQ();
- m_parent.WrittenMemory.fire();
- }
- };
-
- _Writer writer(*this);
- IntelProcessor::memoryWrite();
+void EightBit::Z80::refreshMemory() noexcept {
+ assert(lowered(M1()) && "M1 must be lowered to refresh memory");
+ BUS().ADDRESS() = { REFRESH(), IV() };
+ lowerRFSH();
+ tick();
+ lowerMREQ();
+ raiseMREQ();
+ raiseRFSH();
}
uint8_t EightBit::Z80::memoryRead() noexcept {
-
- class _Reader final {
- Z80& m_parent;
- public:
- _Reader(Z80& parent) noexcept
- : m_parent(parent) {
- m_parent.ReadingMemory.fire();
- if (lowered(m_parent.M1()))
- m_parent.tick();
- m_parent.tick(2);
- m_parent.lowerMREQ();
- }
-
- ~_Reader() noexcept {
- m_parent.raiseMREQ();
- m_parent.ReadMemory.fire();
- }
- };
-
- _Reader reader(*this);
- return IntelProcessor::memoryRead();
-}
-
-void EightBit::Z80::busWrite() noexcept {
+ ReadingMemory.fire();
tick();
- _ActivateWR writer(*this);
- IntelProcessor::busWrite();
-}
-
-uint8_t EightBit::Z80::busRead() noexcept {
+ lowerMREQ();
+ lowerRD();
+ tick();
+ IntelProcessor::memoryRead();
+ raiseRD();
+ raiseMREQ();
+ if (lowered(M1()))
+ refreshMemory();
tick();
- _ActivateRD reader(*this);
- return IntelProcessor::busRead();
+ ReadMemory.fire();
+ return BUS().DATA();
}
void EightBit::Z80::handleRESET() noexcept {
IntelProcessor::handleRESET();
disableInterrupts();
+ IM() = 0;
IV() = 0;
REFRESH() = 0;
SP().word = AF().word = Mask16;
- tick(3);
}
void EightBit::Z80::handleNMI() noexcept {
@@ -218,18 +199,32 @@ void EightBit::Z80::handleNMI() noexcept {
raiseHALT();
IFF2() = IFF1();
IFF1() = false;
- readBusDataM1();
+ lowerM1();
+ raiseM1();
restart(0x66);
}
+uint8_t EightBit::Z80::readDataUnderInterrupt() {
+ lowerM1();
+ tick(3);
+ lowerIORQ();
+ tick();
+ const auto data = BUS().DATA();
+ raiseIORQ();
+ assert(cycles() == 4);
+ refreshMemory();
+ assert(cycles() == 5);
+ raiseM1();
+ return data;
+}
+
void EightBit::Z80::handleINT() noexcept {
+
IntelProcessor::handleINT();
- tick(2); // 2 extra clock cycles introduced to allow the bus to settle
- uint8_t data;
- {
- _ActivateIORQ iorq(*this);
- data = readBusDataM1();
- }
+
+ const auto data = readDataUnderInterrupt();
+ tick();
+ assert(cycles() == 6);
switch (IM()) {
case 0: // i8080 equivalent
@@ -237,11 +232,13 @@ void EightBit::Z80::handleINT() noexcept {
break;
case 1:
restart(7 << 3);
+ assert(cycles() == 13);
break;
case 2:
- tick(7); // How long to allow fetching data from the device...
+ tick();
MEMPTR() = Processor::getWordPaged(IV(), data);
call(MEMPTR());
+ assert(cycles() == 13);
break;
default:
UNREACHABLE;
@@ -257,23 +254,12 @@ void EightBit::Z80::enableInterrupts() {
}
void EightBit::Z80::returnConditionalFlag(const int flag) noexcept {
+ const auto condition = convertCondition(flag);
tick();
- if (convertCondition(flag))
+ if (condition)
ret();
}
-void EightBit::Z80::jrConditionalFlag(const int flag) noexcept {
- jrConditional(convertCondition(flag));
-}
-
-void EightBit::Z80::jumpConditionalFlag(const int flag) noexcept {
- jumpConditional(convertCondition(flag));
-}
-
-void EightBit::Z80::callConditionalFlag(const int flag) noexcept {
- callConditional(convertCondition(flag));
-}
-
void EightBit::Z80::retn() noexcept {
ret();
IFF1() = IFF2();
@@ -283,15 +269,15 @@ void EightBit::Z80::reti() noexcept {
retn();
}
-void EightBit::Z80::jr(int8_t offset) noexcept {
- IntelProcessor::jr(offset);
- tick(5);
+
+void EightBit::Z80::call(register16_t destination) {
+ tick();
+ Processor::call(destination);
}
-int EightBit::Z80::jrConditional(const int condition) noexcept {
- if (!IntelProcessor::jrConditional(condition))
- tick(3);
- return condition;
+void EightBit::Z80::jumpRelative(int8_t offset) noexcept {
+ IntelProcessor::jumpRelative(offset);
+ tick(5);
}
EightBit::register16_t EightBit::Z80::sbc(const register16_t operand, const register16_t value) noexcept {
@@ -345,7 +331,6 @@ EightBit::register16_t EightBit::Z80::add(const register16_t operand, const regi
MEMPTR() = operand + 1;
- tick(7);
return intermediate();
}
@@ -353,12 +338,13 @@ void EightBit::Z80::xhtl(register16_t& exchange) noexcept {
MEMPTR().low = IntelProcessor::memoryRead(SP());
++BUS().ADDRESS();
MEMPTR().high = memoryRead();
- tick();
- IntelProcessor::memoryWrite(exchange.high);
+ BUS().DATA() = exchange.high;
exchange.high = MEMPTR().high;
+ memoryUpdate(2);
--BUS().ADDRESS();
- IntelProcessor::memoryWrite(exchange.low);
+ BUS().DATA() = exchange.low;
exchange.low = MEMPTR().low;
+ memoryUpdate(1);
tick(2);
}
@@ -597,7 +583,7 @@ void EightBit::Z80::writePort(const uint8_t port) noexcept {
void EightBit::Z80::writePort() noexcept {
MEMPTR() = BUS().ADDRESS();
- //tick(2);
+ tick(2);
lowerIORQ();
lowerWR();
tick();
@@ -620,11 +606,12 @@ void EightBit::Z80::readPort(const uint8_t port) noexcept {
void EightBit::Z80::readPort() noexcept {
MEMPTR() = BUS().ADDRESS();
- //tick(2);
+ tick(2);
tick();
lowerIORQ();
lowerRD();
BUS().DATA() = m_ports.read(BUS().ADDRESS());
+ tick();
raiseRD();
raiseIORQ();
tick();
@@ -638,11 +625,6 @@ void EightBit::Z80::fetchDisplacement() noexcept {
//
-uint8_t EightBit::Z80::readBusDataM1() noexcept {
- _ActivateM1 m1(*this);
- return BUS().DATA();
-}
-
// ** From the Z80 CPU User Manual
// Figure 5 depicts the timing during an M1 (op code fetch) cycle. The Program Counter is
@@ -671,22 +653,10 @@ uint8_t EightBit::Z80::readBusDataM1() noexcept {
// CPU.The HALT acknowledge signal is active during this time indicating that the processor
// is in the HALT state
uint8_t EightBit::Z80::fetchInstruction() noexcept {
- uint8_t returned;
- {
- _ActivateM1 m1(*this);
- const auto halted = lowered(HALT());
- returned = IntelProcessor::memoryRead(PC());
- if (UNLIKELY(halted))
- returned = 0; // NOP
- else
- PC()++;
- }
- BUS().ADDRESS() = { REFRESH(), IV() };
- {
- _ActivateRFSH rfsh(*this);
- _ActivateMREQ mreq(*this);
- }
- return returned;
+ lowerM1();
+ IntelProcessor::fetchInstruction();
+ raiseM1();
+ return BUS().DATA();
}
void EightBit::Z80::loadAccumulatorIndirect(addresser_t addresser) noexcept {
@@ -745,7 +715,7 @@ EightBit::register16_t& EightBit::Z80::RP2(const int rp) noexcept {
}
}
-uint8_t EightBit::Z80::R(const int r) noexcept {
+uint8_t& EightBit::Z80::R(const int r, MemoryMapping::AccessLevel access) noexcept {
switch (r) {
case 0:
return B();
@@ -760,7 +730,21 @@ uint8_t EightBit::Z80::R(const int r) noexcept {
case 5:
return HL2().low;
case 6:
- return IntelProcessor::memoryRead(UNLIKELY(displaced()) ? displacedAddress() : HL());
+ if (displaced())
+ displaceAddress();
+ else
+ BUS().ADDRESS() = HL();
+ switch (access) {
+ case MemoryMapping::AccessLevel::ReadOnly:
+ memoryRead();
+ break;
+ case MemoryMapping::AccessLevel::WriteOnly:
+ break;
+ default:
+ UNREACHABLE;
+ break;
+ }
+ return BUS().DATA();
case 7:
return A();
default:
@@ -768,35 +752,11 @@ uint8_t EightBit::Z80::R(const int r) noexcept {
}
}
-void EightBit::Z80::R(const int r, const uint8_t value) noexcept {
- switch (r) {
- case 0:
- B() = value;
- break;
- case 1:
- C() = value;
- break;
- case 2:
- D() = value;
- break;
- case 3:
- E() = value;
- break;
- case 4:
- HL2().high = value;
- break;
- case 5:
- HL2().low = value;
- break;
- case 6:
- IntelProcessor::memoryWrite(UNLIKELY(displaced()) ? displacedAddress() : HL(), value);
- break;
- case 7:
- A() = value;
- break;
- default:
- UNREACHABLE;
- }
+void EightBit::Z80::R(const int r, const uint8_t value, const int ticks) noexcept {
+
+ R(r, MemoryMapping::AccessLevel::WriteOnly) = value;
+ if (r == 6)
+ memoryUpdate(ticks);
}
void EightBit::Z80::R2(const int r, const uint8_t value) noexcept {
@@ -879,11 +839,13 @@ void EightBit::Z80::executeCB(const int x, const int y, const int z) noexcept {
const bool memoryZ = z == 6;
const bool indirect = (!displaced() && memoryZ) || displaced();
+ const auto direct = !indirect;
uint8_t operand;
if (displaced()) {
tick(2);
- operand = IntelProcessor::memoryRead(displacedAddress());
+ displaceAddress();
+ operand = memoryRead();
} else {
operand = R(z);
}
@@ -923,8 +885,8 @@ void EightBit::Z80::executeCB(const int x, const int y, const int z) noexcept {
break;
} case 1: // BIT y, r[z]
bit(y, operand);
- adjustXY(indirect ? MEMPTR().high : operand);
- if (memoryZ)
+ adjustXY(direct ? operand : MEMPTR().high);
+ if (indirect)
tick();
break;
case 2: // RES y, r[z]
@@ -937,8 +899,8 @@ void EightBit::Z80::executeCB(const int x, const int y, const int z) noexcept {
UNREACHABLE;
}
if (update) {
- tick();
if (displaced()) {
+ tick();
IntelProcessor::memoryWrite(operand);
if (!memoryZ)
R2(z, operand);
@@ -980,6 +942,7 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p
default:
UNREACHABLE;
}
+ tick(7);
break;
case 3: // Retrieve/store register pair from/to immediate address
BUS().ADDRESS() = fetchWord();
@@ -1147,16 +1110,16 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
break;
case 2: // DJNZ d
tick();
- jrConditional(--B());
+ jumpRelativeConditional(--B());
break;
case 3: // JR d
- jr(fetchByte());
+ jumpRelative(fetchByte());
break;
case 4: // JR cc,d
case 5:
case 6:
case 7:
- jrConditionalFlag(y - 4);
+ jumpRelativeConditionalFlag(y - 4);
break;
default:
UNREACHABLE;
@@ -1169,6 +1132,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
break;
case 1: // ADD HL,rp
HL2() = add(HL2(), RP(p));
+ tick(7);
break;
default:
UNREACHABLE;
@@ -1237,9 +1201,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
tick(5);
}
const auto original = R(y);
- if (memoryY)
- tick();
- R(y, increment(original));
+ R(y, increment(original), 2);
break;
}
case 5: { // 8-bit DEC
@@ -1248,16 +1210,14 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
tick(5);
}
const auto original = R(y);
- if (memoryY)
- tick();
- R(y, decrement(original));
+ R(y, decrement(original), 2);
break;
}
case 6: { // 8-bit load immediate
if (memoryY && displaced())
fetchDisplacement();
const auto value = fetchByte();
- if (displaced())
+ if (memoryY)
tick(2);
R(y, value); // LD r,n
break;
@@ -1297,24 +1257,20 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
}
break;
case 1: // 8-bit loading
- if ((memoryZ && memoryY)) { // Exception (replaces LD (HL), (HL))
- lowerHALT();
- } else {
+ if (!(memoryZ && memoryY)) {
bool normal = true;
if (displaced()) {
- if (memoryZ || memoryY)
+ if (memoryZ || memoryY) {
fetchDisplacement();
+ tick(5);
+ }
if (memoryZ) {
switch (y) {
case 4:
- if (displaced())
- tick(5);
H() = R(z);
normal = false;
break;
case 5:
- if (displaced())
- tick(5);
L() = R(z);
normal = false;
break;
@@ -1323,25 +1279,20 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
if (memoryY) {
switch (z) {
case 4:
- if (displaced())
- tick(5);
R(y, H());
normal = false;
break;
case 5:
- if (displaced())
- tick(5);
R(y, L());
normal = false;
break;
}
}
}
- if (normal) {
- if (displaced())
- tick(5);
+ if (normal)
R(y, R(z));
- }
+ } else {
+ lowerHALT(); // Exception (replaces LD (HL), (HL))
}
break;
case 2: { // Operate on accumulator and register/memory location
@@ -1399,7 +1350,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
exx();
break;
case 2: // JP (HL)
- jump(HL2());
+ Processor::jump(HL2());
break;
case 3: // LD SP,HL
SP() = HL2();
@@ -1459,6 +1410,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
case 5: // PUSH & various ops
switch (q) {
case 0: // PUSH rp2[p]
+ tick();
pushWord(RP2(p));
break;
case 1:
diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h
index b8d4027..8fa04c4 100644
--- a/inc/IntelProcessor.h
+++ b/inc/IntelProcessor.h
@@ -150,26 +150,55 @@ namespace EightBit {
//
+ register16_t& incrementPC() override;
+ uint8_t fetchInstruction() override;
+
+ //
+
[[nodiscard]] register16_t getWord() final;
void setWord(register16_t value) final;
//
virtual void restart(uint8_t address);
- virtual int callConditional(int condition);
- virtual int jumpConditional(int condition);
- virtual int returnConditional(int condition);
- virtual void jr(int8_t offset) noexcept;
- virtual int jrConditional(int condition);
+ virtual void callConditional(bool condition);
+ virtual void jumpConditional(bool condition);
+ virtual void jumpRelativeConditional(bool condition);
+ virtual void returnConditional(bool condition);
+ virtual void jumpIndirect();
+ virtual void jump();
+ void callIndirect();
+ void call();
+ virtual void jumpRelative(int8_t offset) noexcept;
+ void jumpRelative(uint8_t offset) noexcept { jumpRelative((int8_t)offset); }
void ret() override;
virtual void fetchWordMEMPTR();
- void jumpIndirect();
- void callIndirect();
-
void resetWorkingRegisters() noexcept;
+ [[nodiscard]] virtual bool convertCondition(int flag) noexcept = 0;
+
+ virtual void jumpConditionalFlag(int flag) {
+ jumpConditional(convertCondition(flag));
+ }
+
+ virtual void jumpRelativeConditionalFlag(int flag) {
+ jumpRelativeConditional(convertCondition(flag));
+ }
+
+ virtual void returnConditionalFlag(int flag) {
+ returnConditional(convertCondition(flag));
+ }
+
+ virtual void callConditionalFlag(int flag) {
+ callConditional(convertCondition(flag));
+ }
+
+ virtual void cpl() noexcept {
+ A() = ~A();
+ }
+
private:
static std::array m_halfCarryTableAdd;
static std::array m_halfCarryTableSub;
diff --git a/inc/Processor.h b/inc/Processor.h
index f620f41..43a484d 100644
--- a/inc/Processor.h
+++ b/inc/Processor.h
@@ -70,7 +70,13 @@ namespace EightBit {
virtual uint8_t memoryRead();
virtual uint8_t busRead();
+ virtual register16_t& incrementPC();
+ virtual register16_t& decrementPC();
+
+ virtual void immediateAddress();
+
uint8_t fetchByte();
+ virtual uint8_t fetchInstruction();
[[nodiscard]] virtual register16_t getWord() = 0;
virtual void setWord(register16_t value) = 0;
diff --git a/src/IntelProcessor.cpp b/src/IntelProcessor.cpp
index 6368f88..e2328c6 100644
--- a/src/IntelProcessor.cpp
+++ b/src/IntelProcessor.cpp
@@ -9,9 +9,6 @@ EightBit::IntelProcessor::IntelProcessor(Bus& bus)
for (int i = 0; i < 0x100; ++i)
m_decodedOpcodes.at(i) = i;
- LoweredHALT.connect([this](EventArgs) noexcept { --PC(); });
- RaisedHALT.connect([this](EventArgs) noexcept { ++PC(); });
-
RaisedPOWER.connect([this](EventArgs) {
PC() = SP() = Mask16;
resetWorkingRegisters();
@@ -37,7 +34,7 @@ DEFINE_PIN_LEVEL_CHANGERS(HALT, IntelProcessor);
void EightBit::IntelProcessor::handleRESET() {
Processor::handleRESET();
disableInterrupts();
- jump(0);
+ Processor::jump(0);
}
void EightBit::IntelProcessor::handleINT() {
@@ -54,6 +51,18 @@ uint8_t EightBit::IntelProcessor::pop() {
return memoryRead(SP()++);
}
+
+EightBit::register16_t& EightBit::IntelProcessor::incrementPC() {
+ if (raised(HALT()))
+ Processor::incrementPC();
+ return PC();
+}
+
+uint8_t EightBit::IntelProcessor::fetchInstruction() {
+ fetchByte();
+ return lowered(HALT()) ? (uint8_t)0 : BUS().DATA();
+}
+
EightBit::register16_t EightBit::IntelProcessor::getWord() {
const auto returned = LittleEndianProcessor::getWord();
MEMPTR() = BUS().ADDRESS();
@@ -66,41 +75,38 @@ void EightBit::IntelProcessor::setWord(const register16_t value) {
}
void EightBit::IntelProcessor::restart(const uint8_t address) {
- call(MEMPTR() = { address, 0 });
+ MEMPTR() = { address, 0 };
+ call();
}
-int EightBit::IntelProcessor::callConditional(const int condition) {
+void EightBit::IntelProcessor::callConditional(bool condition) {
fetchWordMEMPTR();
if (condition)
- call(MEMPTR());
- return condition;
+ call();
}
-int EightBit::IntelProcessor::jumpConditional(const int condition) {
+void EightBit::IntelProcessor::jumpConditional(bool condition) {
fetchWordMEMPTR();
if (condition)
- jump(MEMPTR());
- return condition;
+ jump();
}
-int EightBit::IntelProcessor::returnConditional(const int condition) {
+void EightBit::IntelProcessor::jumpRelativeConditional(bool condition) {
+ const auto offset = fetchByte();
+ if (condition)
+ jumpRelative(offset);
+}
+
+void EightBit::IntelProcessor::returnConditional(bool condition) {
if (condition)
ret();
- return condition;
}
-void EightBit::IntelProcessor::jr(const int8_t offset) noexcept {
- jump(MEMPTR() = PC() + offset);
+void EightBit::IntelProcessor::jumpRelative(const int8_t offset) noexcept {
+ MEMPTR() = PC() + offset;
+ jump();
}
-int EightBit::IntelProcessor::jrConditional(const int condition) {
- const auto offsetAddress = PC()++;
- if (condition) {
- const auto offset = memoryRead(offsetAddress);
- jr(offset);
- }
- return condition;
-}
void EightBit::IntelProcessor::ret() {
LittleEndianProcessor::ret();
@@ -114,12 +120,20 @@ void EightBit::IntelProcessor::fetchWordMEMPTR() {
void EightBit::IntelProcessor::jumpIndirect() {
fetchWordMEMPTR();
- jump(MEMPTR());
+ jump();
+}
+
+void EightBit::IntelProcessor::jump() {
+ Processor::jump(MEMPTR());
}
void EightBit::IntelProcessor::callIndirect() {
fetchWordMEMPTR();
- call(MEMPTR());
+ call();
+}
+
+void EightBit::IntelProcessor::call() {
+ Processor::call(MEMPTR());
}
bool EightBit::IntelProcessor::operator==(const EightBit::IntelProcessor& rhs) const noexcept {
diff --git a/src/Processor.cpp b/src/Processor.cpp
index d4d3d38..dfaa1b7 100644
--- a/src/Processor.cpp
+++ b/src/Processor.cpp
@@ -80,8 +80,28 @@ void EightBit::Processor::setWordPaged(const uint8_t page, const uint8_t offset,
setWordPaged(value);
}
+EightBit::register16_t& EightBit::Processor::incrementPC() {
+ PC()++;
+ return PC();
+}
+
+EightBit::register16_t& EightBit::Processor::decrementPC() {
+ PC()--;
+ return PC();
+}
+
+void EightBit::Processor::immediateAddress() {
+ BUS().ADDRESS() = PC();
+ incrementPC();
+}
+
uint8_t EightBit::Processor::fetchByte() {
- return memoryRead(PC()++);
+ immediateAddress();
+ return memoryRead();
+}
+
+uint8_t EightBit::Processor::fetchInstruction() {
+ return fetchByte();
}
EightBit::register16_t EightBit::Processor::getWord(const register16_t address) {