diff --git a/Intel8080/inc/Disassembler.h b/Intel8080/inc/Disassembler.h index 95b006c..47d1ff9 100644 --- a/Intel8080/inc/Disassembler.h +++ b/Intel8080/inc/Disassembler.h @@ -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); diff --git a/Intel8080/inc/Intel8080.h b/Intel8080/inc/Intel8080.h index 4798885..b7168a2 100644 --- a/Intel8080/inc/Intel8080.h +++ b/Intel8080/inc/Intel8080.h @@ -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 ExecutingInstruction; - Signal 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()); } }; } \ No newline at end of file diff --git a/Intel8080/src/Disassembler.cpp b/Intel8080/src/Disassembler.cpp index 2694737..123f10f 100644 --- a/Intel8080/src/Disassembler.cpp +++ b/Intel8080/src/Disassembler.cpp @@ -6,7 +6,7 @@ #include #include -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); diff --git a/Intel8080/src/Intel8080.cpp b/Intel8080/src/Intel8080.cpp index d34c447..86afe35 100644 --- a/Intel8080/src/Intel8080.cpp +++ b/Intel8080/src/Intel8080.cpp @@ -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(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(F(), ++operand); - F() = clearBit(F(), AC, lowNibble(operand)); -} - -void EightBit::Intel8080::decrement(uint8_t& operand) { - F() = adjustSZP(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(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(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(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(F(), A() ^= value); + clearBit(AC | CF); + adjustSZP(A() ^= value); } void EightBit::Intel8080::orr(const uint8_t value) { - F() = clearBit(F(), AC | CF); - F() = adjustSZP(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); diff --git a/Intel8080/test/Board.cpp b/Intel8080/test/Board.cpp index 2799beb..3077583 100644 --- a/Intel8080/test/Board.cpp +++ b/Intel8080/test/Board.cpp @@ -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; diff --git a/Intel8080/test/Board.h b/Intel8080/test/Board.h index ba86b67..75186d2 100644 --- a/Intel8080/test/Board.h +++ b/Intel8080/test/Board.h @@ -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(); }; diff --git a/LR35902/fusetest_LR35902/FuseTestRunner.cpp b/LR35902/fusetest_LR35902/FuseTestRunner.cpp index 037a69f..d62e0f1 100644 --- a/LR35902/fusetest_LR35902/FuseTestRunner.cpp +++ b/LR35902/fusetest_LR35902/FuseTestRunner.cpp @@ -23,7 +23,7 @@ void Fuse::TestRunner::lowerPOWER() noexcept { EightBit::Bus::lowerPOWER(); } -void Fuse::TestRunner::initialise() { +void Fuse::TestRunner::initialise() noexcept { disableGameRom(); } diff --git a/LR35902/fusetest_LR35902/FuseTestRunner.h b/LR35902/fusetest_LR35902/FuseTestRunner.h index d378639..8ab05d5 100644 --- a/LR35902/fusetest_LR35902/FuseTestRunner.h +++ b/LR35902/fusetest_LR35902/FuseTestRunner.h @@ -49,6 +49,6 @@ namespace Fuse { void raisePOWER() noexcept final; void lowerPOWER() noexcept final; - void initialise(); + void initialise() noexcept; }; } \ No newline at end of file diff --git a/LR35902/inc/AbstractColourPalette.h b/LR35902/inc/AbstractColourPalette.h index d2137e0..95f2f99 100644 --- a/LR35902/inc/AbstractColourPalette.h +++ b/LR35902/inc/AbstractColourPalette.h @@ -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]; } diff --git a/LR35902/inc/CharacterDefinition.h b/LR35902/inc/CharacterDefinition.h index a6f2f74..04cf2dd 100644 --- a/LR35902/inc/CharacterDefinition.h +++ b/LR35902/inc/CharacterDefinition.h @@ -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 get(int row) const noexcept; + [[nodiscard]] std::array get(int row) const; private: Ram& m_vram; diff --git a/LR35902/inc/Disassembler.h b/LR35902/inc/Disassembler.h index 4c950ef..1acf52a 100644 --- a/LR35902/inc/Disassembler.h +++ b/LR35902/inc/Disassembler.h @@ -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; } }; } } \ No newline at end of file diff --git a/LR35902/inc/Display.h b/LR35902/inc/Display.h index 14994a9..0d7d0fc 100644 --- a/LR35902/inc/Display.h +++ b/LR35902/inc/Display.h @@ -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 createPalette(int address) noexcept; + [[nodiscard]] std::array 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& palette) noexcept; + const std::array& palette); void renderBackgroundTile( int definitionOffset, int row, int column, int bgCharacters, tile_offset_t offsetType, int offsetX, int offsetY, - const std::array& palette) noexcept; + const std::array& palette); - void renderObjects() noexcept; + void renderObjects(); void renderSpriteTile( int height, int drawX, int drawY, bool flipX, bool flipY, const std::array& palette, - const CharacterDefinition& definition) noexcept; + const CharacterDefinition& definition); void renderBackgroundTile( int drawX, int drawY, const std::array& 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& palette, - const CharacterDefinition& definition) noexcept; + const CharacterDefinition& definition); }; } } \ No newline at end of file diff --git a/LR35902/inc/GameBoyBus.h b/LR35902/inc/GameBoyBus.h index 261d433..e9ccbb6 100644 --- a/LR35902/inc/GameBoyBus.h +++ b/LR35902/inc/GameBoyBus.h @@ -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); diff --git a/LR35902/inc/IoRegisters.h b/LR35902/inc/IoRegisters.h index dfd1020..fcc9a45 100644 --- a/LR35902/inc/IoRegisters.h +++ b/LR35902/inc/IoRegisters.h @@ -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; diff --git a/LR35902/inc/LR35902.h b/LR35902/inc/LR35902.h index 06f0917..122349b 100644 --- a/LR35902/inc/LR35902.h +++ b/LR35902/inc/LR35902.h @@ -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 ExecutingInstruction; Signal 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 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); }; } } \ No newline at end of file diff --git a/LR35902/inc/ObjectAttribute.h b/LR35902/inc/ObjectAttribute.h index 5a08fa4..ed90c10 100644 --- a/LR35902/inc/ObjectAttribute.h +++ b/LR35902/inc/ObjectAttribute.h @@ -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; diff --git a/LR35902/src/CharacterDefinition.cpp b/LR35902/src/CharacterDefinition.cpp index c60b019..6031261 100644 --- a/LR35902/src/CharacterDefinition.cpp +++ b/LR35902/src/CharacterDefinition.cpp @@ -3,12 +3,12 @@ #include -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 EightBit::GameBoy::CharacterDefinition::get(int row) const noexcept { +std::array EightBit::GameBoy::CharacterDefinition::get(int row) const { std::array returned {}; diff --git a/LR35902/src/Disassembler.cpp b/LR35902/src/Disassembler.cpp index b0b20f3..7ba0957 100644 --- a/LR35902/src/Disassembler.cpp +++ b/LR35902/src/Disassembler.cpp @@ -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); diff --git a/LR35902/src/Display.cpp b/LR35902/src/Display.cpp index 72e6460..6280473 100644 --- a/LR35902/src/Display.cpp +++ b/LR35902/src/Display.cpp @@ -7,7 +7,7 @@ #include -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 EightBit::GameBoy::Display::createPalette(const int address) noexcept { +std::array EightBit::GameBoy::Display::createPalette(const int address) { const auto raw = m_bus.IO().peek(address); const std::array palette = { raw & 0b11, @@ -39,12 +39,12 @@ std::array 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& palette) noexcept { + const std::array& 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& 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& palette) noexcept { + const std::array& 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& 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& palette, - const CharacterDefinition& definition) noexcept { + const CharacterDefinition& definition) { const auto width = 8; diff --git a/LR35902/src/GameBoyBus.cpp b/LR35902/src/GameBoyBus.cpp index a27e4dd..248ea2b 100644 --- a/LR35902/src/GameBoyBus.cpp +++ b/LR35902/src/GameBoyBus.cpp @@ -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(); diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp index 197e311..bc790fe 100644 --- a/LR35902/src/LR35902.cpp +++ b/LR35902/src/LR35902.cpp @@ -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(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(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(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(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) { diff --git a/M6502/HarteTest_6502/TestRunner.cpp b/M6502/HarteTest_6502/TestRunner.cpp index f175339..8683ce8 100644 --- a/M6502/HarteTest_6502/TestRunner.cpp +++ b/M6502/HarteTest_6502/TestRunner.cpp @@ -22,4 +22,4 @@ void TestRunner::lowerPOWER() noexcept { EightBit::Bus::lowerPOWER(); } -void TestRunner::initialise() {} +void TestRunner::initialise() noexcept {} diff --git a/M6502/HarteTest_6502/TestRunner.h b/M6502/HarteTest_6502/TestRunner.h index 874aed8..b6afd2e 100644 --- a/M6502/HarteTest_6502/TestRunner.h +++ b/M6502/HarteTest_6502/TestRunner.h @@ -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; } diff --git a/M6502/inc/Disassembly.h b/M6502/inc/Disassembly.h index d534a5f..5e6710f 100644 --- a/M6502/inc/Disassembly.h +++ b/M6502/inc/Disassembly.h @@ -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); diff --git a/M6502/inc/mos6502.h b/M6502/inc/mos6502.h index 3bc1955..6a2df34 100644 --- a/M6502/inc/mos6502.h +++ b/M6502/inc/mos6502.h @@ -35,11 +35,11 @@ namespace EightBit { MOS6502(Bus& bus) noexcept; - Signal ExecutingInstruction; - Signal ExecutedInstruction; + //Signal ExecutingInstruction; + //Signal 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 diff --git a/M6502/src/Disassembly.cpp b/M6502/src/Disassembly.cpp index 9a39795..8996b48 100644 --- a/M6502/src/Disassembly.cpp +++ b/M6502/src/Disassembly.cpp @@ -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)); } //// diff --git a/M6502/src/mos6502.cpp b/M6502/src/mos6502.cpp index 97001ba..4f35d76 100644 --- a/M6502/src/mos6502.cpp +++ b/M6502/src/mos6502.cpp @@ -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 diff --git a/M6502/test/Board.cpp b/M6502/test/Board.cpp index 7a5c38d..7180d27 100644 --- a/M6502/test/Board.cpp +++ b/M6502/test/Board.cpp @@ -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()); } diff --git a/M6532/inc/M6532.h b/M6532/inc/M6532.h index ea57564..dcb2760 100644 --- a/M6532/inc/M6532.h +++ b/M6532/inc/M6532.h @@ -181,7 +181,7 @@ namespace EightBit { class M6532 final : public ClockedChip { public: - M6532() noexcept; + M6532(); virtual ~M6532() = default; /* ___ diff --git a/M6532/src/M6532.cpp b/M6532/src/M6532.cpp index d17d0f4..ba6d09e 100644 --- a/M6532/src/M6532.cpp +++ b/M6532/src/M6532.cpp @@ -3,7 +3,7 @@ #include -EightBit::M6532::M6532() noexcept { +EightBit::M6532::M6532() { Ticked.connect([this](EightBit::EventArgs&) { step(); }); diff --git a/MC6809/inc/Disassembly.h b/MC6809/inc/Disassembly.h index 157d5e7..c2cd501 100644 --- a/MC6809/inc/Disassembly.h +++ b/MC6809/inc/Disassembly.h @@ -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(); diff --git a/MC6809/inc/mc6809.h b/MC6809/inc/mc6809.h index da024e4..999bb98 100644 --- a/MC6809/inc/mc6809.h +++ b/MC6809/inc/mc6809.h @@ -67,31 +67,31 @@ namespace EightBit { Signal 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 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 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 constexpr void adjustNZ(const T datum) noexcept { + template 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 constexpr T through(const T data) noexcept { + template 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); diff --git a/MC6809/src/Disassembly.cpp b/MC6809/src/Disassembly.cpp index a808883..ffe76ef 100644 --- a/MC6809/src/Disassembly.cpp +++ b/MC6809/src/Disassembly.cpp @@ -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; } // diff --git a/MC6809/src/mc6809.cpp b/MC6809/src/mc6809.cpp index 46d7329..38c5ec8 100644 --- a/MC6809/src/mc6809.cpp +++ b/MC6809/src/mc6809.cpp @@ -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(); diff --git a/MC6809/test/Board.cpp b/MC6809/test/Board.cpp index bd1a814..6d2157e 100644 --- a/MC6809/test/Board.cpp +++ b/MC6809/test/Board.cpp @@ -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 }; diff --git a/MC6809/test/Board.h b/MC6809/test/Board.h index 4eb68a2..e29a238 100644 --- a/MC6809/test/Board.h +++ b/MC6809/test/Board.h @@ -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; diff --git a/MC6809/unittest/Board.cpp b/MC6809/unittest/Board.cpp index d1219ff..70fa5b7 100644 --- a/MC6809/unittest/Board.cpp +++ b/MC6809/unittest/Board.cpp @@ -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 }; } diff --git a/MC6809/unittest/Board.h b/MC6809/unittest/Board.h index f7d405a..d01c7f2 100644 --- a/MC6809/unittest/Board.h +++ b/MC6809/unittest/Board.h @@ -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 diff --git a/MC6809/unittest/mc6809_tests.cpp b/MC6809/unittest/mc6809_tests.cpp index ae0925a..c916727 100644 --- a/MC6809/unittest/mc6809_tests.cpp +++ b/MC6809/unittest/mc6809_tests.cpp @@ -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; diff --git a/Ricoh2A03/inc/Ricoh2A03.h b/Ricoh2A03/inc/Ricoh2A03.h index d32ee6d..3ff9a79 100644 --- a/Ricoh2A03/inc/Ricoh2A03.h +++ b/Ricoh2A03/inc/Ricoh2A03.h @@ -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; }; } \ No newline at end of file diff --git a/Ricoh2A03/src/Ricoh2A03.cpp b/Ricoh2A03/src/Ricoh2A03.cpp index f99fa76..a298a9b 100644 --- a/Ricoh2A03/src/Ricoh2A03.cpp +++ b/Ricoh2A03/src/Ricoh2A03.cpp @@ -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(); } diff --git a/Z80/fusetest_Z80/FuseTestRunner.cpp b/Z80/fusetest_Z80/FuseTestRunner.cpp index 1570eb7..a0e012f 100644 --- a/Z80/fusetest_Z80/FuseTestRunner.cpp +++ b/Z80/fusetest_Z80/FuseTestRunner.cpp @@ -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, diff --git a/Z80/fusetest_Z80/FuseTestRunner.h b/Z80/fusetest_Z80/FuseTestRunner.h index 2a5fe21..bceeca1 100644 --- a/Z80/fusetest_Z80/FuseTestRunner.h +++ b/Z80/fusetest_Z80/FuseTestRunner.h @@ -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; }; diff --git a/Z80/inc/Z80.h b/Z80/inc/Z80.h index 0c559ea..246e85c 100644 --- a/Z80/inc/Z80.h +++ b/Z80/inc/Z80.h @@ -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 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 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(); }; } \ No newline at end of file diff --git a/Z80/src/Disassembler.cpp b/Z80/src/Disassembler.cpp index 1ca2487..96948b7 100644 --- a/Z80/src/Disassembler.cpp +++ b/Z80/src/Disassembler.cpp @@ -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); diff --git a/Z80/src/Profiler.cpp b/Z80/src/Profiler.cpp index 1d43600..0adc4b5 100644 --- a/Z80/src/Profiler.cpp +++ b/Z80/src/Profiler.cpp @@ -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 diff --git a/Z80/src/Z80.cpp b/Z80/src/Z80.cpp index 07eb183..787a061 100644 --- a/Z80/src/Z80.cpp +++ b/Z80/src/Z80.cpp @@ -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()); + } +} diff --git a/Z80/test/Board.cpp b/Z80/test/Board.cpp index 3fa31f8..2b07f9e 100644 --- a/Z80/test/Board.cpp +++ b/Z80/test/Board.cpp @@ -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; } diff --git a/inc/BigEndianProcessor.h b/inc/BigEndianProcessor.h index dc37ce9..49b2c29 100644 --- a/inc/BigEndianProcessor.h +++ b/inc/BigEndianProcessor.h @@ -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; }; } diff --git a/inc/Bus.h b/inc/Bus.h index ae3a3c2..c086545 100644 --- a/inc/Bus.h +++ b/inc/Bus.h @@ -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); diff --git a/inc/IntelProcessor.h b/inc/IntelProcessor.h index d66c921..bb924af 100644 --- a/inc/IntelProcessor.h +++ b/inc/IntelProcessor.h @@ -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(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 m_halfCarryTableAdd; static std::array m_halfCarryTableSub; diff --git a/inc/LittleEndianProcessor.h b/inc/LittleEndianProcessor.h index 190d6c4..b1cd7be 100644 --- a/inc/LittleEndianProcessor.h +++ b/inc/LittleEndianProcessor.h @@ -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; }; } diff --git a/inc/Processor.h b/inc/Processor.h index a245d0d..d284c11 100644 --- a/inc/Processor.h +++ b/inc/Processor.h @@ -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; diff --git a/inc/Register.h b/inc/Register.h index 3fac1e9..4609b66 100644 --- a/inc/Register.h +++ b/inc/Register.h @@ -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; } } diff --git a/src/BigEndianProcessor.cpp b/src/BigEndianProcessor.cpp index 7c8145d..ff6ebcc 100644 --- a/src/BigEndianProcessor.cpp +++ b/src/BigEndianProcessor.cpp @@ -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); } diff --git a/src/InputOutput.cpp b/src/InputOutput.cpp index 975be24..3597e2a 100644 --- a/src/InputOutput.cpp +++ b/src/InputOutput.cpp @@ -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]; } } diff --git a/src/IntelProcessor.cpp b/src/IntelProcessor.cpp index 3a81eb5..d07dff3 100644 --- a/src/IntelProcessor.cpp +++ b/src/IntelProcessor.cpp @@ -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); +} diff --git a/src/LittleEndianProcessor.cpp b/src/LittleEndianProcessor.cpp index 4a41b77..9a9ed36 100644 --- a/src/LittleEndianProcessor.cpp +++ b/src/LittleEndianProcessor.cpp @@ -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); } diff --git a/src/Processor.cpp b/src/Processor.cpp index f8b9211..8dc9cdd 100644 --- a/src/Processor.cpp +++ b/src/Processor.cpp @@ -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 {