Lots of miscellaneous cycle accurate updates

This commit is contained in:
Adrian Conlon committed 2026-03-21 16:18:39 +00:00
1 parent 81c1703ea9
commit d533593a14
25 files changed
+603 -615

No files matched your search

+1 -1
View File
@@ -20,4 +20,4 @@ void TestRunner::lowerPOWER() noexcept {
EightBit::Bus::lowerPOWER(); EightBit::Bus::lowerPOWER();
} }
void TestRunner::initialise() {} void TestRunner::initialise() noexcept {}
+1 -1
View File
@@ -19,7 +19,7 @@ public:
void raisePOWER() noexcept final; void raisePOWER() noexcept final;
void lowerPOWER() noexcept final; void lowerPOWER() noexcept final;
void initialise() final; void initialise() noexcept final;
[[nodiscard]] constexpr auto& RAM() noexcept { return m_ram; } [[nodiscard]] constexpr auto& RAM() noexcept { return m_ram; }
[[nodiscard]] constexpr auto& ports() noexcept { return m_ports; } [[nodiscard]] constexpr auto& ports() noexcept { return m_ports; }
+1 -1
View File
@@ -10,7 +10,7 @@ namespace EightBit {
class Disassembler final { class Disassembler final {
public: public:
Disassembler(Bus& bus) noexcept; Disassembler(Bus& bus);
static std::string state(Z80& cpu); static std::string state(Z80& cpu);
std::string disassemble(Z80& cpu); std::string disassemble(Z80& cpu);
+3 -3
View File
@@ -27,21 +27,21 @@ namespace EightBit {
[[nodiscard]] constexpr const auto& instructions() const { return m_instructions; } [[nodiscard]] constexpr const auto& instructions() const { return m_instructions; }
[[nodiscard]] constexpr const auto& addresses() const { return m_addresses; } [[nodiscard]] constexpr const auto& addresses() const { return m_addresses; }
[[nodiscard]] constexpr auto instructions_available() const noexcept { [[nodiscard]] constexpr auto instructions_available() const {
const auto found = std::find_if( const auto found = std::find_if(
instructions().begin(), instructions().end(), instructions().begin(), instructions().end(),
[](const auto& value) { return value != 0; }); [](const auto& value) { return value != 0; });
return found != instructions().end(); return found != instructions().end();
} }
[[nodiscard]] constexpr auto addresses_available() const noexcept { [[nodiscard]] constexpr auto addresses_available() const {
const auto found = std::find_if( const auto found = std::find_if(
addresses().begin(), addresses().end(), addresses().begin(), addresses().end(),
[](const auto& value) { return value != 0; }); [](const auto& value) { return value != 0; });
return found != addresses().end(); return found != addresses().end();
} }
[[nodiscard]] constexpr auto available() const noexcept { [[nodiscard]] constexpr auto available() const {
return instructions_available() || addresses_available(); return instructions_available() || addresses_available();
} }
+44 -277
View File
@@ -29,14 +29,6 @@ namespace EightBit {
DECLARE_PIN_OUTPUT(RD) DECLARE_PIN_OUTPUT(RD)
DECLARE_PIN_OUTPUT(WR) DECLARE_PIN_OUTPUT(WR)
private:
DEFINE_PIN_ACTIVATOR_LOW(RFSH)
DEFINE_PIN_ACTIVATOR_LOW(M1)
DEFINE_PIN_ACTIVATOR_LOW(MREQ)
DEFINE_PIN_ACTIVATOR_LOW(IORQ)
DEFINE_PIN_ACTIVATOR_LOW(RD)
DEFINE_PIN_ACTIVATOR_LOW(WR)
public: public:
struct refresh_t { struct refresh_t {
@@ -70,30 +62,24 @@ namespace EightBit {
CF = Bit0, CF = Bit0,
}; };
Z80(Bus& bus, InputOutput& ports); Z80(Bus& bus, InputOutput& ports) noexcept;
Z80(const Z80& rhs); Z80(const Z80& rhs) noexcept;
bool operator==(const Z80& rhs) const; bool operator==(const Z80& rhs) const noexcept;
void execute() noexcept final; void execute() noexcept final;
void poweredStep() noexcept final; void poweredStep() noexcept final;
[[nodiscard]] const register16_t& AF() const noexcept final; [[nodiscard]] register16_t& AF() noexcept final;
[[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); } [[nodiscard]] register16_t& BC() noexcept final;
[[nodiscard]] const register16_t& BC() const noexcept final; [[nodiscard]] register16_t& DE() noexcept final;
[[nodiscard]] auto& BC() noexcept { return IntelProcessor::BC(); } [[nodiscard]] register16_t& HL() noexcept final;
[[nodiscard]] const register16_t& DE() const noexcept final;
[[nodiscard]] auto& DE() noexcept { return IntelProcessor::DE(); }
[[nodiscard]] const register16_t& HL() const noexcept final;
[[nodiscard]] auto& HL() noexcept { return IntelProcessor::HL(); }
[[nodiscard]] constexpr const auto& IX() const noexcept { return m_ix; } [[nodiscard]] constexpr auto& IX() noexcept { return m_ix; }
NON_CONST_REGISTOR_ACCESSOR(IX);
[[nodiscard]] constexpr auto& IXH() noexcept { return IX().high; } [[nodiscard]] constexpr auto& IXH() noexcept { return IX().high; }
[[nodiscard]] constexpr auto& IXL() noexcept { return IX().low; } [[nodiscard]] constexpr auto& IXL() noexcept { return IX().low; }
[[nodiscard]] constexpr const auto& IY() const noexcept { return m_iy; } [[nodiscard]] constexpr auto& IY() noexcept { return m_iy; }
NON_CONST_REGISTOR_ACCESSOR(IY);
[[nodiscard]] constexpr auto& IYH() noexcept { return IY().high; } [[nodiscard]] constexpr auto& IYH() noexcept { return IY().high; }
[[nodiscard]] constexpr auto& IYL() noexcept { return IY().low; } [[nodiscard]] constexpr auto& IYL() noexcept { return IY().low; }
@@ -109,16 +95,11 @@ namespace EightBit {
// programmer. During refresh, the contents of the I Register are placed on the upper eight // programmer. During refresh, the contents of the I Register are placed on the upper eight
// bits of the address bus. // bits of the address bus.
[[nodiscard]] constexpr auto& REFRESH() noexcept { return m_refresh; } [[nodiscard]] constexpr auto& REFRESH() noexcept { return m_refresh; }
[[nodiscard]] constexpr auto REFRESH() const noexcept { return m_refresh; }
[[nodiscard]] constexpr auto& IV() noexcept { return iv; } [[nodiscard]] constexpr auto& IV() noexcept { return iv; }
[[nodiscard]] constexpr auto IV() const noexcept { return iv; }
[[nodiscard]] constexpr auto& IM() noexcept { return m_interruptMode; } [[nodiscard]] constexpr auto& IM() noexcept { return m_interruptMode; }
[[nodiscard]] constexpr auto IM() const noexcept { return m_interruptMode; }
[[nodiscard]] constexpr auto& IFF1() noexcept { return m_iff1; } [[nodiscard]] constexpr auto& IFF1() noexcept { return m_iff1; }
[[nodiscard]] constexpr auto IFF1() const noexcept { return m_iff1; }
[[nodiscard]] constexpr auto& IFF2() noexcept { return m_iff2; } [[nodiscard]] constexpr auto& IFF2() noexcept { return m_iff2; }
[[nodiscard]] constexpr auto IFF2() const noexcept { return m_iff2; }
[[nodiscard]] constexpr auto& Q() noexcept { return m_q; } [[nodiscard]] constexpr auto& Q() noexcept { return m_q; }
@@ -131,18 +112,20 @@ namespace EightBit {
[[nodiscard]] constexpr auto requestingRead() const noexcept { return lowered(RD()); } [[nodiscard]] constexpr auto requestingRead() const noexcept { return lowered(RD()); }
[[nodiscard]] constexpr auto requestingWrite() const noexcept { return lowered(WR()); } [[nodiscard]] constexpr auto requestingWrite() const noexcept { return lowered(WR()); }
[[nodiscard]] constexpr auto fetchingOpCode() const noexcept { return lowered(M1()); }
protected: protected:
void handleRESET() noexcept final; void handleRESET() noexcept final;
void handleINT() noexcept final; void handleINT() noexcept final;
void memoryUpdate(int ticks) noexcept; void memoryUpdate(int ticks = 1) noexcept;
void memoryWrite() noexcept final; void memoryWrite() noexcept final;
uint8_t memoryRead() noexcept final; uint8_t memoryRead() noexcept final;
void refreshMemory() noexcept; void refreshMemory() noexcept;
void jumpRelative(int8_t offset) noexcept final; void jumpRelative(int8_t offset) noexcept final;
void call(register16_t destination) final; void call(register16_t destination) noexcept final;
private: private:
bool m_interruptPending = false; bool m_interruptPending = false;
@@ -181,23 +164,17 @@ namespace EightBit {
void handleNMI() noexcept; void handleNMI() noexcept;
constexpr void resetPrefixes() noexcept {
m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
}
[[nodiscard]] constexpr auto displaced() const noexcept { return m_prefixDD || m_prefixFD; } [[nodiscard]] constexpr auto displaced() const noexcept { return m_prefixDD || m_prefixFD; }
[[nodiscard]] constexpr void displaceAddress() noexcept { [[nodiscard]] constexpr void displaceAddress() noexcept {
const auto& index_register = m_prefixDD ? IX() : IY(); const auto& index_register = m_prefixDD ? IX() : IY();
const auto address = index_register.word + m_displacement; BUS().ADDRESS() = MEMPTR() = index_register.word + m_displacement;
MEMPTR().word = address;
BUS().ADDRESS() = MEMPTR();
} }
void fetchDisplacement() noexcept; void fetchDisplacement() noexcept;
[[nodiscard]] uint8_t fetchInstruction() noexcept final; [[nodiscard]] uint8_t fetchInstruction() noexcept final;
uint8_t readDataUnderInterrupt(); uint8_t readDataUnderInterrupt() noexcept;
typedef std::function<register16_t(void)> addresser_t; typedef std::function<register16_t(void)> addresser_t;
void loadAccumulatorIndirect(addresser_t addresser) noexcept; void loadAccumulatorIndirect(addresser_t addresser) noexcept;
@@ -339,70 +316,17 @@ namespace EightBit {
return adjustOverflowSub(input, signTest(before), signTest(value), signTest(calculation)); return adjustOverflowSub(input, signTest(before), signTest(value), signTest(calculation));
} }
[[nodiscard]] bool convertCondition(int flag) noexcept override { [[nodiscard]] bool convertCondition(int flag) noexcept final;
switch (flag) {
case 0:
return zero() == 0;
case 1:
return zero() != 0;
case 2:
return carry() == 0;
case 3:
return carry() != 0;
case 4:
return parity() == 0;
case 5:
return parity() != 0;
case 6:
return sign() == 0;
case 7:
return sign() != 0;
default:
UNREACHABLE;
}
}
auto subtract(uint8_t value, int carry = 0) noexcept {
const auto operand = A();
const register16_t subtraction = operand - value - carry;
const auto result = subtraction.low;
adjustHalfCarrySub(operand, value, result);
adjustOverflowSub(operand, value, result);
setBit(NF);
setBit(CF, carryTest(subtraction.high));
adjustSZ(result);
return result;
}
void executeCB(int x, int y, int z) noexcept; void executeCB(int x, int y, int z) noexcept;
void executeED(int x, int y, int z, int p, int q) noexcept; void executeED(int x, int y, int z, int p, int q) noexcept;
void executeOther(int x, int y, int z, int p, int q) noexcept; void executeOther(int x, int y, int z, int p, int q) noexcept;
[[nodiscard]] auto increment(uint8_t operand) noexcept { [[nodiscard]] uint8_t increment(uint8_t operand) noexcept;
clearBit(NF); [[nodiscard]] uint8_t decrement(uint8_t operand) noexcept;
const uint8_t result = operand + 1;
adjustSZXY(result);
setBit(VF, result == Bit7);
clearBit(HC, lowNibble(result));
return result;
}
[[nodiscard]] auto decrement(uint8_t operand) noexcept { void disableInterrupts() noexcept final;
setBit(NF); void enableInterrupts() noexcept final;
clearBit(HC, lowNibble(operand));
const uint8_t result = operand - 1;
adjustSZXY(result);
setBit(VF, result == Mask7);
return result;
}
void disableInterrupts() override;
void enableInterrupts() override;
void retn() noexcept; void retn() noexcept;
void reti() noexcept; void reti() noexcept;
@@ -413,178 +337,35 @@ namespace EightBit {
void adc(register16_t value) noexcept; void adc(register16_t value) noexcept;
void add(register16_t value, int carry = 0) noexcept; void add(register16_t value, int carry = 0) noexcept;
void add(uint8_t value, int carry = 0) noexcept { void add(uint8_t value, int carry = 0) noexcept;
void adc(uint8_t value) noexcept;
void sub(uint8_t value, int carry = 0) noexcept;
uint8_t subtract(uint8_t value, int carry = 0) noexcept;
void sbc(uint8_t value) noexcept;
const auto operand = A(); void andr(uint8_t value) noexcept;
void xorr(uint8_t value) noexcept;
void orr(uint8_t value) noexcept;
void compare(uint8_t value) noexcept;
intermediate() = operand + value + carry; [[nodiscard]] uint8_t rlc(uint8_t operand) noexcept;
const auto result = intermediate().low; [[nodiscard]] uint8_t rrc(uint8_t operand) noexcept;
[[nodiscard]] uint8_t rl(uint8_t operand) noexcept;
[[nodiscard]] uint8_t rr(uint8_t operand) noexcept;
[[nodiscard]] uint8_t sla(uint8_t operand) noexcept;
[[nodiscard]] uint8_t sra(uint8_t operand) noexcept;
[[nodiscard]] uint8_t sll(uint8_t operand) noexcept;
[[nodiscard]] uint8_t srl(uint8_t operand) noexcept;
adjustHalfCarryAdd(operand, value, result); void bit(int n, uint8_t operand) noexcept;
adjustOverflowAdd(operand, value, result);
clearBit(NF);
setBit(CF, carryTest(intermediate().high));
adjustSZXY(result);
A() = result;
}
void adc(uint8_t value) noexcept {
add(value, carry());
}
void sub(uint8_t value, int carry = 0) noexcept {
adjustSZXY(A() = subtract(value, carry));
}
void sbc(uint8_t value) noexcept {
sub(value, carry());
}
[[nodiscard]] void andr(uint8_t value) noexcept {
setBit(HC);
clearBit(CF | NF);
adjustSZPXY(A() &= value);
}
[[nodiscard]] void xorr(uint8_t value) noexcept {
clearBit(HC | CF | NF);
adjustSZPXY(A() ^= value);
}
[[nodiscard]] void orr(uint8_t value) noexcept {
clearBit(HC | CF | NF);
adjustSZPXY(A() |= value);
}
void compare(uint8_t value) noexcept {
subtract(value);
adjustXY(value);
}
[[nodiscard]] auto rlc(uint8_t operand) noexcept {
clearBit(NF | HC);
const auto carry = operand & Bit7;
setBit(CF, carry);
const uint8_t result = (operand << 1) | (carry >> 7);
adjustXY(result);
return result;
}
[[nodiscard]] auto rrc(uint8_t operand) noexcept {
clearBit(NF | HC);
const auto carry = operand & Bit0;
setBit(CF, carry);
const uint8_t result = (operand >> 1) | (carry << 7);
adjustXY(result);
return result;
}
[[nodiscard]] auto rl(uint8_t operand) noexcept {
clearBit(NF | HC);
const auto carrying = carry();
setBit(CF, operand & Bit7);
const uint8_t result = (operand << 1) | carrying;
adjustXY(result);
return result;
}
[[nodiscard]] auto rr(uint8_t operand) noexcept {
clearBit(NF | HC);
const auto carrying = carry();
setBit(CF, operand & Bit0);
const uint8_t result = (operand >> 1) | (carrying << 7);
adjustXY(result);
return result;
}
[[nodiscard]] auto sla(uint8_t operand) noexcept {
clearBit(NF | HC);
setBit(CF, operand & Bit7);
const uint8_t result = operand << 1;
adjustXY(result);
return result;
}
[[nodiscard]] auto sra(uint8_t operand) noexcept {
clearBit(NF | HC);
setBit(CF, operand & Bit0);
const uint8_t result = (operand >> 1) | (operand & Bit7);
adjustXY(result);
return result;
}
[[nodiscard]] auto sll(uint8_t operand) noexcept {
clearBit(NF | HC);
setBit(CF, operand & Bit7);
const uint8_t result = (operand << 1) | Bit0;
adjustXY(result);
return result;
}
[[nodiscard]] auto srl(uint8_t operand) noexcept {
clearBit(NF | HC);
setBit(CF, operand & Bit0);
const uint8_t result = (operand >> 1) & ~Bit7;
adjustXY(result);
setBit(ZF, result);
return result;
}
void bit(int n, uint8_t operand) noexcept {
setBit(HC);
clearBit(NF);
const auto discarded = operand & Chip::bit(n);
adjustSZ(discarded);
clearBit(PF, discarded);
}
[[nodiscard]] static constexpr auto res(int n, uint8_t operand) noexcept { return Chip::clearBit(operand, Chip::bit(n)); } [[nodiscard]] static constexpr auto res(int n, uint8_t operand) noexcept { return Chip::clearBit(operand, Chip::bit(n)); }
[[nodiscard]] static constexpr auto set(int n, uint8_t operand) noexcept { return Chip::setBit(operand, Chip::bit(n)); } [[nodiscard]] static constexpr auto set(int n, uint8_t operand) noexcept { return Chip::setBit(operand, Chip::bit(n)); }
[[nodiscard]] void daa() noexcept { void daa() noexcept;
void scf() noexcept;
auto updated = A(); void ccf() noexcept;
void cpl() noexcept final;
const auto lowAdjust = halfCarry() || (lowNibble(A()) > 9);
const auto highAdjust = carry() || (A() > 0x99);
if (subtracting()) {
if (lowAdjust)
updated -= 6;
if (highAdjust)
updated -= 0x60;
} else {
if (lowAdjust)
updated += 6;
if (highAdjust)
updated += 0x60;
}
adjustStatusFlags((F() & (CF | NF) | (A() > 0x99 ? CF : 0) | halfCarryTest(A() ^ updated)));
adjustSZPXY(A() = updated);
}
void scf() noexcept {
setBit(CF);
clearBit(HC | NF);
adjustXY((Q() ^ F()) | A());
}
void ccf() noexcept {
clearBit(NF);
const auto carrying = carry();
setBit(HC, carrying);
clearBit(CF, carrying);
adjustXY(((Q() ^ F()) | A()));
}
void cpl() noexcept final {
setBit(HC | NF);
IntelProcessor::cpl();
adjustXY(A());
}
void xhtl(register16_t& exchange) noexcept; void xhtl(register16_t& exchange) noexcept;
@@ -605,7 +386,7 @@ namespace EightBit {
void lddr() noexcept; void lddr() noexcept;
void repeatBlockInstruction() noexcept; void repeatBlockInstruction() noexcept;
void adjustBlockRepeatFlagsIO(); void adjustBlockRepeatFlagsIO() noexcept;
void adjustBlockInputOutputFlags(int basis) noexcept; void adjustBlockInputOutputFlags(int basis) noexcept;
void adjustBlockInFlagsIncrement() noexcept; void adjustBlockInFlagsIncrement() noexcept;
void adjustBlockInFlagsDecrement() noexcept; void adjustBlockInFlagsDecrement() noexcept;
@@ -627,21 +408,7 @@ namespace EightBit {
void outd() noexcept; void outd() noexcept;
void otdr() noexcept; void otdr() noexcept;
void neg() noexcept { void neg() noexcept;
setBit(PF, A() == Bit7);
setBit(CF, A());
setBit(NF);
auto original = A();
A() = (~A() + 1); // two's complement
adjustHalfCarrySub(0U, original, A());
adjustOverflowSub(0U, original, A());
adjustSZXY(A());
}
void rrd(register16_t address, uint8_t& update) noexcept; void rrd(register16_t address, uint8_t& update) noexcept;
void rld(register16_t address, uint8_t& update) noexcept; void rld(register16_t address, uint8_t& update) noexcept;
+1 -1
View File
@@ -8,7 +8,7 @@
#include "../inc/Z80.h" #include "../inc/Z80.h"
EightBit::Disassembler::Disassembler(Bus& bus) noexcept EightBit::Disassembler::Disassembler(Bus& bus)
: m_bus(bus) { : m_bus(bus) {
// Disable exceptions where too many format arguments are available // Disable exceptions where too many format arguments are available
m_formatter.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit); m_formatter.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
+331 -89
View File
@@ -3,7 +3,7 @@
// based on http://www.z80.info/decoding.htm // based on http://www.z80.info/decoding.htm
EightBit::Z80::Z80(Bus& bus, InputOutput& ports) EightBit::Z80::Z80(Bus& bus, InputOutput& ports) noexcept
: IntelProcessor(bus), : IntelProcessor(bus),
m_ports(ports) { m_ports(ports) {
RaisedPOWER.connect([this](EventArgs) { RaisedPOWER.connect([this](EventArgs) {
@@ -45,24 +45,19 @@ EightBit::Z80::Z80(Bus& bus, InputOutput& ports)
}); });
} }
EightBit::Z80::Z80(const Z80& rhs) EightBit::Z80::Z80(const Z80& rhs) noexcept
: IntelProcessor(rhs), : IntelProcessor(rhs),
m_ports(rhs.m_ports) { m_ports(rhs.m_ports),
m_registers(rhs.m_registers),
m_registers = rhs.m_registers; m_registerSet(rhs.m_registerSet),
m_registerSet = rhs.m_registerSet; m_accumulatorFlags(rhs.m_accumulatorFlags),
m_accumulatorFlagsSet(rhs.m_accumulatorFlagsSet),
m_accumulatorFlags = rhs.m_accumulatorFlags; m_ix(rhs.m_ix),
m_accumulatorFlagsSet = rhs.m_accumulatorFlagsSet; m_iy(rhs.m_iy),
iv(rhs.iv),
m_ix = rhs.m_ix; m_interruptMode(rhs.m_interruptMode),
m_iy = rhs.m_iy; m_iff1(rhs.m_iff1),
m_iff2(rhs.m_iff2) {
iv = rhs.iv;
m_interruptMode = rhs.m_interruptMode;
m_iff1 = rhs.m_iff1;
m_iff2 = rhs.m_iff2;
RFSH() = rhs.RFSH(); RFSH() = rhs.RFSH();
NMI() = rhs.NMI(); NMI() = rhs.NMI();
M1() = rhs.M1(); M1() = rhs.M1();
@@ -72,47 +67,47 @@ EightBit::Z80::Z80(const Z80& rhs)
WR() = rhs.WR(); WR() = rhs.WR();
} }
bool EightBit::Z80::operator==(const EightBit::Z80& rhs) const { bool EightBit::Z80::operator==(const EightBit::Z80& rhs) const noexcept {
const auto base = IntelProcessor::operator==(rhs); const auto base = IntelProcessor::operator==(rhs);
auto& left = const_cast<Z80&>(*this);
auto& right = const_cast<Z80&>(rhs);
const auto pins = const auto pins =
RFSH() == rhs.RFSH() left.RFSH() == right.RFSH()
&& NMI() == rhs.NMI() && left.NMI() == right.NMI()
&& M1() == rhs.M1() && left.M1() == right.M1()
&& MREQ() == rhs.MREQ() && left.MREQ() == right.MREQ()
&& IORQ() == rhs.IORQ() && left.IORQ() == right.IORQ()
&& RD() == rhs.RD() && left.RD() == right.RD()
&& WR() == rhs.WR(); && left.WR() == right.WR();
auto* z80 = const_cast<Z80*>(this); left.exxAF();
auto& z80_rhs = const_cast<Z80&>(rhs); right.exxAF();
const auto af = left.AF() == right.AF();
left.exxAF();
right.exxAF();
z80->exxAF(); left.exx();
z80_rhs.exxAF(); right.exx();
const auto af = AF() == rhs.AF();
z80->exxAF();
z80_rhs.exxAF();
z80->exx();
z80_rhs.exx();
const auto pairs = const auto pairs =
BC() == rhs.BC() left.BC() == right.BC()
&& DE() == rhs.DE() && left.DE() == right.DE()
&& HL() == rhs.HL(); && left.HL() == right.HL();
z80->exx(); left.exx();
z80_rhs.exx(); right.exx();
const auto indices = const auto indices =
IX() == rhs.IX() left.IX() == right.IX()
&& IY() == rhs.IY(); && left.IY() == right.IY();
const auto miscellaneous = const auto miscellaneous =
REFRESH() == rhs.REFRESH() left.REFRESH() == right.REFRESH()
&& IV() == rhs.IV() && left.IV() == right.IV()
&& IM() == rhs.IM() && left.IM() == right.IM()
&& IFF1() == rhs.IFF1() && left.IFF1() == right.IFF1()
&& IFF2() == rhs.IFF2(); && left.IFF2() == right.IFF2();
return base && pins && af && pairs && indices && miscellaneous; return base && pins && af && pairs && indices && miscellaneous;
} }
@@ -125,19 +120,19 @@ DEFINE_PIN_LEVEL_CHANGERS(IORQ, Z80);
DEFINE_PIN_LEVEL_CHANGERS(RD, Z80); DEFINE_PIN_LEVEL_CHANGERS(RD, Z80);
DEFINE_PIN_LEVEL_CHANGERS(WR, Z80); DEFINE_PIN_LEVEL_CHANGERS(WR, Z80);
const EightBit::register16_t& EightBit::Z80::AF() const noexcept { EightBit::register16_t& EightBit::Z80::AF() noexcept {
return m_accumulatorFlags[m_accumulatorFlagsSet]; return m_accumulatorFlags[m_accumulatorFlagsSet];
} }
const EightBit::register16_t& EightBit::Z80::BC() const noexcept { EightBit::register16_t& EightBit::Z80::BC() noexcept {
return m_registers[m_registerSet][BC_IDX]; return m_registers[m_registerSet][BC_IDX];
} }
const EightBit::register16_t& EightBit::Z80::DE() const noexcept { EightBit::register16_t& EightBit::Z80::DE() noexcept {
return m_registers[m_registerSet][DE_IDX]; return m_registers[m_registerSet][DE_IDX];
} }
const EightBit::register16_t& EightBit::Z80::HL() const noexcept { EightBit::register16_t& EightBit::Z80::HL() noexcept {
return m_registers[m_registerSet][HL_IDX]; return m_registers[m_registerSet][HL_IDX];
} }
@@ -156,11 +151,11 @@ void EightBit::Z80::memoryUpdate(int ticks) noexcept {
} }
void EightBit::Z80::memoryWrite() noexcept { void EightBit::Z80::memoryWrite() noexcept {
memoryUpdate(1); memoryUpdate();
} }
void EightBit::Z80::refreshMemory() noexcept { void EightBit::Z80::refreshMemory() noexcept {
assert(lowered(M1()) && "M1 must be lowered to refresh memory"); assert(fetchingOpCode() && "M1 must be lowered to refresh memory");
BUS().ADDRESS() = { REFRESH(), IV() }; BUS().ADDRESS() = { REFRESH(), IV() };
lowerRFSH(); lowerRFSH();
tick(); tick();
@@ -175,14 +170,14 @@ uint8_t EightBit::Z80::memoryRead() noexcept {
lowerMREQ(); lowerMREQ();
lowerRD(); lowerRD();
tick(); tick();
const auto data = IntelProcessor::memoryRead(); IntelProcessor::memoryRead();
raiseRD(); raiseRD();
raiseMREQ(); raiseMREQ();
if (lowered(M1())) if (fetchingOpCode())
refreshMemory(); refreshMemory();
tick(); tick();
ReadMemory.fire(); ReadMemory.fire();
return data; return BUS().DATA();
} }
void EightBit::Z80::handleRESET() noexcept { void EightBit::Z80::handleRESET() noexcept {
@@ -204,9 +199,9 @@ void EightBit::Z80::handleNMI() noexcept {
restart(0x66); restart(0x66);
} }
uint8_t EightBit::Z80::readDataUnderInterrupt() { uint8_t EightBit::Z80::readDataUnderInterrupt() noexcept {
lowerM1(); lowerM1();
tick(3); tick(2);
lowerIORQ(); lowerIORQ();
tick(); tick();
const auto data = BUS().DATA(); const auto data = BUS().DATA();
@@ -215,6 +210,7 @@ uint8_t EightBit::Z80::readDataUnderInterrupt() {
refreshMemory(); refreshMemory();
assert(cycles() == 5); assert(cycles() == 5);
raiseM1(); raiseM1();
tick();
return data; return data;
} }
@@ -222,8 +218,9 @@ void EightBit::Z80::handleINT() noexcept {
IntelProcessor::handleINT(); IntelProcessor::handleINT();
const auto data = readDataUnderInterrupt();
tick(); tick();
const auto data = readDataUnderInterrupt();
assert(cycles() == 6); assert(cycles() == 6);
switch (IM()) { switch (IM()) {
@@ -235,24 +232,46 @@ void EightBit::Z80::handleINT() noexcept {
assert(cycles() == 13); assert(cycles() == 13);
break; break;
case 2: case 2:
tick();
MEMPTR() = Processor::getWordPaged(IV(), data); MEMPTR() = Processor::getWordPaged(IV(), data);
call(MEMPTR()); call(MEMPTR());
assert(cycles() == 13); assert(cycles() == 19);
break; break;
default: default:
UNREACHABLE; UNREACHABLE;
} }
} }
void EightBit::Z80::disableInterrupts() { void EightBit::Z80::disableInterrupts() noexcept {
IFF1() = IFF2() = false; IFF1() = IFF2() = false;
} }
void EightBit::Z80::enableInterrupts() { void EightBit::Z80::enableInterrupts() noexcept {
IFF1() = IFF2() = true; IFF1() = IFF2() = true;
} }
bool EightBit::Z80::convertCondition(int flag) noexcept {
switch (flag) {
case 0:
return zero() == 0;
case 1:
return zero() != 0;
case 2:
return carry() == 0;
case 3:
return carry() != 0;
case 4:
return parity() == 0;
case 5:
return parity() != 0;
case 6:
return sign() == 0;
case 7:
return sign() != 0;
default:
UNREACHABLE;
}
}
void EightBit::Z80::returnConditionalFlag(const int flag) noexcept { void EightBit::Z80::returnConditionalFlag(const int flag) noexcept {
const auto condition = convertCondition(flag); const auto condition = convertCondition(flag);
tick(); tick();
@@ -269,8 +288,7 @@ void EightBit::Z80::reti() noexcept {
retn(); retn();
} }
void EightBit::Z80::call(register16_t destination) noexcept {
void EightBit::Z80::call(register16_t destination) {
tick(); tick();
Processor::call(destination); Processor::call(destination);
} }
@@ -280,6 +298,70 @@ void EightBit::Z80::jumpRelative(int8_t offset) noexcept {
tick(5); tick(5);
} }
uint8_t EightBit::Z80::increment(uint8_t operand) noexcept {
clearBit(NF);
const uint8_t result = operand + 1;
adjustSZXY(result);
setBit(VF, result == Bit7);
clearBit(HC, lowNibble(result));
return result;
}
uint8_t EightBit::Z80::decrement(uint8_t operand) noexcept {
setBit(NF);
clearBit(HC, lowNibble(operand));
const uint8_t result = operand - 1;
adjustSZXY(result);
setBit(VF, result == Mask7);
return result;
}
void EightBit::Z80::add(uint8_t value, int carry) noexcept {
const auto operand = A();
intermediate() = operand + value + carry;
const auto result = intermediate().low;
adjustHalfCarryAdd(operand, value, result);
adjustOverflowAdd(operand, value, result);
clearBit(NF);
setBit(CF, carryTest(intermediate().high));
adjustSZXY(result);
A() = result;
}
void EightBit::Z80::adc(uint8_t value) noexcept {
add(value, carry());
}
void EightBit::Z80::sub(uint8_t value, int carry) noexcept {
adjustSZXY(A() = subtract(value, carry));
}
void EightBit::Z80::sbc(uint8_t value) noexcept {
sub(value, carry());
}
uint8_t EightBit::Z80::subtract(uint8_t value, int carry) noexcept {
const auto operand = A();
const register16_t subtraction = operand - value - carry;
const auto result = subtraction.low;
adjustHalfCarrySub(operand, value, result);
adjustOverflowSub(operand, value, result);
setBit(NF);
setBit(CF, carryTest(subtraction.high));
adjustSZ(result);
return result;
}
void EightBit::Z80::sbc(const register16_t value) noexcept { void EightBit::Z80::sbc(const register16_t value) noexcept {
const auto operand = HL2(); const auto operand = HL2();
@@ -303,6 +385,7 @@ void EightBit::Z80::sbc(const register16_t value) noexcept {
MEMPTR() = operand + 1; MEMPTR() = operand + 1;
HL2() = intermediate(); HL2() = intermediate();
tick(7);
} }
void EightBit::Z80::adc(const register16_t value) noexcept { void EightBit::Z80::adc(const register16_t value) noexcept {
@@ -324,7 +407,7 @@ void EightBit::Z80::add(const register16_t value, int carry) noexcept {
const auto operand = HL2(); const auto operand = HL2();
const auto addition = operand.word + value.word + carry; const auto addition = operand.word + value.word + carry;
intermediate().word = addition; intermediate() = addition;
clearBit(NF); clearBit(NF);
setBit(CF, addition & Bit16); setBit(CF, addition & Bit16);
@@ -334,6 +417,7 @@ void EightBit::Z80::add(const register16_t value, int carry) noexcept {
MEMPTR() = operand + 1; MEMPTR() = operand + 1;
HL2() = intermediate(); HL2() = intermediate();
tick(7);
} }
void EightBit::Z80::xhtl(register16_t& exchange) noexcept { void EightBit::Z80::xhtl(register16_t& exchange) noexcept {
@@ -346,19 +430,177 @@ void EightBit::Z80::xhtl(register16_t& exchange) noexcept {
--BUS().ADDRESS(); --BUS().ADDRESS();
BUS().DATA() = exchange.low; BUS().DATA() = exchange.low;
exchange.low = MEMPTR().low; exchange.low = MEMPTR().low;
memoryUpdate(1); memoryUpdate();
tick(2); tick(2);
} }
void EightBit::Z80::andr(uint8_t value) noexcept {
setBit(HC);
clearBit(CF | NF);
adjustSZPXY(A() &= value);
}
void EightBit::Z80::xorr(uint8_t value) noexcept {
clearBit(HC | CF | NF);
adjustSZPXY(A() ^= value);
}
void EightBit::Z80::orr(uint8_t value) noexcept {
clearBit(HC | CF | NF);
adjustSZPXY(A() |= value);
}
void EightBit::Z80::compare(uint8_t value) noexcept {
subtract(value);
adjustXY(value);
}
uint8_t EightBit::Z80::rlc(uint8_t operand) noexcept {
clearBit(NF | HC);
const auto carry = operand & Bit7;
setBit(CF, carry);
const uint8_t result = (operand << 1) | (carry >> 7);
adjustXY(result);
return result;
}
uint8_t EightBit::Z80::rrc(uint8_t operand) noexcept {
clearBit(NF | HC);
const auto carry = operand & Bit0;
setBit(CF, carry);
const uint8_t result = (operand >> 1) | (carry << 7);
adjustXY(result);
return result;
}
uint8_t EightBit::Z80::rl(uint8_t operand) noexcept {
clearBit(NF | HC);
const auto carrying = carry();
setBit(CF, operand & Bit7);
const uint8_t result = (operand << 1) | carrying;
adjustXY(result);
return result;
}
uint8_t EightBit::Z80::rr(uint8_t operand) noexcept {
clearBit(NF | HC);
const auto carrying = carry();
setBit(CF, operand & Bit0);
const uint8_t result = (operand >> 1) | (carrying << 7);
adjustXY(result);
return result;
}
uint8_t EightBit::Z80::sla(uint8_t operand) noexcept {
clearBit(NF | HC);
setBit(CF, operand & Bit7);
const uint8_t result = operand << 1;
adjustXY(result);
return result;
}
uint8_t EightBit::Z80::sra(uint8_t operand) noexcept {
clearBit(NF | HC);
setBit(CF, operand & Bit0);
const uint8_t result = (operand >> 1) | (operand & Bit7);
adjustXY(result);
return result;
}
uint8_t EightBit::Z80::sll(uint8_t operand) noexcept {
clearBit(NF | HC);
setBit(CF, operand & Bit7);
const uint8_t result = (operand << 1) | Bit0;
adjustXY(result);
return result;
}
uint8_t EightBit::Z80::srl(uint8_t operand) noexcept {
clearBit(NF | HC);
setBit(CF, operand & Bit0);
const uint8_t result = (operand >> 1) & ~Bit7;
adjustXY(result);
setBit(ZF, result);
return result;
}
void EightBit::Z80::bit(int n, uint8_t operand) noexcept {
setBit(HC);
clearBit(NF);
const auto discarded = operand & Chip::bit(n);
adjustSZ(discarded);
clearBit(PF, discarded);
}
void EightBit::Z80::daa() noexcept {
auto updated = A();
const auto lowAdjust = halfCarry() || (lowNibble(A()) > 9);
const auto highAdjust = carry() || (A() > 0x99);
if (subtracting()) {
if (lowAdjust)
updated -= 6;
if (highAdjust)
updated -= 0x60;
} else {
if (lowAdjust)
updated += 6;
if (highAdjust)
updated += 0x60;
}
adjustStatusFlags((F() & (CF | NF) | (A() > 0x99 ? CF : 0) | halfCarryTest(A() ^ updated)));
adjustSZPXY(A() = updated);
}
void EightBit::Z80::scf() noexcept {
setBit(CF);
clearBit(HC | NF);
adjustXY((Q() ^ F()) | A());
}
void EightBit::Z80::ccf() noexcept {
clearBit(NF);
const auto carrying = carry();
setBit(HC, carrying);
clearBit(CF, carrying);
adjustXY(((Q() ^ F()) | A()));
}
void EightBit::Z80::cpl() noexcept {
setBit(HC | NF);
IntelProcessor::cpl();
adjustXY(A());
}
void EightBit::Z80::neg() noexcept {
setBit(PF, A() == Bit7);
setBit(CF, A());
setBit(NF);
auto original = A();
A() = (~A() + 1); // two's complement
adjustHalfCarrySub(0U, original, A());
adjustOverflowSub(0U, original, A());
adjustSZXY(A());
}
void EightBit::Z80::blockCompare() noexcept { void EightBit::Z80::blockCompare() noexcept {
const auto data = IntelProcessor::memoryRead(HL()); IntelProcessor::memoryRead(HL());
uint8_t result = A() - data; uint8_t result = A() - BUS().DATA();
setBit(PF, --BC().word); setBit(PF, --BC().word);
adjustSZ(result); adjustSZ(result);
adjustHalfCarrySub(A(), data, result); adjustHalfCarrySub(A(), BUS().DATA(), result);
setBit(NF); setBit(NF);
result -= (halfCarry() >> 4); result -= (halfCarry() >> 4);
@@ -395,15 +637,15 @@ void EightBit::Z80::cpdr() noexcept {
repeatBlockInstruction(); repeatBlockInstruction();
tick(5); tick(5);
} else { } else {
MEMPTR().word = PC().word - 2; MEMPTR() = PC().word - 2;
tick(2); tick(2);
} }
} }
void EightBit::Z80::blockLoad() noexcept { void EightBit::Z80::blockLoad() noexcept {
const auto data = IntelProcessor::memoryRead(HL()); IntelProcessor::memoryRead(HL());
IntelProcessor::memoryWrite(DE()); IntelProcessor::memoryWrite(DE());
const auto xy = A() + data; const auto xy = A() + BUS().DATA();
setBit(XF, xy & Bit3); setBit(XF, xy & Bit3);
setBit(YF, xy & Bit1); setBit(YF, xy & Bit1);
clearBit(NF | HC); clearBit(NF | HC);
@@ -443,7 +685,7 @@ void EightBit::Z80::repeatBlockInstruction() noexcept {
adjustXY(PC().high); adjustXY(PC().high);
} }
void EightBit::Z80::adjustBlockRepeatFlagsIO() { void EightBit::Z80::adjustBlockRepeatFlagsIO() noexcept {
if (carry() != 0) { if (carry() != 0) {
const auto negative = signTest(BUS().DATA()) != 0; const auto negative = signTest(BUS().DATA()) != 0;
const uint8_t direction = B() + (negative ? -1 : +1); const uint8_t direction = B() + (negative ? -1 : +1);
@@ -461,11 +703,11 @@ void EightBit::Z80::adjustBlockInputOutputFlags(int basis) noexcept {
} }
void EightBit::Z80::adjustBlockInFlagsIncrement() noexcept { void EightBit::Z80::adjustBlockInFlagsIncrement() noexcept {
adjustBlockInputOutputFlags((C() + 1) + BUS().DATA()); adjustBlockInputOutputFlags((uint8_t)(C() + 1) + BUS().DATA());
} }
void EightBit::Z80::adjustBlockInFlagsDecrement() noexcept { void EightBit::Z80::adjustBlockInFlagsDecrement() noexcept {
adjustBlockInputOutputFlags((C() - 1) + BUS().DATA()); adjustBlockInputOutputFlags((uint8_t)(C() - 1) + BUS().DATA());
} }
void EightBit::Z80::adjustBlockOutFlags() noexcept { void EightBit::Z80::adjustBlockOutFlags() noexcept {
@@ -478,7 +720,7 @@ void EightBit::Z80::blockIn() noexcept {
tick(); tick();
readPort(BC()); readPort(BC());
BUS().ADDRESS() = HL(); BUS().ADDRESS() = HL();
memoryUpdate(1); memoryUpdate();
adjustSZXY(--B()); adjustSZXY(--B());
setBit(NF, BUS().DATA() & SF); setBit(NF, BUS().DATA() & SF);
} }
@@ -555,7 +797,8 @@ void EightBit::Z80::otdr() noexcept {
} }
void EightBit::Z80::rrd(register16_t address, uint8_t& update) noexcept { void EightBit::Z80::rrd(register16_t address, uint8_t& update) noexcept {
(MEMPTR() = BUS().ADDRESS() = address)++; MEMPTR() = BUS().ADDRESS() = address;
++MEMPTR();
const auto memory = memoryRead(); const auto memory = memoryRead();
tick(4); tick(4);
IntelProcessor::memoryWrite(promoteNibble(update) | highNibble(memory)); IntelProcessor::memoryWrite(promoteNibble(update) | highNibble(memory));
@@ -565,7 +808,8 @@ void EightBit::Z80::rrd(register16_t address, uint8_t& update) noexcept {
} }
void EightBit::Z80::rld(register16_t address, uint8_t& update) noexcept { void EightBit::Z80::rld(register16_t address, uint8_t& update) noexcept {
(MEMPTR() = BUS().ADDRESS() = address)++; MEMPTR() = BUS().ADDRESS() = address;
++MEMPTR();
const auto memory = memoryRead(); const auto memory = memoryRead();
tick(4); tick(4);
IntelProcessor::memoryWrite(promoteNibble(memory) | lowNibble(update)); IntelProcessor::memoryWrite(promoteNibble(memory) | lowNibble(update));
@@ -663,12 +907,14 @@ uint8_t EightBit::Z80::fetchInstruction() noexcept {
} }
void EightBit::Z80::loadAccumulatorIndirect(addresser_t addresser) noexcept { void EightBit::Z80::loadAccumulatorIndirect(addresser_t addresser) noexcept {
(MEMPTR() = BUS().ADDRESS() = addresser())++; MEMPTR() = BUS().ADDRESS() = addresser();
++MEMPTR();
A() = memoryRead(); A() = memoryRead();
} }
void EightBit::Z80::storeAccumulatorIndirect(addresser_t addresser) noexcept { void EightBit::Z80::storeAccumulatorIndirect(addresser_t addresser) noexcept {
(MEMPTR() = BUS().ADDRESS() = addresser())++; MEMPTR() = BUS().ADDRESS() = addresser();
++MEMPTR();
MEMPTR().high = BUS().DATA() = A(); MEMPTR().high = BUS().DATA() = A();
memoryWrite(); memoryWrite();
} }
@@ -677,12 +923,13 @@ void EightBit::Z80::readInternalRegister(reader_t reader) noexcept {
adjustSZXY(A() = reader()); adjustSZXY(A() = reader());
clearBit(NF | HC); clearBit(NF | HC);
setBit(PF, IFF2()); setBit(PF, IFF2());
tick();
} }
EightBit::register16_t& EightBit::Z80::HL2() noexcept { EightBit::register16_t& EightBit::Z80::HL2() noexcept {
if (UNLIKELY(m_prefixDD)) if (m_prefixDD)
return IX(); return IX();
if (UNLIKELY(m_prefixFD)) if (m_prefixFD)
return IY(); return IY();
return HL(); return HL();
} }
@@ -755,7 +1002,6 @@ uint8_t& EightBit::Z80::R(const int r, MemoryMapping::AccessLevel access) noexce
} }
void EightBit::Z80::R(const int r, const uint8_t value, const int ticks) noexcept { void EightBit::Z80::R(const int r, const uint8_t value, const int ticks) noexcept {
R(r, MemoryMapping::AccessLevel::WriteOnly) = value; R(r, MemoryMapping::AccessLevel::WriteOnly) = value;
if (r == 6) if (r == 6)
memoryUpdate(ticks); memoryUpdate(ticks);
@@ -944,7 +1190,6 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p
default: default:
UNREACHABLE; UNREACHABLE;
} }
tick(7);
break; break;
case 3: // Retrieve/store register pair from/to immediate address case 3: // Retrieve/store register pair from/to immediate address
BUS().ADDRESS() = fetchWord(); BUS().ADDRESS() = fetchWord();
@@ -1004,11 +1249,9 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p
break; break;
case 2: // LD A,I case 2: // LD A,I
readInternalRegister([this]() { return IV(); }); readInternalRegister([this]() { return IV(); });
tick();
break; break;
case 3: // LD A,R case 3: // LD A,R
readInternalRegister([this]() { return REFRESH(); }); readInternalRegister([this]() { return REFRESH(); });
tick();
break; break;
case 4: // RRD case 4: // RRD
rrd(HL(), A()); rrd(HL(), A());
@@ -1135,7 +1378,6 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
break; break;
case 1: // ADD HL,rp case 1: // ADD HL,rp
add(RP(p)); add(RP(p));
tick(7);
break; break;
default: default:
UNREACHABLE; UNREACHABLE;
+1 -1
View File
@@ -17,7 +17,7 @@ void Board::lowerPOWER() noexcept {
EightBit::Bus::lowerPOWER(); EightBit::Bus::lowerPOWER();
} }
void Board::initialise() { void Board::initialise() noexcept {
auto romDirectory = m_configuration.getRomDirectory(); auto romDirectory = m_configuration.getRomDirectory();
m_ram.load(romDirectory + "/zexall.com", 0x100); // Cringle/Bartholomew m_ram.load(romDirectory + "/zexall.com", 0x100); // Cringle/Bartholomew
+2 -2
View File
@@ -16,12 +16,12 @@ class Board : public EightBit::Bus {
public: public:
Board(const Configuration& configuration); Board(const Configuration& configuration);
EightBit::Z80& CPU() noexcept { return m_cpu; } EightBit::Z80& CPU() { return m_cpu; }
void raisePOWER() noexcept final; void raisePOWER() noexcept final;
void lowerPOWER() noexcept final; void lowerPOWER() noexcept final;
void initialise() final; void initialise() noexcept final;
protected: protected:
EightBit::MemoryMapping mapping(uint16_t address) noexcept final { EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
+9 -8
View File
@@ -8,7 +8,8 @@ namespace EightBit {
class BigEndianProcessor : public Processor { class BigEndianProcessor : public Processor {
public: public:
virtual ~BigEndianProcessor() noexcept {}; virtual ~BigEndianProcessor() noexcept = default;
BigEndianProcessor(const BigEndianProcessor& rhs) noexcept;
[[nodiscard]] register16_t peekWord(register16_t address) noexcept final; [[nodiscard]] register16_t peekWord(register16_t address) noexcept final;
void pokeWord(register16_t address, register16_t value) noexcept final; void pokeWord(register16_t address, register16_t value) noexcept final;
@@ -16,15 +17,15 @@ namespace EightBit {
protected: protected:
BigEndianProcessor(Bus& memory) noexcept; BigEndianProcessor(Bus& memory) noexcept;
[[nodiscard]] register16_t getWord() override; [[nodiscard]] register16_t getWord() noexcept override;
void setWord(register16_t value) override; void setWord(register16_t value) noexcept override;
[[nodiscard]] register16_t getWordPaged() override; [[nodiscard]] register16_t getWordPaged() noexcept override;
void setWordPaged(register16_t value) override; void setWordPaged(register16_t value) noexcept override;
[[nodiscard]] register16_t fetchWord() final; [[nodiscard]] register16_t fetchWord() noexcept override;
void pushWord(register16_t value) final; void pushWord(register16_t value) noexcept override;
[[nodiscard]] register16_t popWord() final; [[nodiscard]] register16_t popWord() noexcept override;
}; };
} }
+5 -5
View File
@@ -26,20 +26,20 @@ namespace EightBit {
[[nodiscard]] constexpr auto DATA() const noexcept { return m_data; } [[nodiscard]] constexpr auto DATA() const noexcept { return m_data; }
[[nodiscard]] constexpr auto& DATA() noexcept { return m_data; } [[nodiscard]] constexpr auto& DATA() noexcept { return m_data; }
[[nodiscard]] virtual uint8_t peek(const uint16_t address) noexcept { return reference(address); } [[nodiscard]] uint8_t peek(const uint16_t address) noexcept { return reference(address); }
[[nodiscard]] auto peek(const register16_t address) noexcept { return peek(address.word); } [[nodiscard]] auto peek(const register16_t address) noexcept { return peek(address.word); }
void poke(const uint8_t value) noexcept { reference() = value; } void poke(const uint8_t value) noexcept { reference() = value; }
virtual void poke(const uint16_t address, const uint8_t value) noexcept { reference(address) = value; } void poke(const uint16_t address, const uint8_t value) noexcept { reference(address) = value; }
void poke(const register16_t address, const uint8_t value) noexcept { poke(address.word, value); } void poke(const register16_t address, const uint8_t value) noexcept { poke(address.word, value); }
[[nodiscard]] uint8_t read(); [[nodiscard]] uint8_t read() noexcept;
void write(); void write() noexcept;
virtual void raisePOWER() noexcept; virtual void raisePOWER() noexcept;
virtual void lowerPOWER() noexcept; virtual void lowerPOWER() noexcept;
virtual void initialise() = 0; virtual void initialise() noexcept = 0;
protected: protected:
[[nodiscard]] uint8_t& reference(uint16_t address) noexcept; [[nodiscard]] uint8_t& reference(uint16_t address) noexcept;
+2 -2
View File
@@ -14,12 +14,12 @@ namespace EightBit {
[[nodiscard]] constexpr auto cycles() const noexcept { return m_cycles; } [[nodiscard]] constexpr auto cycles() const noexcept { return m_cycles; }
void tick() { void tick() noexcept {
++m_cycles; ++m_cycles;
Ticked.fire(); Ticked.fire();
} }
void tick(int extra) { void tick(int extra) noexcept {
for (int i = 0; i < extra; ++i) for (int i = 0; i < extra; ++i)
tick(); tick();
} }
+5 -24
View File
@@ -10,17 +10,17 @@
Signal<EventArgs> Lowered ## name; Signal<EventArgs> Lowered ## name;
#define DECLARE_PIN_LEVEL_RAISE(name) \ #define DECLARE_PIN_LEVEL_RAISE(name) \
virtual void raise ## name(); virtual void raise ## name() noexcept;
#define DECLARE_PIN_LEVEL_LOWER(name) \ #define DECLARE_PIN_LEVEL_LOWER(name) \
virtual void lower ## name(); virtual void lower ## name() noexcept;
#define DECLARE_PIN_LEVEL_CHANGERS(name) \ #define DECLARE_PIN_LEVEL_CHANGERS(name) \
DECLARE_PIN_LEVEL_RAISE(name) \ DECLARE_PIN_LEVEL_RAISE(name) \
DECLARE_PIN_LEVEL_LOWER(name) DECLARE_PIN_LEVEL_LOWER(name)
#define DEFINE_PIN_LEVEL_RAISE(name, within) \ #define DEFINE_PIN_LEVEL_RAISE(name, within) \
void EightBit:: within ::raise ## name() { \ void EightBit:: within ::raise ## name() noexcept { \
if (lowered( name ())) { \ if (lowered( name ())) { \
Raising ## name.fire(); \ Raising ## name.fire(); \
raise( name ()); \ raise( name ()); \
@@ -29,7 +29,7 @@
} }
#define DEFINE_PIN_LEVEL_LOWER(name, within) \ #define DEFINE_PIN_LEVEL_LOWER(name, within) \
void EightBit:: within ::lower ## name() { \ void EightBit:: within ::lower ## name() noexcept { \
if (raised( name ())) { \ if (raised( name ())) { \
Lowering ## name.fire(); \ Lowering ## name.fire(); \
lower( name ()); \ lower( name ()); \
@@ -44,25 +44,6 @@
#define DECLARE_PIN_MEMBER(name) \ #define DECLARE_PIN_MEMBER(name) \
PinLevel m_## name ## _Line = PinLevel::Low; PinLevel m_## name ## _Line = PinLevel::Low;
#define DEFINE_PIN_ACTIVATOR(name, on, off) \
template <class T> class _Activate ## name final { \
T& m_parent; \
public: \
_Activate ## name(T& parent) noexcept \
: m_parent(parent) { \
m_parent. on ## name(); \
} \
~_Activate ## name() noexcept { \
m_parent. off ## name(); \
} \
};
#define DEFINE_PIN_ACTIVATOR_LOW(name) \
DEFINE_PIN_ACTIVATOR(name, lower, raise)
#define DEFINE_PIN_ACTIVATOR_HIGH(name) \
DEFINE_PIN_ACTIVATOR(name, raise, lower)
#define DECLARE_PIN(name, visibility) \ #define DECLARE_PIN(name, visibility) \
public: \ public: \
DECLARE_PIN_SIGNALS(name) \ DECLARE_PIN_SIGNALS(name) \
@@ -114,6 +95,6 @@ namespace EightBit {
[[nodiscard]] constexpr bool powered() const noexcept { return raised(POWER()); } [[nodiscard]] constexpr bool powered() const noexcept { return raised(POWER()); }
protected: protected:
Device() noexcept {}; Device() noexcept = default;
}; };
} }
+36 -63
View File
@@ -9,16 +9,6 @@
#include "Signal.h" #include "Signal.h"
#include "EightBitCompilerDefinitions.h" #include "EightBitCompilerDefinitions.h"
#define NON_CONST_ACCESSOR(accessor, type) \
[[nodiscard]] constexpr auto& accessor() noexcept { \
const auto& consted = *this; \
const auto& reference = consted.accessor(); \
return const_cast<type&>(reference); \
}
#define NON_CONST_REGISTOR_ACCESSOR(accessor) \
NON_CONST_ACCESSOR(accessor, register16_t)
namespace EightBit { namespace EightBit {
class Bus; class Bus;
@@ -52,35 +42,32 @@ namespace EightBit {
} }
[[nodiscard]] constexpr auto& MEMPTR() noexcept { return m_memptr; } [[nodiscard]] constexpr auto& MEMPTR() noexcept { return m_memptr; }
[[nodiscard]] constexpr auto MEMPTR() const noexcept { return m_memptr; }
[[nodiscard]] constexpr auto& SP() noexcept { return m_sp; } [[nodiscard]] constexpr auto& SP() noexcept { return m_sp; }
[[nodiscard]] register16_t SP() const noexcept { return m_sp; }
[[nodiscard]] virtual const register16_t& AF() const noexcept = 0; [[nodiscard]] virtual register16_t& AF() noexcept = 0;
NON_CONST_REGISTOR_ACCESSOR(AF);
[[nodiscard]] auto& A() noexcept { return AF().high; } [[nodiscard]] auto& A() noexcept { return AF().high; }
[[nodiscard]] auto& F() noexcept { return AF().low; } [[nodiscard]] auto& F() noexcept { return AF().low; }
[[nodiscard]] virtual const register16_t& BC() const noexcept = 0; [[nodiscard]] virtual register16_t& BC() noexcept = 0;
NON_CONST_REGISTOR_ACCESSOR(BC);
[[nodiscard]] auto& B() noexcept { return BC().high; } [[nodiscard]] auto& B() noexcept { return BC().high; }
[[nodiscard]] auto& C() noexcept { return BC().low; } [[nodiscard]] auto& C() noexcept { return BC().low; }
[[nodiscard]] virtual const register16_t& DE() const noexcept = 0; [[nodiscard]] virtual register16_t& DE() noexcept = 0;
NON_CONST_REGISTOR_ACCESSOR(DE);
[[nodiscard]] auto& D() noexcept { return DE().high; } [[nodiscard]] auto& D() noexcept { return DE().high; }
[[nodiscard]] auto& E() noexcept { return DE().low; } [[nodiscard]] auto& E() noexcept { return DE().low; }
[[nodiscard]] virtual const register16_t& HL() const noexcept = 0; [[nodiscard]] virtual register16_t& HL() noexcept = 0;
NON_CONST_REGISTOR_ACCESSOR(HL);
[[nodiscard]] auto& H() noexcept { return HL().high; } [[nodiscard]] auto& H() noexcept { return HL().high; }
[[nodiscard]] auto& L() noexcept { return HL().low; } [[nodiscard]] auto& L() noexcept { return HL().low; }
DECLARE_PIN_OUTPUT(HALT) DECLARE_PIN_OUTPUT(HALT)
public:
[[nodiscard]] constexpr bool halted() const noexcept { return lowered(HALT()); }
[[nodiscard]] constexpr bool proceeding() const noexcept { return !halted(); }
protected: protected:
IntelProcessor(Bus& bus); IntelProcessor(Bus& bus) noexcept;
template<class T> [[nodiscard]] static constexpr uint8_t adjustSign(uint8_t f, const uint8_t value) noexcept { template<class T> [[nodiscard]] static constexpr uint8_t adjustSign(uint8_t f, const uint8_t value) noexcept {
return setBit(f, T::SF, value & T::SF); return setBit(f, T::SF, value & T::SF);
@@ -138,65 +125,51 @@ namespace EightBit {
return calculateHalfCarry(m_halfCarryTableSub, before, value, calculation); return calculateHalfCarry(m_halfCarryTableSub, before, value, calculation);
} }
virtual void disableInterrupts() = 0; virtual void disableInterrupts() noexcept = 0;
virtual void enableInterrupts() noexcept = 0;
virtual void enableInterrupts() = 0; void handleRESET() noexcept override;
void handleINT() noexcept override;
void handleRESET() override; void push(uint8_t value) noexcept final;
void handleINT() override; [[nodiscard]] uint8_t pop() noexcept final;
void push(uint8_t value) final;
[[nodiscard]] uint8_t pop() final;
// //
register16_t& incrementPC() override; register16_t& incrementPC() noexcept override;
uint8_t fetchInstruction() override; uint8_t fetchInstruction() noexcept override;
// //
[[nodiscard]] register16_t getWord() final; [[nodiscard]] register16_t getWord() noexcept final;
void setWord(register16_t value) final; void setWord(register16_t value) noexcept final;
// //
void restart(uint8_t address); void restart(uint8_t address) noexcept;
void callConditional(bool condition); void callConditional(bool condition) noexcept;
virtual void jumpConditional(bool condition); virtual void jumpConditional(bool condition) noexcept;
void jumpRelativeConditional(bool condition); void jumpRelativeConditional(bool condition) noexcept;
virtual void returnConditional(bool condition); virtual void returnConditional(bool condition) noexcept;
void jumpIndirect(); void jumpIndirect() noexcept;
void jump(); void jump() noexcept;
void callIndirect(); void callIndirect() noexcept;
void call(); void call() noexcept;
virtual void call(register16_t destination); virtual void call(register16_t destination) noexcept;
virtual void jumpRelative(int8_t offset) noexcept; virtual void jumpRelative(int8_t offset) noexcept;
void jumpRelative(uint8_t offset) noexcept { jumpRelative((int8_t)offset); } void jumpRelative(uint8_t offset) noexcept { jumpRelative(static_cast<int8_t>(offset)); }
void ret() override; void ret() noexcept override;
void resetWorkingRegisters() noexcept; void resetWorkingRegisters() noexcept;
[[nodiscard]] virtual bool convertCondition(int flag) noexcept = 0; [[nodiscard]] virtual bool convertCondition(int flag) noexcept = 0;
virtual void jumpConditionalFlag(int flag) { virtual void jumpConditionalFlag(int flag) noexcept;
jumpConditional(convertCondition(flag)); virtual void jumpRelativeConditionalFlag(int flag) noexcept;
} virtual void returnConditionalFlag(int flag) noexcept;
virtual void callConditionalFlag(int flag) noexcept;
virtual void jumpRelativeConditionalFlag(int flag) { virtual void cpl() noexcept;
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: private:
static std::array<int, 8> m_halfCarryTableAdd; static std::array<int, 8> m_halfCarryTableAdd;
+8 -7
View File
@@ -8,6 +8,7 @@ namespace EightBit {
class LittleEndianProcessor : public Processor { class LittleEndianProcessor : public Processor {
public: public:
virtual ~LittleEndianProcessor() noexcept = default;
LittleEndianProcessor(const LittleEndianProcessor& rhs) noexcept; LittleEndianProcessor(const LittleEndianProcessor& rhs) noexcept;
[[nodiscard]] register16_t peekWord(register16_t address) noexcept final; [[nodiscard]] register16_t peekWord(register16_t address) noexcept final;
@@ -16,15 +17,15 @@ namespace EightBit {
protected: protected:
LittleEndianProcessor(Bus& memory) noexcept; LittleEndianProcessor(Bus& memory) noexcept;
[[nodiscard]] register16_t getWord() override; [[nodiscard]] register16_t getWord() noexcept override;
void setWord(register16_t value) override; void setWord(register16_t value) noexcept override;
[[nodiscard]] register16_t getWordPaged() override; [[nodiscard]] register16_t getWordPaged() noexcept override;
void setWordPaged(register16_t value) override; void setWordPaged(register16_t value) noexcept override;
[[nodiscard]] register16_t fetchWord() final; [[nodiscard]] register16_t fetchWord() noexcept override;
void pushWord(register16_t value) override; void pushWord(register16_t value) noexcept override;
[[nodiscard]] register16_t popWord() override; [[nodiscard]] register16_t popWord() noexcept override;
}; };
} }
+32 -32
View File
@@ -57,53 +57,53 @@ namespace EightBit {
[[nodiscard]] constexpr auto& opcode() noexcept { return m_opcode; } [[nodiscard]] constexpr auto& opcode() noexcept { return m_opcode; }
[[nodiscard]] constexpr auto& BUS() noexcept { return m_bus; } [[nodiscard]] constexpr auto& BUS() noexcept { return m_bus; }
virtual void handleRESET(); virtual void handleRESET() noexcept;
virtual void handleINT(); virtual void handleINT() noexcept;
void memoryWrite(register16_t address, uint8_t data); void memoryWrite(register16_t address, uint8_t data) noexcept;
void memoryWrite(register16_t address); void memoryWrite(register16_t address) noexcept;
void memoryWrite(uint8_t data); void memoryWrite(uint8_t data) noexcept;
virtual void memoryWrite(); virtual void memoryWrite() noexcept;
virtual void busWrite(); virtual void busWrite() noexcept;
uint8_t memoryRead(register16_t address); uint8_t memoryRead(register16_t address) noexcept;
virtual uint8_t memoryRead(); virtual uint8_t memoryRead() noexcept;
virtual uint8_t busRead(); virtual uint8_t busRead() noexcept;
virtual register16_t& incrementPC(); virtual register16_t& incrementPC() noexcept;
virtual register16_t& decrementPC(); virtual register16_t& decrementPC() noexcept;
virtual void immediateAddress(); virtual void immediateAddress() noexcept;
uint8_t fetchByte(); uint8_t fetchByte() noexcept;
virtual uint8_t fetchInstruction(); virtual uint8_t fetchInstruction() noexcept;
[[nodiscard]] virtual register16_t getWord() = 0; [[nodiscard]] virtual register16_t getWord() noexcept = 0;
virtual void setWord(register16_t value) = 0; virtual void setWord(register16_t value) noexcept = 0;
[[nodiscard]] register16_t getWordPaged(register16_t address); [[nodiscard]] register16_t getWordPaged(register16_t address) noexcept;
[[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset); [[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept;
[[nodiscard]] virtual register16_t getWordPaged() = 0; [[nodiscard]] virtual register16_t getWordPaged() noexcept = 0;
void setWordPaged(register16_t address, register16_t value); void setWordPaged(register16_t address, register16_t value) noexcept;
void setWordPaged(uint8_t page, uint8_t offset, register16_t value); void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept;
virtual void setWordPaged(register16_t value) = 0; virtual void setWordPaged(register16_t value) noexcept = 0;
[[nodiscard]] virtual register16_t fetchWord() = 0; [[nodiscard]] virtual register16_t fetchWord() noexcept = 0;
virtual void push(uint8_t value) = 0; virtual void push(uint8_t value) noexcept = 0;
[[nodiscard]] virtual uint8_t pop() = 0; [[nodiscard]] virtual uint8_t pop() noexcept = 0;
virtual void pushWord(register16_t value) = 0; virtual void pushWord(register16_t value) noexcept = 0;
[[nodiscard]] virtual register16_t popWord() = 0; [[nodiscard]] virtual register16_t popWord() noexcept = 0;
[[nodiscard]] register16_t getWord(register16_t address); [[nodiscard]] register16_t getWord(register16_t address) noexcept;
void setWord(register16_t address, register16_t value); void setWord(register16_t address, register16_t value) noexcept;
void jump(const register16_t destination) noexcept; void jump(const register16_t destination) noexcept;
void jump(uint16_t destination) noexcept; void jump(uint16_t destination) noexcept;
virtual void call(register16_t destination); virtual void call(register16_t destination) noexcept;
virtual void ret(); virtual void ret() noexcept;
private: private:
Bus& m_bus; Bus& m_bus;
+1 -1
View File
@@ -8,7 +8,7 @@ namespace EightBit {
class Ram : public Rom { class Ram : public Rom {
public: public:
Ram(size_t size = 0) noexcept; Ram(size_t size = 0) noexcept;
virtual ~Ram() = default; virtual ~Ram() noexcept = default;
[[nodiscard]] uint8_t& reference(uint16_t address) noexcept final; [[nodiscard]] uint8_t& reference(uint16_t address) noexcept final;
void poke(uint16_t address, uint8_t value) noexcept final; void poke(uint16_t address, uint8_t value) noexcept final;
+4 -4
View File
@@ -26,10 +26,10 @@ namespace EightBit {
static int load(std::string path, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1); static int load(std::string path, std::vector<uint8_t>& output, int writeOffset = 0, int readOffset = 0, int limit = -1, int maximumSize = -1);
Rom(size_t size = 0) noexcept; Rom(size_t size = 0) noexcept;
Rom(const Rom& rhs); Rom(const Rom& rhs) noexcept;
virtual ~Rom() = default; virtual ~Rom() noexcept = default;
Rom& operator=(const Rom& rhs); Rom& operator=(const Rom& rhs) noexcept;
bool operator==(const Rom& rhs) const; bool operator==(const Rom& rhs) const noexcept;
[[nodiscard]] uint16_t size() const noexcept final; [[nodiscard]] uint16_t size() const noexcept final;
+5 -3
View File
@@ -17,9 +17,11 @@ namespace EightBit {
m_delegates.push_back(functor); m_delegates.push_back(functor);
} }
void fire(T& e = EventArgs::empty()) const { void fire(T& e = EventArgs::empty()) const noexcept {
for (auto& delegate : m_delegates) const auto firing = !m_delegates.empty();
delegate(e); if (firing)
for (auto& delegate : m_delegates)
delegate(e);
} }
}; };
} }
+13 -10
View File
@@ -4,44 +4,47 @@
EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory) noexcept EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory) noexcept
: Processor(memory) {} : Processor(memory) {}
EightBit::register16_t EightBit::BigEndianProcessor::getWord() { EightBit::BigEndianProcessor::BigEndianProcessor(const BigEndianProcessor& rhs) noexcept
: Processor(rhs) {}
EightBit::register16_t EightBit::BigEndianProcessor::getWord() noexcept {
const auto high = memoryRead(); const auto high = memoryRead();
++BUS().ADDRESS(); ++BUS().ADDRESS();
const auto low = memoryRead(); const auto low = memoryRead();
return { low, high }; return { low, high };
} }
void EightBit::BigEndianProcessor::setWord(const register16_t value) { void EightBit::BigEndianProcessor::setWord(const register16_t value) noexcept {
memoryWrite(value.high); memoryWrite(value.high);
++BUS().ADDRESS(); ++BUS().ADDRESS();
memoryWrite(value.low); memoryWrite(value.low);
} }
EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged() { EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged() noexcept {
const auto high = memoryRead(); const auto high = memoryRead();
++BUS().ADDRESS().low; ++BUS().ADDRESS().low;
const auto low = memoryRead(); const auto low = memoryRead();
return { low, high }; return { low, high };
} }
void EightBit::BigEndianProcessor::setWordPaged(const register16_t value) { void EightBit::BigEndianProcessor::setWordPaged(const register16_t value) noexcept {
memoryWrite(value.high); memoryWrite(value.high);
++BUS().ADDRESS().low; ++BUS().ADDRESS().low;
memoryWrite(value.low); memoryWrite(value.low);
} }
EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() { EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() noexcept {
const auto high = fetchByte(); intermediate().high = fetchByte();
const auto low = fetchByte(); intermediate().low = fetchByte();
return { low, high }; return intermediate();
} }
void EightBit::BigEndianProcessor::pushWord(const register16_t value) { void EightBit::BigEndianProcessor::pushWord(const register16_t value) noexcept {
push(value.low); push(value.low);
push(value.high); push(value.high);
} }
EightBit::register16_t EightBit::BigEndianProcessor::popWord() { EightBit::register16_t EightBit::BigEndianProcessor::popWord() noexcept {
const auto high = pop(); const auto high = pop();
const auto low = pop(); const auto low = pop();
return { low, high }; return { low, high };
+2 -2
View File
@@ -8,14 +8,14 @@ void EightBit::Bus::raisePOWER() noexcept {}
void EightBit::Bus::lowerPOWER() noexcept {} void EightBit::Bus::lowerPOWER() noexcept {}
uint8_t EightBit::Bus::read() { uint8_t EightBit::Bus::read() noexcept {
ReadingByte.fire(); ReadingByte.fire();
const auto returned = DATA() = reference(); const auto returned = DATA() = reference();
ReadByte.fire(); ReadByte.fire();
return returned; return returned;
} }
void EightBit::Bus::write() { void EightBit::Bus::write() noexcept {
WritingByte.fire(); WritingByte.fire();
reference() = DATA(); reference() = DATA();
WrittenByte.fire(); WrittenByte.fire();
+55 -37
View File
@@ -4,7 +4,7 @@
std::array<int, 8> EightBit::IntelProcessor::m_halfCarryTableAdd = { { 0, 0, 1, 0, 1, 0, 1, 1 } }; std::array<int, 8> EightBit::IntelProcessor::m_halfCarryTableAdd = { { 0, 0, 1, 0, 1, 0, 1, 1 } };
std::array<int, 8> EightBit::IntelProcessor::m_halfCarryTableSub = { { 0, 1, 1, 1, 0, 0, 0, 1 } }; std::array<int, 8> EightBit::IntelProcessor::m_halfCarryTableSub = { { 0, 1, 1, 1, 0, 0, 0, 1 } };
EightBit::IntelProcessor::IntelProcessor(Bus& bus) EightBit::IntelProcessor::IntelProcessor(Bus& bus) noexcept
: LittleEndianProcessor(bus) { : LittleEndianProcessor(bus) {
for (int i = 0; i < 0x100; ++i) for (int i = 0; i < 0x100; ++i)
m_decodedOpcodes.at(i) = i; m_decodedOpcodes.at(i) = i;
@@ -17,11 +17,9 @@ EightBit::IntelProcessor::IntelProcessor(Bus& bus)
} }
EightBit::IntelProcessor::IntelProcessor(const IntelProcessor& rhs) noexcept EightBit::IntelProcessor::IntelProcessor(const IntelProcessor& rhs) noexcept
: LittleEndianProcessor(rhs) { : LittleEndianProcessor(rhs),
m_sp(rhs.m_sp),
m_sp = rhs.m_sp; m_memptr(rhs.m_memptr) {
m_memptr = rhs.m_memptr;
HALT() = rhs.HALT(); HALT() = rhs.HALT();
} }
@@ -31,73 +29,72 @@ void EightBit::IntelProcessor::resetWorkingRegisters() noexcept {
DEFINE_PIN_LEVEL_CHANGERS(HALT, IntelProcessor); DEFINE_PIN_LEVEL_CHANGERS(HALT, IntelProcessor);
void EightBit::IntelProcessor::handleRESET() { void EightBit::IntelProcessor::handleRESET() noexcept {
Processor::handleRESET(); Processor::handleRESET();
disableInterrupts(); disableInterrupts();
Processor::jump(0); Processor::jump(0);
} }
void EightBit::IntelProcessor::handleINT() { void EightBit::IntelProcessor::handleINT() noexcept {
Processor::handleINT(); Processor::handleINT();
disableInterrupts();
raiseHALT(); raiseHALT();
disableInterrupts();
} }
void EightBit::IntelProcessor::push(const uint8_t value) { void EightBit::IntelProcessor::push(const uint8_t value) noexcept {
memoryWrite(--SP(), value); memoryWrite(--SP(), value);
} }
uint8_t EightBit::IntelProcessor::pop() { uint8_t EightBit::IntelProcessor::pop() noexcept {
return memoryRead(SP()++); return memoryRead(SP()++);
} }
EightBit::register16_t& EightBit::IntelProcessor::incrementPC() noexcept {
EightBit::register16_t& EightBit::IntelProcessor::incrementPC() { if (proceeding())
if (raised(HALT()))
Processor::incrementPC(); Processor::incrementPC();
return PC(); return PC();
} }
uint8_t EightBit::IntelProcessor::fetchInstruction() { uint8_t EightBit::IntelProcessor::fetchInstruction() noexcept {
const auto data = fetchByte(); const auto data = fetchByte();
return lowered(HALT()) ? (uint8_t)0 : data; return proceeding() ? data : (uint8_t)0;
} }
EightBit::register16_t EightBit::IntelProcessor::getWord() { EightBit::register16_t EightBit::IntelProcessor::getWord() noexcept {
const auto returned = LittleEndianProcessor::getWord(); const auto returned = LittleEndianProcessor::getWord();
MEMPTR() = BUS().ADDRESS(); MEMPTR() = BUS().ADDRESS();
return returned; return returned;
} }
void EightBit::IntelProcessor::setWord(const register16_t value) { void EightBit::IntelProcessor::setWord(const register16_t value) noexcept {
LittleEndianProcessor::setWord(value); LittleEndianProcessor::setWord(value);
MEMPTR() = BUS().ADDRESS(); MEMPTR() = BUS().ADDRESS();
} }
void EightBit::IntelProcessor::restart(const uint8_t address) { void EightBit::IntelProcessor::restart(const uint8_t address) noexcept {
MEMPTR() = { address, 0 }; MEMPTR() = { address, 0 };
call(); call();
} }
void EightBit::IntelProcessor::callConditional(bool condition) { void EightBit::IntelProcessor::callConditional(bool condition) noexcept {
MEMPTR() = fetchWord(); MEMPTR() = fetchWord();
if (condition) if (condition)
call(); call();
} }
void EightBit::IntelProcessor::jumpConditional(bool condition) { void EightBit::IntelProcessor::jumpConditional(bool condition) noexcept {
MEMPTR() = fetchWord(); MEMPTR() = fetchWord();
if (condition) if (condition)
jump(); jump();
} }
void EightBit::IntelProcessor::jumpRelativeConditional(bool condition) { void EightBit::IntelProcessor::jumpRelativeConditional(bool condition) noexcept {
const auto offset = fetchByte(); const auto offset = fetchByte();
if (condition) if (condition)
jumpRelative(offset); jumpRelative(offset);
} }
void EightBit::IntelProcessor::returnConditional(bool condition) { void EightBit::IntelProcessor::returnConditional(bool condition) noexcept {
if (condition) if (condition)
ret(); ret();
} }
@@ -107,42 +104,63 @@ void EightBit::IntelProcessor::jumpRelative(const int8_t offset) noexcept {
jump(); jump();
} }
void EightBit::IntelProcessor::ret() noexcept {
void EightBit::IntelProcessor::ret() {
LittleEndianProcessor::ret(); LittleEndianProcessor::ret();
MEMPTR() = PC(); MEMPTR() = PC();
} }
void EightBit::IntelProcessor::jumpIndirect() { void EightBit::IntelProcessor::jumpIndirect() noexcept {
MEMPTR() = fetchWord(); MEMPTR() = fetchWord();
jump(); jump();
} }
void EightBit::IntelProcessor::jump() { void EightBit::IntelProcessor::jump() noexcept {
Processor::jump(MEMPTR()); Processor::jump(MEMPTR());
} }
void EightBit::IntelProcessor::callIndirect() { void EightBit::IntelProcessor::callIndirect() noexcept {
MEMPTR() = fetchWord(); MEMPTR() = fetchWord();
call(); call();
} }
void EightBit::IntelProcessor::call() { void EightBit::IntelProcessor::call() noexcept {
call(MEMPTR()); call(MEMPTR());
} }
void EightBit::IntelProcessor::call(register16_t destination) { void EightBit::IntelProcessor::call(register16_t destination) noexcept {
Processor::call(destination); Processor::call(destination);
} }
void EightBit::IntelProcessor::jumpConditionalFlag(int flag) noexcept {
jumpConditional(convertCondition(flag));
}
void EightBit::IntelProcessor::jumpRelativeConditionalFlag(int flag) noexcept {
jumpRelativeConditional(convertCondition(flag));
}
void EightBit::IntelProcessor::returnConditionalFlag(int flag) noexcept {
returnConditional(convertCondition(flag));
}
void EightBit::IntelProcessor::callConditionalFlag(int flag) noexcept {
callConditional(convertCondition(flag));
}
void EightBit::IntelProcessor::cpl() noexcept {
A() = ~A();
}
bool EightBit::IntelProcessor::operator==(const EightBit::IntelProcessor& rhs) const noexcept { bool EightBit::IntelProcessor::operator==(const EightBit::IntelProcessor& rhs) const noexcept {
auto& left = const_cast<IntelProcessor&>(*this);
auto& right = const_cast<IntelProcessor&>(rhs);
return return
LittleEndianProcessor::operator==(rhs) LittleEndianProcessor::operator==(rhs)
&& HALT() == rhs.HALT() && left.HALT() == right.HALT()
&& MEMPTR() == rhs.MEMPTR() && left.MEMPTR() == right.MEMPTR()
&& SP() == rhs.SP() && left.SP() == right.SP()
&& AF() == rhs.AF() && left.AF() == right.AF()
&& BC() == rhs.BC() && left.BC() == right.BC()
&& DE() == rhs.DE() && left.DE() == right.DE()
&& HL() == rhs.HL(); && left.HL() == right.HL();
} }
+7 -7
View File
@@ -7,44 +7,44 @@ EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory) noexcept
EightBit::LittleEndianProcessor::LittleEndianProcessor(const LittleEndianProcessor& rhs) noexcept EightBit::LittleEndianProcessor::LittleEndianProcessor(const LittleEndianProcessor& rhs) noexcept
: Processor(rhs) {} : Processor(rhs) {}
EightBit::register16_t EightBit::LittleEndianProcessor::getWord() { EightBit::register16_t EightBit::LittleEndianProcessor::getWord() noexcept {
const auto low = memoryRead(); const auto low = memoryRead();
++BUS().ADDRESS(); ++BUS().ADDRESS();
const auto high = memoryRead(); const auto high = memoryRead();
return { low, high }; return { low, high };
} }
void EightBit::LittleEndianProcessor::setWord(const register16_t value) { void EightBit::LittleEndianProcessor::setWord(const register16_t value) noexcept {
memoryWrite(value.low); memoryWrite(value.low);
++BUS().ADDRESS(); ++BUS().ADDRESS();
memoryWrite(value.high); memoryWrite(value.high);
} }
EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged() { EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged() noexcept {
const auto low = memoryRead(); const auto low = memoryRead();
++BUS().ADDRESS().low; ++BUS().ADDRESS().low;
const auto high = memoryRead(); const auto high = memoryRead();
return { low, high }; return { low, high };
} }
void EightBit::LittleEndianProcessor::setWordPaged(register16_t value) { void EightBit::LittleEndianProcessor::setWordPaged(register16_t value) noexcept {
memoryWrite(value.low); memoryWrite(value.low);
++BUS().ADDRESS().low; ++BUS().ADDRESS().low;
memoryWrite(value.high); memoryWrite(value.high);
} }
EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() { EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() noexcept {
intermediate().low = fetchByte(); intermediate().low = fetchByte();
intermediate().high = fetchByte(); intermediate().high = fetchByte();
return intermediate(); return intermediate();
} }
void EightBit::LittleEndianProcessor::pushWord(const register16_t value) { void EightBit::LittleEndianProcessor::pushWord(const register16_t value) noexcept {
push(value.high); push(value.high);
push(value.low); push(value.low);
} }
EightBit::register16_t EightBit::LittleEndianProcessor::popWord() { EightBit::register16_t EightBit::LittleEndianProcessor::popWord() noexcept {
const auto low = pop(); const auto low = pop();
const auto high = pop(); const auto high = pop();
return { low, high }; return { low, high };
+31 -31
View File
@@ -7,109 +7,109 @@ EightBit::Processor::Processor(Bus& bus) noexcept
EightBit::Processor::Processor(const Processor& rhs) noexcept EightBit::Processor::Processor(const Processor& rhs) noexcept
: ClockedChip(rhs), : ClockedChip(rhs),
m_bus(rhs.m_bus) { m_bus(rhs.m_bus),
m_opcode(rhs.m_opcode),
m_pc(rhs.m_pc),
m_intermediate(rhs.m_intermediate) {
RESET() = rhs.RESET(); RESET() = rhs.RESET();
INT() = rhs.INT(); INT() = rhs.INT();
PC() = rhs.PC();
} }
DEFINE_PIN_LEVEL_CHANGERS(RESET, Processor) DEFINE_PIN_LEVEL_CHANGERS(RESET, Processor)
DEFINE_PIN_LEVEL_CHANGERS(INT, Processor) DEFINE_PIN_LEVEL_CHANGERS(INT, Processor)
void EightBit::Processor::handleRESET() { void EightBit::Processor::handleRESET() noexcept {
raiseRESET(); raiseRESET();
} }
void EightBit::Processor::handleINT() { void EightBit::Processor::handleINT() noexcept {
raiseINT(); raiseINT();
} }
void EightBit::Processor::memoryWrite(const register16_t address, const uint8_t data) { void EightBit::Processor::memoryWrite(const register16_t address, const uint8_t data) noexcept {
BUS().ADDRESS() = address; BUS().ADDRESS() = address;
memoryWrite(data); memoryWrite(data);
} }
void EightBit::Processor::memoryWrite(const register16_t address) { void EightBit::Processor::memoryWrite(const register16_t address) noexcept {
BUS().ADDRESS() = address; BUS().ADDRESS() = address;
memoryWrite(); memoryWrite();
} }
void EightBit::Processor::memoryWrite(const uint8_t data) { void EightBit::Processor::memoryWrite(const uint8_t data) noexcept {
BUS().DATA() = data; BUS().DATA() = data;
memoryWrite(); memoryWrite();
} }
void EightBit::Processor::memoryWrite() { void EightBit::Processor::memoryWrite() noexcept {
busWrite(); busWrite();
} }
void EightBit::Processor::busWrite() { void EightBit::Processor::busWrite() noexcept {
BUS().write(); BUS().write();
} }
uint8_t EightBit::Processor::memoryRead(const register16_t address) { uint8_t EightBit::Processor::memoryRead(const register16_t address) noexcept {
BUS().ADDRESS() = address; BUS().ADDRESS() = address;
return memoryRead(); return memoryRead();
} }
uint8_t EightBit::Processor::memoryRead() { uint8_t EightBit::Processor::memoryRead() noexcept {
return busRead(); return busRead();
} }
uint8_t EightBit::Processor::busRead() { uint8_t EightBit::Processor::busRead() noexcept {
return BUS().read(); return BUS().read();
} }
EightBit::register16_t EightBit::Processor::getWordPaged(register16_t address) { EightBit::register16_t EightBit::Processor::getWordPaged(register16_t address) noexcept {
BUS().ADDRESS() = address; BUS().ADDRESS() = address;
return getWordPaged(); return getWordPaged();
} }
EightBit::register16_t EightBit::Processor::getWordPaged(const uint8_t page, const uint8_t offset) { EightBit::register16_t EightBit::Processor::getWordPaged(const uint8_t page, const uint8_t offset) noexcept {
BUS().ADDRESS() = { offset, page }; BUS().ADDRESS() = { offset, page };
return getWordPaged(); return getWordPaged();
} }
void EightBit::Processor::setWordPaged(register16_t address, const register16_t value) { void EightBit::Processor::setWordPaged(register16_t address, const register16_t value) noexcept {
BUS().ADDRESS() = address; BUS().ADDRESS() = address;
setWordPaged(value); setWordPaged(value);
} }
void EightBit::Processor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) { void EightBit::Processor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) noexcept {
BUS().ADDRESS() = { offset, page }; BUS().ADDRESS() = { offset, page };
setWordPaged(value); setWordPaged(value);
} }
EightBit::register16_t& EightBit::Processor::incrementPC() { EightBit::register16_t& EightBit::Processor::incrementPC() noexcept {
PC()++; return ++PC();
return PC();
} }
EightBit::register16_t& EightBit::Processor::decrementPC() { EightBit::register16_t& EightBit::Processor::decrementPC() noexcept {
PC()--; return --PC();
return PC();
} }
void EightBit::Processor::immediateAddress() { void EightBit::Processor::immediateAddress() noexcept {
BUS().ADDRESS() = PC(); BUS().ADDRESS() = PC();
incrementPC(); incrementPC();
} }
uint8_t EightBit::Processor::fetchByte() { uint8_t EightBit::Processor::fetchByte() noexcept {
immediateAddress(); immediateAddress();
return memoryRead(); return memoryRead();
} }
uint8_t EightBit::Processor::fetchInstruction() { uint8_t EightBit::Processor::fetchInstruction() noexcept {
return fetchByte(); return fetchByte();
} }
EightBit::register16_t EightBit::Processor::getWord(const register16_t address) { EightBit::register16_t EightBit::Processor::getWord(const register16_t address) noexcept {
BUS().ADDRESS() = address; BUS().ADDRESS() = address;
return getWord(); return getWord();
} }
void EightBit::Processor::setWord(const register16_t address, const register16_t value) { void EightBit::Processor::setWord(const register16_t address, const register16_t value) noexcept {
BUS().ADDRESS() = address; BUS().ADDRESS() = address;
setWord(value); setWord(value);
} }
@@ -120,7 +120,7 @@ int EightBit::Processor::step() noexcept {
if (LIKELY(powered())) if (LIKELY(powered()))
poweredStep(); poweredStep();
ExecutedInstruction.fire(); ExecutedInstruction.fire();
ASSUME(cycles() > 0); // ASSUME(cycles() > 0); Not if unpowered!!
return cycles(); return cycles();
} }
@@ -141,15 +141,15 @@ void EightBit::Processor::jump(const register16_t destination) noexcept {
} }
void EightBit::Processor::jump(const uint16_t destination) noexcept { void EightBit::Processor::jump(const uint16_t destination) noexcept {
PC().word = destination; PC() = destination;
} }
void EightBit::Processor::call(const register16_t destination) { void EightBit::Processor::call(const register16_t destination) noexcept {
pushWord(PC()); pushWord(PC());
jump(destination); jump(destination);
} }
void EightBit::Processor::ret() { void EightBit::Processor::ret() noexcept {
jump(popWord()); jump(popWord());
} }
+3 -3
View File
@@ -3,7 +3,7 @@
#include <iostream> #include <iostream>
bool EightBit::Rom::operator==(const Rom& rhs) const { bool EightBit::Rom::operator==(const Rom& rhs) const noexcept {
return BYTES() == rhs.BYTES(); return BYTES() == rhs.BYTES();
} }
@@ -48,10 +48,10 @@ void EightBit::Rom::poke(const uint16_t address, const uint8_t value) noexcept {
EightBit::Rom::Rom(const size_t size) noexcept EightBit::Rom::Rom(const size_t size) noexcept
: m_bytes(size) {} : m_bytes(size) {}
EightBit::Rom::Rom(const Rom& rhs) EightBit::Rom::Rom(const Rom& rhs) noexcept
: m_bytes(rhs.m_bytes) {} : m_bytes(rhs.m_bytes) {}
EightBit::Rom& EightBit::Rom::operator=(const Rom& rhs) { EightBit::Rom& EightBit::Rom::operator=(const Rom& rhs) noexcept {
if (this != &rhs) if (this != &rhs)
m_bytes = rhs.m_bytes; m_bytes = rhs.m_bytes;
return *this; return *this;