mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-06-13 23:29:32 +00:00
Compare commits
3 Commits
739ce39360
...
ad1ab61f74
Author | SHA1 | Date | |
---|---|---|---|
|
ad1ab61f74 | ||
|
c397b4c41b | ||
|
8b6c4a205e |
|
@ -103,8 +103,8 @@ void checker_t::initialiseState(const test_t test) {
|
|||
cpu.P() = initial.p();
|
||||
for (const auto entry : initial.ram()) {
|
||||
auto data = entry.begin();
|
||||
const auto address = uint16_t(int64_t(*data++));
|
||||
const auto value = uint8_t(int64_t(*data));
|
||||
const auto address = uint16_t(int64_t(*data));
|
||||
const auto value = uint8_t(int64_t(*++data));
|
||||
ram.poke(address, value);
|
||||
}
|
||||
}
|
||||
|
@ -113,12 +113,12 @@ void checker_t::initialise() {
|
|||
|
||||
auto& bus = runner();
|
||||
|
||||
bus.ReadByte.connect([this, &bus](EightBit::EventArgs&) {
|
||||
addActualReadCycle(bus.ADDRESS(), bus.DATA());
|
||||
bus.ReadByte.connect([this](EightBit::EventArgs&) {
|
||||
addActualReadCycle(runner().ADDRESS(), runner().DATA());
|
||||
});
|
||||
|
||||
bus.WrittenByte.connect([this, &bus](EightBit::EventArgs&) {
|
||||
addActualWriteCycle(bus.ADDRESS(), bus.DATA());
|
||||
bus.WrittenByte.connect([this](EightBit::EventArgs&) {
|
||||
addActualWriteCycle(runner().ADDRESS(), runner().DATA());
|
||||
});
|
||||
|
||||
os() << std::hex << std::uppercase;
|
||||
|
@ -144,15 +144,15 @@ bool checker_t::checkState(test_t test) {
|
|||
auto expected_data = expected_cycle.begin();
|
||||
const auto& actual = actual_cycles[actual_idx++];
|
||||
|
||||
const auto expected_address = uint16_t(int64_t(*expected_data++));
|
||||
const auto expected_address = uint16_t(int64_t(*expected_data));
|
||||
const auto actual_address = std::get<0>(actual);
|
||||
check("Cycle address", expected_address, actual_address);
|
||||
|
||||
const auto expected_value = uint8_t(int64_t(*expected_data++));
|
||||
const auto expected_value = uint8_t(int64_t(*++expected_data));
|
||||
const auto actual_value = std::get<1>(actual);
|
||||
check("Cycle value", expected_value, actual_value);
|
||||
|
||||
const auto expected_action = (*expected_data).get_string();
|
||||
const auto expected_action = (*++expected_data).get_string();
|
||||
const auto actual_action = std::get<2>(actual);
|
||||
check("Cycle action", expected_action.value_unsafe(), actual_action);
|
||||
}
|
||||
|
@ -176,8 +176,8 @@ bool checker_t::checkState(test_t test) {
|
|||
bool ram_problem = false;
|
||||
for (const auto entry : final.ram()) {
|
||||
auto data = entry.begin();
|
||||
const auto address = uint16_t(int64_t(*data++));
|
||||
const auto value = uint8_t(int64_t(*data));
|
||||
const auto address = uint16_t(int64_t(*data));
|
||||
const auto value = uint8_t(int64_t(*++data));
|
||||
const auto ram_good = check("RAM", address, value, ram.peek(address));
|
||||
if (!ram_good && !ram_problem)
|
||||
ram_problem = true;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#define SIMDJSON_DISABLE_DEPRECATED_API
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace EightBit {
|
|||
|
||||
// Addressing modes
|
||||
|
||||
constexpr void noteUnfixedPage() noexcept { m_unfixed_page = BUS().ADDRESS().high; }
|
||||
constexpr void noteFixedAddress(register16_t fixed) noexcept { m_fixed_page = fixed.high; BUS().ADDRESS().low = fixed.low; }
|
||||
|
||||
constexpr void Address_Immediate() noexcept { BUS().ADDRESS() = PC()++; }
|
||||
void Address_Absolute() noexcept { BUS().ADDRESS() = fetchWord(); }
|
||||
|
@ -115,11 +115,11 @@ namespace EightBit {
|
|||
void Address_ZeroPageWithIndex(uint8_t index) noexcept { AM_ZeroPage(); BUS().ADDRESS().low += index; }
|
||||
void Address_ZeroPageX() noexcept { Address_ZeroPageWithIndex(X()); }
|
||||
void Address_ZeroPageY() noexcept { Address_ZeroPageWithIndex(Y()); }
|
||||
void Address_AbsoluteWithIndex(uint8_t index) noexcept { Address_Absolute(); noteUnfixedPage(); BUS().ADDRESS() += index; }
|
||||
void Address_AbsoluteWithIndex(uint8_t index) noexcept { Address_Absolute(); noteFixedAddress(BUS().ADDRESS() + index); }
|
||||
void Address_AbsoluteX() noexcept { Address_AbsoluteWithIndex(X()); }
|
||||
void Address_AbsoluteY() noexcept { Address_AbsoluteWithIndex(Y()); }
|
||||
void Address_IndexedIndirectX() noexcept { Address_ZeroPageX(); BUS().ADDRESS() = getWordPaged(); }
|
||||
void Address_IndirectIndexedY() noexcept { Address_ZeroPageIndirect(); noteUnfixedPage(); BUS().ADDRESS() += Y(); }
|
||||
void Address_IndirectIndexedY() noexcept { Address_ZeroPageIndirect(); noteFixedAddress(BUS().ADDRESS() + Y()); }
|
||||
|
||||
// Addressing modes, with read
|
||||
|
||||
|
@ -184,19 +184,13 @@ namespace EightBit {
|
|||
}
|
||||
|
||||
void maybe_fixup() noexcept {
|
||||
const auto fixed_page = BUS().ADDRESS().high;
|
||||
BUS().ADDRESS().high = m_unfixed_page;
|
||||
if (m_unfixed_page != fixed_page) {
|
||||
memoryRead();
|
||||
BUS().ADDRESS().high = fixed_page;
|
||||
}
|
||||
if (BUS().ADDRESS().high != m_fixed_page)
|
||||
fixup();
|
||||
}
|
||||
|
||||
void fixup() noexcept {
|
||||
const auto fixed_page = BUS().ADDRESS().high;
|
||||
BUS().ADDRESS().high = m_unfixed_page;
|
||||
memoryRead();
|
||||
BUS().ADDRESS().high = fixed_page;
|
||||
BUS().ADDRESS().high = m_fixed_page;
|
||||
}
|
||||
|
||||
void maybe_fixupR() noexcept { maybe_fixup(); memoryRead(); }
|
||||
|
@ -214,7 +208,7 @@ namespace EightBit {
|
|||
|
||||
// Chew up a cycle
|
||||
void swallow() noexcept { memoryRead(PC()); }
|
||||
void swallow_stack() noexcept { getBytePaged(1, S()); }
|
||||
void swallow_stack() noexcept { memoryRead({ S(), 1 }); }
|
||||
void swallow_fetch() noexcept { fetchByte(); }
|
||||
|
||||
// Instruction implementations
|
||||
|
@ -288,6 +282,7 @@ namespace EightBit {
|
|||
bool m_handlingNMI = false;
|
||||
bool m_handlingINT = false;
|
||||
|
||||
uint8_t m_unfixed_page = 0;
|
||||
//uint8_t m_unfixed_page = 0;
|
||||
uint8_t m_fixed_page = 0;
|
||||
};
|
||||
}
|
|
@ -115,13 +115,13 @@ void EightBit::MOS6502::interrupt() noexcept {
|
|||
void EightBit::MOS6502::busWrite() noexcept {
|
||||
tick();
|
||||
lowerRW();
|
||||
base::busWrite();
|
||||
LittleEndianProcessor::busWrite();
|
||||
}
|
||||
|
||||
uint8_t EightBit::MOS6502::busRead() noexcept {
|
||||
tick();
|
||||
raiseRW();
|
||||
return base::busRead();
|
||||
return LittleEndianProcessor::busRead();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -427,9 +427,9 @@ void EightBit::MOS6502::branch(const int condition) noexcept {
|
|||
const auto relative = int8_t(fetchByte());
|
||||
if (condition) {
|
||||
swallow();
|
||||
m_unfixed_page = PC().high;
|
||||
jump(PC() + relative);
|
||||
BUS().ADDRESS() = PC();
|
||||
const auto address = PC() + relative;
|
||||
noteFixedAddress(address);
|
||||
jump(address);
|
||||
maybe_fixup();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ public:
|
|||
void initialise() final;
|
||||
|
||||
protected:
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
|
||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
virtual constexpr EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
|
||||
return m_mapping;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -33,6 +33,7 @@ private:
|
|||
EightBit::MOS6502 m_cpu = *this;
|
||||
EightBit::Symbols m_symbols;
|
||||
EightBit::Disassembly m_disassembler = { *this, m_cpu, m_symbols };
|
||||
const EightBit::MemoryMapping m_mapping = { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
|
||||
EightBit::register16_t m_oldPC = EightBit::Chip::Mask16;
|
||||
bool m_stopped = false;
|
||||
|
|
|
@ -36,7 +36,7 @@ int EightBit::mc6809::step() noexcept {
|
|||
else if (UNLIKELY(lowered(INT()) && !interruptMasked()))
|
||||
handleINT();
|
||||
else
|
||||
Processor::execute(fetchByte());
|
||||
BigEndianProcessor::execute(fetchByte());
|
||||
}
|
||||
ExecutedInstruction.fire(*this);
|
||||
assert(cycles() > 0);
|
||||
|
@ -115,13 +115,13 @@ void EightBit::mc6809::handleFIRQ() {
|
|||
void EightBit::mc6809::busWrite() noexcept {
|
||||
tick();
|
||||
lowerRW();
|
||||
Processor::busWrite();
|
||||
BigEndianProcessor::busWrite();
|
||||
}
|
||||
|
||||
uint8_t EightBit::mc6809::busRead() noexcept {
|
||||
tick();
|
||||
raiseRW();
|
||||
return Processor::busRead();
|
||||
return BigEndianProcessor::busRead();
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
|
||||
protected:
|
||||
EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
|
||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
return m_mapping;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -35,6 +35,7 @@ private:
|
|||
EightBit::Z80 m_cpu = *this;
|
||||
EightBit::Disassembler m_disassembler = *this;
|
||||
EightBit::Profiler m_profiler = { m_cpu, m_disassembler };
|
||||
const EightBit::MemoryMapping m_mapping = { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
int m_warmstartCount = 0;
|
||||
|
||||
void bdos();
|
||||
|
|
|
@ -14,8 +14,6 @@ namespace EightBit {
|
|||
void pokeWord(register16_t address, register16_t value) noexcept final;
|
||||
|
||||
protected:
|
||||
using base = BigEndianProcessor;
|
||||
|
||||
BigEndianProcessor(Bus& memory) noexcept;
|
||||
|
||||
[[nodiscard]] register16_t getWord() override;
|
||||
|
|
|
@ -70,8 +70,6 @@ namespace EightBit {
|
|||
: Device(rhs) {}
|
||||
|
||||
protected:
|
||||
using base = Chip;
|
||||
|
||||
Chip() noexcept = default;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -14,16 +14,17 @@ namespace EightBit {
|
|||
|
||||
[[nodiscard]] constexpr auto cycles() const noexcept { return m_cycles; }
|
||||
|
||||
void tick(int extra = 1) {
|
||||
for (int i = 0; i < extra; ++i) {
|
||||
void tick() {
|
||||
++m_cycles;
|
||||
Ticked.fire();
|
||||
}
|
||||
|
||||
void tick(int extra) {
|
||||
for (int i = 0; i < extra; ++i)
|
||||
tick();
|
||||
}
|
||||
|
||||
protected:
|
||||
using base = ClockedChip;
|
||||
|
||||
ClockedChip() noexcept = default;
|
||||
|
||||
constexpr void resetCycles() noexcept { m_cycles = 0; }
|
||||
|
|
|
@ -114,8 +114,6 @@ namespace EightBit {
|
|||
[[nodiscard]] constexpr bool powered() const noexcept { return raised(POWER()); }
|
||||
|
||||
protected:
|
||||
using base = Device;
|
||||
|
||||
Device() noexcept {};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -80,8 +80,6 @@ namespace EightBit {
|
|||
DECLARE_PIN_OUTPUT(HALT)
|
||||
|
||||
protected:
|
||||
using base = IntelProcessor;
|
||||
|
||||
IntelProcessor(Bus& bus);
|
||||
|
||||
template<class T> [[nodiscard]] static constexpr uint8_t adjustSign(uint8_t f, const uint8_t value) noexcept {
|
||||
|
|
|
@ -14,8 +14,6 @@ namespace EightBit {
|
|||
void pokeWord(register16_t address, register16_t value) noexcept final;
|
||||
|
||||
protected:
|
||||
using base = LittleEndianProcessor;
|
||||
|
||||
LittleEndianProcessor(Bus& memory) noexcept;
|
||||
|
||||
[[nodiscard]] register16_t getWord() override;
|
||||
|
|
|
@ -39,8 +39,6 @@ namespace EightBit {
|
|||
DECLARE_PIN_INPUT(INT)
|
||||
|
||||
protected:
|
||||
using base = Processor;
|
||||
|
||||
Processor(Bus& memory) noexcept;
|
||||
|
||||
[[nodiscard]] constexpr auto& opcode() noexcept { return m_opcode; }
|
||||
|
@ -59,11 +57,6 @@ namespace EightBit {
|
|||
virtual uint8_t memoryRead();
|
||||
virtual uint8_t busRead();
|
||||
|
||||
uint8_t getBytePaged() { return memoryRead(); }
|
||||
uint8_t getBytePaged(uint8_t page, uint8_t offset);
|
||||
void setBytePaged(uint8_t value) { memoryWrite(value); }
|
||||
void setBytePaged(uint8_t page, uint8_t offset, uint8_t value);
|
||||
|
||||
uint8_t fetchByte();
|
||||
|
||||
[[nodiscard]] virtual register16_t getWord() = 0;
|
||||
|
|
|
@ -45,8 +45,6 @@ public:
|
|||
|
||||
private:
|
||||
handle_t h_;
|
||||
|
||||
private:
|
||||
bool full_ = false;
|
||||
|
||||
constexpr void fill() {
|
||||
|
|
|
@ -18,14 +18,14 @@ void EightBit::BigEndianProcessor::setWord(const register16_t value) {
|
|||
}
|
||||
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged() {
|
||||
const auto high = getBytePaged();
|
||||
const auto high = memoryRead();
|
||||
++BUS().ADDRESS().low;
|
||||
const auto low = memoryRead();
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
void EightBit::BigEndianProcessor::setWordPaged(const register16_t value) {
|
||||
setBytePaged(value.high);
|
||||
memoryWrite(value.high);
|
||||
++BUS().ADDRESS().low;
|
||||
memoryWrite(value.low);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,6 @@ EightBit::ClockedChip::ClockedChip(const ClockedChip& rhs) noexcept
|
|||
|
||||
bool EightBit::ClockedChip::operator==(const EightBit::ClockedChip& rhs) const noexcept {
|
||||
return
|
||||
Device::operator==(rhs)
|
||||
Chip::operator==(rhs)
|
||||
&& cycles() == rhs.cycles();
|
||||
}
|
||||
|
|
|
@ -96,13 +96,13 @@ int EightBit::IntelProcessor::jrConditional(const int condition) {
|
|||
}
|
||||
|
||||
void EightBit::IntelProcessor::ret() {
|
||||
Processor::ret();
|
||||
LittleEndianProcessor::ret();
|
||||
MEMPTR() = PC();
|
||||
}
|
||||
|
||||
bool EightBit::IntelProcessor::operator==(const EightBit::IntelProcessor& rhs) const noexcept {
|
||||
return
|
||||
Processor::operator==(rhs)
|
||||
LittleEndianProcessor::operator==(rhs)
|
||||
&& HALT() == rhs.HALT()
|
||||
&& MEMPTR() == rhs.MEMPTR()
|
||||
&& SP() == rhs.SP()
|
||||
|
|
|
@ -21,14 +21,14 @@ void EightBit::LittleEndianProcessor::setWord(const register16_t value) {
|
|||
}
|
||||
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged() {
|
||||
const auto low = getBytePaged();
|
||||
const auto low = memoryRead();
|
||||
++BUS().ADDRESS().low;
|
||||
const auto high = memoryRead();
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
void EightBit::LittleEndianProcessor::setWordPaged(register16_t value) {
|
||||
setBytePaged(value.low);
|
||||
memoryWrite(value.low);
|
||||
++BUS().ADDRESS().low;
|
||||
memoryWrite(value.high);
|
||||
}
|
||||
|
|
|
@ -60,14 +60,6 @@ uint8_t EightBit::Processor::busRead() {
|
|||
return BUS().read();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Processor::getBytePaged(const uint8_t page, const uint8_t offset) {
|
||||
return memoryRead(register16_t(offset, page));
|
||||
}
|
||||
|
||||
void EightBit::Processor::setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) {
|
||||
memoryWrite(register16_t(offset, page), value);
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::Processor::getWordPaged(register16_t address) {
|
||||
BUS().ADDRESS() = address;
|
||||
return getWordPaged();
|
||||
|
|
Loading…
Reference in New Issue
Block a user