First stage of syncing to .net implementation. Pretty shakey, but test_Z80 runs

This commit is contained in:
Adrian Conlon committed 2026-05-22 21:42:05 +01:00
1 parent 43f1ec55a1
commit 6bec1d473d
59 files changed
+1049 -967

No files matched your search

+1 -1
View File
@@ -12,7 +12,7 @@
namespace EightBit {
class Disassembler {
public:
Disassembler(Bus& bus) noexcept;
Disassembler(Bus& bus);
static std::string state(Intel8080& cpu);
std::string disassemble(Intel8080& cpu);
+92 -120
View File
@@ -15,7 +15,7 @@
namespace EightBit {
class Intel8080 final : public IntelProcessor {
public:
DECLARE_PIN_OUTPUT(DBIN) // Active high
DECLARE_PIN_OUTPUT(DBIN) // Active high
DECLARE_PIN_OUTPUT(WR) // Active low
public:
@@ -29,36 +29,30 @@ namespace EightBit {
Intel8080(Bus& bus);
Signal<Intel8080> ExecutingInstruction;
Signal<Intel8080> ExecutedInstruction;
void execute() noexcept final;
int step() noexcept final;
void poweredStep() noexcept final;
[[nodiscard]] const register16_t& AF() const noexcept final;
[[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); }
[[nodiscard]] const register16_t& BC() const noexcept final;
[[nodiscard]] auto& BC() noexcept { return IntelProcessor::BC(); }
[[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]] register16_t& AF() noexcept final;
[[nodiscard]] register16_t& BC() noexcept final;
[[nodiscard]] register16_t& DE() noexcept final;
[[nodiscard]] register16_t& HL() noexcept final;
[[nodiscard]] bool requestingIO() noexcept { return m_requestIO; }
[[nodiscard]] bool requestingMemory() noexcept { return m_requestMemory; }
[[nodiscard]] constexpr bool requestingIO() const noexcept { return m_requestIO; }
[[nodiscard]] constexpr bool requestingMemory() const noexcept { return m_requestMemory; }
[[nodiscard]] bool requestingRead() noexcept { return raised(DBIN()); }
[[nodiscard]] bool requestingWrite() noexcept { return lowered(WR()); }
[[nodiscard]] constexpr bool requestingRead() const noexcept { return raised(DBIN()); }
[[nodiscard]] constexpr bool requestingWrite() const noexcept { return lowered(WR()); }
protected:
void handleRESET() noexcept final;
void handleINT() noexcept final;
void memoryUpdate(int ticks = 1) noexcept;
void memoryWrite() noexcept final;
uint8_t memoryRead() noexcept final;
void busWrite() noexcept final;
uint8_t busRead() noexcept final;
//void busWrite() noexcept final;
//uint8_t busRead() noexcept final;
private:
bool m_requestIO = false;
@@ -66,122 +60,100 @@ namespace EightBit {
bool m_interruptEnable = false;
register16_t af;
register16_t bc = Mask16;
register16_t de = Mask16;
register16_t hl = Mask16;
register16_t m_af;
register16_t m_bc = Mask16;
register16_t m_de = Mask16;
register16_t m_hl = Mask16;
auto R(const int r) {
switch (r) {
case 0b000:
return B();
case 0b001:
return C();
case 0b010:
return D();
case 0b011:
return E();
case 0b100:
return H();
case 0b101:
return L();
case 0b110:
return IntelProcessor::memoryRead(HL());
case 0b111:
return A();
default:
UNREACHABLE;
}
uint8_t R(int r);
void R(int r, uint8_t value);
register16_t& RP(int rp);
register16_t& RP2(int rp);
[[nodiscard]] static constexpr auto zeroTest(uint8_t data) noexcept { return data & ZF; }
[[nodiscard]] static constexpr auto carryTest(uint8_t data) noexcept { return data & CF; }
[[nodiscard]] static constexpr auto parityTest(uint8_t data) noexcept { return data & PF; }
[[nodiscard]] static constexpr auto signTest(uint8_t data) noexcept { return data & SF; }
[[nodiscard]] static constexpr auto auxiliaryCarryTest(uint8_t data) noexcept { return data & AC; }
[[nodiscard]] constexpr auto zero() noexcept { return zeroTest(F()); }
[[nodiscard]] constexpr auto carry() noexcept { return carryTest(F()); }
[[nodiscard]] constexpr auto parity() noexcept { return parityTest(F()); }
[[nodiscard]] constexpr auto sign() noexcept { return signTest(F()); }
[[nodiscard]] constexpr auto auxiliaryCarry() noexcept { return auxiliaryCarryTest(F()); }
void adjustStatusFlags(uint8_t value) noexcept { F() = value; }
void setBit(StatusBits flag) noexcept { return adjustStatusFlags(setBit(F(), flag)); }
void setBit(int flag) noexcept { return setBit((StatusBits)flag); }
[[nodiscard]] static constexpr uint8_t setBit(uint8_t f, StatusBits flag) noexcept { return Chip::setBit(f, (uint8_t)flag); }
void setBit(StatusBits flag, int condition) noexcept { adjustStatusFlags(Chip::setBit(F(), flag, condition)); }
[[nodiscard]] static constexpr uint8_t setBit(uint8_t f, StatusBits flag, int condition) noexcept { return Chip::setBit(f, (uint8_t)flag, condition); }
void setBit(StatusBits flag, bool condition) noexcept { adjustStatusFlags(setBit(F(), flag, condition)); }
void setBit(int flag, bool condition) noexcept { setBit((StatusBits)flag, condition); }
[[nodiscard]] static constexpr uint8_t setBit(uint8_t f, StatusBits flag, bool condition) noexcept { return Chip::setBit(f, (uint8_t)flag, condition); }
void clearBit(StatusBits flag) noexcept { adjustStatusFlags(clearBit(F(), flag)); }
void clearBit(int flag) noexcept { clearBit((StatusBits)flag); }
[[nodiscard]] static constexpr uint8_t clearBit(uint8_t f, StatusBits flag) noexcept { return Chip::clearBit(f, (uint8_t)flag); }
void clearBit(StatusBits flag, int condition) noexcept { adjustStatusFlags(clearBit(F(), flag, condition)); }
[[nodiscard]] static constexpr uint8_t clearBit(uint8_t f, StatusBits flag, int condition) noexcept { return Chip::clearBit(f, (uint8_t)flag, condition); }
void adjustSign(uint8_t value) noexcept { adjustStatusFlags(adjustSign(F(), value)); }
[[nodiscard]] static constexpr uint8_t adjustSign(uint8_t input, uint8_t value) noexcept { return setBit(input, SF, signTest(value)); }
void adjustZero(uint8_t value) noexcept { adjustStatusFlags(adjustZero(F(), value)); }
[[nodiscard]] static constexpr uint8_t adjustZero(uint8_t input, uint8_t value) noexcept { return clearBit(input, ZF, value); }
void adjustParity(uint8_t value) noexcept { adjustStatusFlags(adjustParity(F(), value)); }
[[nodiscard]] static constexpr uint8_t adjustParity(uint8_t input, uint8_t value) noexcept { return setBit(input, PF, evenParity(value)); }
void adjustSZ(uint8_t value) noexcept { adjustStatusFlags(adjustSZ(F(), value)); }
[[nodiscard]] static constexpr uint8_t adjustSZ(uint8_t input, uint8_t value) noexcept {
input = adjustSign(input, value);
return adjustZero(input, value);
}
void R(int r, const uint8_t value) {
switch (r) {
case 0b000:
B() = value;
break;
case 0b001:
C() = value;
break;
case 0b010:
D() = value;
break;
case 0b011:
E() = value;
break;
case 0b100:
H() = value;
break;
case 0b101:
L() = value;
break;
case 0b110:
IntelProcessor::memoryWrite(HL(), value);
break;
case 0b111:
A() = value;
break;
default:
UNREACHABLE;
}
void adjustSZP(uint8_t value) noexcept { adjustStatusFlags(adjustSZP(F(), value)); }
[[nodiscard]] static constexpr uint8_t adjustSZP(uint8_t input, uint8_t value) noexcept {
input = adjustSZ(input, value);
return adjustParity(input, value);
}
auto& RP(const int rp) {
switch (rp) {
case 0b00:
return BC();
case 0b01:
return DE();
case 0b10:
return HL();
case 0b11:
return SP();
default:
UNREACHABLE;
}
[[nodiscard]] static constexpr auto adjustAuxilliaryCarryAdd(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept {
return setBit(f, AC, calculateHalfCarryAdd(before, value, calculation));
}
auto& RP2(const int rp) {
switch (rp) {
case 0b00:
return BC();
case 0b01:
return DE();
case 0b10:
return HL();
case 0b11:
return AF();
default:
UNREACHABLE;
}
void adjustAuxiliaryCarryAdd(uint8_t before, uint8_t value, int calculation) noexcept {
adjustStatusFlags(adjustAuxilliaryCarryAdd(F(), before, value, calculation));
}
static void adjustAuxiliaryCarryAdd(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
f = setBit(f, AC, calculateHalfCarryAdd(before, value, calculation));
[[nodiscard]] static constexpr auto adjustAuxiliaryCarrySub(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept {
return setBit(f, AC, calculateHalfCarrySub(before, value, calculation));
}
static void adjustAuxiliaryCarrySub(uint8_t& f, uint8_t before, uint8_t value, int calculation) {
f = clearBit(f, AC, calculateHalfCarrySub(before, value, calculation));
void adjustAuxiliaryCarrySub(uint8_t before, uint8_t value, int calculation) noexcept {
adjustStatusFlags(adjustAuxiliaryCarrySub(F(), before, value, calculation));
}
void subtract(uint8_t& operand, uint8_t value, int carry = 0);
[[nodiscard]] bool convertCondition(int flag) noexcept final;
void execute(int x, int y, int z, int p, int q);
void increment(uint8_t& operand);
void decrement(uint8_t& operand);
[[nodiscard]] uint8_t increment(uint8_t operand);
[[nodiscard]] uint8_t decrement(uint8_t operand);
void di();
void ei();
int returnConditionalFlag(int flag);
int jumpConditionalFlag(int flag);
int callConditionalFlag(int flag);
void disableInterrupts() noexcept final;
void enableInterrupts() noexcept final;
void add(register16_t value);
void add(uint8_t value, int carry = 0);
void adc(uint8_t value);
void sub(uint8_t value, int carry = 0) noexcept;
uint8_t subtract(uint8_t value, int carry = 0);
void sbb(uint8_t value);
void andr(uint8_t value);
void xorr(uint8_t value);
void orr(uint8_t value);
@@ -206,14 +178,14 @@ namespace EightBit {
uint8_t portRead(uint8_t port);
uint8_t portRead();
void requestIO() noexcept { assert(!requestingMemory()); m_requestIO = true; }
void releaseIO() noexcept { m_requestIO = false; }
void requestMemory() noexcept { assert(!requestingIO()); m_requestMemory = true; }
void releaseMemory() noexcept { m_requestMemory = false; }
constexpr void requestIO() noexcept { assert(!requestingMemory()); m_requestIO = true; }
constexpr void releaseIO() noexcept { m_requestIO = false; }
constexpr void requestMemory() noexcept { assert(!requestingIO()); m_requestMemory = true; }
constexpr void releaseMemory() noexcept { m_requestMemory = false; }
void requestRead() { raise(DBIN()); }
void releaseRead() { lower(DBIN()); }
void requestWrite() { lower(WR()); }
void releaseWrite() { raise(WR()); }
constexpr void requestRead() noexcept { raise(DBIN()); }
constexpr void releaseRead() noexcept { lower(DBIN()); }
constexpr void requestWrite() noexcept { lower(WR()); }
constexpr void releaseWrite() noexcept { raise(WR()); }
};
}
+2 -2
View File
@@ -6,7 +6,7 @@
#include <iomanip>
#include <bitset>
EightBit::Disassembler::Disassembler(Bus& bus) noexcept
EightBit::Disassembler::Disassembler(Bus& bus)
: m_bus(bus) {
// Disable exceptions where too many format arguments are available
m_formatter.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
@@ -177,7 +177,7 @@ std::string EightBit::Disassembler::disassemble(Intel8080& cpu, uint16_t pc) {
auto q = (y & 1);
auto immediate = BUS().peek(pc + 1);
auto absolute = cpu.peekWord(pc + 1).word;
auto absolute = cpu.peekShort(pc + 1).word;
auto displacement = (int8_t)immediate;
auto relative = pc + displacement + 2;
auto indexedImmediate = BUS().peek(pc + 1);
+195 -169
View File
@@ -12,29 +12,28 @@ EightBit::Intel8080::Intel8080(Bus& bus)
releaseRead();
releaseWrite();
di();
disableInterrupts();
});
}
DEFINE_PIN_LEVEL_CHANGERS(DBIN, Intel8080);
DEFINE_PIN_LEVEL_CHANGERS(WR, Intel8080);
const EightBit::register16_t& EightBit::Intel8080::AF() const noexcept {
auto* processor = const_cast<Intel8080*>(this);
processor->af.low = (af.low | Bit1) & ~(Bit5 | Bit3);
return af;
EightBit::register16_t& EightBit::Intel8080::AF() noexcept {
m_af.low = (m_af.low | Bit1) & ~(Bit5 | Bit3);
return m_af;
}
const EightBit::register16_t& EightBit::Intel8080::BC() const noexcept {
return bc;
EightBit::register16_t& EightBit::Intel8080::BC() noexcept {
return m_bc;
}
const EightBit::register16_t& EightBit::Intel8080::DE() const noexcept {
return de;
EightBit::register16_t& EightBit::Intel8080::DE() noexcept {
return m_de;
}
const EightBit::register16_t& EightBit::Intel8080::HL() const noexcept {
return hl;
EightBit::register16_t& EightBit::Intel8080::HL() noexcept {
return m_hl;
}
void EightBit::Intel8080::memoryWrite() noexcept {
@@ -65,101 +64,138 @@ uint8_t EightBit::Intel8080::busRead() noexcept {
void EightBit::Intel8080::handleRESET() noexcept {
IntelProcessor::handleRESET();
di();
tick(3);
disableInterrupts();
}
void EightBit::Intel8080::handleINT() noexcept {
IntelProcessor::handleINT();
raiseHALT();
if (m_interruptEnable) {
di();
Processor::execute(BUS().DATA());
}
Processor::execute(BUS().DATA());
}
void EightBit::Intel8080::di() {
void EightBit::Intel8080::disableInterrupts() noexcept {
m_interruptEnable = false;
}
void EightBit::Intel8080::ei() {
void EightBit::Intel8080::enableInterrupts() noexcept {
m_interruptEnable = true;
}
void EightBit::Intel8080::increment(uint8_t& operand) {
F() = adjustSZP<Intel8080>(F(), ++operand);
F() = clearBit(F(), AC, lowNibble(operand));
}
void EightBit::Intel8080::decrement(uint8_t& operand) {
F() = adjustSZP<Intel8080>(F(), --operand);
F() = setBit(F(), AC, lowNibble(operand) != Mask4);
}
int EightBit::Intel8080::jumpConditionalFlag(const int flag) {
switch (flag) {
case 0: // NZ
return jumpConditional(!(F() & ZF));
case 1: // Z
return jumpConditional(F() & ZF);
case 2: // NC
return jumpConditional(!(F() & CF));
case 3: // C
return jumpConditional(F() & CF);
case 4: // PO
return jumpConditional(!(F() & PF));
case 5: // PE
return jumpConditional(F() & PF);
case 6: // P
return jumpConditional(!(F() & SF));
case 7: // M
return jumpConditional(F() & SF);
uint8_t EightBit::Intel8080::R(const int r) {
switch (r) {
case 0b000:
return B();
case 0b001:
return C();
case 0b010:
return D();
case 0b011:
return E();
case 0b100:
return H();
case 0b101:
return L();
case 0b110:
return IntelProcessor::memoryRead(HL());
case 0b111:
return A();
default:
UNREACHABLE;
}
}
int EightBit::Intel8080::returnConditionalFlag(const int flag) {
switch (flag) {
case 0: // NZ
return returnConditional(!(F() & ZF));
case 1: // Z
return returnConditional(F() & ZF);
case 2: // NC
return returnConditional(!(F() & CF));
case 3: // C
return returnConditional(F() & CF);
case 4: // PO
return returnConditional(!(F() & PF));
case 5: // PE
return returnConditional(F() & PF);
case 6: // P
return returnConditional(!(F() & SF));
case 7: // M
return returnConditional(F() & SF);
void EightBit::Intel8080::R(int r, const uint8_t value) {
switch (r) {
case 0b000:
B() = value;
break;
case 0b001:
C() = value;
break;
case 0b010:
D() = value;
break;
case 0b011:
E() = value;
break;
case 0b100:
H() = value;
break;
case 0b101:
L() = value;
break;
case 0b110:
IntelProcessor::memoryWrite(HL(), value);
break;
case 0b111:
A() = value;
break;
default:
UNREACHABLE;
}
}
int EightBit::Intel8080::callConditionalFlag(const int flag) {
EightBit::register16_t& EightBit::Intel8080::RP(const int rp) {
switch (rp) {
case 0b00:
return BC();
case 0b01:
return DE();
case 0b10:
return HL();
case 0b11:
return SP();
default:
UNREACHABLE;
}
}
EightBit::register16_t& EightBit::Intel8080::RP2(const int rp) {
switch (rp) {
case 0b00:
return BC();
case 0b01:
return DE();
case 0b10:
return HL();
case 0b11:
return AF();
default:
UNREACHABLE;
}
}
uint8_t EightBit::Intel8080::increment(uint8_t operand) {
const uint8_t result = operand + 1;
adjustSZP(result);
clearBit(AC, lowNibble(result));
return result;
}
uint8_t EightBit::Intel8080::decrement(uint8_t operand) {
const uint8_t result = operand - 1;
adjustSZP(result);
setBit(AC, lowNibble(result) != Mask4);
return result;
}
bool EightBit::Intel8080::convertCondition(int flag) noexcept {
switch (flag) {
case 0: // NZ
return callConditional(!(F() & ZF));
case 1: // Z
return callConditional(F() & ZF);
case 2: // NC
return callConditional(!(F() & CF));
case 3: // C
return callConditional(F() & CF);
case 4: // PO
return callConditional(!(F() & PF));
case 5: // PE
return callConditional(F() & PF);
case 6: // P
return callConditional(!(F() & SF));
case 7: // M
return callConditional(F() & SF);
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;
}
@@ -175,53 +211,59 @@ void EightBit::Intel8080::add(const uint8_t value, const int carry) {
const register16_t result = A() + value + carry;
adjustAuxiliaryCarryAdd(F(), A(), value, result.word);
adjustAuxiliaryCarryAdd(A(), value, result.word);
A() = result.low;
F() = setBit(F(), CF, result.word & Bit8);
F() = adjustSZP<Intel8080>(F(), A());
setBit(CF, result.word & Bit8);
adjustSZP(A());
}
void EightBit::Intel8080::adc(const uint8_t value) {
add(value, F() & CF);
add(value, carry());
}
void EightBit::Intel8080::subtract(uint8_t& operand, const uint8_t value, const int carry) {
uint8_t EightBit::Intel8080::subtract(const uint8_t value, const int carry) {
const register16_t result = operand - value - carry;
const auto operand = A();
adjustAuxiliaryCarrySub(F(), operand, value, result.word);
const register16_t subtraction = operand - value - carry;
const auto result = subtraction.low;
operand = result.low;
adjustAuxiliaryCarrySub(operand, value, subtraction.word);
F() = setBit(F(), CF, result.word & Bit8);
F() = adjustSZP<Intel8080>(F(), operand);
setBit(CF, subtraction.word & Bit8);
adjustSZP(operand);
return result;
}
void EightBit::Intel8080::sub(uint8_t value, int carry) noexcept {
A() = subtract(value, carry);
}
void EightBit::Intel8080::sbb(const uint8_t value) {
subtract(A(), value, F() & CF);
sub(value, carry());
}
void EightBit::Intel8080::andr(const uint8_t value) {
F() = setBit(F(), AC, (A() | value) & Bit3);
F() = clearBit(F(), CF);
F() = adjustSZP<Intel8080>(F(), A() &= value);
setBit(AC, (A() | value) & Bit3);
clearBit(CF);
adjustSZP(A() &= value);
}
void EightBit::Intel8080::xorr(const uint8_t value) {
F() = clearBit(F(), AC | CF);
F() = adjustSZP<Intel8080>(F(), A() ^= value);
clearBit(AC | CF);
adjustSZP(A() ^= value);
}
void EightBit::Intel8080::orr(const uint8_t value) {
F() = clearBit(F(), AC | CF);
F() = adjustSZP<Intel8080>(F(), A() |= value);
clearBit(AC | CF);
adjustSZP(A() |= value);
}
void EightBit::Intel8080::compare(const uint8_t value) {
auto original = A();
subtract(original, value);
subtract(value);
}
void EightBit::Intel8080::rlc() {
@@ -237,22 +279,22 @@ void EightBit::Intel8080::rrc() {
}
void EightBit::Intel8080::rl() {
const auto carry = F() & CF;
const auto carrying = carry();
F() = setBit(F(), CF, A() & Bit7);
A() = (A() << 1) | carry;
A() = (A() << 1) | carrying;
}
void EightBit::Intel8080::rr() {
const auto carry = F() & CF;
const auto carrying = carry();
F() = setBit(F(), CF, A() & Bit0);
A() = (A() >> 1) | (carry << 7);
A() = (A() >> 1) | (carrying << 7);
}
void EightBit::Intel8080::daa() {
const auto& before = A();
auto carry = F() & CF;
uint8_t addition = 0;
if ((F() & AC) || lowNibble(before) > 9) {
if (auxiliaryCarry() || lowNibble(before) > 9) {
addition = 0x6;
}
if ((F() & CF) || highNibble(before) > 9 || (highNibble(before) >= 9 && lowNibble(before) > 9)) {
@@ -279,11 +321,14 @@ void EightBit::Intel8080::xhtl(register16_t& exchange) {
MEMPTR().low = IntelProcessor::memoryRead(SP());
++BUS().ADDRESS();
MEMPTR().high = memoryRead();
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();
tick(2);
}
void EightBit::Intel8080::portWrite(const uint8_t port) {
@@ -310,23 +355,18 @@ uint8_t EightBit::Intel8080::portRead() {
return returned;
}
int EightBit::Intel8080::step() noexcept {
ExecutingInstruction.fire(*this);
resetCycles();
if (LIKELY(powered())) {
if (UNLIKELY(lowered(RESET()))) {
handleRESET();
} else if (UNLIKELY(lowered(INT()))) {
void EightBit::Intel8080::poweredStep() noexcept {
if (UNLIKELY(lowered(RESET()))) {
handleRESET();
} else if (UNLIKELY(lowered(INT()))) {
if (m_interruptEnable) {
handleINT();
} else if (UNLIKELY(lowered(HALT()))) {
Processor::execute(0); // NOP
} else {
Processor::execute(fetchByte());
}
} else if (UNLIKELY(lowered(HALT()))) {
Processor::execute(0); // NOP
} else {
Processor::execute(fetchByte());
}
ExecutedInstruction.fire(*this);
ASSUME(cycles() > 0);
return cycles();
}
void EightBit::Intel8080::execute() noexcept {
@@ -406,7 +446,7 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
break;
case 2: // LD HL,(nn)
BUS().ADDRESS() = fetchWord();
HL() = getWord();
HL() = getShort();
tick(16);
break;
case 3: // LD A,(nn)
@@ -437,14 +477,12 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
break;
case 4: { // 8-bit INC
auto operand = R(y);
increment(operand);
R(y, operand);
R(y, increment(operand));
tick(4);
break;
} case 5: { // 8-bit DEC
auto operand = R(y);
decrement(operand);
R(y, operand);
R(y, decrement(operand));
tick(4);
if (UNLIKELY(y == 6))
tick(7);
@@ -500,45 +538,42 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
}
tick(4);
break;
case 2: // Operate on accumulator and register/memory location
case 2: { // Operate on accumulator and register/memory location
const auto value = R(z);
switch (y) {
case 0: // ADD A,r
add(R(z));
add(value);
break;
case 1: // ADC A,r
adc(R(z));
adc(value);
break;
case 2: // SUB r
subtract(A(), R(z));
sub(value);
break;
case 3: // SBC A,r
sbb(R(z));
sbb(value);
break;
case 4: // AND r
andr(R(z));
andr(value);
break;
case 5: // XOR r
xorr(R(z));
xorr(value);
break;
case 6: // OR r
orr(R(z));
orr(value);
break;
case 7: // CP r
compare(R(z));
compare(value);
break;
default:
UNREACHABLE;
}
tick(4);
if (UNLIKELY(z == 6))
tick(3);
break;
}
case 3:
switch (z) {
case 0: // Conditional return
if (returnConditionalFlag(y))
tick(6);
tick(5);
returnConditionalFlag(y);
break;
case 1: // POP & various ops
switch (q) {
@@ -553,8 +588,7 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
tick(10);
break;
case 2: // JP HL
jump(HL());
tick(4);
Processor::jump(HL());
break;
case 3: // LD SP,HL
SP() = HL();
@@ -568,17 +602,14 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
break;
case 2: // Conditional jump
jumpConditionalFlag(y);
tick(10);
break;
case 3: // Assorted operations
switch (y) {
case 0: // JP nn
jump(fetchWord());
tick(10);
Processor::jump(fetchWord());
break;
case 2: // OUT (n),A
portWrite(fetchByte());
tick(11);
break;
case 3: // IN A,(n)
A() = portRead(fetchByte());
@@ -586,26 +617,20 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
break;
case 4: // EX (SP),HL
xhtl(HL());
tick(19);
break;
case 5: // EX DE,HL
std::swap(DE(), HL());
tick(4);
break;
case 6: // DI
di();
tick(4);
disableInterrupts();
break;
case 7: // EI
ei();
tick(4);
enableInterrupts();
break;
}
break;
case 4: // Conditional call: CALL cc[y], nn
if (callConditionalFlag(y))
tick(7);
tick(10);
callConditionalFlag(y);
break;
case 5: // PUSH & various ops
switch (q) {
@@ -625,37 +650,38 @@ void EightBit::Intel8080::execute(const int x, const int y, const int z, const i
UNREACHABLE;
}
break;
case 6: // Operate on accumulator and immediate operand: alu[y] n
case 6: { // Operate on accumulator and immediate operand: alu[y] n
const auto operand = fetchByte();
switch (y) {
case 0: // ADD A,n
add(fetchByte());
add(operand);
break;
case 1: // ADC A,n
adc(fetchByte());
adc(operand);
break;
case 2: // SUB n
subtract(A(), fetchByte());
sub(operand);
break;
case 3: // SBC A,n
sbb(fetchByte());
sbb(operand);
break;
case 4: // AND n
andr(fetchByte());
andr(operand);
break;
case 5: // XOR n
xorr(fetchByte());
xorr(operand);
break;
case 6: // OR n
orr(fetchByte());
orr(operand);
break;
case 7: // CP n
compare(fetchByte());
compare(operand);
break;
default:
UNREACHABLE;
}
tick(7);
break;
}
case 7: // Restart: RST y * 8
restart(y << 3);
tick(11);
+7 -7
View File
@@ -22,7 +22,7 @@ void Board::lowerPOWER() noexcept {
EightBit::Bus::lowerPOWER();
}
void Board::initialise() {
void Board::initialise() noexcept {
auto romDirectory = m_configuration.getRomDirectory();
@@ -46,13 +46,13 @@ void Board::initialise() {
}
poke(0, 0xc3); // JMP
CPU().pokeWord(1, m_configuration.getStartAddress());
CPU().pokeShort(1, m_configuration.getStartAddress());
poke(5, 0xc9); // ret
}
void Board::Cpu_ExecutingInstruction_Cpm(EightBit::Intel8080& cpu) {
switch (cpu.PC().word) {
void Board::Cpu_ExecutingInstruction_Cpm(EightBit::EventArgs&) {
switch (CPU().PC().word) {
case 0x0: // CP/M warm start
if (++m_warmstartCount == 2) {
lowerPOWER();
@@ -84,15 +84,15 @@ void Board::bdos() {
}
}
void Board::Cpu_ExecutingInstruction_Profile(EightBit::Intel8080& cpu) {
void Board::Cpu_ExecutingInstruction_Profile(EightBit::EventArgs&) {
const auto pc = cpu.PC();
const auto pc = CPU().PC();
m_profiler.addAddress(pc.word);
m_profiler.addInstruction(peek(pc.word));
}
void Board::Cpu_ExecutingInstruction_Debug(const EightBit::Intel8080& cpu) {
void Board::Cpu_ExecutingInstruction_Debug(const EightBit::EventArgs&) {
const std::string disassembled =
EightBit::Disassembler::state(CPU()) + '\t' + m_disassembler.disassemble(CPU()) + '\n';
std::cerr << disassembled;
+4 -4
View File
@@ -20,7 +20,7 @@ public:
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
virtual void initialise() final;
virtual void initialise() noexcept final;
protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
@@ -36,10 +36,10 @@ private:
EightBit::Profiler m_profiler;
int m_warmstartCount = 0;
void Cpu_ExecutingInstruction_Cpm(EightBit::Intel8080& cpu);
void Cpu_ExecutingInstruction_Cpm(EightBit::EventArgs&);
void Cpu_ExecutingInstruction_Debug(const EightBit::Intel8080& cpu);
void Cpu_ExecutingInstruction_Profile(EightBit::Intel8080& cpu);
void Cpu_ExecutingInstruction_Debug(const EightBit::EventArgs&);
void Cpu_ExecutingInstruction_Profile(EightBit::EventArgs&);
void bdos();
};
+1 -1
View File
@@ -23,7 +23,7 @@ void Fuse::TestRunner::lowerPOWER() noexcept {
EightBit::Bus::lowerPOWER();
}
void Fuse::TestRunner::initialise() {
void Fuse::TestRunner::initialise() noexcept {
disableGameRom();
}
+1 -1
View File
@@ -49,6 +49,6 @@ namespace Fuse {
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
void initialise();
void initialise() noexcept;
};
}
+1 -1
View File
@@ -17,7 +17,7 @@ namespace EightBit {
AbstractColourPalette() = default;
[[nodiscard]] auto colour(size_t index) const noexcept {
[[nodiscard]] auto colour(size_t index) const {
assert(index < m_colours.size());
return m_colours[index];
}
+2 -2
View File
@@ -10,9 +10,9 @@ namespace EightBit {
namespace GameBoy {
class CharacterDefinition final {
public:
CharacterDefinition(Ram& vram, uint16_t address) noexcept;
CharacterDefinition(Ram& vram, uint16_t address);
[[nodiscard]] std::array<int, 8> get(int row) const noexcept;
[[nodiscard]] std::array<int, 8> get(int row) const;
private:
Ram& m_vram;
+2 -2
View File
@@ -15,7 +15,7 @@ namespace EightBit {
class Disassembler {
public:
Disassembler(Bus& bus) noexcept;
Disassembler(Bus& bus);
static std::string state(LR35902& cpu);
std::string disassemble(LR35902& cpu);
@@ -71,7 +71,7 @@ namespace EightBit {
static std::string cc(int flag);
static std::string alu(int which);
Bus& BUS() noexcept { return m_bus; }
Bus& BUS() { return m_bus; }
};
}
}
+12 -12
View File
@@ -27,12 +27,12 @@ namespace EightBit {
PixelCount = RasterWidth * RasterHeight,
};
Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram) noexcept;
Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram);
[[nodiscard]] const auto& pixels() const noexcept { return m_pixels; }
[[nodiscard]] const auto& pixels() const { return m_pixels; }
void renderCurrentScanline() noexcept;
void loadObjectAttributes() noexcept;
void renderCurrentScanline();
void loadObjectAttributes();
private:
enum class tile_offset_t {
@@ -48,42 +48,42 @@ namespace EightBit {
uint8_t m_control = 0;
uint8_t m_scanLine = 0;
[[nodiscard]] std::array<int, 4> createPalette(int address) noexcept;
[[nodiscard]] std::array<int, 4> createPalette(int address);
void renderBackground() noexcept;
void renderBackground();
void renderBackground(
int bgArea, int bgCharacters,
tile_offset_t offsetType,
int offsetX, int offsetY,
const std::array<int, 4>& palette) noexcept;
const std::array<int, 4>& palette);
void renderBackgroundTile(
int definitionOffset,
int row, int column,
int bgCharacters, tile_offset_t offsetType,
int offsetX, int offsetY,
const std::array<int, 4>& palette) noexcept;
const std::array<int, 4>& palette);
void renderObjects() noexcept;
void renderObjects();
void renderSpriteTile(
int height,
int drawX, int drawY,
bool flipX, bool flipY,
const std::array<int, 4>& palette,
const CharacterDefinition& definition) noexcept;
const CharacterDefinition& definition);
void renderBackgroundTile(
int drawX, int drawY,
const std::array<int, 4>& palette,
const CharacterDefinition& definition) noexcept;
const CharacterDefinition& definition);
void renderTile(
int height,
int drawX, int drawY,
bool flipX, bool flipY, bool allowTransparencies,
const std::array<int, 4>& palette,
const CharacterDefinition& definition) noexcept;
const CharacterDefinition& definition);
};
}
}
+10 -10
View File
@@ -34,23 +34,23 @@ namespace EightBit {
RomPageSize = 0x4000
};
Bus() noexcept;
Bus();
void raisePOWER() noexcept override;
void lowerPOWER() noexcept override;
[[nodiscard]] auto& CPU() noexcept { return m_cpu; }
[[nodiscard]] auto& VRAM() noexcept { return m_videoRam; }
[[nodiscard]] auto& OAMRAM() noexcept { return m_oamRam; }
[[nodiscard]] auto& IO() noexcept { return m_ioPorts; }
[[nodiscard]] auto& CPU() { return m_cpu; }
[[nodiscard]] auto& VRAM() { return m_videoRam; }
[[nodiscard]] auto& OAMRAM() { return m_oamRam; }
[[nodiscard]] auto& IO() { return m_ioPorts; }
void reset();
void disableGameRom() noexcept { m_disableGameRom = true; }
void enableGameRom() noexcept { m_disableGameRom = false; }
void disableGameRom() { m_disableGameRom = true; }
void enableGameRom() { m_disableGameRom = false; }
[[nodiscard]] bool gameRomDisabled() const noexcept { return m_disableGameRom; }
[[nodiscard]] bool gameRomEnabled() const noexcept { return !gameRomDisabled(); }
[[nodiscard]] bool gameRomDisabled() const { return m_disableGameRom; }
[[nodiscard]] bool gameRomEnabled() const { return !gameRomDisabled(); }
void loadBootRom(std::string path);
void loadGameRom(std::string path);
@@ -94,7 +94,7 @@ namespace EightBit {
void validateCartridgeType();
void Bus_WrittenByte(EightBit::EventArgs) noexcept;
void Bus_WrittenByte(EightBit::EventArgs);
void runRasterLines(int lines);
void runVerticalBlankLines(int lines);
+12 -12
View File
@@ -133,35 +133,35 @@ namespace EightBit {
void updateLcdStatusMode(int mode);
void disableBootRom() noexcept { m_disableBootRom = true; }
void enableBootRom() noexcept { m_disableBootRom = false; }
void disableBootRom() { m_disableBootRom = true; }
void enableBootRom() { m_disableBootRom = false; }
auto bootRomDisabled() const noexcept { return m_disableBootRom; }
auto bootRomEnabled() const noexcept { return !bootRomDisabled(); }
auto bootRomDisabled() const { return m_disableBootRom; }
auto bootRomEnabled() const { return !bootRomDisabled(); }
void pressRight() { m_p14 = m_p10 = false; triggerKeypadInterrupt(); }
void releaseRight() noexcept { m_p14 = m_p10 = true; }
void releaseRight() { m_p14 = m_p10 = true; }
void pressLeft() { m_p14 = m_p11 = false, triggerKeypadInterrupt(); }
void releaseLeft() noexcept { m_p14 = m_p11 = true; }
void releaseLeft() { m_p14 = m_p11 = true; }
void pressUp() { m_p14 = m_p12 = false, triggerKeypadInterrupt(); }
void releaseUp() noexcept { m_p14 = m_p12 = true; }
void releaseUp() { m_p14 = m_p12 = true; }
void pressDown() { m_p14 = m_p13 = false, triggerKeypadInterrupt(); }
void releaseDown() noexcept { m_p14 = m_p13 = true; }
void releaseDown() { m_p14 = m_p13 = true; }
void pressA() { m_p15 = m_p10 = false, triggerKeypadInterrupt(); }
void releaseA() noexcept { m_p15 = m_p10 = true; }
void releaseA() { m_p15 = m_p10 = true; }
void pressB() { m_p15 = m_p11 = false, triggerKeypadInterrupt(); }
void releaseB() noexcept { m_p15 = m_p11 = true; }
void releaseB() { m_p15 = m_p11 = true; }
void pressSelect() { m_p15 = m_p12 = false, triggerKeypadInterrupt(); }
void releaseSelect() noexcept { m_p15 = m_p12 = true; }
void releaseSelect() { m_p15 = m_p12 = true; }
void pressStart() { m_p15 = m_p13 = false, triggerKeypadInterrupt(); }
void releaseStart() noexcept { m_p15 = m_p13 = true; }
void releaseStart() { m_p15 = m_p13 = true; }
private:
Bus& m_bus;
+61 -61
View File
@@ -13,6 +13,11 @@ namespace EightBit {
class Bus;
class LR35902 final : public IntelProcessor {
public:
DECLARE_PIN_OUTPUT(MWR)
DECLARE_PIN_OUTPUT(RD)
DECLARE_PIN_OUTPUT(WR)
public:
enum StatusBits {
ZF = Bit7,
@@ -26,20 +31,16 @@ namespace EightBit {
Signal<LR35902> ExecutingInstruction;
Signal<LR35902> ExecutedInstruction;
[[nodiscard]] const register16_t& AF() const noexcept final;
[[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); }
[[nodiscard]] const register16_t& BC() const noexcept final;
[[nodiscard]] auto& BC() noexcept { return IntelProcessor::BC(); }
[[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]] register16_t& AF() noexcept final;
[[nodiscard]] register16_t& BC() noexcept final;
[[nodiscard]] register16_t& DE() noexcept final;
[[nodiscard]] register16_t& HL() noexcept final;
bool& IME() noexcept { return m_ime; }
bool& IME() { return m_ime; }
[[nodiscard]] uint8_t enabledInterrupts() noexcept;
[[nodiscard]] uint8_t flaggedInterrupts() noexcept;
[[nodiscard]] uint8_t maskedInterrupts() noexcept;
[[nodiscard]] uint8_t enabledInterrupts();
[[nodiscard]] uint8_t flaggedInterrupts();
[[nodiscard]] uint8_t maskedInterrupts();
Signal<EventArgs> MachineTicked;
@@ -48,102 +49,101 @@ namespace EightBit {
protected:
void execute() noexcept final;
int step() noexcept final;
void poweredStep() noexcept final;
void handleRESET() noexcept final;
void handleINT() noexcept final;
void memoryUpdate(int ticks) noexcept;
void memoryWrite() noexcept final;
uint8_t memoryRead() noexcept final;
void pushWord(register16_t value) noexcept final;
void jr(int8_t offset) noexcept final;
int jumpConditional(int condition) noexcept final;
int returnConditional(int condition) noexcept final;
int jrConditional(int condition) noexcept final;
void jumpRelative(int8_t offset) noexcept final;
void jumpConditional(bool condition) noexcept final;
void returnConditional(bool condition) noexcept final;
void ret() noexcept final;
void jumpIndirect() noexcept final;
private:
Bus& m_bus;
register16_t af = 0xffff;
register16_t bc = 0xffff;
register16_t de = 0xffff;
register16_t hl = 0xffff;
register16_t m_af = 0xffff;
register16_t m_bc = 0xffff;
register16_t m_de = 0xffff;
register16_t m_hl = 0xffff;
bool m_ime = false;
bool m_stopped = false;
bool m_ei = false;
bool m_prefixCB = false;
[[nodiscard]] uint8_t R(int r);
void R(int r, uint8_t value);
[[nodiscard]] register16_t& RP(int rp) noexcept;
[[nodiscard]] register16_t& RP2(int rp) noexcept;
[[nodiscard]] register16_t& RP(int rp);
[[nodiscard]] register16_t& RP2(int rp);
[[nodiscard]] static constexpr auto adjustHalfCarryAdd(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
[[nodiscard]] static constexpr auto adjustHalfCarryAdd(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) {
return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation));
}
[[nodiscard]] static constexpr auto adjustHalfCarrySub(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
[[nodiscard]] static constexpr auto adjustHalfCarrySub(uint8_t f, const uint8_t before, const uint8_t value, const int calculation) {
return setBit(f, HC, calculateHalfCarrySub(before, value, calculation));
}
[[nodiscard]] static bool convertCondition(uint8_t f, int flag) noexcept;
[[nodiscard]] bool convertCondition(int flag) noexcept final;
static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0);
void executeCB(int x, int y, int z, int p, int q);
void executeOther(int x, int y, int z, int p, int q);
[[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t increment(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t decrement(uint8_t& f, uint8_t operand);
void stop(bool value = true) noexcept { m_stopped = value; }
void start() noexcept { stop(false); }
[[nodiscard]] bool stopped() const noexcept { return m_stopped; }
void stop(bool value = true) { m_stopped = value; }
void start() { stop(false); }
[[nodiscard]] bool stopped() const { return m_stopped; }
void di() noexcept;
void ei() noexcept;
[[nodiscard]] constexpr bool& EI() noexcept { return m_ei; }
virtual void disableInterrupts() noexcept final;
virtual void enableInterrupts() noexcept final;
void reti();
void jrConditionalFlag(uint8_t f, int flag);
void returnConditionalFlag(uint8_t f, int flag);
void jumpConditionalFlag(uint8_t f, int flag);
void callConditionalFlag(uint8_t f, int flag);
[[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value);
[[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
[[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static void compare(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
[[nodiscard]] static uint8_t add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0);
[[nodiscard]] static uint8_t adc(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value);
static uint8_t andr(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t xorr(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t orr(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static void compare(uint8_t& f, uint8_t operand, uint8_t value);
[[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t rlc(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t rrc(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t rl(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t rr(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t sla(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t sra(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand);
static void bit(uint8_t& f, int n, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t res(int n, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t set(int n, uint8_t operand) noexcept;
static void bit(uint8_t& f, int n, uint8_t operand);
[[nodiscard]] static uint8_t res(int n, uint8_t operand);
[[nodiscard]] static uint8_t set(int n, uint8_t operand);
[[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand);
static void scf(uint8_t& f, uint8_t operand) noexcept;
static void ccf(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand) noexcept;
static void scf(uint8_t& f, uint8_t operand);
static void ccf(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t cpl(uint8_t& f, uint8_t operand);
[[nodiscard]] static uint8_t swap(uint8_t& f, uint8_t operand) noexcept;
[[nodiscard]] static uint8_t swap(uint8_t& f, uint8_t operand);
};
}
}
+10 -10
View File
@@ -14,18 +14,18 @@ namespace EightBit {
ObjectAttribute() = default;
ObjectAttribute(Ram& ram, uint16_t address);
[[nodiscard]] auto positionY() const noexcept { return m_positionY; }
[[nodiscard]] auto positionX() const noexcept { return m_positionX; }
[[nodiscard]] auto pattern() const noexcept { return m_pattern; }
[[nodiscard]] auto flags() const noexcept { return m_flags; }
[[nodiscard]] auto positionY() const { return m_positionY; }
[[nodiscard]] auto positionX() const { return m_positionX; }
[[nodiscard]] auto pattern() const { return m_pattern; }
[[nodiscard]] auto flags() const { return m_flags; }
[[nodiscard]] auto priority() const noexcept { return flags() & Chip::Bit7; }
[[nodiscard]] auto priority() const { return flags() & Chip::Bit7; }
[[nodiscard]] auto highPriority() const noexcept { return !!priority(); }
[[nodiscard]] auto lowPriority() const noexcept { return !priority(); }
[[nodiscard]] auto flipY() const noexcept { return !!(flags() & Chip::Bit6); }
[[nodiscard]] auto flipX() const noexcept { return !!(flags() & Chip::Bit5); }
[[nodiscard]] auto palette() const noexcept { return (flags() & Chip::Bit4) >> 4; }
[[nodiscard]] auto highPriority() const { return !!priority(); }
[[nodiscard]] auto lowPriority() const { return !priority(); }
[[nodiscard]] auto flipY() const { return !!(flags() & Chip::Bit6); }
[[nodiscard]] auto flipX() const { return !!(flags() & Chip::Bit5); }
[[nodiscard]] auto palette() const { return (flags() & Chip::Bit4) >> 4; }
private:
uint8_t m_positionY;
+2 -2
View File
@@ -3,12 +3,12 @@
#include <Ram.h>
EightBit::GameBoy::CharacterDefinition::CharacterDefinition(Ram& vram, const uint16_t address) noexcept
EightBit::GameBoy::CharacterDefinition::CharacterDefinition(Ram& vram, const uint16_t address)
: m_vram(vram),
m_address(address) {
}
std::array<int, 8> EightBit::GameBoy::CharacterDefinition::get(int row) const noexcept {
std::array<int, 8> EightBit::GameBoy::CharacterDefinition::get(int row) const {
std::array<int, 8> returned {};
+2 -2
View File
@@ -8,7 +8,7 @@
#include "../inc/LR35902.h"
#include "../inc/IoRegisters.h"
EightBit::GameBoy::Disassembler::Disassembler(Bus& bus) noexcept
EightBit::GameBoy::Disassembler::Disassembler(Bus& bus)
: m_bus(bus) {
// Disable exceptions where too many format arguments are available
m_formatter.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
@@ -170,7 +170,7 @@ void EightBit::GameBoy::Disassembler::disassemble(std::ostringstream& output, LR
auto q = (y & 1);
auto immediate = BUS().peek(pc + 1);
auto absolute = cpu.peekWord(pc + 1).word;
auto absolute = cpu.peekShort(pc + 1).word;
auto displacement = (int8_t)immediate;
auto relative = pc + displacement + 2;
auto indexedImmediate = BUS().peek(pc + 1);
+11 -11
View File
@@ -7,7 +7,7 @@
#include <Processor.h>
EightBit::GameBoy::Display::Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram) noexcept
EightBit::GameBoy::Display::Display(const AbstractColourPalette* colours, Bus& bus, Ram& oam, Ram& vram)
: m_bus(bus),
m_oam(oam),
m_vram(vram),
@@ -15,7 +15,7 @@ EightBit::GameBoy::Display::Display(const AbstractColourPalette* colours, Bus& b
}
#pragma optimize ("t", off)
void EightBit::GameBoy::Display::renderCurrentScanline() noexcept {
void EightBit::GameBoy::Display::renderCurrentScanline() {
m_scanLine = m_bus.IO().peek(IoRegisters::LY);
if (m_scanLine < RasterHeight) {
m_control = m_bus.IO().peek(IoRegisters::LCDC);
@@ -28,7 +28,7 @@ void EightBit::GameBoy::Display::renderCurrentScanline() noexcept {
}
#pragma optimize ("t", on)
std::array<int, 4> EightBit::GameBoy::Display::createPalette(const int address) noexcept {
std::array<int, 4> EightBit::GameBoy::Display::createPalette(const int address) {
const auto raw = m_bus.IO().peek(address);
const std::array<int, 4> palette = {
raw & 0b11,
@@ -39,12 +39,12 @@ std::array<int, 4> EightBit::GameBoy::Display::createPalette(const int address)
return palette;
}
void EightBit::GameBoy::Display::loadObjectAttributes() noexcept {
void EightBit::GameBoy::Display::loadObjectAttributes() {
for (int i = 0; i < 40; ++i)
m_objectAttributes[i] = ObjectAttribute(m_oam, 4 * i);
}
void EightBit::GameBoy::Display::renderObjects() noexcept {
void EightBit::GameBoy::Display::renderObjects() {
const auto objBlockHeight = (m_control & IoRegisters::OBJ_SIZE) ? 16 : 8;
@@ -84,7 +84,7 @@ void EightBit::GameBoy::Display::renderObjects() noexcept {
}
#pragma optimize ("t", off)
void EightBit::GameBoy::Display::renderBackground() noexcept {
void EightBit::GameBoy::Display::renderBackground() {
const auto palette = createPalette(IoRegisters::BGP);
@@ -109,7 +109,7 @@ void EightBit::GameBoy::Display::renderBackground() noexcept {
void EightBit::GameBoy::Display::renderBackground(
int bgArea, int bgCharacters, tile_offset_t offsetType,
int offsetX, int offsetY,
const std::array<int, 4>& palette) noexcept {
const std::array<int, 4>& palette) {
const int row = (m_scanLine - offsetY) / 8;
const auto address = bgArea + (row * BufferCharacterWidth);
@@ -131,7 +131,7 @@ void EightBit::GameBoy::Display::renderSpriteTile(
const int drawX, const int drawY,
const bool flipX, const bool flipY,
const std::array<int, 4>& palette,
const CharacterDefinition& definition) noexcept {
const CharacterDefinition& definition) {
renderTile(
height,
drawX, drawY,
@@ -145,7 +145,7 @@ void EightBit::GameBoy::Display::renderBackgroundTile(
int row, int column,
int bgCharacters, tile_offset_t offsetType,
int offsetX, int offsetY,
const std::array<int, 4>& palette) noexcept {
const std::array<int, 4>& palette) {
const auto definition = CharacterDefinition(m_vram, bgCharacters + definitionOffset);
const auto drawX = (column * 8) + offsetX;
@@ -160,7 +160,7 @@ void EightBit::GameBoy::Display::renderBackgroundTile(
void EightBit::GameBoy::Display::renderBackgroundTile(
const int drawX, const int drawY,
const std::array<int, 4>& palette,
const CharacterDefinition& definition) noexcept {
const CharacterDefinition& definition) {
renderTile(
8,
drawX, drawY,
@@ -174,7 +174,7 @@ void EightBit::GameBoy::Display::renderTile(
const int drawX, const int drawY,
const bool flipX, const bool flipY, const bool allowTransparencies,
const std::array<int, 4>& palette,
const CharacterDefinition& definition) noexcept {
const CharacterDefinition& definition) {
const auto width = 8;
+2 -2
View File
@@ -2,7 +2,7 @@
#include "../inc/GameBoyBus.h"
#include "../inc/Display.h"
EightBit::GameBoy::Bus::Bus() noexcept
EightBit::GameBoy::Bus::Bus()
: m_cpu(*this),
m_ioPorts(*this) {
WrittenByte.connect(std::bind(&GameBoy::Bus::Bus_WrittenByte, this, std::placeholders::_1));
@@ -40,7 +40,7 @@ void EightBit::GameBoy::Bus::loadGameRom(const std::string path) {
validateCartridgeType();
}
void EightBit::GameBoy::Bus::Bus_WrittenByte(EightBit::EventArgs) noexcept {
void EightBit::GameBoy::Bus::Bus_WrittenByte(EightBit::EventArgs) {
const auto address = ADDRESS().word;
const auto value = DATA();
+124 -122
View File
@@ -4,55 +4,80 @@
// based on http://www.z80.info/decoding.htm
DEFINE_PIN_LEVEL_CHANGERS(MWR, GameBoy::LR35902);
DEFINE_PIN_LEVEL_CHANGERS(RD, GameBoy::LR35902);
DEFINE_PIN_LEVEL_CHANGERS(WR, GameBoy::LR35902);
EightBit::GameBoy::LR35902::LR35902(Bus& memory)
: IntelProcessor(memory),
m_bus(memory) {
RaisedPOWER.connect([this](EventArgs) {
raiseWR();
raiseRD();
raiseMWR();
EI() = false;
});
RaisingHALT.connect([this](EventArgs) {
++PC();
});
MachineTicked.connect([this](EventArgs) {
m_bus.IO().incrementTimers();
m_bus.IO().transferDma();
});
}
const EightBit::register16_t& EightBit::GameBoy::LR35902::AF() const noexcept {
auto* gb = const_cast<LR35902*>(this);
gb->af.low = higherNibble(af.low);
return af;
EightBit::register16_t& EightBit::GameBoy::LR35902::AF() noexcept {
m_af.low = higherNibble(m_af.low);
return m_af;
}
const EightBit::register16_t& EightBit::GameBoy::LR35902::BC() const noexcept {
return bc;
EightBit::register16_t& EightBit::GameBoy::LR35902::BC() noexcept {
return m_bc;
}
const EightBit::register16_t& EightBit::GameBoy::LR35902::DE() const noexcept {
return de;
EightBit::register16_t& EightBit::GameBoy::LR35902::DE() noexcept {
return m_de;
}
const EightBit::register16_t& EightBit::GameBoy::LR35902::HL() const noexcept {
return hl;
EightBit::register16_t& EightBit::GameBoy::LR35902::HL() noexcept {
return m_hl;
}
void EightBit::GameBoy::LR35902::handleRESET() noexcept {
IntelProcessor::handleRESET();
di();
SP() = Mask16 - 1;
tickMachine(4);
}
void EightBit::GameBoy::LR35902::handleINT() noexcept {
IntelProcessor::handleINT();
raiseHALT();
di();
restart(BUS().DATA());
}
void EightBit::GameBoy::LR35902::memoryUpdate(int ticks) noexcept {
lowerMWR();
lowerWR();
IntelProcessor::memoryWrite();
tickMachine(ticks);
raiseWR();
raiseMWR();
}
void EightBit::GameBoy::LR35902::memoryWrite() noexcept {
tickMachine();
IntelProcessor::memoryWrite();
memoryUpdate(1);
}
uint8_t EightBit::GameBoy::LR35902::memoryRead() noexcept {
tickMachine();
return IntelProcessor::memoryRead();
lowerMWR();
lowerRD();
IntelProcessor::memoryRead();
tickMachine();
raiseRD();
raiseMWR();
return BUS().DATA();
}
void EightBit::GameBoy::LR35902::pushWord(register16_t value) noexcept {
@@ -60,43 +85,42 @@ void EightBit::GameBoy::LR35902::pushWord(register16_t value) noexcept {
IntelProcessor::pushWord(value);
}
void EightBit::GameBoy::LR35902::jr(int8_t offset) noexcept {
IntelProcessor::jr(offset);
void EightBit::GameBoy::LR35902::jumpRelative(int8_t offset) noexcept {
IntelProcessor::jumpRelative(offset);
tickMachine();
}
int EightBit::GameBoy::LR35902::jumpConditional(const int condition) noexcept {
if (IntelProcessor::jumpConditional(condition))
void EightBit::GameBoy::LR35902::jumpConditional(bool condition) noexcept {
IntelProcessor::jumpConditional(condition);
if (condition)
tickMachine();
return condition;
}
int EightBit::GameBoy::LR35902::returnConditional(const int condition) noexcept {
void EightBit::GameBoy::LR35902::returnConditional(bool condition) noexcept {
tickMachine();
IntelProcessor::returnConditional(condition);
tickMachine();
return condition;
}
int EightBit::GameBoy::LR35902::jrConditional(const int condition) noexcept {
if (!IntelProcessor::jrConditional(condition))
tickMachine();
return condition;
}
void EightBit::GameBoy::LR35902::ret() noexcept {
IntelProcessor::ret();
tickMachine();
}
void EightBit::GameBoy::LR35902::di() noexcept {
void EightBit::GameBoy::LR35902::jumpIndirect() noexcept {
IntelProcessor::jumpIndirect();
tickMachine();
}
void EightBit::GameBoy::LR35902::disableInterrupts() noexcept {
IME() = false;
}
void EightBit::GameBoy::LR35902::ei() noexcept {
void EightBit::GameBoy::LR35902::enableInterrupts() noexcept {
IME() = true;
}
uint8_t EightBit::GameBoy::LR35902::increment(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::increment(uint8_t& f, const uint8_t operand) {
f = clearBit(f, NF);
const uint8_t result = operand + 1;
f = adjustZero<LR35902>(f, result);
@@ -104,7 +128,7 @@ uint8_t EightBit::GameBoy::LR35902::increment(uint8_t& f, const uint8_t operand)
return result;
}
uint8_t EightBit::GameBoy::LR35902::decrement(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::decrement(uint8_t& f, const uint8_t operand) {
f = setBit(f, NF);
f = clearBit(f, HC, lowNibble(operand));
const uint8_t result = operand - 1;
@@ -166,7 +190,7 @@ void EightBit::GameBoy::LR35902::R(const int r, const uint8_t value) {
}
}
EightBit::register16_t& EightBit::GameBoy::LR35902::RP(const int rp) noexcept {
EightBit::register16_t& EightBit::GameBoy::LR35902::RP(const int rp) {
switch (rp) {
case 0b00:
return BC();
@@ -181,7 +205,7 @@ EightBit::register16_t& EightBit::GameBoy::LR35902::RP(const int rp) noexcept {
}
}
EightBit::register16_t& EightBit::GameBoy::LR35902::RP2(const int rp) noexcept {
EightBit::register16_t& EightBit::GameBoy::LR35902::RP2(const int rp) {
switch (rp) {
case 0b00:
return BC();
@@ -196,42 +220,26 @@ EightBit::register16_t& EightBit::GameBoy::LR35902::RP2(const int rp) noexcept {
}
}
bool EightBit::GameBoy::LR35902::convertCondition(const uint8_t f, int flag) noexcept {
bool EightBit::GameBoy::LR35902::convertCondition(int flag) noexcept {
ASSUME(flag >= 0);
ASSUME(flag <= 7);
switch (flag) {
case 0:
return !(f & ZF);
return !(F() & ZF);
case 1:
return f & ZF;
return F() & ZF;
case 2:
return !(f & CF);
return !(F() & CF);
case 3:
return f & CF;
return F() & CF;
default:
UNREACHABLE;
}
}
void EightBit::GameBoy::LR35902::returnConditionalFlag(const uint8_t f, const int flag) {
returnConditional(convertCondition(f, flag));
}
void EightBit::GameBoy::LR35902::jrConditionalFlag(const uint8_t f, const int flag) {
jrConditional(convertCondition(f, flag));
}
void EightBit::GameBoy::LR35902::jumpConditionalFlag(uint8_t f, const int flag) {
jumpConditional(convertCondition(f, flag));
}
void EightBit::GameBoy::LR35902::callConditionalFlag(uint8_t f, const int flag) {
callConditional(convertCondition(f, flag));
}
void EightBit::GameBoy::LR35902::reti() {
ret();
ei();
enableInterrupts();
}
EightBit::register16_t EightBit::GameBoy::LR35902::add(uint8_t& f, const register16_t operand, const register16_t value) {
@@ -250,7 +258,7 @@ EightBit::register16_t EightBit::GameBoy::LR35902::add(uint8_t& f, const registe
return result;
}
uint8_t EightBit::GameBoy::LR35902::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
uint8_t EightBit::GameBoy::LR35902::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) {
const register16_t addition = operand + value + carry;
const auto result = addition.low;
@@ -264,11 +272,11 @@ uint8_t EightBit::GameBoy::LR35902::add(uint8_t& f, const uint8_t operand, const
return result;
}
uint8_t EightBit::GameBoy::LR35902::adc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
uint8_t EightBit::GameBoy::LR35902::adc(uint8_t& f, const uint8_t operand, const uint8_t value) {
return add(f, operand, value, (f & CF) >> 4);
}
uint8_t EightBit::GameBoy::LR35902::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
uint8_t EightBit::GameBoy::LR35902::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) {
const register16_t subtraction = operand - value - carry;
const auto result = subtraction.low;
@@ -282,11 +290,11 @@ uint8_t EightBit::GameBoy::LR35902::subtract(uint8_t& f, const uint8_t operand,
return result;
}
uint8_t EightBit::GameBoy::LR35902::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
uint8_t EightBit::GameBoy::LR35902::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) {
return subtract(f, operand, value, (f & CF) >> 4);
}
uint8_t EightBit::GameBoy::LR35902::andr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
uint8_t EightBit::GameBoy::LR35902::andr(uint8_t& f, const uint8_t operand, const uint8_t value) {
f = setBit(f, HC);
f = clearBit(f, CF | NF);
const uint8_t result = operand & value;
@@ -294,76 +302,76 @@ uint8_t EightBit::GameBoy::LR35902::andr(uint8_t& f, const uint8_t operand, cons
return result;
}
uint8_t EightBit::GameBoy::LR35902::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
uint8_t EightBit::GameBoy::LR35902::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) {
f = clearBit(f, HC | CF | NF);
const uint8_t result = operand ^ value;
f = adjustZero<LR35902>(f, result);
return result;
}
uint8_t EightBit::GameBoy::LR35902::orr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
uint8_t EightBit::GameBoy::LR35902::orr(uint8_t& f, const uint8_t operand, const uint8_t value) {
f = clearBit(f, HC | CF | NF);
const uint8_t result = operand | value;
f = adjustZero<LR35902>(f, result);
return result;
}
void EightBit::GameBoy::LR35902::compare(uint8_t& f, uint8_t operand, const uint8_t value) noexcept {
void EightBit::GameBoy::LR35902::compare(uint8_t& f, uint8_t operand, const uint8_t value) {
subtract(f, operand, value);
}
uint8_t EightBit::GameBoy::LR35902::rlc(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::rlc(uint8_t& f, const uint8_t operand) {
f = clearBit(f, NF | HC | ZF);
const auto carry = operand & Bit7;
f = setBit(f, CF, carry);
return (operand << 1) | (carry >> 7);
}
uint8_t EightBit::GameBoy::LR35902::rrc(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::rrc(uint8_t& f, const uint8_t operand) {
f = clearBit(f, NF | HC | ZF);
const auto carry = operand & Bit0;
f = setBit(f, CF, carry);
return (operand >> 1) | (carry << 7);
}
uint8_t EightBit::GameBoy::LR35902::rl(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::rl(uint8_t& f, const uint8_t operand) {
f = clearBit(f, NF | HC | ZF);
const auto carry = f & CF;
f = setBit(f, CF, operand & Bit7);
return (operand << 1) | (carry >> 4); // CF at Bit4
}
uint8_t EightBit::GameBoy::LR35902::rr(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::rr(uint8_t& f, const uint8_t operand) {
f = clearBit(f, NF | HC | ZF);
const auto carry = f & CF;
f = setBit(f, CF, operand & Bit0);
return (operand >> 1) | (carry << 3); // CF at Bit4
}
uint8_t EightBit::GameBoy::LR35902::sla(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::sla(uint8_t& f, const uint8_t operand) {
f = clearBit(f, NF | HC | ZF);
f = setBit(f, CF, operand & Bit7);
return operand << 1;
}
uint8_t EightBit::GameBoy::LR35902::sra(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::sra(uint8_t& f, const uint8_t operand) {
f = clearBit(f, NF | HC | ZF);
f = setBit(f, CF, operand & Bit0);
return (operand >> 1) | (operand & Bit7);
}
uint8_t EightBit::GameBoy::LR35902::swap(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::swap(uint8_t& f, const uint8_t operand) {
f = clearBit(f, NF | HC | CF);
return promoteNibble(operand) | demoteNibble(operand);
}
uint8_t EightBit::GameBoy::LR35902::srl(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::srl(uint8_t& f, const uint8_t operand) {
f = clearBit(f, NF | HC | ZF);
f = setBit(f, CF, operand & Bit0);
return (operand >> 1) & ~Bit7;
}
void EightBit::GameBoy::LR35902::bit(uint8_t& f, const int n, const uint8_t operand) noexcept {
void EightBit::GameBoy::LR35902::bit(uint8_t& f, const int n, const uint8_t operand) {
ASSUME(n >= 0);
ASSUME(n <= 7);
const auto carry = f & CF;
@@ -371,19 +379,19 @@ void EightBit::GameBoy::LR35902::bit(uint8_t& f, const int n, const uint8_t oper
f = setBit(f, CF, carry);
}
uint8_t EightBit::GameBoy::LR35902::res(const int n, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::res(const int n, const uint8_t operand) {
ASSUME(n >= 0);
ASSUME(n <= 7);
return clearBit(operand, Chip::bit(n));
}
uint8_t EightBit::GameBoy::LR35902::set(const int n, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::set(const int n, const uint8_t operand) {
ASSUME(n >= 0);
ASSUME(n <= 7);
return setBit(operand, Chip::bit(n));
}
uint8_t EightBit::GameBoy::LR35902::daa(uint8_t& f, uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::daa(uint8_t& f, uint8_t operand) {
int updated = operand;
@@ -408,67 +416,61 @@ uint8_t EightBit::GameBoy::LR35902::daa(uint8_t& f, uint8_t operand) noexcept {
return result;
}
uint8_t EightBit::GameBoy::LR35902::cpl(uint8_t& f, const uint8_t operand) noexcept {
uint8_t EightBit::GameBoy::LR35902::cpl(uint8_t& f, const uint8_t operand) {
f = setBit(f, HC | NF);
return ~operand;
}
void EightBit::GameBoy::LR35902::scf(uint8_t& f, const uint8_t operand) noexcept {
void EightBit::GameBoy::LR35902::scf(uint8_t& f, const uint8_t operand) {
f = setBit(f, CF);
f = clearBit(f, HC | NF);
}
void EightBit::GameBoy::LR35902::ccf(uint8_t& f, const uint8_t operand) noexcept {
void EightBit::GameBoy::LR35902::ccf(uint8_t& f, const uint8_t operand) {
f = clearBit(f, NF | HC);
f = clearBit(f, CF, f & CF);
}
uint8_t EightBit::GameBoy::LR35902::enabledInterrupts() noexcept {
uint8_t EightBit::GameBoy::LR35902::enabledInterrupts() {
return BUS().peek(IoRegisters::BASE + IoRegisters::IE);
}
uint8_t EightBit::GameBoy::LR35902::flaggedInterrupts() noexcept {
uint8_t EightBit::GameBoy::LR35902::flaggedInterrupts() {
return m_bus.IO().peek(IoRegisters::IF);
}
uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() noexcept {
uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() {
return enabledInterrupts() & flaggedInterrupts();
}
int EightBit::GameBoy::LR35902::step() noexcept {
void EightBit::GameBoy::LR35902::poweredStep() noexcept {
ExecutingInstruction.fire(*this);
m_prefixCB = false;
resetCycles();
if (LIKELY(powered())) {
const auto masked = maskedInterrupts();
if (masked) {
if (IME()) {
m_bus.IO().poke(IoRegisters::IF, 0);
lowerINT();
const int index = findFirstSet(masked);
BUS().DATA() = 0x38 + (index << 3);
} else {
raiseHALT();
}
}
if (UNLIKELY(lowered(RESET()))) {
handleRESET();
} else if (UNLIKELY(lowered(INT()))) {
handleINT();
} else if (UNLIKELY(lowered(HALT()))) {
IntelProcessor::memoryRead(PC());
//Processor::execute(0); // NOP
if (EI()) {
enableInterrupts();
EI() = false;
}
const auto masked = maskedInterrupts();
if (masked) {
if (IME()) {
m_bus.IO().poke(IoRegisters::IF, 0);
lowerINT();
const int index = findFirstSet(masked);
BUS().DATA() = 0x38 + (index << 3);
} else {
Processor::execute(fetchByte());
raiseHALT();
}
}
ExecutedInstruction.fire(*this);
assert(cycles() > 0);
assert(cycles() % 4 == 0);
return cycles();
if (UNLIKELY(lowered(RESET()))) {
handleRESET();
} else if (UNLIKELY(lowered(INT()))) {
handleINT();
} else {
Processor::execute(fetchByte());
}
}
void EightBit::GameBoy::LR35902::execute() noexcept {
@@ -551,15 +553,16 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
break;
case 2: // GB: STOP
stop();
tickMachine(2);
break;
case 3: // JR d
jr(fetchByte());
jumpRelative(fetchByte());
break;
case 4: // JR cc,d
case 5:
case 6:
case 7:
jrConditionalFlag(F(), y - 4);
jumpRelativeConditionalFlag(y - 4);
break;
default:
UNREACHABLE;
@@ -722,7 +725,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
case 1:
case 2:
case 3:
returnConditionalFlag(F(), y);
returnConditionalFlag(y);
break;
case 4: // GB: LD (FF00 + n),A
IntelProcessor::memoryWrite(IoRegisters::BASE + fetchByte(), A());
@@ -772,7 +775,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
reti();
break;
case 2: // JP HL
jump(HL());
Processor::jump(HL());
break;
case 3: // LD SP,HL
SP() = HL();
@@ -792,7 +795,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
case 1:
case 2:
case 3:
jumpConditionalFlag(F(), y);
jumpConditionalFlag(y);
break;
case 4: // GB: LD (FF00 + C),A
IntelProcessor::memoryWrite(IoRegisters::BASE + C(), A());
@@ -815,23 +818,22 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
case 3: // Assorted operations
switch (y) {
case 0: // JP nn
jump(MEMPTR() = fetchWord());
tickMachine();
jumpIndirect();
break;
case 1: // CB prefix
m_prefixCB = true;
Processor::execute(fetchByte());
break;
case 6: // DI
di();
disableInterrupts();
break;
case 7: // EI
ei();
EI() = true;
break;
}
break;
case 4: // Conditional call: CALL cc[y], nn
callConditionalFlag(F(), y);
callConditionalFlag(y);
break;
case 5: // PUSH & various ops
switch (q) {
+1 -1
View File
@@ -22,4 +22,4 @@ void TestRunner::lowerPOWER() noexcept {
EightBit::Bus::lowerPOWER();
}
void TestRunner::initialise() {}
void TestRunner::initialise() noexcept {}
+1 -1
View File
@@ -18,7 +18,7 @@ public:
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
void initialise() final;
void initialise() noexcept final;
[[nodiscard]] constexpr auto& RAM() noexcept { return m_ram; }
[[nodiscard]] constexpr auto& CPU() noexcept { return m_cpu; }
+1 -1
View File
@@ -415,7 +415,7 @@ namespace EightBit {
static void dump(std::ostream& out, int value, int width);
uint8_t getByte(uint16_t address);
uint16_t getWord(uint16_t address);
uint16_t getShort(uint16_t address);
std::string dump_Byte(uint16_t address);
std::string dump_DByte(uint16_t address);
+6 -4
View File
@@ -35,11 +35,11 @@ namespace EightBit {
MOS6502(Bus& bus) noexcept;
Signal<MOS6502> ExecutingInstruction;
Signal<MOS6502> ExecutedInstruction;
//Signal<MOS6502> ExecutingInstruction;
//Signal<MOS6502> ExecutedInstruction;
void execute() noexcept final;
[[nodiscard]] int step() noexcept final;
void poweredStep() noexcept final;
[[nodiscard]] constexpr auto& X() noexcept { return m_x; }
[[nodiscard]] constexpr auto& Y() noexcept { return m_y; }
@@ -106,7 +106,7 @@ namespace EightBit {
}
// Read the opcode within the existing cycle
void fetchInstruction() noexcept {
uint8_t fetchInstruction() noexcept final {
// Instruction fetch beginning
lowerSYNC();
@@ -121,6 +121,8 @@ namespace EightBit {
// Instruction fetch has now completed
raiseSYNC();
return opcode();
}
// Addressing modes
+3 -3
View File
@@ -474,8 +474,8 @@ uint8_t EightBit::Disassembly::getByte(uint16_t address) {
return BUS().peek(address);
}
uint16_t EightBit::Disassembly::getWord(uint16_t address) {
return processor.peekWord(address).word;
uint16_t EightBit::Disassembly::getShort(uint16_t address) {
return processor.peekShort(address).word;
}
////
@@ -489,7 +489,7 @@ std::string EightBit::Disassembly::dump_DByte(uint16_t address) {
}
std::string EightBit::Disassembly::dump_Word(uint16_t address) {
return dump_WordValue(getWord(address));
return dump_WordValue(getShort(address));
}
////
+15 -25
View File
@@ -20,37 +20,27 @@ DEFINE_PIN_LEVEL_CHANGERS(SYNC, MOS6502)
DEFINE_PIN_LEVEL_CHANGERS(RDY, MOS6502)
DEFINE_PIN_LEVEL_CHANGERS(RW, MOS6502)
int EightBit::MOS6502::step() noexcept {
void EightBit::MOS6502::poweredStep() noexcept {
resetCycles();
tick(); // A cycle is used, whether RDY is high or not
ExecutingInstruction.fire(*this);
if (LIKELY(powered())) {
if (UNLIKELY(lowered(SO())))
handleSO();
tick(); // A cycle is used, whether RDY is high or not
if (LIKELY(raised(RDY()))) {
if (UNLIKELY(lowered(SO())))
handleSO();
fetchInstruction();
if (LIKELY(raised(RDY()))) {
fetchInstruction();
// Priority: RESET > NMI > INT
if (UNLIKELY(lowered(RESET())))
handleRESET();
else if (UNLIKELY(lowered(NMI())))
handleNMI();
else if (UNLIKELY(lowered(INT()) && !interruptMasked()))
handleINT();
else
execute();
}
// Priority: RESET > NMI > INT
if (UNLIKELY(lowered(RESET())))
handleRESET();
else if (UNLIKELY(lowered(NMI())))
handleNMI();
else if (UNLIKELY(lowered(INT()) && !interruptMasked()))
handleINT();
else
execute();
}
ExecutedInstruction.fire(*this);
ASSUME(cycles() > 0);
return cycles();
}
// Interrupt (etc.) handlers
+5 -5
View File
@@ -34,8 +34,8 @@ void Board::initialise() noexcept {
// Disassembly output
if (m_configuration.isDebugMode())
CPU().ExecutingInstruction.connect([this] (EightBit::MOS6502& cpu) {
const auto address = cpu.PC();
CPU().ExecutingInstruction.connect([this] (EightBit::EventArgs&) {
const auto address = CPU().PC();
const auto cell = peek(address);
std::cout << std::hex;
@@ -53,8 +53,8 @@ void Board::initialise() noexcept {
});
// Loop detected stop condition
CPU().ExecutedInstruction.connect([this] (EightBit::MOS6502& cpu) {
const auto pc = cpu.PC();
CPU().ExecutedInstruction.connect([this] (EightBit::EventArgs&) {
const auto pc = CPU().PC();
if (m_oldPC != pc) {
m_oldPC = pc;
} else {
@@ -65,5 +65,5 @@ void Board::initialise() noexcept {
});
poke(0x00, 0x4c);
CPU().pokeWord(1, m_configuration.getStartAddress());
CPU().pokeShort(1, m_configuration.getStartAddress());
}
+1 -1
View File
@@ -181,7 +181,7 @@
namespace EightBit {
class M6532 final : public ClockedChip {
public:
M6532() noexcept;
M6532();
virtual ~M6532() = default;
/* ___
+1 -1
View File
@@ -3,7 +3,7 @@
#include <cassert>
EightBit::M6532::M6532() noexcept {
EightBit::M6532::M6532() {
Ticked.connect([this](EightBit::EventArgs&) {
step();
});
+1 -1
View File
@@ -46,7 +46,7 @@ namespace EightBit {
[[nodiscard]] Bus& BUS() { return m_bus; }
[[nodiscard]] uint8_t getByte(uint16_t address);
[[nodiscard]] uint16_t getWord(uint16_t address);
[[nodiscard]] uint16_t getShort(uint16_t address);
[[nodiscard]] std::string disassembleUnprefixed();
[[nodiscard]] std::string disassemble10();
+66 -66
View File
@@ -67,31 +67,31 @@ namespace EightBit {
Signal<mc6809> ExecutedInstruction;
void execute() noexcept final;
[[nodiscard]] int step() noexcept final;
void poweredStep() noexcept final;
[[nodiscard]] constexpr auto& D() noexcept { return m_d; }
[[nodiscard]] constexpr auto& A() noexcept { return D().high; }
[[nodiscard]] constexpr auto& B() noexcept { return D().low; }
[[nodiscard]] constexpr auto& D() { return m_d; }
[[nodiscard]] constexpr auto& A() { return D().high; }
[[nodiscard]] constexpr auto& B() { return D().low; }
[[nodiscard]] constexpr auto& X() noexcept { return m_x; }
[[nodiscard]] constexpr auto& Y() noexcept { return m_y; }
[[nodiscard]] constexpr auto& U() noexcept { return m_u; }
[[nodiscard]] constexpr auto& S() noexcept { return m_s; }
[[nodiscard]] constexpr auto& X() { return m_x; }
[[nodiscard]] constexpr auto& Y() { return m_y; }
[[nodiscard]] constexpr auto& U() { return m_u; }
[[nodiscard]] constexpr auto& S() { return m_s; }
[[nodiscard]] constexpr auto& DP() noexcept { return m_dp; }
[[nodiscard]] constexpr auto& CC() noexcept { return m_cc; }
[[nodiscard]] constexpr const auto& CC() const noexcept { return m_cc; }
[[nodiscard]] constexpr auto& DP() { return m_dp; }
[[nodiscard]] constexpr auto& CC() { return m_cc; }
[[nodiscard]] constexpr const auto& CC() const { return m_cc; }
// Flag checking
[[nodiscard]] constexpr auto fastInterruptMasked() const noexcept { return CC() & FF; }
[[nodiscard]] constexpr auto interruptMasked() const noexcept { return CC() & IF; }
[[nodiscard]] constexpr auto fastInterruptMasked() const { return CC() & FF; }
[[nodiscard]] constexpr auto interruptMasked() const { return CC() & IF; }
[[nodiscard]] constexpr auto negative() const noexcept { return CC() & NF; }
[[nodiscard]] constexpr auto zero() const noexcept { return CC() & ZF; }
[[nodiscard]] constexpr auto overflow() const noexcept { return CC() & VF; }
[[nodiscard]] constexpr auto carry() const noexcept { return CC() & CF; }
[[nodiscard]] constexpr auto halfCarry() const noexcept { return CC() & HF; }
[[nodiscard]] constexpr auto negative() const { return CC() & NF; }
[[nodiscard]] constexpr auto zero() const { return CC() & ZF; }
[[nodiscard]] constexpr auto overflow() const { return CC() & VF; }
[[nodiscard]] constexpr auto carry() const { return CC() & CF; }
[[nodiscard]] constexpr auto halfCarry() const { return CC() & HF; }
// |---------------|-----------------------------------|
// | MPU State | |
@@ -104,9 +104,9 @@ namespace EightBit {
// | 1 | 1 | HALT Acknowledge |
// |-------|-------|-----------------------------------|
[[nodiscard]] auto halted() noexcept { return lowered(HALT()); }
void halt() noexcept { --PC(); lowerHALT(); }
void proceed() noexcept { ++PC(); raiseHALT(); }
[[nodiscard]] auto halted() { return lowered(HALT()); }
void halt() { --PC(); lowerHALT(); }
void proceed() { ++PC(); raiseHALT(); }
protected:
// Default push/pop handlers
@@ -163,21 +163,21 @@ namespace EightBit {
// Stack manipulation
void push(register16_t& stack, uint8_t value);
void pushS(const uint8_t value) { push(S(), value); }
void pushU(const uint8_t value) { push(U(), value); }
void push(register16_t& stack, uint8_t value) noexcept;
void pushS(const uint8_t value) noexcept { push(S(), value); }
void pushU(const uint8_t value) noexcept { push(U(), value); }
void pushWord(register16_t& stack, const register16_t value) {
void pushWord(register16_t& stack, const register16_t value) noexcept {
push(stack, value.low);
push(stack, value.high);
}
void pushWordS(const register16_t value) { pushWord(S(), value); }
void pushWordU(const register16_t value) { pushWord(U(), value); }
void pushWordS(const register16_t value) noexcept { pushWord(S(), value); }
void pushWordU(const register16_t value) noexcept { pushWord(U(), value); }
[[nodiscard]] uint8_t pop(register16_t& stack);
[[nodiscard]] uint8_t popS() { return pop(S()); }
[[nodiscard]] uint8_t popU() { return pop(U()); }
[[nodiscard]] uint8_t pop(register16_t& stack) noexcept;
[[nodiscard]] uint8_t popS() noexcept { return pop(S()); }
[[nodiscard]] uint8_t popU() noexcept { return pop(U()); }
[[nodiscard]] register16_t popWord(register16_t& stack) {
const auto high = pop(stack);
@@ -190,9 +190,9 @@ namespace EightBit {
// Interrupt (etc.) handlers
void handleHALT();
void handleNMI();
void handleFIRQ();
void handleHALT() noexcept;
void handleNMI() noexcept;
void handleFIRQ() noexcept;
// Execution helpers
@@ -204,7 +204,7 @@ namespace EightBit {
[[nodiscard]] register16_t& RR(int which);
// Register selection for 8-bit transfer/exchange
[[nodiscard]] uint8_t& referenceTransfer8(int specifier) noexcept;
[[nodiscard]] uint8_t& referenceTransfer8(int specifier);
// Register selection for 16-bit transfer/exchange
[[nodiscard]] register16_t& referenceTransfer16(int specifier);
@@ -235,46 +235,46 @@ namespace EightBit {
// Flag adjustment
template<class T> constexpr void adjustZero(const T datum) noexcept { CC() = clearBit(CC(), ZF, datum); }
constexpr void adjustZero(const register16_t datum) noexcept { CC() = clearBit(CC(), ZF, datum.word); }
constexpr void adjustNegative(const uint8_t datum) noexcept { CC() = setBit(CC(), NF, datum & Bit7); }
constexpr void adjustNegative(const register16_t datum) noexcept { adjustNegative(datum.high); }
constexpr void adjustNegative(const uint16_t datum) noexcept { adjustNegative(register16_t(datum)); }
template<class T> constexpr void adjustZero(const T datum) { CC() = clearBit(CC(), ZF, datum); }
constexpr void adjustZero(const register16_t datum) { CC() = clearBit(CC(), ZF, datum.word); }
constexpr void adjustNegative(const uint8_t datum) { CC() = setBit(CC(), NF, datum & Bit7); }
constexpr void adjustNegative(const register16_t datum) { adjustNegative(datum.high); }
constexpr void adjustNegative(const uint16_t datum) { adjustNegative(register16_t(datum)); }
template<class T> constexpr void adjustNZ(const T datum) noexcept {
template<class T> constexpr void adjustNZ(const T datum) {
adjustZero(datum);
adjustNegative(datum);
}
constexpr void adjustCarry(const uint16_t datum) noexcept { CC() = setBit(CC(), CF, datum & Bit8); } // 8-bit addition
constexpr void adjustCarry(const uint32_t datum) noexcept { CC() = setBit(CC(), CF, datum & Bit16); } // 16-bit addition
constexpr void adjustCarry(const register16_t datum) noexcept { adjustCarry(datum.word); }
constexpr void adjustCarry(const uint16_t datum) { CC() = setBit(CC(), CF, datum & Bit8); } // 8-bit addition
constexpr void adjustCarry(const uint32_t datum) { CC() = setBit(CC(), CF, datum & Bit16); } // 16-bit addition
constexpr void adjustCarry(const register16_t datum) { adjustCarry(datum.word); }
constexpr void adjustBorrow(const uint16_t datum) noexcept { CC() = clearBit(CC(), CF, datum & Bit8); } // 8-bit subtraction
constexpr void adjustBorrow(const uint32_t datum) noexcept { CC() = clearBit(CC(), CF, datum & Bit16); } // 16-bit subtraction
constexpr void adjustBorrow(const register16_t datum) noexcept { adjustBorrow(datum.word); }
constexpr void adjustBorrow(const uint16_t datum) { CC() = clearBit(CC(), CF, datum & Bit8); } // 8-bit subtraction
constexpr void adjustBorrow(const uint32_t datum) { CC() = clearBit(CC(), CF, datum & Bit16); } // 16-bit subtraction
constexpr void adjustBorrow(const register16_t datum) { adjustBorrow(datum.word); }
constexpr void adjustOverflow(const uint8_t before, const uint8_t data, const register16_t after) noexcept {
constexpr void adjustOverflow(const uint8_t before, const uint8_t data, const register16_t after) {
const uint8_t lowAfter = after.low;
const uint8_t highAfter = after.high;
CC() = setBit(CC(), VF, (before ^ data ^ lowAfter ^ (highAfter << 7)) & Bit7);
}
constexpr void adjustOverflow(const uint16_t before, const uint16_t data, const uint32_t after) noexcept {
constexpr void adjustOverflow(const uint16_t before, const uint16_t data, const uint32_t after) {
const uint16_t lowAfter = after & Mask16;
const uint16_t highAfter = after >> 16;
CC() = setBit(CC(), VF, (before ^ data ^ lowAfter ^ (highAfter << 15)) & Bit15);
}
constexpr void adjustOverflow(const register16_t before, const register16_t data, const register16_t after) noexcept {
constexpr void adjustOverflow(const register16_t before, const register16_t data, const register16_t after) {
adjustOverflow(before.word, data.word, after.word);
}
constexpr void adjustHalfCarry(const uint8_t before, const uint8_t data, const uint8_t after) noexcept {
constexpr void adjustHalfCarry(const uint8_t before, const uint8_t data, const uint8_t after) {
CC() = setBit(CC(), HF, (before ^ data ^ after) & Bit4);
}
constexpr void adjustAddition(const uint8_t before, const uint8_t data, const register16_t after) noexcept {
constexpr void adjustAddition(const uint8_t before, const uint8_t data, const register16_t after) {
const auto result = after.low;
adjustNZ(result);
adjustCarry(after);
@@ -282,52 +282,52 @@ namespace EightBit {
adjustHalfCarry(before, data, result);
}
constexpr void adjustAddition(const uint16_t before, const uint16_t data, const uint32_t after) noexcept {
constexpr void adjustAddition(const uint16_t before, const uint16_t data, const uint32_t after) {
const register16_t result = after & Mask16;
adjustNZ(result);
adjustCarry(after);
adjustOverflow(before, data, after);
}
constexpr void adjustAddition(const register16_t before, const register16_t data, const uint32_t after) noexcept {
constexpr void adjustAddition(const register16_t before, const register16_t data, const uint32_t after) {
adjustAddition(before.word, data.word, after);
}
constexpr void adjustSubtraction(const uint8_t before, const uint8_t data, const register16_t after) noexcept {
constexpr void adjustSubtraction(const uint8_t before, const uint8_t data, const register16_t after) {
const auto result = after.low;
adjustNZ(result);
adjustCarry(after);
adjustOverflow(before, data, after);
}
constexpr void adjustSubtraction(const uint16_t before, const uint16_t data, const uint32_t after) noexcept {
constexpr void adjustSubtraction(const uint16_t before, const uint16_t data, const uint32_t after) {
const register16_t result = after & Mask16;
adjustNZ(result);
adjustCarry(after);
adjustOverflow(before, data, after);
}
constexpr void adjustSubtraction(const register16_t before, const register16_t data, const uint32_t after) noexcept {
constexpr void adjustSubtraction(const register16_t before, const register16_t data, const uint32_t after) {
adjustSubtraction(before.word, data.word, after);
}
[[nodiscard]] constexpr auto LS() const noexcept { return carry() || zero(); } // (C OR Z)
[[nodiscard]] constexpr auto HI() const noexcept { return !LS(); } // !(C OR Z)
[[nodiscard]] constexpr auto LT() const noexcept { return (negative() >> 3) ^ (overflow() >> 1); } // (N XOR V)
[[nodiscard]] constexpr auto GE() const noexcept { return !LT(); } // !(N XOR V)
[[nodiscard]] constexpr auto LE() const noexcept { return zero() || LT(); } // (Z OR (N XOR V))
[[nodiscard]] constexpr auto GT() const noexcept { return !LE(); } // !(Z OR (N XOR V))
[[nodiscard]] constexpr auto LS() const { return carry() || zero(); } // (C OR Z)
[[nodiscard]] constexpr auto HI() const { return !LS(); } // !(C OR Z)
[[nodiscard]] constexpr auto LT() const { return (negative() >> 3) ^ (overflow() >> 1); } // (N XOR V)
[[nodiscard]] constexpr auto GE() const { return !LT(); } // !(N XOR V)
[[nodiscard]] constexpr auto LE() const { return zero() || LT(); } // (Z OR (N XOR V))
[[nodiscard]] constexpr auto GT() const { return !LE(); } // !(Z OR (N XOR V))
// Branching
auto branch(const register16_t destination, const bool condition) noexcept {
auto branch(const register16_t destination, const bool condition) {
if (condition)
jump(destination);
return condition;
}
void branchShort(const bool condition) noexcept {
void branchShort(const bool condition) {
branch(Address_relative_byte(), condition);
}
@@ -343,7 +343,7 @@ namespace EightBit {
void saveRegisterState();
void restoreRegisterState();
template <class T> constexpr T through(const T data) noexcept {
template <class T> constexpr T through(const T data) {
CC() = clearBit(CC(), VF);
adjustNZ(data);
return data;
@@ -365,7 +365,7 @@ namespace EightBit {
void cwai(uint8_t data);
uint8_t da(uint8_t operand);
uint8_t dec(uint8_t operand);
[[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data) noexcept;
[[nodiscard]] uint8_t eorr(uint8_t operand, uint8_t data);
void exg(uint8_t data);
uint8_t inc(uint8_t operand);
void jsr(register16_t address);
+8 -8
View File
@@ -710,7 +710,7 @@ std::string EightBit::Disassembly::Address_indexed(std::string mnemomic) {
<< wrapIndirect(dump_ByteValue(byte) + "," + r, indirect);
break;
case 0b1001: // n,R (sixteen-bit)
word = getWord(++m_address);
word = getShort(++m_address);
output
<< dump_WordValue(word)
<< "\t" << mnemomic << "\t"
@@ -729,7 +729,7 @@ std::string EightBit::Disassembly::Address_indexed(std::string mnemomic) {
<< wrapIndirect(dump_RelativeValue((int8_t)byte) + ",PCR", indirect);
break;
case 0b1101: // n,PCR (sixteen-bit)
word = getWord(++m_address);
word = getShort(++m_address);
output
<< dump_WordValue(word)
<< "\t" << mnemomic << "\t"
@@ -737,7 +737,7 @@ std::string EightBit::Disassembly::Address_indexed(std::string mnemomic) {
break;
case 0b1111: // [n]
assert(indirect);
word = getWord(++m_address);
word = getShort(++m_address);
output
<< dump_WordValue(word)
<< "\t" << mnemomic << "\t"
@@ -759,7 +759,7 @@ std::string EightBit::Disassembly::Address_indexed(std::string mnemomic) {
std::string EightBit::Disassembly::Address_extended(std::string mnemomic) {
std::ostringstream output;
const auto word = getWord(++m_address);
const auto word = getShort(++m_address);
output
<< dump_WordValue(word)
<< "\t" << mnemomic << "\t"
@@ -779,7 +779,7 @@ std::string EightBit::Disassembly::Address_relative_byte(std::string mnemomic) {
std::string EightBit::Disassembly::Address_relative_word(std::string mnemomic) {
std::ostringstream output;
const auto word = getWord(++m_address);
const auto word = getShort(++m_address);
output
<< dump_WordValue(word)
<< "\t" << mnemomic << "\t"
@@ -801,7 +801,7 @@ std::string EightBit::Disassembly::AM_immediate_byte(std::string mnemomic) {
std::string EightBit::Disassembly::AM_immediate_word(std::string mnemomic) {
std::ostringstream output;
const auto word = getWord(++m_address);
const auto word = getShort(++m_address);
output
<< dump_WordValue(word)
<< "\t" << mnemomic << "\t"
@@ -882,8 +882,8 @@ uint8_t EightBit::Disassembly::getByte(uint16_t address) {
return BUS().peek(address);
}
uint16_t EightBit::Disassembly::getWord(uint16_t address) {
return CPU().peekWord(address).word;
uint16_t EightBit::Disassembly::getShort(uint16_t address) {
return CPU().peekShort(address).word;
}
//
+20 -20
View File
@@ -20,10 +20,10 @@ DEFINE_PIN_LEVEL_CHANGERS(BA, mc6809);
DEFINE_PIN_LEVEL_CHANGERS(BS, mc6809);
DEFINE_PIN_LEVEL_CHANGERS(RW, mc6809);
int EightBit::mc6809::step() noexcept {
resetCycles();
ExecutingInstruction.fire(*this);
if (LIKELY(powered())) {
void EightBit::mc6809::poweredStep() noexcept {
//resetCycles();
//ExecutingInstruction.fire(*this);
//if (LIKELY(powered())) {
m_prefix10 = m_prefix11 = false;
if (UNLIKELY(halted()))
handleHALT();
@@ -37,15 +37,15 @@ int EightBit::mc6809::step() noexcept {
handleINT();
else
BigEndianProcessor::execute(fetchByte());
}
ExecutedInstruction.fire(*this);
assert(cycles() > 0);
return cycles();
//}
//ExecutedInstruction.fire(*this);
//assert(cycles() > 0);
//return cycles();
}
// Interrupt (etc.) handlers
void EightBit::mc6809::handleHALT() {
void EightBit::mc6809::handleHALT() noexcept {
raiseBA();
raiseBS();
}
@@ -62,11 +62,11 @@ void EightBit::mc6809::handleRESET() noexcept {
memoryRead();
memoryRead();
memoryRead();
jump(getWord());
jump(getShort());
eat();
}
void EightBit::mc6809::handleNMI() {
void EightBit::mc6809::handleNMI() noexcept {
raiseNMI();
lowerBA();
raiseBS();
@@ -95,7 +95,7 @@ void EightBit::mc6809::handleINT() noexcept {
eat();
}
void EightBit::mc6809::handleFIRQ() {
void EightBit::mc6809::handleFIRQ() noexcept {
raiseFIRQ();
lowerBA();
raiseBS();
@@ -635,11 +635,11 @@ uint8_t EightBit::mc6809::pop() noexcept {
return popS();
}
void EightBit::mc6809::push(register16_t& stack, const uint8_t value) {
void EightBit::mc6809::push(register16_t& stack, const uint8_t value) noexcept {
memoryWrite(--stack, value);
}
uint8_t EightBit::mc6809::pop(register16_t& stack) {
uint8_t EightBit::mc6809::pop(register16_t& stack) noexcept {
return memoryRead(stack++);
}
@@ -757,7 +757,7 @@ EightBit::register16_t EightBit::mc6809::Address_indexed() {
UNREACHABLE;
}
if (indirect) {
address = Processor::getWord(address);
address = Processor::getShort(address);
eat();
}
} else {
@@ -800,15 +800,15 @@ EightBit::register16_t EightBit::mc6809::AM_immediate_word() {
}
EightBit::register16_t EightBit::mc6809::AM_direct_word() {
return Processor::getWord(Address_direct());
return Processor::getShort(Address_direct());
}
EightBit::register16_t EightBit::mc6809::AM_indexed_word() {
return Processor::getWord(Address_indexed());
return Processor::getShort(Address_indexed());
}
EightBit::register16_t EightBit::mc6809::AM_extended_word() {
return Processor::getWord(Address_extended());
return Processor::getShort(Address_extended());
}
//
@@ -922,11 +922,11 @@ uint8_t EightBit::mc6809::dec(const uint8_t operand) {
return result;
}
uint8_t EightBit::mc6809::eorr(const uint8_t operand, const uint8_t data) noexcept {
uint8_t EightBit::mc6809::eorr(const uint8_t operand, const uint8_t data) {
return through((uint8_t)(operand ^ data));
}
uint8_t& EightBit::mc6809::referenceTransfer8(const int specifier) noexcept {
uint8_t& EightBit::mc6809::referenceTransfer8(const int specifier) {
switch (specifier) {
case 0b1000:
return A();
+3 -3
View File
@@ -4,7 +4,7 @@
Board::Board(const Configuration& configuration)
: m_configuration(configuration) {}
void Board::raisePOWER() noexcept {
void Board::raisePOWER() {
EightBit::Bus::raisePOWER();
@@ -26,7 +26,7 @@ void Board::raisePOWER() noexcept {
accessAcia();
}
void Board::lowerPOWER() noexcept {
void Board::lowerPOWER() {
if (m_configuration.isProfileMode()) {
m_profiler.EmitLine.connect([this](EightBit::ProfileLineEventArgs line) {
@@ -111,7 +111,7 @@ void Board::initialise() {
}
}
EightBit::MemoryMapping Board::mapping(uint16_t address) noexcept {
EightBit::MemoryMapping Board::mapping(uint16_t address) {
if (address < 0x8000)
return { m_ram, 0x0000, EightBit::Chip::Mask16, EightBit::MemoryMapping::AccessLevel::ReadWrite };
+3 -3
View File
@@ -20,13 +20,13 @@ public:
auto& CPU() { return m_cpu; }
auto& ACIA() { return m_acia; }
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
void raisePOWER() final;
void lowerPOWER() final;
virtual void initialise() final;
protected:
EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
EightBit::MemoryMapping mapping(uint16_t address) final;
private:
const Configuration& m_configuration;
+3 -3
View File
@@ -3,7 +3,7 @@
Board::Board() {}
void Board::raisePOWER() noexcept {
void Board::raisePOWER() {
EightBit::Bus::raisePOWER();
CPU().raisePOWER();
@@ -16,7 +16,7 @@ void Board::raisePOWER() noexcept {
CPU().raiseHALT();
}
void Board::lowerPOWER() noexcept {
void Board::lowerPOWER() {
CPU().lowerPOWER();
EightBit::Bus::lowerPOWER();
}
@@ -33,6 +33,6 @@ void Board::initialise() {
});
}
EightBit::MemoryMapping Board::mapping(uint16_t) noexcept {
EightBit::MemoryMapping Board::mapping(uint16_t) {
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
}
+4 -4
View File
@@ -9,15 +9,15 @@ class Board final : public EightBit::Bus {
public:
Board();
constexpr EightBit::mc6809& CPU() noexcept { return m_cpu; }
constexpr EightBit::mc6809& CPU() { return m_cpu; }
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
void raisePOWER() final;
void lowerPOWER() final;
protected:
void initialise() final;
EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
EightBit::MemoryMapping mapping(uint16_t address) final;
private:
EightBit::Ram m_ram = 0x10000; // 0000 - FFFF, 64K RAM
+2 -2
View File
@@ -998,7 +998,7 @@ TEST_CASE("Subroutines", "[JSR][RTS]") {
SECTION("JSR") {
// Set up a word to test at address 0x205
cpu.pokeWord(0x205, 0x03ff);
cpu.pokeShort(0x205, 0x03ff);
// Set register D
cpu.D() = 0x105;
@@ -1044,7 +1044,7 @@ TEST_CASE("Subroutines", "[JSR][RTS]") {
cpu.S().word = 0x300;
cpu.pokeWord(0x300, 0x102C); // Write return address
cpu.pokeShort(0x300, 0x102C); // Write return address
board.poke(0xB00, 0x39); // RTS
cpu.PC().word = 0xB00;
+2 -2
View File
@@ -11,7 +11,7 @@ namespace EightBit {
virtual ~Ricoh2A03() = default;
protected:
uint8_t sub(uint8_t operand, int borrow) noexcept final;
void adc() noexcept final;
uint8_t sub(uint8_t operand, int borrow) final;
void adc() final;
};
}
+2 -2
View File
@@ -5,10 +5,10 @@ EightBit::Ricoh2A03::Ricoh2A03(Bus& bus)
: MOS6502(bus) {
}
uint8_t EightBit::Ricoh2A03::sub(uint8_t operand, int borrow) noexcept {
uint8_t EightBit::Ricoh2A03::sub(uint8_t operand, int borrow) {
return MOS6502::sub_b(operand, borrow);
}
void EightBit::Ricoh2A03::adc() noexcept {
void EightBit::Ricoh2A03::adc() {
MOS6502::adc_b();
}
+3 -3
View File
@@ -49,7 +49,7 @@ void Fuse::TestRunner::addActualEvent(const std::string& specifier) {
//
void Fuse::TestRunner::raisePOWER() noexcept {
void Fuse::TestRunner::raisePOWER() {
EightBit::Bus::raisePOWER();
m_cpu.raisePOWER();
m_cpu.raiseRESET();
@@ -58,12 +58,12 @@ void Fuse::TestRunner::raisePOWER() noexcept {
m_test.transferRegisters(m_cpu);
}
void Fuse::TestRunner::lowerPOWER() noexcept {
void Fuse::TestRunner::lowerPOWER() {
m_cpu.lowerPOWER();
EightBit::Bus::lowerPOWER();
}
EightBit::MemoryMapping Fuse::TestRunner::mapping(uint16_t address) noexcept {
EightBit::MemoryMapping Fuse::TestRunner::mapping(uint16_t address) {
return {
m_ram,
0x0000,
+3 -3
View File
@@ -42,7 +42,7 @@ namespace Fuse {
void dumpActualEvents() const;
protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
virtual EightBit::MemoryMapping mapping(uint16_t address) final;
public:
TestRunner(const Test& test, const ExpectedTestResult& expected);
@@ -51,8 +51,8 @@ namespace Fuse {
bool failed() const { return m_failed; }
bool unimplemented() const { return m_unimplemented; }
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
void raisePOWER() final;
void lowerPOWER() final;
void initialise() final;
};
+9 -3
View File
@@ -168,7 +168,7 @@ namespace EightBit {
[[nodiscard]] constexpr void displaceAddress() noexcept {
const auto& index_register = m_prefixDD ? IX() : IY();
BUS().ADDRESS() = MEMPTR() = index_register.word + m_displacement;
BUS().ADDRESS() = MEMPTR() = index_register.joined + m_displacement;
}
void fetchDisplacement() noexcept;
@@ -177,8 +177,8 @@ namespace EightBit {
uint8_t readDataUnderInterrupt() noexcept;
typedef std::function<register16_t(void)> addresser_t;
void loadAccumulatorIndirect(addresser_t addresser) noexcept;
void storeAccumulatorIndirect(addresser_t addresser) noexcept;
//void loadAccumulatorIndirect(addresser_t addresser) noexcept;
//void storeAccumulatorIndirect(addresser_t addresser) noexcept;
typedef std::function<uint8_t(void)> reader_t;
void readInternalRegister(reader_t reader) noexcept;
@@ -420,5 +420,11 @@ namespace EightBit {
void readPort(register16_t port) noexcept;
void readPort(uint8_t port) noexcept;
void readPort() noexcept;
void loadImmediate(int y);
void popRegisterPair(int p);
void pushRegisterPair(int p);
void prefixCB();
};
}
+2 -2
View File
@@ -165,7 +165,7 @@ std::string EightBit::Disassembler::alu(int which) {
}
std::string EightBit::Disassembler::disassemble(Z80& cpu) {
return disassemble(cpu, cpu.PC().word);
return disassemble(cpu, cpu.PC().joined);
}
std::string EightBit::Disassembler::disassemble(Z80& cpu, uint16_t address) {
@@ -189,7 +189,7 @@ void EightBit::Disassembler::disassemble(std::ostringstream& output, Z80& cpu, u
auto q = decoded.q;
auto immediate = BUS().peek(pc + 1);
auto absolute = cpu.peekWord(pc + 1).word;
auto absolute = cpu.peekShort(pc + 1).joined;
auto displacement = (int8_t)immediate;
auto relative = pc + displacement + 2;
auto indexedImmediate = BUS().peek(pc + 1);
+1 -1
View File
@@ -43,7 +43,7 @@ void EightBit::Profiler::dumpAddressProfiles() const {
for (int i = 0; i < 0x10000; ++i) {
auto count = m_addresses[i];
m_cpu.PC().word = i;
m_cpu.PC().joined = i;
if (count > 0)
std::cout
+90 -58
View File
@@ -25,7 +25,7 @@ EightBit::Z80::Z80(Bus& bus, InputOutput& ports) noexcept
exx();
IX() = IY() = Mask16;
resetWorkingRegisters();
resetRegisterSet();
});
RaisedM1.connect([this](EventArgs) {
@@ -186,7 +186,7 @@ void EightBit::Z80::handleRESET() noexcept {
IM() = 0;
IV() = 0;
REFRESH() = 0;
SP().word = AF().word = Mask16;
SP().joined = AF().joined = Mask16;
}
void EightBit::Z80::handleNMI() noexcept {
@@ -218,9 +218,8 @@ void EightBit::Z80::handleINT() noexcept {
IntelProcessor::handleINT();
tick();
const auto data = readDataUnderInterrupt();
tick();
assert(cycles() == 6);
switch (IM()) {
@@ -232,8 +231,8 @@ void EightBit::Z80::handleINT() noexcept {
assert(cycles() == 13);
break;
case 2:
MEMPTR() = Processor::getWordPaged(IV(), data);
call(MEMPTR());
Processor::getPagedInto(IV(), data, MEMPTR());
IntelProcessor::call();
assert(cycles() == 19);
break;
default:
@@ -366,7 +365,7 @@ void EightBit::Z80::sbc(const register16_t value) noexcept {
const auto operand = HL2();
const auto subtraction = operand.word - value.word - carry();
const auto subtraction = operand.joined - value.joined - carry();
intermediate() = subtraction;
setBit(NF);
@@ -406,7 +405,7 @@ void EightBit::Z80::add(const register16_t value, int carry) noexcept {
const auto operand = HL2();
const auto addition = operand.word + value.word + carry;
const auto addition = operand.joined + value.joined + carry;
intermediate() = addition;
clearBit(NF);
@@ -597,7 +596,7 @@ void EightBit::Z80::blockCompare() noexcept {
IntelProcessor::memoryRead(HL());
uint8_t result = A() - BUS().DATA();
setBit(PF, --BC().word);
setBit(PF, --BC().joined);
adjustSZ(result);
adjustHalfCarrySub(A(), BUS().DATA(), result);
@@ -637,7 +636,7 @@ void EightBit::Z80::cpdr() noexcept {
repeatBlockInstruction();
tick(5);
} else {
MEMPTR() = PC().word - 2;
MEMPTR() = PC().joined - 2;
tick(2);
}
}
@@ -649,7 +648,7 @@ void EightBit::Z80::blockLoad() noexcept {
setBit(XF, xy & Bit3);
setBit(YF, xy & Bit1);
clearBit(NF | HC);
setBit(PF, --BC().word);
setBit(PF, --BC().joined);
tick(2);
}
@@ -867,7 +866,8 @@ void EightBit::Z80::readPort() noexcept {
//
void EightBit::Z80::fetchDisplacement() noexcept {
m_displacement = fetchByte();
fetchByte();
m_displacement = BUS().DATA();
}
//
@@ -906,18 +906,18 @@ uint8_t EightBit::Z80::fetchInstruction() noexcept {
return data;
}
void EightBit::Z80::loadAccumulatorIndirect(addresser_t addresser) noexcept {
MEMPTR() = BUS().ADDRESS() = addresser();
++MEMPTR();
A() = memoryRead();
}
void EightBit::Z80::storeAccumulatorIndirect(addresser_t addresser) noexcept {
MEMPTR() = BUS().ADDRESS() = addresser();
++MEMPTR();
MEMPTR().high = BUS().DATA() = A();
memoryWrite();
}
//void EightBit::Z80::loadAccumulatorIndirect(addresser_t addresser) noexcept {
// MEMPTR() = BUS().ADDRESS() = addresser();
// ++MEMPTR();
// A() = memoryRead();
//}
//
//void EightBit::Z80::storeAccumulatorIndirect(addresser_t addresser) noexcept {
// MEMPTR() = BUS().ADDRESS() = addresser();
// ++MEMPTR();
// MEMPTR().high = BUS().DATA() = A();
// memoryWrite();
//}
void EightBit::Z80::readInternalRegister(reader_t reader) noexcept {
adjustSZXY(A() = reader());
@@ -1192,13 +1192,14 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p
}
break;
case 3: // Retrieve/store register pair from/to immediate address
BUS().ADDRESS() = fetchWord();
fetchShortAddress();
switch (q) {
case 0: // LD (nn), rp[p]
setWord(RP(p));
setShort(RP(p));
break;
case 1: // LD rp[p], (nn)
RP(p) = getWord();
getShort();
RP(p) = intermediate();
break;
default:
UNREACHABLE;
@@ -1359,7 +1360,8 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
jumpRelativeConditional(--B());
break;
case 3: // JR d
jumpRelative(fetchByte());
fetchByte();
jumpRelative(BUS().DATA());
break;
case 4: // JR cc,d
case 5:
@@ -1374,7 +1376,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
case 1: // 16-bit load immediate/add
switch (q) {
case 0: // LD rp,nn
RP(p) = fetchWord();
fetchInto(RP(p));
break;
case 1: // ADD HL,rp
add(RP(p));
@@ -1388,17 +1390,18 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
case 0:
switch (p) {
case 0: // LD (BC),A
storeAccumulatorIndirect([this]() { return BC(); });
writeMemoryIndirect(BC(), A());
break;
case 1: // LD (DE),A
storeAccumulatorIndirect([this]() { return DE(); });
writeMemoryIndirect(DE(), A());
break;
case 2: // LD (nn),HL
BUS().ADDRESS() = fetchWord();
setWord(HL2());
fetchShortAddress();
setShort(HL2());
break;
case 3: // LD (nn),A
storeAccumulatorIndirect([this]() { return fetchWord(); });
fetchInto(MEMPTR());
writeMemoryIndirect(A());
break;
default:
UNREACHABLE;
@@ -1407,17 +1410,23 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
case 1:
switch (p) {
case 0: // LD A,(BC)
loadAccumulatorIndirect([this]() { return BC(); });
readMemoryIndirect(BC());
A() = BUS().DATA();
break;
case 1: // LD A,(DE)
loadAccumulatorIndirect([this]() { return DE(); });
readMemoryIndirect(DE());
A() = BUS().DATA();
break;
case 2: // LD HL,(nn)
BUS().ADDRESS() = fetchWord();
HL2() = getWord();
fetchShortAddress();
getShort();
HL2() = intermediate();
break;
case 3: // LD A,(nn)
loadAccumulatorIndirect([this]() { return fetchWord(); });
fetchInto(MEMPTR());
readMemoryIndirect();
A() = BUS().DATA();
break;
default:
UNREACHABLE;
@@ -1459,12 +1468,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
break;
}
case 6: { // 8-bit load immediate
if (memoryY && displaced())
fetchDisplacement();
const auto value = fetchByte();
if (memoryY)
tick(2);
R(y, value); // LD r,n
loadImmediate(y);
break;
}
case 7: // Assorted operations on accumulator/flags
@@ -1584,7 +1588,7 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
case 1: // POP & various ops
switch (q) {
case 0: // POP rp2[p]
RP2(p) = popWord();
popRegisterPair(p);
break;
case 1:
switch (p) {
@@ -1618,19 +1622,15 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
jumpIndirect();
break;
case 1: // CB prefix
m_prefixCB = true;
if (displaced()) {
fetchDisplacement();
IntelProcessor::execute(fetchByte());
} else {
IntelProcessor::execute(fetchInstruction());
}
prefixCB();
break;
case 2: // OUT (n),A
writePort(fetchByte());
fetchByte();
writePort(BUS().DATA());
break;
case 3: // IN A,(n)
readPort(fetchByte());
fetchByte();
readPort(BUS().DATA());
A() = BUS().DATA();
break;
case 4: // EX (SP),HL
@@ -1655,8 +1655,9 @@ 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));
//tick();
//pushWord(RP2(p));
pushRegisterPair(p);
break;
case 1:
switch (p) {
@@ -1684,7 +1685,8 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
}
break;
case 6: { // Operate on accumulator and immediate operand: alu[y] n
const auto operand = fetchByte();
fetchByte();
auto operand = BUS().DATA();
switch (y) {
case 0: // ADD A,n
add(operand);
@@ -1724,3 +1726,33 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
break;
}
}
void EightBit::Z80::loadImmediate(int y) {
auto memoryY = y == 6;
if (memoryY && displaced())
fetchDisplacement();
fetchByte(); // LD r,n
if (memoryY)
tick(2);
R(y, BUS().DATA());
}
void EightBit::Z80::popRegisterPair(int p) {
popInto(RP2(p));
}
void EightBit::Z80::pushRegisterPair(int p) {
tick();
pushShort(RP2(p));
}
void EightBit::Z80::prefixCB() {
m_prefixCB = true;
if (displaced()) {
fetchDisplacement();
fetchByte();
Processor::execute(BUS().DATA());
} else {
Processor::execute(fetchInstruction());
}
}
+4 -4
View File
@@ -27,7 +27,7 @@ void Board::initialise() noexcept {
});
m_cpu.ExecutingInstruction.connect([this] (EightBit::EventArgs) {
switch (m_cpu.PC().word) {
switch (m_cpu.PC().joined) {
case 0x0: // CP/M warm start
if (++m_warmstartCount == 2) {
lowerPOWER();
@@ -46,7 +46,7 @@ void Board::initialise() noexcept {
if (m_configuration.isProfileMode())
m_cpu.ExecutingInstruction.connect([this] (EightBit::EventArgs) {
const auto pc = m_cpu.PC();
m_profiler.addAddress(pc.word);
m_profiler.addAddress(pc.joined);
m_profiler.addInstruction(peek(pc));
});
@@ -60,7 +60,7 @@ void Board::initialise() noexcept {
});
poke(0, 0xc3); // JMP
CPU().pokeWord(1, m_configuration.getStartAddress());
CPU().pokeShort(1, m_configuration.getStartAddress());
poke(5, 0xc9); // ret
}
@@ -70,7 +70,7 @@ void Board::bdos() {
std::cout << CPU().E();
break;
case 0x9:
for (uint16_t i = CPU().DE().word; peek(i) != '$'; ++i)
for (uint16_t i = CPU().DE().joined; peek(i) != '$'; ++i)
std::cout << peek(i);
break;
}
+10 -10
View File
@@ -11,21 +11,21 @@ namespace EightBit {
virtual ~BigEndianProcessor() noexcept = default;
BigEndianProcessor(const BigEndianProcessor& rhs) noexcept;
[[nodiscard]] register16_t peekWord(register16_t address) noexcept final;
void pokeWord(register16_t address, register16_t value) noexcept final;
[[nodiscard]] register16_t peekShort(uint16_t address) noexcept final;
void pokeShort(uint16_t address, register16_t value) noexcept final;
protected:
BigEndianProcessor(Bus& memory) noexcept;
[[nodiscard]] register16_t getWord() noexcept override;
void setWord(register16_t value) noexcept override;
void getInto(register16_t& into) noexcept override;
void setShort(register16_t value) noexcept override;
void getPagedInto(register16_t& into) noexcept override;
void setPaged(register16_t value) noexcept override;
[[nodiscard]] register16_t getWordPaged() noexcept override;
void setWordPaged(register16_t value) noexcept override;
void fetchInto(register16_t& into) noexcept override;
[[nodiscard]] register16_t fetchWord() noexcept override;
void pushWord(register16_t value) noexcept override;
[[nodiscard]] register16_t popWord() noexcept override;
void pushShort(register16_t value) noexcept override;
void popInto(register16_t& into) noexcept override;
};
}
+3 -3
View File
@@ -27,11 +27,11 @@ namespace EightBit {
[[nodiscard]] constexpr auto& DATA() noexcept { return m_data; }
[[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.joined); }
void poke(const uint8_t value) noexcept { reference() = 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.joined, value); }
[[nodiscard]] uint8_t read() noexcept;
void write() noexcept;
@@ -43,7 +43,7 @@ namespace EightBit {
protected:
[[nodiscard]] uint8_t& reference(uint16_t address) noexcept;
[[nodiscard]] uint8_t& reference() noexcept { return reference(ADDRESS().word); }
[[nodiscard]] uint8_t& reference() noexcept { return reference(ADDRESS().joined); }
void loadHexFile(const std::string& path);
+17 -7
View File
@@ -132,7 +132,7 @@ namespace EightBit {
void handleINT() noexcept override;
void push(uint8_t value) noexcept final;
[[nodiscard]] uint8_t pop() noexcept final;
void pop() noexcept final;
//
@@ -141,26 +141,25 @@ namespace EightBit {
//
[[nodiscard]] register16_t getWord() noexcept final;
void setWord(register16_t value) noexcept final;
void getShort() noexcept final;
void setShort(register16_t value) noexcept final;
//
void restart(uint8_t address) noexcept;
void callConditional(bool condition) noexcept;
virtual void jumpConditional(bool condition) noexcept;
void jumpRelativeConditional(bool condition) noexcept;
virtual void jumpRelativeConditional(bool condition) noexcept;
virtual void returnConditional(bool condition) noexcept;
void jumpIndirect() noexcept;
virtual void jumpIndirect() noexcept;
void jump() noexcept;
void callIndirect() noexcept;
void call() noexcept;
virtual void call(register16_t destination) noexcept;
virtual void jumpRelative(int8_t offset) noexcept;
void jumpRelative(uint8_t offset) noexcept { jumpRelative(static_cast<int8_t>(offset)); }
void ret() noexcept override;
void resetWorkingRegisters() noexcept;
void resetRegisterSet() noexcept;
[[nodiscard]] virtual bool convertCondition(int flag) noexcept = 0;
@@ -171,6 +170,17 @@ namespace EightBit {
virtual void cpl() noexcept;
void readMemoryIndirect(register16_t via) noexcept;
void readMemoryIndirect() noexcept;
void writeMemoryIndirect(register16_t via, uint8_t data) noexcept;
void writeMemoryIndirect(uint8_t data) noexcept;
virtual void memoryUpdate(int ticks) noexcept = 0;
virtual uint8_t& R(int r, MemoryMapping::AccessLevel access) noexcept = 0;
void R(int r, uint8_t value, int ticks = 1) noexcept;
private:
static std::array<int, 8> m_halfCarryTableAdd;
static std::array<int, 8> m_halfCarryTableSub;
+9 -9
View File
@@ -11,21 +11,21 @@ namespace EightBit {
virtual ~LittleEndianProcessor() noexcept = default;
LittleEndianProcessor(const LittleEndianProcessor& rhs) noexcept;
[[nodiscard]] register16_t peekWord(register16_t address) noexcept final;
void pokeWord(register16_t address, register16_t value) noexcept final;
[[nodiscard]] register16_t peekShort(uint16_t address) noexcept final;
void pokeShort(uint16_t address, register16_t value) noexcept final;
protected:
LittleEndianProcessor(Bus& memory) noexcept;
[[nodiscard]] register16_t getWord() noexcept override;
void setWord(register16_t value) noexcept override;
void getInto(register16_t& into) noexcept override;
void setShort(register16_t value) noexcept override;
[[nodiscard]] register16_t getWordPaged() noexcept override;
void setWordPaged(register16_t value) noexcept override;
void getPagedInto(register16_t& into) noexcept override;
void setPaged(register16_t value) noexcept override;
[[nodiscard]] register16_t fetchWord() noexcept override;
void fetchInto(register16_t& into) noexcept override;
void pushWord(register16_t value) noexcept override;
[[nodiscard]] register16_t popWord() noexcept override;
void pushShort(register16_t value) noexcept override;
void popInto(register16_t& into) noexcept override;
};
}
+22 -18
View File
@@ -45,8 +45,8 @@ namespace EightBit {
virtual void execute() noexcept = 0;
void execute(uint8_t value) noexcept;
[[nodiscard]] virtual register16_t peekWord(register16_t address) noexcept = 0;
virtual void pokeWord(register16_t address, register16_t value) noexcept = 0;
[[nodiscard]] virtual register16_t peekShort(uint16_t address) noexcept = 0;
virtual void pokeShort(uint16_t address, register16_t value) noexcept = 0;
DECLARE_PIN_INPUT(RESET)
DECLARE_PIN_INPUT(INT)
@@ -71,33 +71,37 @@ namespace EightBit {
virtual uint8_t busRead() noexcept;
virtual register16_t& incrementPC() noexcept;
virtual register16_t& decrementPC() noexcept;
virtual void immediateAddress() noexcept;
uint8_t fetchByte() noexcept;
void fetchByte() noexcept;
virtual uint8_t fetchInstruction() noexcept;
[[nodiscard]] virtual register16_t getWord() noexcept = 0;
virtual void setWord(register16_t value) noexcept = 0;
virtual void getInto(register16_t& into) noexcept = 0;
virtual void getShort() noexcept { getInto(m_intermediate); }
virtual void setShort(register16_t value) noexcept = 0;
[[nodiscard]] register16_t getWordPaged(register16_t address) noexcept;
[[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept;
[[nodiscard]] virtual register16_t getWordPaged() noexcept = 0;
void setWordPaged(register16_t address, register16_t value) noexcept;
void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept;
virtual void setWordPaged(register16_t value) noexcept = 0;
void getShortPaged(register16_t address) noexcept;
void getShortPaged(uint8_t page, uint8_t offset) noexcept;
void getPagedInto(uint8_t page, uint8_t offset, register16_t& into);
void getShortPaged() noexcept { getPagedInto(m_intermediate); }
virtual void getPagedInto(register16_t& into) noexcept = 0;
void setPaged(register16_t address, register16_t value) noexcept;
void setPaged(uint8_t page, uint8_t offset, register16_t value) noexcept;
virtual void setPaged(register16_t value) noexcept = 0;
[[nodiscard]] virtual register16_t fetchWord() noexcept = 0;
virtual void fetchInto(register16_t& into) noexcept = 0;
void fetchShort() noexcept { fetchInto(m_intermediate); }
void fetchShortAddress() noexcept;
virtual void push(uint8_t value) noexcept = 0;
[[nodiscard]] virtual uint8_t pop() noexcept = 0;
virtual void pop() noexcept = 0;
virtual void pushWord(register16_t value) noexcept = 0;
[[nodiscard]] virtual register16_t popWord() noexcept = 0;
virtual void pushShort(register16_t value) noexcept = 0;
virtual void popInto(register16_t& into) noexcept = 0;
[[nodiscard]] register16_t getWord(register16_t address) noexcept;
void setWord(register16_t address, register16_t value) noexcept;
void getShort(register16_t address) noexcept;
void setShort(register16_t address, register16_t value) noexcept;
void jump(const register16_t destination) noexcept;
void jump(uint16_t destination) noexcept;
+16 -16
View File
@@ -31,19 +31,19 @@ namespace EightBit {
uint8_t low;
#endif
};
uint16_t word;
uint16_t joined;
constexpr register16_t() noexcept : word(0) {}
constexpr register16_t(const uint16_t w) noexcept : word(w) {}
constexpr register16_t() noexcept : joined(0) {}
constexpr register16_t(const uint16_t w) noexcept : joined(w) {}
constexpr register16_t(const uint8_t l, const uint8_t h) noexcept : low(l), high(h) {}
constexpr auto& operator++() noexcept {
++word;
++joined;
return *this;
}
constexpr auto& operator--() noexcept {
--word;
--joined;
return *this;
}
@@ -60,24 +60,24 @@ namespace EightBit {
}
constexpr auto& operator+=(const register16_t rhs) noexcept {
this->word += rhs.word;
this->joined += rhs.joined;
return *this;
}
constexpr auto& operator-=(const register16_t rhs) noexcept {
this->word -= rhs.word;
this->joined -= rhs.joined;
return *this;
}
[[nodiscard]] constexpr auto operator==(const register16_t& rhs) const noexcept { return word == rhs.word; }
[[nodiscard]] constexpr auto operator!=(const register16_t& rhs) const noexcept { return word != rhs.word; }
[[nodiscard]] constexpr auto operator<(const register16_t& rhs) const noexcept { return word < rhs.word; }
[[nodiscard]] constexpr auto operator<=(const register16_t& rhs) const noexcept { return word <= rhs.word; }
[[nodiscard]] constexpr auto operator>(const register16_t& rhs) const noexcept { return word > rhs.word; }
[[nodiscard]] constexpr auto operator>=(const register16_t& rhs) const noexcept { return word >= rhs.word; }
[[nodiscard]] constexpr auto operator==(const register16_t& rhs) const noexcept { return joined == rhs.joined; }
[[nodiscard]] constexpr auto operator!=(const register16_t& rhs) const noexcept { return joined != rhs.joined; }
[[nodiscard]] constexpr auto operator<(const register16_t& rhs) const noexcept { return joined < rhs.joined; }
[[nodiscard]] constexpr auto operator<=(const register16_t& rhs) const noexcept { return joined <= rhs.joined; }
[[nodiscard]] constexpr auto operator>(const register16_t& rhs) const noexcept { return joined > rhs.joined; }
[[nodiscard]] constexpr auto operator>=(const register16_t& rhs) const noexcept { return joined >= rhs.joined; }
[[nodiscard]] constexpr auto zero() const noexcept { return word == 0; }
[[nodiscard]] constexpr auto nonzero() const noexcept { return word != 0; }
[[nodiscard]] constexpr auto zero() const noexcept { return joined == 0; }
[[nodiscard]] constexpr auto nonzero() const noexcept { return joined != 0; }
};
[[nodiscard]] constexpr inline auto operator+(register16_t lhs, const register16_t rhs) noexcept {
@@ -91,6 +91,6 @@ namespace EightBit {
}
inline auto& operator<<(std::ostream& output, const register16_t value) {
return output << std::hex << std::setw(4) << std::setfill('0') << value.word;
return output << std::hex << std::setw(4) << std::setfill('0') << value.joined;
}
}
+39 -35
View File
@@ -7,56 +7,60 @@ EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory) noexcept
EightBit::BigEndianProcessor::BigEndianProcessor(const BigEndianProcessor& rhs) noexcept
: Processor(rhs) {}
EightBit::register16_t EightBit::BigEndianProcessor::getWord() noexcept {
const auto high = memoryRead();
++BUS().ADDRESS();
const auto low = memoryRead();
EightBit::register16_t EightBit::BigEndianProcessor::peekShort(uint16_t address) noexcept {
const auto high = BUS().peek(address);
const auto low = BUS().peek(++address);
return { low, high };
}
void EightBit::BigEndianProcessor::setWord(const register16_t value) noexcept {
memoryWrite(value.high);
void EightBit::BigEndianProcessor::pokeShort(uint16_t address, const register16_t value) noexcept {
BUS().poke(address, value.high);
BUS().poke(++address, value.low);
}
void EightBit::BigEndianProcessor::fetchInto(register16_t& into) noexcept {
fetchByte();
into.high = BUS().DATA();
fetchByte();
into.low = BUS().DATA();
}
void EightBit::BigEndianProcessor::getInto(register16_t& into) noexcept {
memoryRead();
into.high = BUS().DATA();
++BUS().ADDRESS();
memoryWrite(value.low);
memoryRead();
into.low = BUS().DATA();
}
EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged() noexcept {
const auto high = memoryRead();
void EightBit::BigEndianProcessor::getPagedInto(register16_t& into) noexcept {
memoryRead();
into.high = BUS().DATA();
++BUS().ADDRESS().low;
const auto low = memoryRead();
return { low, high };
memoryRead();
into.low = BUS().DATA();
}
void EightBit::BigEndianProcessor::setWordPaged(const register16_t value) noexcept {
memoryWrite(value.high);
++BUS().ADDRESS().low;
memoryWrite(value.low);
void EightBit::BigEndianProcessor::popInto(register16_t& into) noexcept {
pop();
into.high = BUS().DATA();
pop();
into.low = BUS().DATA();
}
EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() noexcept {
intermediate().high = fetchByte();
intermediate().low = fetchByte();
return intermediate();
}
void EightBit::BigEndianProcessor::pushWord(const register16_t value) noexcept {
void EightBit::BigEndianProcessor::pushShort(register16_t value) noexcept {
push(value.low);
push(value.high);
}
EightBit::register16_t EightBit::BigEndianProcessor::popWord() noexcept {
const auto high = pop();
const auto low = pop();
return { low, high };
void EightBit::BigEndianProcessor::setShort(register16_t value) noexcept {
memoryWrite(value.high);
++BUS().ADDRESS();
memoryWrite(value.low);
}
EightBit::register16_t EightBit::BigEndianProcessor::peekWord(const register16_t address) noexcept {
const auto high = BUS().peek(address);
const auto low = BUS().peek(address + 1);
return { low, high };
}
void EightBit::BigEndianProcessor::pokeWord(const register16_t address, const register16_t value) noexcept {
BUS().poke(address, value.high);
BUS().poke(address + 1, value.low);
void EightBit::BigEndianProcessor::setPaged(register16_t value) noexcept {
memoryWrite(value.high);
++BUS().ADDRESS().low;
memoryWrite(value.low);
}
+4 -4
View File
@@ -11,13 +11,13 @@ uint8_t InputOutput::read(register16_t port) {
uint8_t InputOutput::readInputPort(register16_t port) {
ReadingPort.fire(port);
const auto value = _input[port.word];
const auto value = _input[port.joined];
ReadPort.fire(port);
return value;
}
void InputOutput::writeInputPort(register16_t port, uint8_t value) {
_input[port.word] = value;
_input[port.joined] = value;
}
// Output port actions
@@ -28,12 +28,12 @@ void InputOutput::write(register16_t port, uint8_t value) {
void InputOutput::writeOutputPort(register16_t port, uint8_t value) {
WritingPort.fire(port);
_output[port.word] = value;
_output[port.joined] = value;
WrittenPort.fire(port);
}
uint8_t InputOutput::readOutputPort(register16_t port) {
return _output[port.word];
return _output[port.joined];
}
}
+46 -22
View File
@@ -11,7 +11,7 @@ EightBit::IntelProcessor::IntelProcessor(Bus& bus) noexcept
RaisedPOWER.connect([this](EventArgs) {
PC() = SP() = Mask16;
resetWorkingRegisters();
resetRegisterSet();
raiseHALT();
});
}
@@ -23,7 +23,7 @@ EightBit::IntelProcessor::IntelProcessor(const IntelProcessor& rhs) noexcept
HALT() = rhs.HALT();
}
void EightBit::IntelProcessor::resetWorkingRegisters() noexcept {
void EightBit::IntelProcessor::resetRegisterSet() noexcept {
AF() = BC() = DE() = HL() = Mask16;
}
@@ -45,8 +45,8 @@ void EightBit::IntelProcessor::push(const uint8_t value) noexcept {
memoryWrite(--SP(), value);
}
uint8_t EightBit::IntelProcessor::pop() noexcept {
return memoryRead(SP()++);
void EightBit::IntelProcessor::pop() noexcept {
memoryRead(SP()++);
}
EightBit::register16_t& EightBit::IntelProcessor::incrementPC() noexcept {
@@ -56,18 +56,17 @@ EightBit::register16_t& EightBit::IntelProcessor::incrementPC() noexcept {
}
uint8_t EightBit::IntelProcessor::fetchInstruction() noexcept {
const auto data = fetchByte();
return proceeding() ? data : (uint8_t)0;
fetchByte();
return proceeding() ? BUS().DATA() : (uint8_t)0;
}
EightBit::register16_t EightBit::IntelProcessor::getWord() noexcept {
const auto returned = LittleEndianProcessor::getWord();
void EightBit::IntelProcessor::getShort() noexcept {
LittleEndianProcessor::getShort();
MEMPTR() = BUS().ADDRESS();
return returned;
}
void EightBit::IntelProcessor::setWord(const register16_t value) noexcept {
LittleEndianProcessor::setWord(value);
void EightBit::IntelProcessor::setShort(const register16_t value) noexcept {
LittleEndianProcessor::setShort(value);
MEMPTR() = BUS().ADDRESS();
}
@@ -77,21 +76,21 @@ void EightBit::IntelProcessor::restart(const uint8_t address) noexcept {
}
void EightBit::IntelProcessor::callConditional(bool condition) noexcept {
MEMPTR() = fetchWord();
fetchInto(MEMPTR());
if (condition)
call();
}
void EightBit::IntelProcessor::jumpConditional(bool condition) noexcept {
MEMPTR() = fetchWord();
fetchInto(MEMPTR());
if (condition)
jump();
}
void EightBit::IntelProcessor::jumpRelativeConditional(bool condition) noexcept {
const auto offset = fetchByte();
fetchByte();
if (condition)
jumpRelative(offset);
jumpRelative(BUS().DATA());
}
void EightBit::IntelProcessor::returnConditional(bool condition) noexcept {
@@ -110,7 +109,7 @@ void EightBit::IntelProcessor::ret() noexcept {
}
void EightBit::IntelProcessor::jumpIndirect() noexcept {
MEMPTR() = fetchWord();
fetchInto(MEMPTR());
jump();
}
@@ -119,16 +118,12 @@ void EightBit::IntelProcessor::jump() noexcept {
}
void EightBit::IntelProcessor::callIndirect() noexcept {
MEMPTR() = fetchWord();
fetchInto(MEMPTR());
call();
}
void EightBit::IntelProcessor::call() noexcept {
call(MEMPTR());
}
void EightBit::IntelProcessor::call(register16_t destination) noexcept {
Processor::call(destination);
LittleEndianProcessor::call(MEMPTR());
}
void EightBit::IntelProcessor::jumpConditionalFlag(int flag) noexcept {
@@ -164,3 +159,32 @@ bool EightBit::IntelProcessor::operator==(const EightBit::IntelProcessor& rhs) c
&& left.DE() == right.DE()
&& left.HL() == right.HL();
}
void EightBit::IntelProcessor::readMemoryIndirect(register16_t via) noexcept {
MEMPTR() = via;
readMemoryIndirect();
}
void EightBit::IntelProcessor::readMemoryIndirect() noexcept {
BUS().ADDRESS() = MEMPTR();
++MEMPTR();
memoryRead();
}
void EightBit::IntelProcessor::writeMemoryIndirect(register16_t via, uint8_t data) noexcept {
MEMPTR() = via;
writeMemoryIndirect(data);
}
void EightBit::IntelProcessor::writeMemoryIndirect(uint8_t data) noexcept {
BUS().ADDRESS() = MEMPTR();
++MEMPTR();
MEMPTR().high = BUS().DATA() = data;
memoryWrite();
}
void EightBit::IntelProcessor::R(int r, uint8_t value, int ticks) noexcept {
R(r, MemoryMapping::AccessLevel::WriteOnly) = value;
if (r == 6)
memoryUpdate(ticks);
}
+39 -35
View File
@@ -7,56 +7,60 @@ EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory) noexcept
EightBit::LittleEndianProcessor::LittleEndianProcessor(const LittleEndianProcessor& rhs) noexcept
: Processor(rhs) {}
EightBit::register16_t EightBit::LittleEndianProcessor::getWord() noexcept {
const auto low = memoryRead();
++BUS().ADDRESS();
const auto high = memoryRead();
EightBit::register16_t EightBit::LittleEndianProcessor::peekShort(uint16_t address) noexcept {
const auto low = BUS().peek(address);
const auto high = BUS().peek(++address);
return { low, high };
}
void EightBit::LittleEndianProcessor::setWord(const register16_t value) noexcept {
memoryWrite(value.low);
void EightBit::LittleEndianProcessor::pokeShort(uint16_t address, const register16_t value) noexcept {
BUS().poke(address, value.low);
BUS().poke(++address, value.high);
}
void EightBit::LittleEndianProcessor::fetchInto(register16_t& into) noexcept {
fetchByte();
into.low = BUS().DATA();
fetchByte();
into.high = BUS().DATA();
}
void EightBit::LittleEndianProcessor::getInto(register16_t& into) noexcept {
memoryRead();
into.low = BUS().DATA();
++BUS().ADDRESS();
memoryWrite(value.high);
memoryRead();
into.high = BUS().DATA();
}
EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged() noexcept {
const auto low = memoryRead();
void EightBit::LittleEndianProcessor::getPagedInto(register16_t& into) noexcept {
memoryRead();
into.low = BUS().DATA();
++BUS().ADDRESS().low;
const auto high = memoryRead();
return { low, high };
memoryRead();
into.high = BUS().DATA();
}
void EightBit::LittleEndianProcessor::setWordPaged(register16_t value) noexcept {
memoryWrite(value.low);
++BUS().ADDRESS().low;
memoryWrite(value.high);
void EightBit::LittleEndianProcessor::popInto(register16_t& into) noexcept {
pop();
into.low = BUS().DATA();
pop();
into.high = BUS().DATA();
}
EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() noexcept {
intermediate().low = fetchByte();
intermediate().high = fetchByte();
return intermediate();
}
void EightBit::LittleEndianProcessor::pushWord(const register16_t value) noexcept {
void EightBit::LittleEndianProcessor::pushShort(register16_t value) noexcept {
push(value.high);
push(value.low);
}
EightBit::register16_t EightBit::LittleEndianProcessor::popWord() noexcept {
const auto low = pop();
const auto high = pop();
return { low, high };
void EightBit::LittleEndianProcessor::setShort(register16_t value) noexcept {
memoryWrite(value.low);
++BUS().ADDRESS();
memoryWrite(value.high);
}
EightBit::register16_t EightBit::LittleEndianProcessor::peekWord(const register16_t address) noexcept {
const auto low = BUS().peek(address);
const auto high = BUS().peek(address + 1);
return { low, high };
}
void EightBit::LittleEndianProcessor::pokeWord(const register16_t address, const register16_t value) noexcept {
BUS().poke(address, value.low);
BUS().poke(address + 1, value.high);
void EightBit::LittleEndianProcessor::setPaged(register16_t value) noexcept {
memoryWrite(value.low);
++BUS().ADDRESS().low;
memoryWrite(value.high);
}
+30 -24
View File
@@ -62,65 +62,71 @@ uint8_t EightBit::Processor::busRead() noexcept {
return BUS().read();
}
EightBit::register16_t EightBit::Processor::getWordPaged(register16_t address) noexcept {
void EightBit::Processor::getShortPaged(register16_t address) noexcept {
BUS().ADDRESS() = address;
return getWordPaged();
getShortPaged();
}
EightBit::register16_t EightBit::Processor::getWordPaged(const uint8_t page, const uint8_t offset) noexcept {
void EightBit::Processor::getShortPaged(const uint8_t page, const uint8_t offset) noexcept {
BUS().ADDRESS() = { offset, page };
return getWordPaged();
getShortPaged();
}
void EightBit::Processor::setWordPaged(register16_t address, const register16_t value) noexcept {
void EightBit::Processor::getPagedInto(uint8_t page, uint8_t offset, register16_t& into) {
BUS().ADDRESS() = { offset, page };
getPagedInto(into);
}
void EightBit::Processor::setPaged(register16_t address, const register16_t value) noexcept {
BUS().ADDRESS() = address;
setWordPaged(value);
setPaged(value);
}
void EightBit::Processor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) noexcept {
void EightBit::Processor::setPaged(const uint8_t page, const uint8_t offset, const register16_t value) noexcept {
BUS().ADDRESS() = { offset, page };
setWordPaged(value);
setPaged(value);
}
EightBit::register16_t& EightBit::Processor::incrementPC() noexcept {
return ++PC();
}
EightBit::register16_t& EightBit::Processor::decrementPC() noexcept {
return --PC();
}
void EightBit::Processor::immediateAddress() noexcept {
BUS().ADDRESS() = PC();
incrementPC();
}
uint8_t EightBit::Processor::fetchByte() noexcept {
void EightBit::Processor::fetchByte() noexcept {
immediateAddress();
return memoryRead();
memoryRead();
}
uint8_t EightBit::Processor::fetchInstruction() noexcept {
return fetchByte();
fetchByte();
return BUS().DATA();
}
EightBit::register16_t EightBit::Processor::getWord(const register16_t address) noexcept {
BUS().ADDRESS() = address;
return getWord();
void EightBit::Processor::fetchShortAddress() noexcept {
fetchShort();
BUS().ADDRESS() = m_intermediate;
}
void EightBit::Processor::setWord(const register16_t address, const register16_t value) noexcept {
void EightBit::Processor::getShort(const register16_t address) noexcept {
BUS().ADDRESS() = address;
setWord(value);
getShort();
}
void EightBit::Processor::setShort(const register16_t address, const register16_t value) noexcept {
BUS().ADDRESS() = address;
setShort(value);
}
int EightBit::Processor::step() noexcept {
resetCycles();
ExecutingInstruction.fire();
if (LIKELY(powered()))
if (powered())
poweredStep();
ExecutedInstruction.fire();
// ASSUME(cycles() > 0); Not if unpowered!!
return cycles();
}
@@ -145,12 +151,12 @@ void EightBit::Processor::jump(const uint16_t destination) noexcept {
}
void EightBit::Processor::call(const register16_t destination) noexcept {
pushWord(PC());
pushShort(PC());
jump(destination);
}
void EightBit::Processor::ret() noexcept {
jump(popWord());
popInto(PC());
}
bool EightBit::Processor::operator==(const EightBit::Processor& rhs) const noexcept {