mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-04-22 08:41:12 +00:00
Tidy up noexcept specification
This commit is contained in:
parent
83b7efdd03
commit
8e0092ec9d
Gaming
Intel8080
LR35902
fusetest_LR35902
inc
src
M6502
MC6809
Z80
fusetest_Z80
FuseExpectedTestResult.cppFuseExpectedTestResult.hFuseMemoryDatum.cppFuseMemoryDatum.hFuseRegisterState.cppFuseRegisterState.hFuseTest.cppFuseTest.hFuseTestEvent.cppFuseTestEvent.hFuseTestEvents.cppFuseTestEvents.hFuseTestRunner.cppFuseTestRunner.h
inc
src
test
inc
BigEndianProcessor.hBus.hClockedChip.hDevice.hIntelProcessor.hLittleEndianProcessor.hProcessor.hSignal.hTestHarness.h
src
@ -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;
|
||||
|
@ -25,7 +25,7 @@ int Game::displayHeight() const noexcept {
|
||||
return rasterHeight();
|
||||
}
|
||||
|
||||
void Game::raisePOWER() {
|
||||
void Game::raisePOWER() noexcept {
|
||||
|
||||
Device::raisePOWER();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ protected:
|
||||
public:
|
||||
TestRunner();
|
||||
|
||||
void raisePOWER() final;
|
||||
void lowerPOWER() final;
|
||||
void raisePOWER() noexcept final;
|
||||
void lowerPOWER() noexcept final;
|
||||
|
||||
void initialise() final;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 };
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
@ -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;;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
@ -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];
|
||||
|
||||
const auto equalCycles = expectation.cycles == actual.cycles;
|
||||
const auto equalSpecifier = expectation.specifier == actual.specifier;
|
||||
const auto equalAddress = expectation.address == actual.address;
|
||||
const auto equalValue = expectation.value == actual.value;
|
||||
|
||||
const auto equal = equalCycles && equalSpecifier && equalAddress && equalValue;
|
||||
eventFailure = !equal;
|
||||
}
|
||||
auto eventFailure = m_expectedEvents != m_actualEvents;
|
||||
|
||||
if (eventFailure) {
|
||||
dumpExpectedEvents();
|
||||
@ -435,28 +370,12 @@ void Fuse::TestRunner::checkEvents() {
|
||||
|
||||
void Fuse::TestRunner::dumpExpectedEvents() const {
|
||||
std::cerr << "++++ Dumping expected events:" << std::endl;
|
||||
dumpEvents(m_expectedEvents.events);
|
||||
m_expectedEvents.dump();
|
||||
}
|
||||
|
||||
void Fuse::TestRunner::dumpActualEvents() const {
|
||||
std::cerr << "++++ Dumping actual events:" << std::endl;
|
||||
dumpEvents(m_actualEvents.events);
|
||||
}
|
||||
|
||||
void Fuse::TestRunner::dumpEvents(const std::vector<TestEvent>& events) {
|
||||
for (const auto& event : events) {
|
||||
dumpEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void Fuse::TestRunner::dumpEvent(const TestEvent& event) {
|
||||
std::cerr << " Event issue " <<
|
||||
"Cycles = " << event.cycles <<
|
||||
", Specifier = " << event.specifier <<
|
||||
", Address = " << EightBit::Disassembler::hex((uint16_t)event.address);
|
||||
if (!boost::algorithm::ends_with(event.specifier, "C"))
|
||||
std::cerr << ", Value=" << EightBit::Disassembler::hex((uint8_t)event.value);
|
||||
std::cerr << std::endl;
|
||||
m_actualEvents.dump();
|
||||
}
|
||||
|
||||
void Fuse::TestRunner::run() {
|
||||
|
@ -26,9 +26,6 @@ namespace Fuse {
|
||||
|
||||
int m_totalCycles;
|
||||
|
||||
void initialiseRegisters();
|
||||
void initialiseMemory();
|
||||
|
||||
void check();
|
||||
void checkRegisters();
|
||||
void checkMemory();
|
||||
@ -44,9 +41,6 @@ namespace Fuse {
|
||||
void dumpExpectedEvents() const;
|
||||
void dumpActualEvents() const;
|
||||
|
||||
static void dumpEvents(const std::vector<TestEvent>& events);
|
||||
static void dumpEvent(const TestEvent& event);
|
||||
|
||||
protected:
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) noexcept final;
|
||||
|
||||
@ -57,9 +51,9 @@ 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;
|
||||
|
||||
virtual void initialise() final;
|
||||
void initialise() final;
|
||||
};
|
||||
}
|
444
Z80/inc/Z80.h
444
Z80/inc/Z80.h
@ -89,8 +89,8 @@ namespace EightBit {
|
||||
Signal<EventArgs> WritingIO;
|
||||
Signal<EventArgs> WrittenIO;
|
||||
|
||||
int execute() final;
|
||||
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(); }
|
||||
@ -101,15 +101,15 @@ namespace EightBit {
|
||||
[[nodiscard]] const register16_t& HL() const noexcept final;
|
||||
[[nodiscard]] auto& HL() noexcept { return IntelProcessor::HL(); }
|
||||
|
||||
[[nodiscard]] const auto& IX() const noexcept { return m_ix; }
|
||||
[[nodiscard]] constexpr const auto& IX() const noexcept { return m_ix; }
|
||||
NON_CONST_REGISTOR_ACCESSOR(IX);
|
||||
[[nodiscard]] auto& IXH() noexcept { return IX().high; }
|
||||
[[nodiscard]] auto& IXL() noexcept { return IX().low; }
|
||||
[[nodiscard]] constexpr auto& IXH() noexcept { return IX().high; }
|
||||
[[nodiscard]] constexpr auto& IXL() noexcept { return IX().low; }
|
||||
|
||||
[[nodiscard]] const auto& IY() const noexcept { return m_iy; }
|
||||
[[nodiscard]] constexpr const auto& IY() const noexcept { return m_iy; }
|
||||
NON_CONST_REGISTOR_ACCESSOR(IY);
|
||||
[[nodiscard]] auto& IYH() noexcept { return IY().high; }
|
||||
[[nodiscard]] auto& IYL() noexcept { return IY().low; }
|
||||
[[nodiscard]] constexpr auto& IYH() noexcept { return IY().high; }
|
||||
[[nodiscard]] constexpr auto& IYL() noexcept { return IY().low; }
|
||||
|
||||
// ** From the Z80 CPU User Manual
|
||||
// Memory Refresh(R) Register.The Z80 CPU contains a memory refresh counter,
|
||||
@ -144,19 +144,19 @@ namespace EightBit {
|
||||
[[nodiscard]] constexpr auto requestingWrite() const noexcept { return lowered(WR()); }
|
||||
|
||||
protected:
|
||||
void handleRESET() final;
|
||||
void handleINT() final;
|
||||
void handleRESET() noexcept final;
|
||||
void handleINT() noexcept final;
|
||||
|
||||
void pushWord(register16_t destination) final;
|
||||
void pushWord(register16_t destination) 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;
|
||||
|
||||
void jr(int8_t offset) final;
|
||||
int jrConditional(int condition) final;
|
||||
void jr(int8_t offset) noexcept final;
|
||||
int jrConditional(int condition) noexcept final;
|
||||
|
||||
private:
|
||||
enum { BC_IDX, DE_IDX, HL_IDX };
|
||||
@ -184,136 +184,376 @@ namespace EightBit {
|
||||
|
||||
int8_t m_displacement = 0;
|
||||
|
||||
void handleNMI();
|
||||
void handleNMI() noexcept;
|
||||
|
||||
void resetPrefixes() noexcept;
|
||||
constexpr void resetPrefixes() noexcept {
|
||||
m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr auto displaced() const noexcept { return m_prefixDD || m_prefixFD; }
|
||||
[[nodiscard]] uint16_t displacedAddress() noexcept;
|
||||
void fetchDisplacement();
|
||||
[[nodiscard]] uint8_t fetchOpCode();
|
||||
|
||||
uint8_t readBusDataM1();
|
||||
[[nodiscard]] constexpr uint16_t displacedAddress() noexcept {
|
||||
const auto address = (m_prefixDD ? IX() : IY()).word + m_displacement;
|
||||
MEMPTR().word = address;
|
||||
return address;
|
||||
}
|
||||
|
||||
void fetchDisplacement() noexcept;
|
||||
[[nodiscard]] uint8_t fetchOpCode() noexcept;
|
||||
|
||||
uint8_t readBusDataM1() noexcept;
|
||||
|
||||
typedef std::function<register16_t(void)> addresser_t;
|
||||
void loadAccumulatorIndirect(addresser_t addresser);
|
||||
void storeAccumulatorIndirect(addresser_t addresser);
|
||||
void loadAccumulatorIndirect(addresser_t addresser) noexcept;
|
||||
void storeAccumulatorIndirect(addresser_t addresser) noexcept;
|
||||
|
||||
typedef std::function<uint8_t(void)> reader_t;
|
||||
void readInternalRegister(reader_t reader);
|
||||
void readInternalRegister(reader_t reader) noexcept;
|
||||
|
||||
[[nodiscard]] register16_t& HL2() noexcept;
|
||||
[[nodiscard]] register16_t& RP(int rp) noexcept;
|
||||
[[nodiscard]] register16_t& RP2(int rp) noexcept;
|
||||
|
||||
[[nodiscard]] uint8_t R(int r);
|
||||
void R(int r, uint8_t value);
|
||||
void R2(int r, uint8_t value);
|
||||
[[nodiscard]] uint8_t R(int r) noexcept;
|
||||
void R(int r, uint8_t value) noexcept;
|
||||
void R2(int r, uint8_t value) noexcept;
|
||||
|
||||
[[nodiscard]] static uint8_t adjustHalfCarryAdd(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept;
|
||||
[[nodiscard]] static uint8_t adjustHalfCarrySub(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept;
|
||||
[[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept;
|
||||
[[nodiscard]] static uint8_t adjustOverflowAdd(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept;
|
||||
[[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept;
|
||||
[[nodiscard]] static uint8_t adjustOverflowSub(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept;
|
||||
[[nodiscard]] static constexpr auto adjustHalfCarryAdd(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept {
|
||||
return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool convertCondition(uint8_t f, int flag) noexcept;
|
||||
[[nodiscard]] static constexpr auto adjustHalfCarrySub(uint8_t f, uint8_t before, uint8_t value, int calculation) noexcept {
|
||||
return setBit(f, HC, calculateHalfCarrySub(before, value, calculation));
|
||||
}
|
||||
|
||||
static uint8_t subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
|
||||
[[nodiscard]] static constexpr auto adjustOverflowAdd(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept {
|
||||
const auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative);
|
||||
return setBit(f, VF, overflow);
|
||||
}
|
||||
|
||||
void executeCB(int x, int y, int z);
|
||||
void executeED(int x, int y, int z, int p, int q);
|
||||
void executeOther(int x, int y, int z, int p, int q);
|
||||
[[nodiscard]] static constexpr auto adjustOverflowAdd(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept {
|
||||
return adjustOverflowAdd(f, before & SF, value & SF, calculation & SF);
|
||||
}
|
||||
|
||||
[[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 constexpr auto adjustOverflowSub(uint8_t f, int beforeNegative, int valueNegative, int afterNegative) noexcept {
|
||||
const auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative);
|
||||
return setBit(f, VF, overflow);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr auto adjustOverflowSub(uint8_t f, uint8_t before, uint8_t value, uint8_t calculation) noexcept {
|
||||
return adjustOverflowSub(f, before & SF, value & SF, calculation & SF);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool convertCondition(uint8_t f, int flag) noexcept {
|
||||
switch (flag) {
|
||||
case 0:
|
||||
return !(f & ZF);
|
||||
case 1:
|
||||
return f & ZF;
|
||||
case 2:
|
||||
return !(f & CF);
|
||||
case 3:
|
||||
return f & CF;
|
||||
case 4:
|
||||
return !(f & PF);
|
||||
case 5:
|
||||
return f & PF;
|
||||
case 6:
|
||||
return !(f & SF);
|
||||
case 7:
|
||||
return f & SF;
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr auto subtract(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept {
|
||||
const register16_t subtraction = operand - value - carry;
|
||||
const auto result = subtraction.low;
|
||||
|
||||
f = adjustHalfCarrySub(f, operand, value, result);
|
||||
f = adjustOverflowSub(f, operand, value, result);
|
||||
|
||||
f = setBit(f, NF);
|
||||
f = setBit(f, CF, subtraction.high & CF);
|
||||
f = adjustSZ<Z80>(f, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void executeCB(int x, int y, int z) noexcept;
|
||||
void executeED(int x, int y, int z, int p, int q) noexcept;
|
||||
void executeOther(int x, int y, int z, int p, int q) noexcept;
|
||||
|
||||
[[nodiscard]] static constexpr auto increment(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF);
|
||||
const uint8_t result = operand + 1;
|
||||
f = adjustSZXY<Z80>(f, result);
|
||||
f = setBit(f, VF, result == Bit7);
|
||||
f = clearBit(f, HC, lowNibble(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr auto decrement(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = setBit(f, NF);
|
||||
f = clearBit(f, HC, lowNibble(operand));
|
||||
const uint8_t result = operand - 1;
|
||||
f = adjustSZXY<Z80>(f, result);
|
||||
f = setBit(f, VF, result == Mask7);
|
||||
return result;
|
||||
}
|
||||
|
||||
void di() noexcept;
|
||||
void ei() noexcept;
|
||||
|
||||
void retn();
|
||||
void reti();
|
||||
void retn() noexcept;
|
||||
void reti() noexcept;
|
||||
|
||||
void returnConditionalFlag(uint8_t f, int flag);
|
||||
void jrConditionalFlag(uint8_t f, int flag);
|
||||
void callConditionalFlag(uint8_t f, int flag);
|
||||
void jumpConditionalFlag(uint8_t f, int flag);
|
||||
void returnConditionalFlag(uint8_t f, int flag) noexcept;
|
||||
void jrConditionalFlag(uint8_t f, int flag) noexcept;
|
||||
void callConditionalFlag(uint8_t f, int flag) noexcept;
|
||||
void jumpConditionalFlag(uint8_t f, int flag) noexcept;
|
||||
|
||||
[[nodiscard]] register16_t sbc(uint8_t& f, register16_t operand, register16_t value);
|
||||
[[nodiscard]] register16_t adc(uint8_t& f, register16_t operand, register16_t value);
|
||||
[[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value, int carry = 0);
|
||||
[[nodiscard]] register16_t sbc(uint8_t& f, register16_t operand, register16_t value) noexcept;
|
||||
[[nodiscard]] register16_t adc(uint8_t& f, register16_t operand, register16_t value) noexcept;
|
||||
[[nodiscard]] register16_t add(uint8_t& f, register16_t operand, register16_t value, int carry = 0) noexcept;
|
||||
|
||||
[[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 sub(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept;
|
||||
[[nodiscard]] static uint8_t sbc(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
[[nodiscard]] 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;
|
||||
static void compare(uint8_t& f, uint8_t operand, uint8_t value) noexcept;
|
||||
[[nodiscard]] static constexpr auto add(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept {
|
||||
const register16_t addition = operand + value + carry;
|
||||
const auto result = addition.low;
|
||||
|
||||
[[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 sll(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static uint8_t srl(uint8_t& f, uint8_t operand) noexcept;
|
||||
f = adjustHalfCarryAdd(f, operand, value, result);
|
||||
f = adjustOverflowAdd(f, operand, value, result);
|
||||
|
||||
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;
|
||||
f = clearBit(f, NF);
|
||||
f = setBit(f, CF, addition.high & CF);
|
||||
f = adjustSZXY<Z80>(f, result);
|
||||
|
||||
[[nodiscard]] static uint8_t daa(uint8_t& f, uint8_t operand) noexcept;
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
[[nodiscard]] static constexpr auto adc(uint8_t& f, uint8_t operand, uint8_t value) noexcept {
|
||||
return add(f, operand, value, f & CF);
|
||||
}
|
||||
|
||||
void xhtl(register16_t& exchange);
|
||||
[[nodiscard]] static constexpr auto sub(uint8_t& f, uint8_t operand, uint8_t value, int carry = 0) noexcept {
|
||||
const auto subtraction = subtract(f, operand, value, carry);
|
||||
f = adjustSZXY<Z80>(f, subtraction);
|
||||
return subtraction;
|
||||
}
|
||||
|
||||
void blockCompare(uint8_t& f, uint8_t value, register16_t source, register16_t& counter);
|
||||
[[nodiscard]] static constexpr auto sbc(uint8_t& f, uint8_t operand, uint8_t value) noexcept {
|
||||
return sub(f, operand, value, f & CF);
|
||||
}
|
||||
|
||||
void cpi(uint8_t& f, uint8_t value);
|
||||
[[nodiscard]] bool cpir(uint8_t& f, uint8_t value);
|
||||
[[nodiscard]] static constexpr auto andr(uint8_t& f, uint8_t operand, uint8_t value) noexcept {
|
||||
f = setBit(f, HC);
|
||||
f = clearBit(f, CF | NF);
|
||||
const uint8_t result = operand & value;
|
||||
f = adjustSZPXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void cpd(uint8_t& f, uint8_t value);
|
||||
[[nodiscard]] bool cpdr(uint8_t& f, uint8_t value);
|
||||
[[nodiscard]] static constexpr auto xorr(uint8_t& f, uint8_t operand, uint8_t value) noexcept {
|
||||
f = clearBit(f, HC | CF | NF);
|
||||
const uint8_t result = operand ^ value;
|
||||
f = adjustSZPXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void blockLoad(uint8_t& f, uint8_t a, register16_t source, register16_t destination, register16_t& counter);
|
||||
[[nodiscard]] static constexpr auto orr(uint8_t& f, uint8_t operand, uint8_t value) noexcept {
|
||||
f = clearBit(f, HC | CF | NF);
|
||||
const uint8_t result = operand | value;
|
||||
f = adjustSZPXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ldi(uint8_t& f, uint8_t a);
|
||||
[[nodiscard]] bool ldir(uint8_t& f, uint8_t a);
|
||||
static void compare(uint8_t& f, uint8_t operand, uint8_t value) noexcept {
|
||||
subtract(f, operand, value);
|
||||
f = adjustXY<Z80>(f, value);
|
||||
}
|
||||
|
||||
void ldd(uint8_t& f, uint8_t a);
|
||||
[[nodiscard]] bool lddr(uint8_t& f, uint8_t a);
|
||||
[[nodiscard]] static constexpr auto rlc(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = operand & Bit7;
|
||||
f = setBit(f, CF, carry);
|
||||
const uint8_t result = (operand << 1) | (carry >> 7);
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void blockIn(register16_t& source, register16_t destination);
|
||||
[[nodiscard]] static constexpr auto rrc(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = operand & Bit0;
|
||||
f = setBit(f, CF, carry);
|
||||
const uint8_t result = (operand >> 1) | (carry << 7);
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ini();
|
||||
[[nodiscard]] bool inir();
|
||||
[[nodiscard]] static constexpr auto rl(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
const uint8_t result = (operand << 1) | carry;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ind();
|
||||
[[nodiscard]] bool indr();
|
||||
[[nodiscard]] static constexpr auto rr(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
const uint8_t result = (operand >> 1) | (carry << 7);
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void blockOut(register16_t source, register16_t& destination);
|
||||
[[nodiscard]] static constexpr auto sla(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
const uint8_t result = operand << 1;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void outi();
|
||||
[[nodiscard]] bool otir();
|
||||
[[nodiscard]] static constexpr auto sra(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
const uint8_t result = (operand >> 1) | (operand & Bit7);
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void outd();
|
||||
[[nodiscard]] bool otdr();
|
||||
[[nodiscard]] static constexpr auto sll(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
const uint8_t result = (operand << 1) | Bit0;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] uint8_t neg(uint8_t& f, uint8_t operand) noexcept;
|
||||
[[nodiscard]] static constexpr auto srl(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
const uint8_t result = (operand >> 1) & ~Bit7;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
f = setBit(f, ZF, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void rrd(uint8_t& f, register16_t address, uint8_t& update);
|
||||
void rld(uint8_t& f, register16_t address, uint8_t& update);
|
||||
static constexpr void bit(uint8_t& f, int n, uint8_t operand) noexcept {
|
||||
f = setBit(f, HC);
|
||||
f = clearBit(f, NF);
|
||||
const auto discarded = operand & Chip::bit(n);
|
||||
f = adjustSZ<Z80>(f, discarded);
|
||||
f = clearBit(f, PF, discarded);
|
||||
}
|
||||
|
||||
void portWrite(uint8_t port);
|
||||
void portWrite();
|
||||
[[nodiscard]] static constexpr auto res(int n, uint8_t operand) noexcept { return clearBit(operand, Chip::bit(n)); }
|
||||
[[nodiscard]] static constexpr auto set(int n, uint8_t operand) noexcept { return setBit(operand, Chip::bit(n)); }
|
||||
|
||||
uint8_t portRead(uint8_t port);
|
||||
uint8_t portRead();
|
||||
[[nodiscard]] static constexpr auto daa(uint8_t& f, uint8_t operand) noexcept {
|
||||
const auto lowAdjust = (f & HC) || (lowNibble(operand) > 9);
|
||||
const auto highAdjust = (f & CF) || (operand > 0x99);
|
||||
|
||||
auto updated = operand;
|
||||
if (f & NF) {
|
||||
if (lowAdjust)
|
||||
updated -= 6;
|
||||
if (highAdjust)
|
||||
updated -= 0x60;
|
||||
} else {
|
||||
if (lowAdjust)
|
||||
updated += 6;
|
||||
if (highAdjust)
|
||||
updated += 0x60;
|
||||
}
|
||||
|
||||
f = (f & (CF | NF)) | (operand > 0x99 ? CF : 0) | ((operand ^ updated) & HC);
|
||||
|
||||
f = adjustSZPXY<Z80>(f, updated);
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
static constexpr void scf(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = setBit(f, CF);
|
||||
f = clearBit(f, HC | NF);
|
||||
f = adjustXY<Z80>(f, operand);
|
||||
}
|
||||
|
||||
static constexpr void ccf(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, HC, carry);
|
||||
f = clearBit(f, CF, carry);
|
||||
f = adjustXY<Z80>(f, operand);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr auto cpl(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = setBit(f, HC | NF);
|
||||
const uint8_t result = ~operand;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void xhtl(register16_t& exchange) noexcept;
|
||||
|
||||
void blockCompare(uint8_t& f, uint8_t value, register16_t source, register16_t& counter) noexcept;
|
||||
|
||||
void cpi(uint8_t& f, uint8_t value) noexcept;
|
||||
[[nodiscard]] bool cpir(uint8_t& f, uint8_t value) noexcept;
|
||||
|
||||
void cpd(uint8_t& f, uint8_t value) noexcept;
|
||||
[[nodiscard]] bool cpdr(uint8_t& f, uint8_t value) noexcept;
|
||||
|
||||
void blockLoad(uint8_t& f, uint8_t a, register16_t source, register16_t destination, register16_t& counter) noexcept;
|
||||
|
||||
void ldi(uint8_t& f, uint8_t a) noexcept;
|
||||
[[nodiscard]] bool ldir(uint8_t& f, uint8_t a) noexcept;
|
||||
|
||||
void ldd(uint8_t& f, uint8_t a) noexcept;
|
||||
[[nodiscard]] bool lddr(uint8_t& f, uint8_t a) noexcept;
|
||||
|
||||
void blockIn(register16_t& source, register16_t destination) noexcept;
|
||||
|
||||
void ini() noexcept;
|
||||
[[nodiscard]] bool inir() noexcept;
|
||||
|
||||
void ind() noexcept;
|
||||
[[nodiscard]] bool indr() noexcept;
|
||||
|
||||
void blockOut(register16_t source, register16_t& destination) noexcept;
|
||||
|
||||
void outi() noexcept;
|
||||
[[nodiscard]] bool otir() noexcept;
|
||||
|
||||
void outd() noexcept;
|
||||
[[nodiscard]] bool otdr() noexcept;
|
||||
|
||||
[[nodiscard]] static constexpr auto neg(uint8_t& f, uint8_t operand) noexcept {
|
||||
f = setBit(f, PF, operand == Bit7);
|
||||
f = setBit(f, CF, operand);
|
||||
f = setBit(f, NF);
|
||||
|
||||
const uint8_t result = (~operand + 1); // two's complement
|
||||
|
||||
f = adjustHalfCarrySub(f, 0U, operand, result);
|
||||
f = adjustOverflowSub(f, 0U, operand, result);
|
||||
|
||||
f = adjustSZXY<Z80>(f, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void rrd(uint8_t& f, register16_t address, uint8_t& update) noexcept;
|
||||
void rld(uint8_t& f, register16_t address, uint8_t& update) noexcept;
|
||||
|
||||
void portWrite(uint8_t port) noexcept;
|
||||
void portWrite() noexcept;
|
||||
|
||||
uint8_t portRead(uint8_t port) noexcept;
|
||||
uint8_t portRead() noexcept;
|
||||
};
|
||||
}
|
442
Z80/src/Z80.cpp
442
Z80/src/Z80.cpp
@ -46,8 +46,6 @@ EightBit::Z80::Z80(const Z80& rhs)
|
||||
m_ix = rhs.m_ix;
|
||||
m_iy = rhs.m_iy;
|
||||
|
||||
m_refresh = rhs.m_refresh;
|
||||
|
||||
iv = rhs.iv;
|
||||
m_interruptMode = rhs.m_interruptMode;
|
||||
m_iff1 = rhs.m_iff1;
|
||||
@ -131,23 +129,24 @@ const EightBit::register16_t& EightBit::Z80::HL() const noexcept {
|
||||
return m_registers[m_registerSet][HL_IDX];
|
||||
}
|
||||
|
||||
void EightBit::Z80::pushWord(const register16_t destination) {
|
||||
void EightBit::Z80::pushWord(const register16_t destination) noexcept {
|
||||
tick();
|
||||
IntelProcessor::pushWord(destination);
|
||||
}
|
||||
|
||||
void EightBit::Z80::memoryWrite() {
|
||||
void EightBit::Z80::memoryWrite() noexcept {
|
||||
|
||||
class _Writer final {
|
||||
Z80& m_parent;
|
||||
public:
|
||||
_Writer(Z80& parent) : m_parent(parent) {
|
||||
_Writer(Z80& parent) noexcept
|
||||
: m_parent(parent) {
|
||||
m_parent.WritingMemory.fire();
|
||||
m_parent.tick(2);
|
||||
m_parent.lowerMREQ();
|
||||
}
|
||||
|
||||
~_Writer() {
|
||||
~_Writer() noexcept {
|
||||
m_parent.raiseMREQ();
|
||||
m_parent.WrittenMemory.fire();
|
||||
}
|
||||
@ -157,12 +156,13 @@ void EightBit::Z80::memoryWrite() {
|
||||
IntelProcessor::memoryWrite();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::memoryRead() {
|
||||
uint8_t EightBit::Z80::memoryRead() noexcept {
|
||||
|
||||
class _Reader final {
|
||||
Z80& m_parent;
|
||||
public:
|
||||
_Reader(Z80& parent) : m_parent(parent) {
|
||||
_Reader(Z80& parent) noexcept
|
||||
: m_parent(parent) {
|
||||
m_parent.ReadingMemory.fire();
|
||||
if (lowered(m_parent.M1()))
|
||||
m_parent.tick();
|
||||
@ -170,7 +170,7 @@ uint8_t EightBit::Z80::memoryRead() {
|
||||
m_parent.lowerMREQ();
|
||||
}
|
||||
|
||||
~_Reader() {
|
||||
~_Reader() noexcept {
|
||||
m_parent.raiseMREQ();
|
||||
m_parent.ReadMemory.fire();
|
||||
}
|
||||
@ -180,27 +180,28 @@ uint8_t EightBit::Z80::memoryRead() {
|
||||
return IntelProcessor::memoryRead();
|
||||
}
|
||||
|
||||
void EightBit::Z80::busWrite() {
|
||||
void EightBit::Z80::busWrite() noexcept {
|
||||
tick();
|
||||
_ActivateWR writer(*this);
|
||||
IntelProcessor::busWrite();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::busRead() {
|
||||
uint8_t EightBit::Z80::busRead() noexcept {
|
||||
tick();
|
||||
_ActivateRD reader(*this);
|
||||
return IntelProcessor::busRead();
|
||||
}
|
||||
|
||||
void EightBit::Z80::handleRESET() {
|
||||
void EightBit::Z80::handleRESET() noexcept {
|
||||
IntelProcessor::handleRESET();
|
||||
di();
|
||||
IV() = REFRESH() = 0;
|
||||
IV() = 0;
|
||||
REFRESH() = 0;
|
||||
SP().word = AF().word = Mask16;
|
||||
tick(3);
|
||||
}
|
||||
|
||||
void EightBit::Z80::handleNMI() {
|
||||
void EightBit::Z80::handleNMI() noexcept {
|
||||
raiseNMI();
|
||||
raiseHALT();
|
||||
IFF2() = IFF1();
|
||||
@ -209,7 +210,7 @@ void EightBit::Z80::handleNMI() {
|
||||
restart(0x66);
|
||||
}
|
||||
|
||||
void EightBit::Z80::handleINT() {
|
||||
void EightBit::Z80::handleINT() noexcept {
|
||||
IntelProcessor::handleINT();
|
||||
tick(2); // 2 extra clock cycles introduced to allow the bus to settle
|
||||
uint8_t data;
|
||||
@ -242,112 +243,45 @@ void EightBit::Z80::ei() noexcept {
|
||||
IFF1() = IFF2() = true;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::increment(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF);
|
||||
const uint8_t result = operand + 1;
|
||||
f = adjustSZXY<Z80>(f, result);
|
||||
f = setBit(f, VF, result == Bit7);
|
||||
f = clearBit(f, HC, lowNibble(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::decrement(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = setBit(f, NF);
|
||||
f = clearBit(f, HC, lowNibble(operand));
|
||||
const uint8_t result = operand - 1;
|
||||
f = adjustSZXY<Z80>(f, result);
|
||||
f = setBit(f, VF, result == Mask7);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustHalfCarryAdd(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
||||
return setBit(f, HC, calculateHalfCarryAdd(before, value, calculation));
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustHalfCarrySub(const uint8_t f, const uint8_t before, const uint8_t value, const int calculation) noexcept {
|
||||
return setBit(f, HC, calculateHalfCarrySub(before, value, calculation));
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) noexcept {
|
||||
return adjustOverflowAdd(f, before & SF, value & SF, calculation & SF);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustOverflowAdd(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) noexcept {
|
||||
const auto overflow = (beforeNegative == valueNegative) && (beforeNegative != afterNegative);
|
||||
return setBit(f, VF, overflow);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const uint8_t before, const uint8_t value, const uint8_t calculation) noexcept {
|
||||
return adjustOverflowSub(f, before & SF, value & SF, calculation & SF);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adjustOverflowSub(const uint8_t f, const int beforeNegative, const int valueNegative, const int afterNegative) noexcept {
|
||||
const auto overflow = (beforeNegative != valueNegative) && (beforeNegative != afterNegative);
|
||||
return setBit(f, VF, overflow);
|
||||
}
|
||||
|
||||
bool EightBit::Z80::convertCondition(const uint8_t f, int flag) noexcept {
|
||||
switch (flag) {
|
||||
case 0:
|
||||
return !(f & ZF);
|
||||
case 1:
|
||||
return f & ZF;
|
||||
case 2:
|
||||
return !(f & CF);
|
||||
case 3:
|
||||
return f & CF;
|
||||
case 4:
|
||||
return !(f & PF);
|
||||
case 5:
|
||||
return f & PF;
|
||||
case 6:
|
||||
return !(f & SF);
|
||||
case 7:
|
||||
return f & SF;
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
void EightBit::Z80::returnConditionalFlag(const uint8_t f, const int flag) {
|
||||
void EightBit::Z80::returnConditionalFlag(const uint8_t f, const int flag) noexcept {
|
||||
tick();
|
||||
if (convertCondition(f, flag))
|
||||
ret();
|
||||
}
|
||||
|
||||
void EightBit::Z80::jrConditionalFlag(const uint8_t f, const int flag) {
|
||||
void EightBit::Z80::jrConditionalFlag(const uint8_t f, const int flag) noexcept {
|
||||
jrConditional(convertCondition(f, flag));
|
||||
}
|
||||
|
||||
void EightBit::Z80::jumpConditionalFlag(const uint8_t f, const int flag) {
|
||||
void EightBit::Z80::jumpConditionalFlag(const uint8_t f, const int flag) noexcept {
|
||||
jumpConditional(convertCondition(f, flag));
|
||||
}
|
||||
|
||||
void EightBit::Z80::callConditionalFlag(const uint8_t f, const int flag) {
|
||||
void EightBit::Z80::callConditionalFlag(const uint8_t f, const int flag) noexcept {
|
||||
callConditional(convertCondition(f, flag));
|
||||
}
|
||||
|
||||
void EightBit::Z80::retn() {
|
||||
void EightBit::Z80::retn() noexcept {
|
||||
ret();
|
||||
IFF1() = IFF2();
|
||||
}
|
||||
|
||||
void EightBit::Z80::reti() {
|
||||
void EightBit::Z80::reti() noexcept {
|
||||
retn();
|
||||
}
|
||||
|
||||
void EightBit::Z80::jr(int8_t offset) {
|
||||
void EightBit::Z80::jr(int8_t offset) noexcept {
|
||||
IntelProcessor::jr(offset);
|
||||
tick(5);
|
||||
}
|
||||
|
||||
int EightBit::Z80::jrConditional(const int condition) {
|
||||
int EightBit::Z80::jrConditional(const int condition) noexcept {
|
||||
if (!IntelProcessor::jrConditional(condition))
|
||||
tick(3);
|
||||
return condition;
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::Z80::sbc(uint8_t& f, const register16_t operand, const register16_t value) {
|
||||
EightBit::register16_t EightBit::Z80::sbc(uint8_t& f, const register16_t operand, const register16_t value) noexcept {
|
||||
|
||||
const auto subtraction = operand.word - value.word - (f & CF);
|
||||
const register16_t result = subtraction;
|
||||
@ -371,7 +305,7 @@ EightBit::register16_t EightBit::Z80::sbc(uint8_t& f, const register16_t operand
|
||||
return result;
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::Z80::adc(uint8_t& f, const register16_t operand, const register16_t value) {
|
||||
EightBit::register16_t EightBit::Z80::adc(uint8_t& f, const register16_t operand, const register16_t value) noexcept {
|
||||
|
||||
const auto result = add(f, operand, value, f & CF);
|
||||
f = clearBit(f, ZF, result.word);
|
||||
@ -386,7 +320,7 @@ EightBit::register16_t EightBit::Z80::adc(uint8_t& f, const register16_t operand
|
||||
return result;
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::Z80::add(uint8_t& f, const register16_t operand, const register16_t value, int carry) {
|
||||
EightBit::register16_t EightBit::Z80::add(uint8_t& f, const register16_t operand, const register16_t value, int carry) noexcept {
|
||||
|
||||
const int addition = operand.word + value.word + carry;
|
||||
const register16_t result = addition;
|
||||
@ -402,227 +336,7 @@ EightBit::register16_t EightBit::Z80::add(uint8_t& f, const register16_t operand
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::add(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
|
||||
|
||||
const register16_t addition = operand + value + carry;
|
||||
const auto result = addition.low;
|
||||
|
||||
f = adjustHalfCarryAdd(f, operand, value, result);
|
||||
f = adjustOverflowAdd(f, operand, value, result);
|
||||
|
||||
f = clearBit(f, NF);
|
||||
f = setBit(f, CF, addition.high & CF);
|
||||
f = adjustSZXY<Z80>(f, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::adc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
return add(f, operand, value, f & CF);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::subtract(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
|
||||
|
||||
const register16_t subtraction = operand - value - carry;
|
||||
const auto result = subtraction.low;
|
||||
|
||||
f = adjustHalfCarrySub(f, operand, value, result);
|
||||
f = adjustOverflowSub(f, operand, value, result);
|
||||
|
||||
f = setBit(f, NF);
|
||||
f = setBit(f, CF, subtraction.high & CF);
|
||||
f = adjustSZ<Z80>(f, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::sub(uint8_t& f, const uint8_t operand, const uint8_t value, const int carry) noexcept {
|
||||
const auto subtraction = subtract(f, operand, value, carry);
|
||||
f = adjustXY<Z80>(f, subtraction);
|
||||
return subtraction;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::sbc(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
return sub(f, operand, value, f & CF);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::andr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
f = setBit(f, HC);
|
||||
f = clearBit(f, CF | NF);
|
||||
const uint8_t result = operand & value;
|
||||
f = adjustSZPXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::xorr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
f = clearBit(f, HC | CF | NF);
|
||||
const uint8_t result = operand ^ value;
|
||||
f = adjustSZPXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::orr(uint8_t& f, const uint8_t operand, const uint8_t value) noexcept {
|
||||
f = clearBit(f, HC | CF | NF);
|
||||
const uint8_t result = operand | value;
|
||||
f = adjustSZPXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void EightBit::Z80::compare(uint8_t& f, uint8_t operand, const uint8_t value) noexcept {
|
||||
subtract(f, operand, value);
|
||||
f = adjustXY<Z80>(f, value);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::rlc(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = operand & Bit7;
|
||||
f = setBit(f, CF, carry);
|
||||
const uint8_t result = (operand << 1) | (carry >> 7);
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::rrc(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = operand & Bit0;
|
||||
f = setBit(f, CF, carry);
|
||||
const uint8_t result = (operand >> 1) | (carry << 7);
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::rl(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
const uint8_t result = (operand << 1) | carry;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::rr(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
const uint8_t result = (operand >> 1) | (carry << 7);
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
uint8_t EightBit::Z80::sla(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
const uint8_t result = operand << 1;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::sra(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
const uint8_t result = (operand >> 1) | (operand & Bit7);
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::sll(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit7);
|
||||
const uint8_t result = (operand << 1) | Bit0;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::srl(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF | HC);
|
||||
f = setBit(f, CF, operand & Bit0);
|
||||
const uint8_t result = (operand >> 1) & ~Bit7;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
f = setBit(f, ZF, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void EightBit::Z80::bit(uint8_t& f, const int n, const uint8_t operand) noexcept {
|
||||
f = setBit(f, HC);
|
||||
f = clearBit(f, NF);
|
||||
const auto discarded = operand & Chip::bit(n);
|
||||
f = adjustSZ<Z80>(f, discarded);
|
||||
f = clearBit(f, PF, discarded);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::res(const int n, const uint8_t operand) noexcept {
|
||||
return clearBit(operand, Chip::bit(n));
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::set(const int n, const uint8_t operand) noexcept {
|
||||
return setBit(operand, Chip::bit(n));
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::neg(uint8_t& f, uint8_t operand) noexcept {
|
||||
|
||||
f = setBit(f, PF, operand == Bit7);
|
||||
f = setBit(f, CF, operand);
|
||||
f = setBit(f, NF);
|
||||
|
||||
const uint8_t result = (~operand + 1); // two's complement
|
||||
|
||||
f = adjustHalfCarrySub(f, 0U, operand, result);
|
||||
f = adjustOverflowSub(f, 0U, operand, result);
|
||||
|
||||
f = adjustSZXY<Z80>(f, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::daa(uint8_t& f, uint8_t operand) noexcept {
|
||||
|
||||
const auto lowAdjust = (f & HC) || (lowNibble(operand) > 9);
|
||||
const auto highAdjust = (f & CF) || (operand > 0x99);
|
||||
|
||||
auto updated = operand;
|
||||
if (f & NF) {
|
||||
if (lowAdjust)
|
||||
updated -= 6;
|
||||
if (highAdjust)
|
||||
updated -= 0x60;
|
||||
} else {
|
||||
if (lowAdjust)
|
||||
updated += 6;
|
||||
if (highAdjust)
|
||||
updated += 0x60;
|
||||
}
|
||||
|
||||
f = (f & (CF | NF)) | (operand > 0x99 ? CF : 0) | ((operand ^ updated) & HC);
|
||||
|
||||
f = adjustSZPXY<Z80>(f, updated);
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::cpl(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = setBit(f, HC | NF);
|
||||
const uint8_t result = ~operand;
|
||||
f = adjustXY<Z80>(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void EightBit::Z80::scf(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = setBit(f, CF);
|
||||
f = clearBit(f, HC | NF);
|
||||
f = adjustXY<Z80>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::Z80::ccf(uint8_t& f, const uint8_t operand) noexcept {
|
||||
f = clearBit(f, NF);
|
||||
const auto carry = f & CF;
|
||||
f = setBit(f, HC, carry);
|
||||
f = clearBit(f, CF, carry);
|
||||
f = adjustXY<Z80>(f, operand);
|
||||
}
|
||||
|
||||
void EightBit::Z80::xhtl(register16_t& exchange) {
|
||||
void EightBit::Z80::xhtl(register16_t& exchange) noexcept {
|
||||
MEMPTR().low = IntelProcessor::memoryRead(SP());
|
||||
++BUS().ADDRESS();
|
||||
MEMPTR().high = memoryRead();
|
||||
@ -635,7 +349,7 @@ void EightBit::Z80::xhtl(register16_t& exchange) {
|
||||
tick(2);
|
||||
}
|
||||
|
||||
void EightBit::Z80::blockCompare(uint8_t& f, const uint8_t value, const register16_t source, register16_t& counter) {
|
||||
void EightBit::Z80::blockCompare(uint8_t& f, const uint8_t value, const register16_t source, register16_t& counter) noexcept {
|
||||
|
||||
const auto contents = IntelProcessor::memoryRead(source);
|
||||
uint8_t result = value - contents;
|
||||
@ -654,27 +368,27 @@ void EightBit::Z80::blockCompare(uint8_t& f, const uint8_t value, const register
|
||||
tick(5);
|
||||
}
|
||||
|
||||
void EightBit::Z80::cpi(uint8_t& f, uint8_t value) {
|
||||
void EightBit::Z80::cpi(uint8_t& f, uint8_t value) noexcept {
|
||||
blockCompare(f, value, HL()++, BC());
|
||||
++MEMPTR();
|
||||
}
|
||||
|
||||
void EightBit::Z80::cpd(uint8_t& f, uint8_t value) {
|
||||
void EightBit::Z80::cpd(uint8_t& f, uint8_t value) noexcept {
|
||||
blockCompare(f, value, HL()--, BC());
|
||||
--MEMPTR();
|
||||
}
|
||||
|
||||
bool EightBit::Z80::cpir(uint8_t& f, uint8_t value) {
|
||||
bool EightBit::Z80::cpir(uint8_t& f, uint8_t value) noexcept {
|
||||
cpi(f, value);
|
||||
return (f & PF) && !(f & ZF); // See CPI
|
||||
}
|
||||
|
||||
bool EightBit::Z80::cpdr(uint8_t& f, uint8_t value) {
|
||||
bool EightBit::Z80::cpdr(uint8_t& f, uint8_t value) noexcept {
|
||||
cpd(f, value);
|
||||
return (f & PF) && !(f & ZF); // See CPD
|
||||
}
|
||||
|
||||
void EightBit::Z80::blockLoad(uint8_t& f, const uint8_t a, const register16_t source, const register16_t destination, register16_t& counter) {
|
||||
void EightBit::Z80::blockLoad(uint8_t& f, const uint8_t a, const register16_t source, const register16_t destination, register16_t& counter) noexcept {
|
||||
const auto value = IntelProcessor::memoryRead(source);
|
||||
IntelProcessor::memoryWrite(destination);
|
||||
const auto xy = a + value;
|
||||
@ -685,25 +399,25 @@ void EightBit::Z80::blockLoad(uint8_t& f, const uint8_t a, const register16_t so
|
||||
tick(2);
|
||||
}
|
||||
|
||||
void EightBit::Z80::ldd(uint8_t& f, const uint8_t a) {
|
||||
void EightBit::Z80::ldd(uint8_t& f, const uint8_t a) noexcept {
|
||||
blockLoad(f, a, HL()--, DE()--, BC());
|
||||
}
|
||||
|
||||
void EightBit::Z80::ldi(uint8_t& f, const uint8_t a) {
|
||||
void EightBit::Z80::ldi(uint8_t& f, const uint8_t a) noexcept {
|
||||
blockLoad(f, a, HL()++, DE()++, BC());
|
||||
}
|
||||
|
||||
bool EightBit::Z80::ldir(uint8_t& f, const uint8_t a) {
|
||||
bool EightBit::Z80::ldir(uint8_t& f, const uint8_t a) noexcept {
|
||||
ldi(f, a);
|
||||
return !!(f & PF); // See LDI
|
||||
}
|
||||
|
||||
bool EightBit::Z80::lddr(uint8_t& f, const uint8_t a) {
|
||||
bool EightBit::Z80::lddr(uint8_t& f, const uint8_t a) noexcept {
|
||||
ldd(f, a);
|
||||
return !!(f & PF); // See LDD
|
||||
}
|
||||
|
||||
void EightBit::Z80::blockIn(register16_t& source, const register16_t destination) {
|
||||
void EightBit::Z80::blockIn(register16_t& source, const register16_t destination) noexcept {
|
||||
MEMPTR() = BUS().ADDRESS() = source;
|
||||
tick();
|
||||
portRead();
|
||||
@ -713,27 +427,27 @@ void EightBit::Z80::blockIn(register16_t& source, const register16_t destination
|
||||
F() = setBit(F(), NF);
|
||||
}
|
||||
|
||||
void EightBit::Z80::ini() {
|
||||
void EightBit::Z80::ini() noexcept {
|
||||
blockIn(BC(), HL()++);
|
||||
++MEMPTR();
|
||||
}
|
||||
|
||||
void EightBit::Z80::ind() {
|
||||
void EightBit::Z80::ind() noexcept {
|
||||
blockIn(BC(), HL()--);
|
||||
--MEMPTR();
|
||||
}
|
||||
|
||||
bool EightBit::Z80::inir() {
|
||||
bool EightBit::Z80::inir() noexcept {
|
||||
ini();
|
||||
return !(F() & ZF); // See INI
|
||||
}
|
||||
|
||||
bool EightBit::Z80::indr() {
|
||||
bool EightBit::Z80::indr() noexcept {
|
||||
ind();
|
||||
return !(F() & ZF); // See IND
|
||||
}
|
||||
|
||||
void EightBit::Z80::blockOut(const register16_t source, register16_t& destination) {
|
||||
void EightBit::Z80::blockOut(const register16_t source, register16_t& destination) noexcept {
|
||||
tick();
|
||||
const auto value = IntelProcessor::memoryRead(source);
|
||||
destination.high = decrement(F(), destination.high);
|
||||
@ -745,27 +459,27 @@ void EightBit::Z80::blockOut(const register16_t source, register16_t& destinatio
|
||||
F() = adjustParity<Z80>(F(), ((value + L()) & Mask3) ^ B());
|
||||
}
|
||||
|
||||
void EightBit::Z80::outi() {
|
||||
void EightBit::Z80::outi() noexcept {
|
||||
blockOut(HL()++, BC());
|
||||
++MEMPTR();
|
||||
}
|
||||
|
||||
void EightBit::Z80::outd() {
|
||||
void EightBit::Z80::outd() noexcept {
|
||||
blockOut(HL()--, BC());
|
||||
--MEMPTR();
|
||||
}
|
||||
|
||||
bool EightBit::Z80::otir() {
|
||||
bool EightBit::Z80::otir() noexcept {
|
||||
outi();
|
||||
return !(F() & ZF); // See OUTI
|
||||
}
|
||||
|
||||
bool EightBit::Z80::otdr() {
|
||||
bool EightBit::Z80::otdr() noexcept {
|
||||
outd();
|
||||
return !(F() & ZF); // See OUTD
|
||||
}
|
||||
|
||||
void EightBit::Z80::rrd(uint8_t& f, register16_t address, uint8_t& update) {
|
||||
void EightBit::Z80::rrd(uint8_t& f, register16_t address, uint8_t& update) noexcept {
|
||||
(MEMPTR() = BUS().ADDRESS() = address)++;
|
||||
const auto memory = memoryRead();
|
||||
tick(4);
|
||||
@ -775,7 +489,7 @@ void EightBit::Z80::rrd(uint8_t& f, register16_t address, uint8_t& update) {
|
||||
f = clearBit(f, NF | HC);
|
||||
}
|
||||
|
||||
void EightBit::Z80::rld(uint8_t& f, register16_t address, uint8_t& update) {
|
||||
void EightBit::Z80::rld(uint8_t& f, register16_t address, uint8_t& update) noexcept {
|
||||
(MEMPTR() = BUS().ADDRESS() = address)++;
|
||||
const auto memory = memoryRead();
|
||||
tick(4);
|
||||
@ -785,23 +499,24 @@ void EightBit::Z80::rld(uint8_t& f, register16_t address, uint8_t& update) {
|
||||
f = clearBit(f, NF | HC);
|
||||
}
|
||||
|
||||
void EightBit::Z80::portWrite(const uint8_t port) {
|
||||
void EightBit::Z80::portWrite(const uint8_t port) noexcept {
|
||||
MEMPTR() = BUS().ADDRESS() = { port, A() };
|
||||
BUS().DATA() = A();
|
||||
portWrite();
|
||||
++MEMPTR().low;
|
||||
}
|
||||
|
||||
void EightBit::Z80::portWrite() {
|
||||
void EightBit::Z80::portWrite() noexcept {
|
||||
|
||||
class _Writer final {
|
||||
Z80& m_parent;
|
||||
public:
|
||||
_Writer(Z80& parent) : m_parent(parent) {
|
||||
_Writer(Z80& parent) noexcept
|
||||
: m_parent(parent) {
|
||||
m_parent.WritingIO.fire();
|
||||
}
|
||||
|
||||
~_Writer() {
|
||||
~_Writer() noexcept {
|
||||
m_parent.WrittenIO.fire();
|
||||
m_parent.tick(3);
|
||||
}
|
||||
@ -812,22 +527,23 @@ void EightBit::Z80::portWrite() {
|
||||
busWrite();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::portRead(const uint8_t port) {
|
||||
uint8_t EightBit::Z80::portRead(const uint8_t port) noexcept {
|
||||
MEMPTR() = BUS().ADDRESS() = { port, A() };
|
||||
++MEMPTR().low;
|
||||
return portRead();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::portRead() {
|
||||
uint8_t EightBit::Z80::portRead() noexcept {
|
||||
|
||||
class _Reader final {
|
||||
Z80& m_parent;
|
||||
public:
|
||||
_Reader(Z80& parent) : m_parent(parent) {
|
||||
_Reader(Z80& parent) noexcept
|
||||
: m_parent(parent) {
|
||||
m_parent.ReadingIO.fire();
|
||||
}
|
||||
|
||||
~_Reader() {
|
||||
~_Reader() noexcept {
|
||||
m_parent.ReadIO.fire();
|
||||
m_parent.tick(3);
|
||||
}
|
||||
@ -840,23 +556,13 @@ uint8_t EightBit::Z80::portRead() {
|
||||
|
||||
//
|
||||
|
||||
void EightBit::Z80::resetPrefixes() noexcept {
|
||||
m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
uint16_t EightBit::Z80::displacedAddress() noexcept {
|
||||
return MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement;
|
||||
}
|
||||
|
||||
void EightBit::Z80::fetchDisplacement() {
|
||||
void EightBit::Z80::fetchDisplacement() noexcept {
|
||||
m_displacement = fetchByte();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
uint8_t EightBit::Z80::readBusDataM1() {
|
||||
uint8_t EightBit::Z80::readBusDataM1() noexcept {
|
||||
_ActivateM1 m1(*this);
|
||||
return BUS().DATA();
|
||||
}
|
||||
@ -888,7 +594,7 @@ uint8_t EightBit::Z80::readBusDataM1() {
|
||||
// received from the memory is ignored and an NOP instruction is forced internally to the
|
||||
// CPU.The HALT acknowledge signal is active during this time indicating that the processor
|
||||
// is in the HALT state
|
||||
uint8_t EightBit::Z80::fetchOpCode() {
|
||||
uint8_t EightBit::Z80::fetchOpCode() noexcept {
|
||||
uint8_t returned;
|
||||
{
|
||||
_ActivateM1 m1(*this);
|
||||
@ -907,18 +613,18 @@ uint8_t EightBit::Z80::fetchOpCode() {
|
||||
return returned;
|
||||
}
|
||||
|
||||
void EightBit::Z80::loadAccumulatorIndirect(addresser_t addresser) {
|
||||
void EightBit::Z80::loadAccumulatorIndirect(addresser_t addresser) noexcept {
|
||||
(MEMPTR() = BUS().ADDRESS() = addresser())++;
|
||||
A() = memoryRead();
|
||||
}
|
||||
|
||||
void EightBit::Z80::storeAccumulatorIndirect(addresser_t addresser) {
|
||||
void EightBit::Z80::storeAccumulatorIndirect(addresser_t addresser) noexcept {
|
||||
(MEMPTR() = BUS().ADDRESS() = addresser())++;
|
||||
MEMPTR().high = BUS().DATA() = A();
|
||||
memoryWrite();
|
||||
}
|
||||
|
||||
void EightBit::Z80::readInternalRegister(reader_t reader) {
|
||||
void EightBit::Z80::readInternalRegister(reader_t reader) noexcept {
|
||||
F() = adjustSZXY<Z80>(F(), A() = reader());
|
||||
F() = clearBit(F(), NF | HC);
|
||||
F() = setBit(F(), PF, IFF2());
|
||||
@ -963,7 +669,7 @@ EightBit::register16_t& EightBit::Z80::RP2(const int rp) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t EightBit::Z80::R(const int r) {
|
||||
uint8_t EightBit::Z80::R(const int r) noexcept {
|
||||
switch (r) {
|
||||
case 0:
|
||||
return B();
|
||||
@ -986,7 +692,7 @@ uint8_t EightBit::Z80::R(const int r) {
|
||||
}
|
||||
}
|
||||
|
||||
void EightBit::Z80::R(const int r, const uint8_t value) {
|
||||
void EightBit::Z80::R(const int r, const uint8_t value) noexcept {
|
||||
switch (r) {
|
||||
case 0:
|
||||
B() = value;
|
||||
@ -1017,7 +723,7 @@ void EightBit::Z80::R(const int r, const uint8_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
void EightBit::Z80::R2(const int r, const uint8_t value) {
|
||||
void EightBit::Z80::R2(const int r, const uint8_t value) noexcept {
|
||||
switch (r) {
|
||||
case 0:
|
||||
B() = value;
|
||||
@ -1048,7 +754,7 @@ void EightBit::Z80::R2(const int r, const uint8_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
int EightBit::Z80::step() {
|
||||
int EightBit::Z80::step() noexcept {
|
||||
resetCycles();
|
||||
ExecutingInstruction.fire(*this);
|
||||
if (LIKELY(powered())) {
|
||||
@ -1075,7 +781,7 @@ int EightBit::Z80::step() {
|
||||
return cycles();
|
||||
}
|
||||
|
||||
int EightBit::Z80::execute() {
|
||||
int EightBit::Z80::execute() noexcept {
|
||||
|
||||
const auto& decoded = getDecodedOpcode(opcode());
|
||||
|
||||
@ -1097,7 +803,7 @@ int EightBit::Z80::execute() {
|
||||
return cycles();
|
||||
}
|
||||
|
||||
void EightBit::Z80::executeCB(const int x, const int y, const int z) {
|
||||
void EightBit::Z80::executeCB(const int x, const int y, const int z) noexcept {
|
||||
|
||||
const bool memoryZ = z == 6;
|
||||
const bool indirect = (!displaced() && memoryZ) || displaced();
|
||||
@ -1170,7 +876,7 @@ void EightBit::Z80::executeCB(const int x, const int y, const int z) {
|
||||
}
|
||||
}
|
||||
|
||||
void EightBit::Z80::executeED(const int x, const int y, const int z, const int p, const int q) {
|
||||
void EightBit::Z80::executeED(const int x, const int y, const int z, const int p, const int q) noexcept {
|
||||
|
||||
switch (x) {
|
||||
case 0:
|
||||
@ -1385,7 +1091,7 @@ void EightBit::Z80::executeED(const int x, const int y, const int z, const int p
|
||||
}
|
||||
}
|
||||
|
||||
void EightBit::Z80::executeOther(const int x, const int y, const int z, const int p, const int q) {
|
||||
void EightBit::Z80::executeOther(const int x, const int y, const int z, const int p, const int q) noexcept {
|
||||
const bool memoryY = y == 6;
|
||||
const bool memoryZ = z == 6;
|
||||
switch (x) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
Board::Board(const Configuration& configuration)
|
||||
: m_configuration(configuration) {}
|
||||
|
||||
void Board::raisePOWER() {
|
||||
void Board::raisePOWER() noexcept {
|
||||
EightBit::Bus::raisePOWER();
|
||||
CPU().raisePOWER();
|
||||
CPU().raiseRESET();
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
|
||||
EightBit::Z80& CPU() noexcept { return m_cpu; }
|
||||
|
||||
void raisePOWER() final;
|
||||
void raisePOWER() noexcept final;
|
||||
void lowerPOWER() noexcept final;
|
||||
|
||||
void initialise() final;
|
||||
|
@ -16,15 +16,15 @@ namespace EightBit {
|
||||
protected:
|
||||
BigEndianProcessor(Bus& memory);
|
||||
|
||||
[[nodiscard]] register16_t getWord() override;
|
||||
void setWord(register16_t value) override;
|
||||
[[nodiscard]] register16_t getWord() noexcept override;
|
||||
void setWord(register16_t value) noexcept override;
|
||||
|
||||
[[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) override;
|
||||
void setWordPaged(uint8_t page, uint8_t offset, register16_t value) override;
|
||||
[[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept override;
|
||||
void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept override;
|
||||
|
||||
[[nodiscard]] register16_t fetchWord() final;
|
||||
[[nodiscard]] register16_t fetchWord() noexcept final;
|
||||
|
||||
void pushWord(register16_t value) final;
|
||||
[[nodiscard]] register16_t popWord() final;
|
||||
void pushWord(register16_t value) noexcept final;
|
||||
[[nodiscard]] register16_t popWord() noexcept final;
|
||||
};
|
||||
}
|
||||
|
12
inc/Bus.h
12
inc/Bus.h
@ -33,21 +33,21 @@ namespace EightBit {
|
||||
virtual 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); }
|
||||
|
||||
[[nodiscard]] uint8_t read();
|
||||
[[nodiscard]] uint8_t read() noexcept;
|
||||
template<class T> [[nodiscard]] auto read(const T address) {
|
||||
ADDRESS() = address;
|
||||
return read();
|
||||
}
|
||||
|
||||
void write();
|
||||
void write(uint8_t value);
|
||||
template<class T> void write(const T offset, const uint8_t value) {
|
||||
void write() noexcept;
|
||||
void write(uint8_t value) noexcept;
|
||||
template<class T> void write(const T offset, const uint8_t value) noexcept {
|
||||
ADDRESS() = offset;
|
||||
write(value);
|
||||
}
|
||||
|
||||
virtual void raisePOWER();
|
||||
virtual void lowerPOWER();
|
||||
virtual void raisePOWER() noexcept;
|
||||
virtual void lowerPOWER() noexcept;
|
||||
|
||||
virtual void initialise() = 0;
|
||||
|
||||
|
@ -16,13 +16,17 @@ namespace EightBit {
|
||||
|
||||
[[nodiscard]] constexpr auto cycles() const noexcept { return m_cycles; }
|
||||
|
||||
void tick(int extra);
|
||||
void tick();
|
||||
void tick(int extra = 1) noexcept {
|
||||
for (int i = 0; i < extra; ++i) {
|
||||
++m_cycles;
|
||||
Ticked.fire();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
ClockedChip() noexcept = default;
|
||||
|
||||
void resetCycles() noexcept;
|
||||
constexpr void resetCycles() noexcept { m_cycles = 0; }
|
||||
|
||||
private:
|
||||
int m_cycles = 0;
|
||||
|
@ -10,17 +10,17 @@
|
||||
Signal<EventArgs> Lowered ## name;
|
||||
|
||||
#define DECLARE_PIN_LEVEL_RAISE(name) \
|
||||
virtual void raise ## name();
|
||||
virtual void raise ## name() noexcept;
|
||||
|
||||
#define DECLARE_PIN_LEVEL_LOWER(name) \
|
||||
virtual void lower ## name();
|
||||
virtual void lower ## name() noexcept;
|
||||
|
||||
#define DECLARE_PIN_LEVEL_CHANGERS(name) \
|
||||
DECLARE_PIN_LEVEL_RAISE(name) \
|
||||
DECLARE_PIN_LEVEL_LOWER(name)
|
||||
|
||||
#define DEFINE_PIN_LEVEL_RAISE(name, within) \
|
||||
void EightBit:: within ::raise ## name() { \
|
||||
void EightBit:: within ::raise ## name() noexcept { \
|
||||
if (lowered( name ())) { \
|
||||
Raising ## name.fire(); \
|
||||
raise( name ()); \
|
||||
@ -29,7 +29,7 @@
|
||||
}
|
||||
|
||||
#define DEFINE_PIN_LEVEL_LOWER(name, within) \
|
||||
void EightBit:: within ::lower ## name() { \
|
||||
void EightBit:: within ::lower ## name() noexcept { \
|
||||
if (raised( name ())) { \
|
||||
Lowering ## name.fire(); \
|
||||
lower( name ()); \
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "EightBitCompilerDefinitions.h"
|
||||
|
||||
#define NON_CONST_ACCESSOR(accessor, type) \
|
||||
[[nodiscard]] auto& accessor() noexcept { \
|
||||
[[nodiscard]] constexpr auto& accessor() noexcept { \
|
||||
const auto& consted = *this; \
|
||||
const auto& reference = consted.accessor(); \
|
||||
return const_cast<type&>(reference); \
|
||||
@ -140,25 +140,25 @@ namespace EightBit {
|
||||
return calculateHalfCarry(m_halfCarryTableSub, before, value, calculation);
|
||||
}
|
||||
|
||||
void handleRESET() override;
|
||||
void handleRESET() noexcept override;
|
||||
|
||||
void push(uint8_t value) final;
|
||||
[[nodiscard]] uint8_t pop() final;
|
||||
void push(uint8_t value) noexcept final;
|
||||
[[nodiscard]] uint8_t pop() noexcept final;
|
||||
|
||||
//
|
||||
|
||||
[[nodiscard]] register16_t getWord() final;
|
||||
void setWord(register16_t value) final;
|
||||
[[nodiscard]] register16_t getWord() noexcept final;
|
||||
void setWord(register16_t value) noexcept final;
|
||||
|
||||
//
|
||||
|
||||
virtual void restart(uint8_t address);
|
||||
virtual int callConditional(int condition);
|
||||
virtual int jumpConditional(int condition);
|
||||
virtual int returnConditional(int condition);
|
||||
virtual void jr(int8_t offset);
|
||||
virtual int jrConditional(int condition);
|
||||
void ret() override;
|
||||
virtual void restart(uint8_t address) noexcept;
|
||||
virtual int callConditional(int condition) noexcept;
|
||||
virtual int jumpConditional(int condition) noexcept;
|
||||
virtual int returnConditional(int condition) noexcept;
|
||||
virtual void jr(int8_t offset) noexcept;
|
||||
virtual int jrConditional(int condition) noexcept;
|
||||
void ret() noexcept override;
|
||||
|
||||
void resetWorkingRegisters();
|
||||
|
||||
|
@ -17,15 +17,15 @@ namespace EightBit {
|
||||
protected:
|
||||
LittleEndianProcessor(Bus& memory);
|
||||
|
||||
[[nodiscard]] register16_t getWord() override;
|
||||
void setWord(register16_t value) override;
|
||||
[[nodiscard]] register16_t getWord() noexcept override;
|
||||
void setWord(register16_t value) noexcept override;
|
||||
|
||||
[[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) override;
|
||||
void setWordPaged(uint8_t page, uint8_t offset, register16_t value) override;
|
||||
[[nodiscard]] register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept override;
|
||||
void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept override;
|
||||
|
||||
[[nodiscard]] register16_t fetchWord() final;
|
||||
[[nodiscard]] register16_t fetchWord() noexcept final;
|
||||
|
||||
void pushWord(register16_t value) override;
|
||||
[[nodiscard]] register16_t popWord() override;
|
||||
void pushWord(register16_t value) noexcept override;
|
||||
[[nodiscard]] register16_t popWord() noexcept override;
|
||||
};
|
||||
}
|
||||
|
@ -29,10 +29,10 @@ namespace EightBit {
|
||||
[[nodiscard]] constexpr auto& PC() noexcept { return m_pc; }
|
||||
[[nodiscard]] constexpr const auto& PC() const noexcept { return m_pc; }
|
||||
|
||||
int run(int limit);
|
||||
virtual int step() = 0;
|
||||
virtual int execute() = 0;
|
||||
int execute(uint8_t value);
|
||||
int run(int limit) noexcept;
|
||||
virtual int step() noexcept = 0;
|
||||
virtual int execute() noexcept = 0;
|
||||
int 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;
|
||||
@ -46,44 +46,44 @@ namespace EightBit {
|
||||
[[nodiscard]] constexpr auto& opcode() noexcept { return m_opcode; }
|
||||
[[nodiscard]] constexpr auto& BUS() noexcept { return m_bus; }
|
||||
|
||||
virtual void handleRESET();
|
||||
virtual void handleINT();
|
||||
virtual void handleRESET() noexcept;
|
||||
virtual void handleINT() noexcept;
|
||||
|
||||
void memoryWrite(register16_t address, uint8_t data);
|
||||
void memoryWrite(register16_t address);
|
||||
void memoryWrite(uint8_t data);
|
||||
virtual void memoryWrite();
|
||||
virtual void busWrite();
|
||||
void memoryWrite(register16_t address, uint8_t data) noexcept;
|
||||
void memoryWrite(register16_t address) noexcept;
|
||||
void memoryWrite(uint8_t data) noexcept;
|
||||
virtual void memoryWrite() noexcept;
|
||||
virtual void busWrite() noexcept;
|
||||
|
||||
uint8_t memoryRead(register16_t address);
|
||||
virtual uint8_t memoryRead();
|
||||
virtual uint8_t busRead();
|
||||
uint8_t memoryRead(register16_t address) noexcept;
|
||||
virtual uint8_t memoryRead() noexcept;
|
||||
virtual uint8_t busRead() noexcept;
|
||||
|
||||
uint8_t getBytePaged(uint8_t page, uint8_t offset);
|
||||
void setBytePaged(uint8_t page, uint8_t offset, uint8_t value);
|
||||
uint8_t getBytePaged(uint8_t page, uint8_t offset) noexcept;
|
||||
void setBytePaged(uint8_t page, uint8_t offset, uint8_t value) noexcept;
|
||||
|
||||
uint8_t fetchByte();
|
||||
uint8_t fetchByte() noexcept;
|
||||
|
||||
[[nodiscard]] virtual register16_t getWord() = 0;
|
||||
virtual void setWord(register16_t value) = 0;
|
||||
[[nodiscard]] virtual register16_t getWord() noexcept = 0;
|
||||
virtual void setWord(register16_t value) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual register16_t getWordPaged(uint8_t page, uint8_t offset) = 0;
|
||||
virtual void setWordPaged(uint8_t page, uint8_t offset, register16_t value) = 0;
|
||||
[[nodiscard]] virtual register16_t getWordPaged(uint8_t page, uint8_t offset) noexcept = 0;
|
||||
virtual void setWordPaged(uint8_t page, uint8_t offset, register16_t value) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual register16_t fetchWord() = 0;
|
||||
[[nodiscard]] virtual register16_t fetchWord() noexcept = 0;
|
||||
|
||||
virtual void push(uint8_t value) = 0;
|
||||
[[nodiscard]] virtual uint8_t pop() = 0;
|
||||
virtual void push(uint8_t value) noexcept = 0;
|
||||
[[nodiscard]] virtual uint8_t pop() noexcept = 0;
|
||||
|
||||
virtual void pushWord(register16_t value) = 0;
|
||||
[[nodiscard]] virtual register16_t popWord() = 0;
|
||||
virtual void pushWord(register16_t value) noexcept = 0;
|
||||
[[nodiscard]] virtual register16_t popWord() noexcept = 0;
|
||||
|
||||
[[nodiscard]] register16_t getWord(register16_t address);
|
||||
void setWord(register16_t address, register16_t value);
|
||||
[[nodiscard]] register16_t getWord(register16_t address) noexcept;
|
||||
void setWord(register16_t address, register16_t value) noexcept;
|
||||
|
||||
void jump(const register16_t destination) noexcept;
|
||||
virtual void call(register16_t destination);
|
||||
virtual void ret();
|
||||
virtual void call(register16_t destination) noexcept;
|
||||
virtual void ret() noexcept;
|
||||
|
||||
private:
|
||||
Bus& m_bus;
|
||||
|
@ -17,7 +17,7 @@ namespace EightBit {
|
||||
m_delegates.push_back(functor);
|
||||
}
|
||||
|
||||
void fire(T& e = EventArgs::empty()) const {
|
||||
void fire(T& e = EventArgs::empty()) const noexcept {
|
||||
for (auto& delegate : m_delegates)
|
||||
delegate(e);
|
||||
}
|
||||
|
@ -17,9 +17,8 @@
|
||||
namespace EightBit {
|
||||
template<class ConfigurationT, class BoardT> class TestHarness final {
|
||||
public:
|
||||
TestHarness(const ConfigurationT& configuration)
|
||||
: m_board(configuration) {
|
||||
}
|
||||
TestHarness(const ConfigurationT& configuration) noexcept
|
||||
: m_board(configuration) {}
|
||||
|
||||
~TestHarness() {
|
||||
std::cout << std::dec << std::endl;
|
||||
@ -55,7 +54,7 @@ namespace EightBit {
|
||||
return (long long)floating;
|
||||
}
|
||||
|
||||
void run() {
|
||||
void run() noexcept {
|
||||
m_startTime = now();
|
||||
m_totalCycles = m_instructions = 0L;
|
||||
m_startHostCycles = currentHostCycles();
|
||||
|
@ -4,44 +4,44 @@
|
||||
EightBit::BigEndianProcessor::BigEndianProcessor(Bus& memory)
|
||||
: Processor(memory) {}
|
||||
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::getWord() {
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::getWord() noexcept {
|
||||
const auto high = memoryRead();
|
||||
++BUS().ADDRESS();
|
||||
const auto low = memoryRead();
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
void EightBit::BigEndianProcessor::setWord(const register16_t value) {
|
||||
void EightBit::BigEndianProcessor::setWord(const register16_t value) noexcept {
|
||||
memoryWrite(value.high);
|
||||
++BUS().ADDRESS();
|
||||
memoryWrite(value.low);
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) {
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) noexcept {
|
||||
const auto high = getBytePaged(page, offset);
|
||||
++BUS().ADDRESS().low;
|
||||
const auto low = memoryRead();
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
void EightBit::BigEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) {
|
||||
void EightBit::BigEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) noexcept {
|
||||
setBytePaged(page, offset, value.high);
|
||||
++BUS().ADDRESS().low;
|
||||
memoryWrite(value.low);
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() {
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::fetchWord() noexcept {
|
||||
const auto high = fetchByte();
|
||||
const auto low = fetchByte();
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
void EightBit::BigEndianProcessor::pushWord(const register16_t value) {
|
||||
void EightBit::BigEndianProcessor::pushWord(const register16_t value) noexcept {
|
||||
push(value.low);
|
||||
push(value.high);
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::popWord() {
|
||||
EightBit::register16_t EightBit::BigEndianProcessor::popWord() noexcept {
|
||||
const auto high = pop();
|
||||
const auto low = pop();
|
||||
return { low, high };
|
||||
|
10
src/Bus.cpp
10
src/Bus.cpp
@ -4,24 +4,24 @@
|
||||
#include "../inc/IntelHexFile.h"
|
||||
#include "../inc/EightBitCompilerDefinitions.h"
|
||||
|
||||
void EightBit::Bus::raisePOWER() {}
|
||||
void EightBit::Bus::raisePOWER() noexcept {}
|
||||
|
||||
void EightBit::Bus::lowerPOWER() {}
|
||||
void EightBit::Bus::lowerPOWER() noexcept {}
|
||||
|
||||
uint8_t EightBit::Bus::read() {
|
||||
uint8_t EightBit::Bus::read() noexcept {
|
||||
ReadingByte.fire();
|
||||
const auto returned = DATA() = reference();
|
||||
ReadByte.fire();
|
||||
return returned;
|
||||
}
|
||||
|
||||
void EightBit::Bus::write() {
|
||||
void EightBit::Bus::write() noexcept {
|
||||
WritingByte.fire();
|
||||
reference() = DATA();
|
||||
WrittenByte.fire();
|
||||
}
|
||||
|
||||
void EightBit::Bus::write(const uint8_t value) {
|
||||
void EightBit::Bus::write(const uint8_t value) noexcept {
|
||||
DATA() = value;
|
||||
write();
|
||||
}
|
||||
|
@ -6,20 +6,6 @@ EightBit::ClockedChip::ClockedChip(const ClockedChip& rhs)
|
||||
m_cycles = rhs.m_cycles;
|
||||
}
|
||||
|
||||
void EightBit::ClockedChip::tick(const int extra) {
|
||||
for (int i = 0; i < extra; ++i)
|
||||
tick();
|
||||
}
|
||||
|
||||
void EightBit::ClockedChip::tick() {
|
||||
++m_cycles;
|
||||
Ticked.fire();
|
||||
}
|
||||
|
||||
void EightBit::ClockedChip::resetCycles() noexcept {
|
||||
m_cycles = 0;
|
||||
}
|
||||
|
||||
bool EightBit::ClockedChip::operator==(const EightBit::ClockedChip& rhs) const {
|
||||
return
|
||||
Device::operator==(rhs)
|
||||
|
@ -34,59 +34,59 @@ void EightBit::IntelProcessor::resetWorkingRegisters() {
|
||||
|
||||
DEFINE_PIN_LEVEL_CHANGERS(HALT, IntelProcessor);
|
||||
|
||||
void EightBit::IntelProcessor::handleRESET() {
|
||||
void EightBit::IntelProcessor::handleRESET() noexcept {
|
||||
Processor::handleRESET();
|
||||
PC() = 0;
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::push(const uint8_t value) {
|
||||
void EightBit::IntelProcessor::push(const uint8_t value) noexcept {
|
||||
memoryWrite(--SP(), value);
|
||||
}
|
||||
|
||||
uint8_t EightBit::IntelProcessor::pop() {
|
||||
uint8_t EightBit::IntelProcessor::pop() noexcept {
|
||||
return memoryRead(SP()++);
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::IntelProcessor::getWord() {
|
||||
EightBit::register16_t EightBit::IntelProcessor::getWord() noexcept {
|
||||
const auto returned = LittleEndianProcessor::getWord();
|
||||
MEMPTR() = BUS().ADDRESS();
|
||||
return returned;
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::setWord(const register16_t value) {
|
||||
void EightBit::IntelProcessor::setWord(const register16_t value) noexcept {
|
||||
LittleEndianProcessor::setWord(value);
|
||||
MEMPTR() = BUS().ADDRESS();
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::restart(const uint8_t address) {
|
||||
void EightBit::IntelProcessor::restart(const uint8_t address) noexcept {
|
||||
call(MEMPTR() = { address, 0 });
|
||||
}
|
||||
|
||||
int EightBit::IntelProcessor::callConditional(const int condition) {
|
||||
int EightBit::IntelProcessor::callConditional(const int condition) noexcept {
|
||||
MEMPTR() = fetchWord();
|
||||
if (condition)
|
||||
call(MEMPTR());
|
||||
return condition;
|
||||
}
|
||||
|
||||
int EightBit::IntelProcessor::jumpConditional(const int condition) {
|
||||
int EightBit::IntelProcessor::jumpConditional(const int condition) noexcept {
|
||||
MEMPTR() = fetchWord();
|
||||
if (condition)
|
||||
jump(MEMPTR());
|
||||
return condition;
|
||||
}
|
||||
|
||||
int EightBit::IntelProcessor::returnConditional(const int condition) {
|
||||
int EightBit::IntelProcessor::returnConditional(const int condition) noexcept {
|
||||
if (condition)
|
||||
ret();
|
||||
return condition;
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::jr(const int8_t offset) {
|
||||
void EightBit::IntelProcessor::jr(const int8_t offset) noexcept {
|
||||
jump(MEMPTR() = PC() + offset);
|
||||
}
|
||||
|
||||
int EightBit::IntelProcessor::jrConditional(const int condition) {
|
||||
int EightBit::IntelProcessor::jrConditional(const int condition) noexcept {
|
||||
const auto offsetAddress = PC()++;
|
||||
if (condition) {
|
||||
const auto offset = memoryRead(offsetAddress);
|
||||
@ -95,7 +95,7 @@ int EightBit::IntelProcessor::jrConditional(const int condition) {
|
||||
return condition;
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::ret() {
|
||||
void EightBit::IntelProcessor::ret() noexcept {
|
||||
Processor::ret();
|
||||
MEMPTR() = PC();
|
||||
}
|
||||
|
@ -7,44 +7,44 @@ EightBit::LittleEndianProcessor::LittleEndianProcessor(Bus& memory)
|
||||
EightBit::LittleEndianProcessor::LittleEndianProcessor(const LittleEndianProcessor& rhs)
|
||||
: Processor(rhs) {}
|
||||
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::getWord() {
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::getWord() noexcept {
|
||||
const auto low = memoryRead();
|
||||
++BUS().ADDRESS();
|
||||
const auto high = memoryRead();
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
void EightBit::LittleEndianProcessor::setWord(const register16_t value) {
|
||||
void EightBit::LittleEndianProcessor::setWord(const register16_t value) noexcept {
|
||||
memoryWrite(value.low);
|
||||
++BUS().ADDRESS();
|
||||
memoryWrite(value.high);
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) {
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::getWordPaged(const uint8_t page, const uint8_t offset) noexcept {
|
||||
const auto low = getBytePaged(page, offset);
|
||||
++BUS().ADDRESS().low;
|
||||
const auto high = memoryRead();
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
void EightBit::LittleEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) {
|
||||
void EightBit::LittleEndianProcessor::setWordPaged(const uint8_t page, const uint8_t offset, const register16_t value) noexcept {
|
||||
setBytePaged(page, offset, value.low);
|
||||
++BUS().ADDRESS().low;
|
||||
memoryWrite(value.high);
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() {
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::fetchWord() noexcept {
|
||||
const auto low = fetchByte();
|
||||
const auto high = fetchByte();
|
||||
return { low, high };
|
||||
}
|
||||
|
||||
void EightBit::LittleEndianProcessor::pushWord(const register16_t value) {
|
||||
void EightBit::LittleEndianProcessor::pushWord(const register16_t value) noexcept {
|
||||
push(value.high);
|
||||
push(value.low);
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::popWord() {
|
||||
EightBit::register16_t EightBit::LittleEndianProcessor::popWord() noexcept {
|
||||
const auto low = pop();
|
||||
const auto high = pop();
|
||||
return { low, high };
|
||||
|
@ -16,80 +16,80 @@ EightBit::Processor::Processor(const Processor& rhs)
|
||||
DEFINE_PIN_LEVEL_CHANGERS(RESET, Processor);
|
||||
DEFINE_PIN_LEVEL_CHANGERS(INT, Processor);
|
||||
|
||||
void EightBit::Processor::handleRESET() {
|
||||
void EightBit::Processor::handleRESET() noexcept {
|
||||
raiseRESET();
|
||||
}
|
||||
|
||||
void EightBit::Processor::handleINT() {
|
||||
void EightBit::Processor::handleINT() noexcept {
|
||||
raiseINT();
|
||||
}
|
||||
|
||||
void EightBit::Processor::memoryWrite(const register16_t address, const uint8_t data) {
|
||||
void EightBit::Processor::memoryWrite(const register16_t address, const uint8_t data) noexcept {
|
||||
BUS().ADDRESS() = address;
|
||||
memoryWrite(data);
|
||||
}
|
||||
|
||||
void EightBit::Processor::memoryWrite(const register16_t address) {
|
||||
void EightBit::Processor::memoryWrite(const register16_t address) noexcept {
|
||||
BUS().ADDRESS() = address;
|
||||
memoryWrite();
|
||||
}
|
||||
|
||||
void EightBit::Processor::memoryWrite(const uint8_t data) {
|
||||
void EightBit::Processor::memoryWrite(const uint8_t data) noexcept {
|
||||
BUS().DATA() = data;
|
||||
memoryWrite();
|
||||
}
|
||||
|
||||
void EightBit::Processor::memoryWrite() {
|
||||
void EightBit::Processor::memoryWrite() noexcept {
|
||||
busWrite();
|
||||
}
|
||||
|
||||
void EightBit::Processor::busWrite() {
|
||||
void EightBit::Processor::busWrite() noexcept {
|
||||
BUS().write();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Processor::memoryRead(const register16_t address) {
|
||||
uint8_t EightBit::Processor::memoryRead(const register16_t address) noexcept {
|
||||
BUS().ADDRESS() = address;
|
||||
return memoryRead();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Processor::memoryRead() {
|
||||
uint8_t EightBit::Processor::memoryRead() noexcept {
|
||||
return busRead();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Processor::busRead() {
|
||||
uint8_t EightBit::Processor::busRead() noexcept {
|
||||
return BUS().read();
|
||||
}
|
||||
|
||||
uint8_t EightBit::Processor::getBytePaged(const uint8_t page, const uint8_t offset) {
|
||||
uint8_t EightBit::Processor::getBytePaged(const uint8_t page, const uint8_t offset) noexcept {
|
||||
return memoryRead(register16_t(offset, page));
|
||||
}
|
||||
|
||||
void EightBit::Processor::setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) {
|
||||
void EightBit::Processor::setBytePaged(const uint8_t page, const uint8_t offset, const uint8_t value) noexcept {
|
||||
memoryWrite(register16_t(offset, page), value);
|
||||
}
|
||||
|
||||
uint8_t EightBit::Processor::fetchByte() {
|
||||
uint8_t EightBit::Processor::fetchByte() noexcept {
|
||||
return memoryRead(PC()++);
|
||||
}
|
||||
|
||||
EightBit::register16_t EightBit::Processor::getWord(const register16_t address) {
|
||||
EightBit::register16_t EightBit::Processor::getWord(const register16_t address) noexcept {
|
||||
BUS().ADDRESS() = address;
|
||||
return getWord();
|
||||
}
|
||||
|
||||
void EightBit::Processor::setWord(const register16_t address, const register16_t value) {
|
||||
void EightBit::Processor::setWord(const register16_t address, const register16_t value) noexcept {
|
||||
BUS().ADDRESS() = address;
|
||||
setWord(value);
|
||||
}
|
||||
|
||||
int EightBit::Processor::run(const int limit) {
|
||||
int EightBit::Processor::run(const int limit) noexcept {
|
||||
int current = 0;
|
||||
while (LIKELY(powered() && (current < limit)))
|
||||
current += step();
|
||||
return current;
|
||||
}
|
||||
|
||||
int EightBit::Processor::execute(const uint8_t value) {
|
||||
int EightBit::Processor::execute(const uint8_t value) noexcept {
|
||||
opcode() = value;
|
||||
return execute();
|
||||
}
|
||||
@ -98,12 +98,12 @@ void EightBit::Processor::jump(const register16_t destination) noexcept {
|
||||
PC() = destination;
|
||||
}
|
||||
|
||||
void EightBit::Processor::call(const register16_t destination) {
|
||||
void EightBit::Processor::call(const register16_t destination) noexcept {
|
||||
pushWord(PC());
|
||||
jump(destination);
|
||||
}
|
||||
|
||||
void EightBit::Processor::ret() {
|
||||
void EightBit::Processor::ret() noexcept {
|
||||
jump(popWord());
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user