Tidy up noexcept specification

This commit is contained in:
Adrian Conlon 2022-01-17 19:10:15 +00:00
parent 83b7efdd03
commit 8e0092ec9d
57 changed files with 831 additions and 851 deletions

View File

@ -23,7 +23,7 @@ namespace Gaming {
virtual ~Game();
virtual void runLoop();
void raisePOWER() override;
void raisePOWER() noexcept override;
protected:
[[nodiscard]] virtual float fps() const noexcept = 0;

View File

@ -25,7 +25,7 @@ int Game::displayHeight() const noexcept {
return rasterHeight();
}
void Game::raisePOWER() {
void Game::raisePOWER() noexcept {
Device::raisePOWER();

View File

@ -32,8 +32,8 @@ namespace EightBit {
Signal<Intel8080> ExecutingInstruction;
Signal<Intel8080> ExecutedInstruction;
virtual int execute() final;
virtual int step() final;
int execute() noexcept final;
int step() noexcept final;
[[nodiscard]] const register16_t& AF() const noexcept final;
[[nodiscard]] auto& AF() noexcept { return IntelProcessor::AF(); }
@ -51,14 +51,14 @@ namespace EightBit {
[[nodiscard]] bool requestingWrite() noexcept { return lowered(WR()); }
protected:
void handleRESET() final;
void handleINT() final;
void handleRESET() noexcept final;
void handleINT() noexcept final;
void memoryWrite() final;
uint8_t memoryRead() final;
void memoryWrite() noexcept final;
uint8_t memoryRead() noexcept final;
void busWrite() final;
uint8_t busRead() final;
void busWrite() noexcept final;
uint8_t busRead() noexcept final;
private:
bool m_requestIO = false;

View File

@ -37,39 +37,39 @@ const EightBit::register16_t& EightBit::Intel8080::HL() const noexcept {
return hl;
}
void EightBit::Intel8080::memoryWrite() {
void EightBit::Intel8080::memoryWrite() noexcept {
requestMemory();
IntelProcessor::memoryWrite();
releaseMemory();
}
uint8_t EightBit::Intel8080::memoryRead() {
uint8_t EightBit::Intel8080::memoryRead() noexcept {
requestMemory();
const auto returned = IntelProcessor::memoryRead();
releaseMemory();
return returned;
}
void EightBit::Intel8080::busWrite() {
void EightBit::Intel8080::busWrite() noexcept {
requestWrite();
IntelProcessor::busWrite();
releaseWrite();
}
uint8_t EightBit::Intel8080::busRead() {
uint8_t EightBit::Intel8080::busRead() noexcept {
requestRead();
const auto returned = IntelProcessor::busRead();
releaseRead();
return returned;
}
void EightBit::Intel8080::handleRESET() {
void EightBit::Intel8080::handleRESET() noexcept {
IntelProcessor::handleRESET();
di();
tick(3);
}
void EightBit::Intel8080::handleINT() {
void EightBit::Intel8080::handleINT() noexcept {
IntelProcessor::handleINT();
raiseHALT();
if (m_interruptEnable) {
@ -310,7 +310,7 @@ uint8_t EightBit::Intel8080::portRead() {
return returned;
}
int EightBit::Intel8080::step() {
int EightBit::Intel8080::step() noexcept {
ExecutingInstruction.fire(*this);
resetCycles();
if (LIKELY(powered())) {
@ -328,7 +328,7 @@ int EightBit::Intel8080::step() {
return cycles();
}
int EightBit::Intel8080::execute() {
int EightBit::Intel8080::execute() noexcept {
const auto& decoded = getDecodedOpcode(opcode());

View File

@ -10,14 +10,14 @@ Board::Board(const Configuration& configuration)
m_disassembler(*this) {
}
void Board::raisePOWER() {
void Board::raisePOWER() noexcept {
EightBit::Bus::raisePOWER();
CPU().raisePOWER();
CPU().raiseRESET();
CPU().raiseINT();
}
void Board::lowerPOWER() {
void Board::lowerPOWER() noexcept {
CPU().lowerPOWER();
EightBit::Bus::lowerPOWER();
}

View File

@ -17,8 +17,8 @@ public:
EightBit::Intel8080& CPU() { return m_cpu; }
const EightBit::Intel8080& CPU() const { return m_cpu; }
virtual void raisePOWER() final;
virtual void lowerPOWER() final;
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
virtual void initialise() final;

View File

@ -9,7 +9,7 @@ Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& expecte
//
void Fuse::TestRunner::raisePOWER() {
void Fuse::TestRunner::raisePOWER() noexcept {
EightBit::Bus::raisePOWER();
CPU().raisePOWER();
CPU().raiseRESET();
@ -18,7 +18,7 @@ void Fuse::TestRunner::raisePOWER() {
initialiseMemory();
}
void Fuse::TestRunner::lowerPOWER() {
void Fuse::TestRunner::lowerPOWER() noexcept {
CPU().lowerPOWER();
EightBit::Bus::lowerPOWER();
}

View File

@ -46,8 +46,8 @@ namespace Fuse {
bool failed() const { return m_failed; }
bool unimplemented() const { return m_unimplemented; }
virtual void raisePOWER() final;
virtual void lowerPOWER() final;
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
void initialise();
};

View File

@ -36,8 +36,8 @@ namespace EightBit {
Bus() noexcept;
virtual void raisePOWER() override;
virtual void lowerPOWER() override;
void raisePOWER() noexcept override;
void lowerPOWER() noexcept override;
[[nodiscard]] auto& CPU() noexcept { return m_cpu; }
[[nodiscard]] auto& VRAM() noexcept { return m_videoRam; }

View File

@ -47,22 +47,22 @@ namespace EightBit {
void tickMachine() { tick(4); MachineTicked.fire(); }
protected:
int execute() final;
int step() final;
int execute() noexcept final;
int step() noexcept final;
void handleRESET() final;
void handleINT() final;
void handleRESET() noexcept final;
void handleINT() noexcept final;
void memoryWrite() final;
uint8_t memoryRead() final;
void memoryWrite() noexcept final;
uint8_t memoryRead() noexcept final;
void pushWord(register16_t value) final;
void pushWord(register16_t value) noexcept final;
void jr(int8_t offset) final;
int jumpConditional(int condition) final;
int returnConditional(int condition) final;
int jrConditional(int condition) final;
void ret() 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 ret() noexcept final;
private:
Bus& m_bus;

View File

@ -8,14 +8,14 @@ EightBit::GameBoy::Bus::Bus() noexcept
WrittenByte.connect(std::bind(&GameBoy::Bus::Bus_WrittenByte, this, std::placeholders::_1));
}
void EightBit::GameBoy::Bus::raisePOWER() {
void EightBit::GameBoy::Bus::raisePOWER() noexcept {
EightBit::Bus::raisePOWER();
CPU().raisePOWER();
CPU().raiseINT();
reset();
}
void EightBit::GameBoy::Bus::lowerPOWER() {
void EightBit::GameBoy::Bus::lowerPOWER() noexcept {
CPU().lowerPOWER();
EightBit::Bus::lowerPOWER();
}

View File

@ -31,59 +31,59 @@ const EightBit::register16_t& EightBit::GameBoy::LR35902::HL() const noexcept {
return hl;
}
void EightBit::GameBoy::LR35902::handleRESET() {
void EightBit::GameBoy::LR35902::handleRESET() noexcept {
IntelProcessor::handleRESET();
di();
SP() = Mask16 - 1;
tickMachine(4);
}
void EightBit::GameBoy::LR35902::handleINT() {
void EightBit::GameBoy::LR35902::handleINT() noexcept {
IntelProcessor::handleINT();
raiseHALT();
di();
restart(BUS().DATA());
}
void EightBit::GameBoy::LR35902::memoryWrite() {
void EightBit::GameBoy::LR35902::memoryWrite() noexcept {
tickMachine();
IntelProcessor::memoryWrite();
}
uint8_t EightBit::GameBoy::LR35902::memoryRead() {
uint8_t EightBit::GameBoy::LR35902::memoryRead() noexcept {
tickMachine();
return IntelProcessor::memoryRead();
}
void EightBit::GameBoy::LR35902::pushWord(register16_t value) {
void EightBit::GameBoy::LR35902::pushWord(register16_t value) noexcept {
tickMachine();
IntelProcessor::pushWord(value);
}
void EightBit::GameBoy::LR35902::jr(int8_t offset) {
void EightBit::GameBoy::LR35902::jr(int8_t offset) noexcept {
IntelProcessor::jr(offset);
tickMachine();
}
int EightBit::GameBoy::LR35902::jumpConditional(const int condition) {
int EightBit::GameBoy::LR35902::jumpConditional(const int condition) noexcept {
if (IntelProcessor::jumpConditional(condition))
tickMachine();
return condition;
}
int EightBit::GameBoy::LR35902::returnConditional(const int condition) {
int EightBit::GameBoy::LR35902::returnConditional(const int condition) noexcept {
IntelProcessor::returnConditional(condition);
tickMachine();
return condition;
}
int EightBit::GameBoy::LR35902::jrConditional(const int condition) {
int EightBit::GameBoy::LR35902::jrConditional(const int condition) noexcept {
if (!IntelProcessor::jrConditional(condition))
tickMachine();
return condition;
}
void EightBit::GameBoy::LR35902::ret() {
void EightBit::GameBoy::LR35902::ret() noexcept {
IntelProcessor::ret();
tickMachine();
}
@ -435,7 +435,7 @@ uint8_t EightBit::GameBoy::LR35902::maskedInterrupts() noexcept {
return enabledInterrupts() & flaggedInterrupts();
}
int EightBit::GameBoy::LR35902::step() {
int EightBit::GameBoy::LR35902::step() noexcept {
ExecutingInstruction.fire(*this);
m_prefixCB = false;
@ -470,7 +470,7 @@ int EightBit::GameBoy::LR35902::step() {
return cycles();
}
int EightBit::GameBoy::LR35902::execute() {
int EightBit::GameBoy::LR35902::execute() noexcept {
const auto& decoded = getDecodedOpcode(opcode());
@ -486,8 +486,7 @@ int EightBit::GameBoy::LR35902::execute() {
else
executeCB(x, y, z, p, q);
if (UNLIKELY(cycles() == 0))
throw std::logic_error("Unhandled opcode");
assert(cycles() > 0);
return cycles();
}
@ -802,14 +801,14 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in
IntelProcessor::memoryWrite(IoRegisters::BASE + C(), A());
break;
case 5: // GB: LD (nn),A
BUS().ADDRESS() = MEMPTR() = fetchWord();
IntelProcessor::memoryWrite(A());
MEMPTR() = BUS().ADDRESS() = fetchWord();
IntelProcessor::memoryWrite(A());
break;
case 6: // GB: LD A,(FF00 + C)
A() = IntelProcessor::memoryRead(IoRegisters::BASE + C());
break;
case 7: // GB: LD A,(nn)
BUS().ADDRESS() = MEMPTR() = fetchWord();
MEMPTR() = BUS().ADDRESS() = fetchWord();
A() = memoryRead();
break;
default:

View File

@ -7,7 +7,7 @@ EightBit::MemoryMapping TestRunner::mapping(const uint16_t address) noexcept {
return { RAM(), 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
}
void TestRunner::raisePOWER() {
void TestRunner::raisePOWER() noexcept {
EightBit::Bus::raisePOWER();
CPU().raisePOWER();
CPU().raiseRESET();
@ -17,7 +17,7 @@ void TestRunner::raisePOWER() {
CPU().raiseRDY();
}
void TestRunner::lowerPOWER() {
void TestRunner::lowerPOWER() noexcept {
CPU().lowerPOWER();
EightBit::Bus::lowerPOWER();
}

View File

@ -15,8 +15,8 @@ protected:
public:
TestRunner();
void raisePOWER() final;
void lowerPOWER() final;
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
void initialise() final;

View File

@ -38,8 +38,8 @@ namespace EightBit {
Signal<MOS6502> ExecutingInstruction;
Signal<MOS6502> ExecutedInstruction;
int execute() final;
[[nodiscard]] int step() final;
int execute() noexcept final;
[[nodiscard]] int step() noexcept final;
[[nodiscard]] constexpr auto& X() noexcept { return x; }
[[nodiscard]] constexpr auto& Y() noexcept { return y; }
@ -50,11 +50,11 @@ namespace EightBit {
[[nodiscard]] constexpr const auto& P() const noexcept { return p; }
protected:
void handleRESET() final;
void handleINT() final;
void handleRESET() noexcept final;
void handleINT() noexcept final;
void busWrite() final;
[[nodiscard]] uint8_t busRead() final;
void busWrite() noexcept final;
[[nodiscard]] uint8_t busRead() noexcept final;
[[nodiscard]] virtual uint8_t sub(uint8_t operand, uint8_t data, int borrow = 0) noexcept;
[[nodiscard]] uint8_t sbc(uint8_t operand, uint8_t data) noexcept;
@ -71,16 +71,16 @@ namespace EightBit {
const uint8_t RSTvector = 0xfc; // RST vector
const uint8_t NMIvector = 0xfa; // NMI vector
void handleNMI();
void handleSO();
void handleNMI() noexcept;
void handleSO() noexcept;
void interrupt();
void push(uint8_t value) final;
[[nodiscard]] uint8_t pop() final;
void push(uint8_t value) noexcept final;
[[nodiscard]] uint8_t pop() noexcept final;
// Dummy stack push, used during RESET
void dummyPush(uint8_t value);
void dummyPush(uint8_t value) noexcept;
// Addressing modes

View File

@ -20,7 +20,7 @@ DEFINE_PIN_LEVEL_CHANGERS(SYNC, MOS6502);
DEFINE_PIN_LEVEL_CHANGERS(RDY, MOS6502);
DEFINE_PIN_LEVEL_CHANGERS(RW, MOS6502);
int EightBit::MOS6502::step() {
int EightBit::MOS6502::step() noexcept {
resetCycles();
ExecutingInstruction.fire(*this);
if (LIKELY(powered())) {
@ -46,25 +46,25 @@ int EightBit::MOS6502::step() {
// Interrupt (etc.) handlers
void EightBit::MOS6502::handleSO() {
void EightBit::MOS6502::handleSO() noexcept {
raiseSO();
P() |= VF;
}
void EightBit::MOS6502::handleRESET() {
void EightBit::MOS6502::handleRESET() noexcept {
raiseRESET();
m_handlingRESET = true;
opcode() = 0x00; // BRK
}
void EightBit::MOS6502::handleNMI() {
void EightBit::MOS6502::handleNMI() noexcept {
raiseNMI();
m_handlingNMI = true;
opcode() = 0x00; // BRK
}
void EightBit::MOS6502::handleINT() {
void EightBit::MOS6502::handleINT() noexcept {
raiseINT();
m_handlingINT = true;
opcode() = 0x00; // BRK
@ -92,13 +92,13 @@ void EightBit::MOS6502::interrupt() {
//
void EightBit::MOS6502::busWrite() {
void EightBit::MOS6502::busWrite() noexcept {
tick();
lowerRW();
Processor::busWrite();
}
uint8_t EightBit::MOS6502::busRead() {
uint8_t EightBit::MOS6502::busRead() noexcept {
tick();
raiseRW();
return Processor::busRead();
@ -106,7 +106,7 @@ uint8_t EightBit::MOS6502::busRead() {
//
int EightBit::MOS6502::execute() {
int EightBit::MOS6502::execute() noexcept {
raiseSYNC(); // Instruction fetch has now completed
@ -391,15 +391,15 @@ int EightBit::MOS6502::execute() {
////
void EightBit::MOS6502::push(uint8_t value) {
void EightBit::MOS6502::push(uint8_t value) noexcept {
setBytePaged(1, S()--, value);
}
uint8_t EightBit::MOS6502::pop() {
uint8_t EightBit::MOS6502::pop() noexcept {
return getBytePaged(1, ++S());
}
void EightBit::MOS6502::dummyPush(const uint8_t value) {
void EightBit::MOS6502::dummyPush(const uint8_t value) noexcept {
tick();
BUS().DATA() = value;
BUS().ADDRESS() = { S()--, 1 };

View File

@ -10,7 +10,7 @@
Board::Board(const Configuration& configuration)
: m_configuration(configuration) {}
void Board::raisePOWER() {
void Board::raisePOWER() noexcept {
EightBit::Bus::raisePOWER();
CPU().raisePOWER();
CPU().raiseRESET();
@ -20,7 +20,7 @@ void Board::raisePOWER() {
CPU().raiseRDY();
}
void Board::lowerPOWER() {
void Board::lowerPOWER() noexcept {
CPU().lowerPOWER();
EightBit::Bus::lowerPOWER();
}

View File

@ -17,10 +17,10 @@ public:
EightBit::MOS6502& CPU() { return m_cpu; }
virtual void raisePOWER() final;
virtual void lowerPOWER() final;
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
virtual void initialise() final;
void initialise() final;
protected:
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final {

View File

@ -66,8 +66,8 @@ namespace EightBit {
Signal<mc6809> ExecutingInstruction;
Signal<mc6809> ExecutedInstruction;
int execute() final;
[[nodiscard]] int step() final;
int execute() noexcept final;
[[nodiscard]] int step() noexcept final;
[[nodiscard]] constexpr auto& D() noexcept { return m_d; }
[[nodiscard]] constexpr auto& A() noexcept { return D().high; }
@ -111,21 +111,21 @@ namespace EightBit {
protected:
// Default push/pop handlers
void push(uint8_t value) final;
[[nodiscard]] uint8_t pop() final;
void push(uint8_t value) noexcept final;
[[nodiscard]] uint8_t pop() noexcept final;
// Interrupt (etc.) handlers
void handleRESET() final;
void handleINT() final;
void handleRESET() noexcept final;
void handleINT() noexcept final;
// Bus reader/writers
void busWrite() final;
uint8_t busRead() final;
void busWrite() noexcept final;
uint8_t busRead() noexcept final;
void call(register16_t destination) final;
void ret() final;
void call(register16_t destination) noexcept final;
void ret() noexcept final;
private:
const uint8_t RESETvector = 0xfe; // RESET vector

View File

@ -20,7 +20,7 @@ DEFINE_PIN_LEVEL_CHANGERS(BA, mc6809);
DEFINE_PIN_LEVEL_CHANGERS(BS, mc6809);
DEFINE_PIN_LEVEL_CHANGERS(RW, mc6809);
int EightBit::mc6809::step() {
int EightBit::mc6809::step() noexcept {
resetCycles();
ExecutingInstruction.fire(*this);
if (LIKELY(powered())) {
@ -49,7 +49,7 @@ void EightBit::mc6809::handleHALT() {
raiseBS();
}
void EightBit::mc6809::handleRESET() {
void EightBit::mc6809::handleRESET() noexcept {
BigEndianProcessor::handleRESET();
memoryRead({ RESETvector, 0xff });
raiseNMI();
@ -80,7 +80,7 @@ void EightBit::mc6809::handleNMI() {
eat();
}
void EightBit::mc6809::handleINT() {
void EightBit::mc6809::handleINT() noexcept {
BigEndianProcessor::handleINT();
lowerBA();
raiseBS();
@ -111,13 +111,13 @@ void EightBit::mc6809::handleFIRQ() {
//
void EightBit::mc6809::busWrite() {
void EightBit::mc6809::busWrite() noexcept {
tick();
lowerRW();
Processor::busWrite();
}
uint8_t EightBit::mc6809::busRead() {
uint8_t EightBit::mc6809::busRead() noexcept {
tick();
raiseRW();
return Processor::busRead();
@ -125,21 +125,21 @@ uint8_t EightBit::mc6809::busRead() {
//
void EightBit::mc6809::call(register16_t destination) {
void EightBit::mc6809::call(register16_t destination) noexcept {
memoryRead(destination);
eat();
BigEndianProcessor::pushWord(PC());
jump(destination);
}
void EightBit::mc6809::ret() {
void EightBit::mc6809::ret() noexcept {
BigEndianProcessor::ret();
eat();
}
//
int EightBit::mc6809::execute() {
int EightBit::mc6809::execute() noexcept {
lowerBA();
lowerBS();
const bool prefixed = m_prefix10 || m_prefix11;
@ -628,11 +628,11 @@ void EightBit::mc6809::execute11() {
//
void EightBit::mc6809::push(const uint8_t value) {
void EightBit::mc6809::push(const uint8_t value) noexcept {
pushS(value);
}
uint8_t EightBit::mc6809::pop() {
uint8_t EightBit::mc6809::pop() noexcept {
return popS();
}

View File

@ -4,7 +4,7 @@
Board::Board(const Configuration& configuration)
: m_configuration(configuration) {}
void Board::raisePOWER() {
void Board::raisePOWER() noexcept {
EightBit::Bus::raisePOWER();
@ -26,7 +26,7 @@ void Board::raisePOWER() {
accessAcia();
}
void Board::lowerPOWER() {
void Board::lowerPOWER() noexcept {
if (m_configuration.isProfileMode()) {
m_profiler.EmitLine.connect([this](EightBit::ProfileLineEventArgs line) {

View File

@ -20,8 +20,8 @@ public:
auto& CPU() { return m_cpu; }
auto& ACIA() { return m_acia; }
void raisePOWER() final;
void lowerPOWER() final;
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
virtual void initialise() final;

View File

@ -3,7 +3,7 @@
Board::Board() {}
void Board::raisePOWER() {
void Board::raisePOWER() noexcept {
EightBit::Bus::raisePOWER();
CPU().raisePOWER();
@ -16,7 +16,7 @@ void Board::raisePOWER() {
CPU().raiseHALT();
}
void Board::lowerPOWER() {
void Board::lowerPOWER() noexcept {
CPU().lowerPOWER();
EightBit::Bus::lowerPOWER();
}

View File

@ -11,8 +11,8 @@ public:
constexpr EightBit::mc6809& CPU() noexcept { return m_cpu; }
void raisePOWER() final;
void lowerPOWER() final;
void raisePOWER() noexcept final;
void lowerPOWER() noexcept final;
protected:
void initialise() final;

View File

@ -45,4 +45,15 @@ void Fuse::ExpectedTestResult::read(std::ifstream& file) {
memoryData.push_back(datum);
}
} while (!line.empty());
}
}
// returns a vector of: address, expected, actual
std::vector<std::tuple<int, int, int>> Fuse::ExpectedTestResult::findDifferences(const EightBit::Memory& memory) const {
std::vector<std::tuple<int, int, int>> returned;
for (const auto& memoryDatum : memoryData) {
const auto found = memoryDatum.findDifferences(memory);
if (!found.empty())
returned.insert(returned.end(), found.begin(), found.end());
}
return returned;
}

View File

@ -3,6 +3,7 @@
#include <fstream>
#include <string>
#include <vector>
#include <tuple>
#include "FuseTestEvents.h"
#include "FuseRegisterState.h"
@ -23,5 +24,8 @@ namespace Fuse {
: finish(false) {}
void read(std::ifstream& file);
// returns a vector of: address, expected, actual
std::vector<std::tuple<int, int, int>> findDifferences(const EightBit::Memory& memory) const;
};
}

View File

@ -17,4 +17,21 @@ void Fuse::MemoryDatum::read(std::ifstream& file) {
if (!completed)
bytes.push_back(byte);
} while (!completed);
}
}
void Fuse::MemoryDatum::transfer(EightBit::Memory& memory) const {
memory.load(bytes, address);
}
// returns a vector of: address, expected, actual
std::vector<std::tuple<int, int, int>> Fuse::MemoryDatum::findDifferences(const EightBit::Memory& memory) const {
std::vector<std::tuple<int, int, int>> returned;
for (int i = 0; i < bytes.size(); ++i) {
const auto expected = bytes[i];
int address = this->address + i;
const auto actual = memory.peek(address);
if (expected != actual)
returned.push_back({ address, expected, actual });
}
return returned;;
}

View File

@ -3,6 +3,9 @@
#include <cinttypes>
#include <vector>
#include <fstream>
#include <tuple>
#include <Memory.h>
namespace Fuse {
class MemoryDatum {
@ -19,5 +22,10 @@ namespace Fuse {
bool finished() const { return finish; }
void read(std::ifstream& file);
void transfer(EightBit::Memory& memory) const;
// returns a vector of: address, expected, actual
std::vector<std::tuple<int, int, int>> findDifferences(const EightBit::Memory& memory) const;
};
}

View File

@ -1,6 +1,8 @@
#include "stdafx.h"
#include "FuseRegisterState.h"
#include <Z80.h>
Fuse::RegisterState::RegisterState()
: registers(NUMBER_OF_REGISTERS) {
}
@ -11,10 +13,10 @@ void Fuse::RegisterState::read(std::ifstream& file) {
}
void Fuse::RegisterState::readExternal(std::ifstream& file) {
for (int idx = 0; idx < registers.size(); ++idx) {
for (auto& r : registers) {
int input;
file >> input;
registers[idx] = input;
r = input;
}
}
@ -30,3 +32,31 @@ void Fuse::RegisterState::readInternal(std::ifstream& file) {
file >> tstates;
file >> std::hex;
}
void Fuse::RegisterState::transfer(EightBit::Z80& cpu) const {
cpu.AF() = registers[AF_];
cpu.BC() = registers[BC_];
cpu.DE() = registers[DE_];
cpu.HL() = registers[HL_];
cpu.exx();
cpu.exxAF();
cpu.AF() = registers[AF];
cpu.BC() = registers[BC];
cpu.DE() = registers[DE];
cpu.HL() = registers[HL];
cpu.IX() = registers[IX];
cpu.IY() = registers[IY];
cpu.SP() = registers[SP];
cpu.PC() = registers[PC];
cpu.MEMPTR() = registers[MEMPTR];
cpu.IV() = i;
cpu.REFRESH() = r;
cpu.IFF1() = iff1;
cpu.IFF2() = iff2;
cpu.IM() = im;
}

View File

@ -1,11 +1,14 @@
#pragma once
#include <vector>
#include <string>
#include <fstream>
#include <Register.h>
namespace EightBit {
class Z80;
}
namespace Fuse {
class RegisterState {
public:
@ -13,11 +16,11 @@ namespace Fuse {
AF, BC, DE, HL, AF_, BC_, DE_, HL_, IX, IY, SP, PC, MEMPTR, NUMBER_OF_REGISTERS
};
std::vector<EightBit::register16_t> registers;
int i, r;
bool iff1, iff2;
int im;
bool halted;
int tstates;
int i = -1, r = -1;
bool iff1 = false, iff2 = false;
int im = -1;
bool halted = false;
int tstates = -1;
public:
RegisterState();
@ -25,5 +28,7 @@ namespace Fuse {
void read(std::ifstream& file);
void readInternal(std::ifstream& file);
void readExternal(std::ifstream& file);
void transfer(EightBit::Z80& cpu) const;
};
}

View File

@ -23,3 +23,12 @@ void Fuse::Test::read(std::ifstream& file) {
memoryData.push_back(memoryDatum);
} while (!complete);
}
void Fuse::Test::transferMemory(EightBit::Memory& memory) const {
for (const auto& memoryDatum : memoryData)
memoryDatum.transfer(memory);
}
void Fuse::Test::transferRegisters(EightBit::Z80 & cpu) const {
registerState.transfer(cpu);
}

View File

@ -7,6 +7,9 @@
#include "FuseMemoryDatum.h"
#include "FuseRegisterState.h"
#include <Memory.h>
#include <Z80.h>
namespace Fuse {
class Test {
public:
@ -16,5 +19,8 @@ namespace Fuse {
bool finish = false;
void read(std::ifstream& file);
void transferMemory(EightBit::Memory& memory) const;
void transferRegisters(EightBit::Z80& cpu) const;
};
}

View File

@ -1,6 +1,18 @@
#include "stdafx.h"
#include "FuseTestEvent.h"
#include <boost/algorithm/string/predicate.hpp>
#include <Disassembler.h>
bool Fuse::TestEvent::operator==(const TestEvent& rhs) const {
const auto equalCycles = cycles == rhs.cycles;
const auto equalSpecifier = specifier == rhs.specifier;
const auto equalAddress = address == rhs.address;
const auto equalValue = value == rhs.value;
return equalCycles && equalSpecifier && equalAddress && equalValue;
}
void Fuse::TestEvent::read(std::ifstream& file) {
auto prior = file.tellg();
@ -31,4 +43,14 @@ void Fuse::TestEvent::read(std::ifstream& file) {
if (!valid) {
file.seekg(prior);
}
}
void Fuse::TestEvent::dump() const {
std::cerr << " Event issue " <<
"Cycles = " << cycles <<
", Specifier = " << specifier <<
", Address = " << EightBit::Disassembler::hex((uint16_t)address);
if (!boost::algorithm::ends_with(specifier, "C"))
std::cerr << ", Value=" << EightBit::Disassembler::hex((uint8_t)value);
std::cerr << std::endl;
}

View File

@ -12,9 +12,12 @@ namespace Fuse {
TestEvent()
: valid(false),
cycles(-1), address(-1), value(-1) {
}
cycles(-1), address(-1), value(-1) {}
bool operator==(const TestEvent& rhs) const;
void read(std::ifstream& file);
void dump() const;
};
}

View File

@ -1,6 +1,15 @@
#include "stdafx.h"
#include "FuseTestEvents.h"
bool Fuse::TestEvents::operator==(const TestEvents& rhs) const {
auto unequal = events.size() != rhs.events.size();
for (int i = 0; !unequal && (i < events.size()); ++i) {
const auto equal = events[i] == rhs.events[i];
unequal = !equal;
}
return !unequal;
}
void Fuse::TestEvents::read(std::ifstream& file) {
bool complete = false;
do {
@ -11,3 +20,8 @@ void Fuse::TestEvents::read(std::ifstream& file) {
events.push_back(event);
} while (!complete);
}
void Fuse::TestEvents::dump() const {
for (const auto& event : events)
event.dump();
}

View File

@ -8,6 +8,10 @@ namespace Fuse {
public:
std::vector<TestEvent> events;
bool operator==(const TestEvents& rhs) const;
void read(std::ifstream& file);
void dump() const;
};
}

View File

@ -51,16 +51,16 @@ void Fuse::TestRunner::addActualEvent(const std::string& specifier) {
//
void Fuse::TestRunner::raisePOWER() {
void Fuse::TestRunner::raisePOWER() noexcept {
EightBit::Bus::raisePOWER();
m_cpu.raisePOWER();
m_cpu.raiseRESET();
m_cpu.raiseINT();
m_cpu.raiseNMI();
initialiseRegisters();
m_test.transferRegisters(m_cpu);
}
void Fuse::TestRunner::lowerPOWER() {
void Fuse::TestRunner::lowerPOWER() noexcept {
m_cpu.lowerPOWER();
EightBit::Bus::lowerPOWER();
}
@ -99,47 +99,7 @@ EightBit::MemoryMapping Fuse::TestRunner::mapping(uint16_t address) noexcept {
}
void Fuse::TestRunner::initialise() {
initialiseMemory();
}
void Fuse::TestRunner::initialiseRegisters() {
const auto& testState = m_test.registerState;
const auto& inputRegisters = testState.registers;
m_cpu.AF() = inputRegisters[Fuse::RegisterState::AF_];
m_cpu.BC() = inputRegisters[Fuse::RegisterState::BC_];
m_cpu.DE() = inputRegisters[Fuse::RegisterState::DE_];
m_cpu.HL() = inputRegisters[Fuse::RegisterState::HL_];
m_cpu.exx();
m_cpu.exxAF();
m_cpu.AF() = inputRegisters[Fuse::RegisterState::AF];
m_cpu.BC() = inputRegisters[Fuse::RegisterState::BC];
m_cpu.DE() = inputRegisters[Fuse::RegisterState::DE];
m_cpu.HL() = inputRegisters[Fuse::RegisterState::HL];
m_cpu.IX() = inputRegisters[Fuse::RegisterState::IX];
m_cpu.IY() = inputRegisters[Fuse::RegisterState::IY];
m_cpu.SP() = inputRegisters[Fuse::RegisterState::SP];
m_cpu.PC() = inputRegisters[Fuse::RegisterState::PC];
m_cpu.MEMPTR() = inputRegisters[Fuse::RegisterState::MEMPTR];
m_cpu.IV() = testState.i;
m_cpu.REFRESH() = testState.r;
m_cpu.IFF1() = testState.iff1;
m_cpu.IFF2() = testState.iff2;
m_cpu.IM() = testState.im;
}
void Fuse::TestRunner::initialiseMemory() {
for (auto memoryDatum : m_test.memoryData) {
auto address = memoryDatum.address;
auto bytes = memoryDatum.bytes;
for (int i = 0; i < bytes.size(); ++i)
m_ram.poke(address + i, bytes[i]);
}
m_test.transferMemory(m_ram);
}
//
@ -378,51 +338,26 @@ void Fuse::TestRunner::checkRegisters() {
}
void Fuse::TestRunner::checkMemory() {
bool first = true;
for (auto memoryDatum : m_result.memoryData) {
auto bytes = memoryDatum.bytes;
for (int i = 0; i < bytes.size(); ++i) {
auto expected = bytes[i];
uint16_t address = memoryDatum.address + i;
auto actual = m_ram.peek(address);
if (expected != actual) {
m_failed = true;
if (first) {
first = false;
std::cerr << "**** Failed test (Memory): " << m_test.description << std::endl;
}
std::cerr
<< "**** Difference: "
<< "Address: " << EightBit::Disassembler::hex(address)
<< " Expected: " << EightBit::Disassembler::hex(expected)
<< " Actual: " << EightBit::Disassembler::hex(actual)
<< std::endl;
}
const auto differences = m_result.findDifferences(m_ram);
const auto failure = !differences.empty();
if (failure) {
m_failed = true;
std::cerr << "**** Failed test (Memory): " << m_test.description << std::endl;
for (const auto& difference : differences) {
const auto [address, expected, actual] = difference;
std::cerr
<< "**** Difference: "
<< "Address: " << EightBit::Disassembler::hex((uint16_t)address)
<< " Expected: " << EightBit::Disassembler::hex((uint8_t)expected)
<< " Actual: " << EightBit::Disassembler::hex((uint8_t)actual)
<< std::endl;
}
}
}
void Fuse::TestRunner::checkEvents() {
const auto& expectations = m_expectedEvents.events;
const auto& actuals = m_actualEvents.events;
auto eventFailure = expectations.size() != actuals.size();
for (auto i = 0; !eventFailure && (i < expectations.size()); ++i) {
const auto& expectation = expectations[i];
const auto& actual = actuals[i];