Compare commits

...

3 Commits

Author SHA1 Message Date
Adrian Conlon ad1ab61f74 Small 6502 consolidation 2024-03-18 21:38:51 +00:00
Adrian Conlon c397b4c41b Swap fixed/unfixed page usage 2024-03-18 21:04:50 +00:00
Adrian Conlon 8b6c4a205e Lot's of small niggles corrected across the EightBit libraries 2024-03-18 13:03:41 +00:00
21 changed files with 55 additions and 82 deletions

View File

@ -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;

View File

@ -1,5 +1,7 @@
#pragma once
#define SIMDJSON_DISABLE_DEPRECATED_API
#include <cassert>
#include <chrono>
#include <cstdint>

View File

@ -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;
};
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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();
}
//

View File

@ -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();

View File

@ -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;

View File

@ -70,8 +70,6 @@ namespace EightBit {
: Device(rhs) {}
protected:
using base = Chip;
Chip() noexcept = default;
};
}

View File

@ -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) {
++m_cycles;
Ticked.fire();
}
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; }

View File

@ -114,8 +114,6 @@ namespace EightBit {
[[nodiscard]] constexpr bool powered() const noexcept { return raised(POWER()); }
protected:
using base = Device;
Device() noexcept {};
};
}

View File

@ -71,18 +71,18 @@ inline int EightBit::findFirstSet(const unsigned long value) noexcept {
#ifdef _MSC_VER
# define ASSUME(x) __assume(x);
# define ASSUME(x) __assume(x);
# define LIKELY(x) (x)
# define LIKELY(x) (x)
# define UNLIKELY(x) (x)
# define UNREACHABLE { ASSUME(0); assert(false && "unreachable"); }
#elif defined(__GNUG__)
# define ASSUME(x) { if (!x) __builtin_unreachable(); }
# define ASSUME(x) { if (!x) __builtin_unreachable(); }
# define LIKELY(x) __builtin_expect(!!(x), 1)
# define LIKELY(x) __builtin_expect(!!(x), 1)
# define UNLIKELY(x) __builtin_expect(!!(x), 0)
# define UNREACHABLE __builtin_unreachable();
@ -91,7 +91,7 @@ inline int EightBit::findFirstSet(const unsigned long value) noexcept {
# define ASSUME(x) assert(x);
# define LIKELY(x) (x)
# define LIKELY(x) (x)
# define UNLIKELY(x) (x)
# define UNREACHABLE ASSUME(0)

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -45,8 +45,6 @@ public:
private:
handle_t h_;
private:
bool full_ = false;
constexpr void fill() {

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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()

View File

@ -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);
}

View File

@ -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();