mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-02-20 22:29:01 +00:00
Start big refactor of device/CPU pin usage (to allow pin events throughout).
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
parent
9755a5fcd2
commit
92d23d82d6
@ -8,6 +8,7 @@
|
||||
#include <Bus.h>
|
||||
#include <InputOutput.h>
|
||||
#include <IntelProcessor.h>
|
||||
#include <EventArgs.h>
|
||||
#include <Signal.h>
|
||||
#include <Register.h>
|
||||
|
||||
|
@ -10,15 +10,16 @@ Board::Board(const Configuration& configuration)
|
||||
m_disassembler(*this) {
|
||||
}
|
||||
|
||||
void Board::powerOn() {
|
||||
EightBit::Bus::powerOn();
|
||||
CPU().powerOn();
|
||||
CPU().reset();
|
||||
void Board::raisePOWER() {
|
||||
EightBit::Bus::raisePOWER();
|
||||
CPU().raisePOWER();
|
||||
CPU().raiseRESET();
|
||||
CPU().raiseINT();
|
||||
}
|
||||
|
||||
void Board::powerOff() {
|
||||
CPU().powerOff();
|
||||
EightBit::Bus::powerOff();
|
||||
void Board::lowerPOWER() {
|
||||
CPU().lowerPOWER();
|
||||
EightBit::Bus::lowerPOWER();
|
||||
}
|
||||
|
||||
void Board::initialise() {
|
||||
@ -30,6 +31,10 @@ void Board::initialise() {
|
||||
m_ram.load(romDirectory + "/8080EX1.COM", 0x100); // Cringle/Bartholomew
|
||||
//m_ram.load(romDirectory + "/CPUTEST.COM", 0x100); // SuperSoft diagnostics
|
||||
|
||||
m_cpu.LoweredHALT.connect([this](EightBit::EventArgs) {
|
||||
lowerPOWER();
|
||||
});
|
||||
|
||||
m_cpu.ExecutingInstruction.connect(std::bind(&Board::Cpu_ExecutingInstruction_Cpm, this, std::placeholders::_1));
|
||||
|
||||
if (m_configuration.isProfileMode()) {
|
||||
@ -49,8 +54,8 @@ void Board::initialise() {
|
||||
void Board::Cpu_ExecutingInstruction_Cpm(EightBit::Intel8080& cpu) {
|
||||
switch (cpu.PC().word) {
|
||||
case 0x0: // CP/M warm start
|
||||
if (++m_warmstartCount == 3) {
|
||||
powerOff();
|
||||
if (++m_warmstartCount == 2) {
|
||||
lowerPOWER();
|
||||
if (m_configuration.isProfileMode()) {
|
||||
m_profiler.dump();
|
||||
}
|
||||
|
@ -17,11 +17,12 @@ public:
|
||||
EightBit::Intel8080& CPU() { return m_cpu; }
|
||||
const EightBit::Intel8080& CPU() const { return m_cpu; }
|
||||
|
||||
virtual void powerOn() final;
|
||||
virtual void powerOff() final;
|
||||
virtual void raisePOWER() final;
|
||||
virtual void lowerPOWER() final;
|
||||
|
||||
virtual void initialise() final;
|
||||
|
||||
protected:
|
||||
virtual void initialise() final;
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final {
|
||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
}
|
||||
|
@ -9,16 +9,18 @@ Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& expecte
|
||||
|
||||
//
|
||||
|
||||
void Fuse::TestRunner::powerOn() {
|
||||
EightBit::Bus::powerOn();
|
||||
CPU().powerOn();
|
||||
void Fuse::TestRunner::raisePOWER() {
|
||||
EightBit::Bus::raisePOWER();
|
||||
CPU().raisePOWER();
|
||||
CPU().raiseRESET();
|
||||
CPU().raiseINT();
|
||||
initialiseRegisters();
|
||||
initialiseMemory();
|
||||
}
|
||||
|
||||
void Fuse::TestRunner::powerOff() {
|
||||
CPU().powerOff();
|
||||
EightBit::Bus::powerOff();
|
||||
void Fuse::TestRunner::lowerPOWER() {
|
||||
CPU().lowerPOWER();
|
||||
EightBit::Bus::lowerPOWER();
|
||||
}
|
||||
|
||||
void Fuse::TestRunner::initialise() {
|
||||
@ -182,7 +184,8 @@ void Fuse::TestRunner::checkMemory() {
|
||||
|
||||
void Fuse::TestRunner::run() {
|
||||
|
||||
powerOn();
|
||||
raisePOWER();
|
||||
initialise();
|
||||
auto allowedCycles = m_test.registerState.tstates;
|
||||
try {
|
||||
CPU().run(allowedCycles);
|
||||
|
@ -21,7 +21,6 @@ namespace Fuse {
|
||||
|
||||
EightBit::Ram m_ram = 0x10000;
|
||||
|
||||
void initialise();
|
||||
void initialiseRegisters();
|
||||
void initialiseMemory();
|
||||
|
||||
@ -47,7 +46,9 @@ namespace Fuse {
|
||||
bool failed() const { return m_failed; }
|
||||
bool unimplemented() const { return m_unimplemented; }
|
||||
|
||||
virtual void powerOn() final;
|
||||
virtual void powerOff() final;
|
||||
virtual void raisePOWER() final;
|
||||
virtual void lowerPOWER() final;
|
||||
|
||||
void initialise();
|
||||
};
|
||||
}
|
@ -36,8 +36,8 @@ namespace EightBit {
|
||||
|
||||
Bus() noexcept;
|
||||
|
||||
virtual void powerOn() override;
|
||||
virtual void powerOff() override;
|
||||
virtual void raisePOWER() override;
|
||||
virtual void lowerPOWER() override;
|
||||
|
||||
auto& CPU() { return m_cpu; }
|
||||
auto& VRAM() { return m_videoRam; }
|
||||
|
@ -8,15 +8,15 @@ EightBit::GameBoy::Bus::Bus() noexcept
|
||||
WrittenByte.connect(std::bind(&GameBoy::Bus::Bus_WrittenByte, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::Bus::powerOn() {
|
||||
EightBit::Bus::powerOn();
|
||||
CPU().powerOn();
|
||||
void EightBit::GameBoy::Bus::raisePOWER() {
|
||||
EightBit::Bus::raisePOWER();
|
||||
CPU().raisePOWER();
|
||||
reset();
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::Bus::powerOff() {
|
||||
CPU().powerOff();
|
||||
EightBit::Bus::powerOff();
|
||||
void EightBit::GameBoy::Bus::lowerPOWER() {
|
||||
CPU().lowerPOWER();
|
||||
EightBit::Bus::lowerPOWER();
|
||||
}
|
||||
|
||||
void EightBit::GameBoy::Bus::reset() {
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <LittleEndianProcessor.h>
|
||||
#include <Register.h>
|
||||
#include <Signal.h>
|
||||
#include <EventArgs.h>
|
||||
|
||||
namespace EightBit {
|
||||
|
||||
@ -30,9 +31,30 @@ namespace EightBit {
|
||||
Signal<MOS6502> ExecutingInstruction;
|
||||
Signal<MOS6502> ExecutedInstruction;
|
||||
|
||||
virtual int execute() final;
|
||||
virtual int step() final;
|
||||
virtual void powerOn() final;
|
||||
Signal<EventArgs> RaisedNMI;
|
||||
Signal<EventArgs> LoweredNMI;
|
||||
|
||||
Signal<EventArgs> RaisedSO;
|
||||
Signal<EventArgs> LoweredSO;
|
||||
|
||||
Signal<EventArgs> RaisedSYNC;
|
||||
Signal<EventArgs> LoweredSYNC;
|
||||
|
||||
Signal<EventArgs> RaisedRDY;
|
||||
Signal<EventArgs> LoweredRDY;
|
||||
|
||||
int execute() final;
|
||||
int step() final;
|
||||
void raisePOWER() final;
|
||||
|
||||
virtual void lowerNMI();
|
||||
virtual void raiseNMI();
|
||||
|
||||
virtual void lowerSO();
|
||||
virtual void raiseSO();
|
||||
|
||||
virtual void lowerRDY();
|
||||
virtual void raiseRDY();
|
||||
|
||||
auto& X() { return x; }
|
||||
auto& Y() { return y; }
|
||||
@ -48,8 +70,11 @@ namespace EightBit {
|
||||
auto& RDY() { return m_rdyLine; } // In
|
||||
|
||||
protected:
|
||||
virtual void lowerSYNC();
|
||||
virtual void raiseSYNC();
|
||||
|
||||
virtual void handleRESET() final;
|
||||
virtual void handleIRQ() final;
|
||||
virtual void handleINT() final;
|
||||
|
||||
virtual void busWrite() final;
|
||||
virtual uint8_t busRead() final;
|
||||
@ -186,15 +211,15 @@ namespace EightBit {
|
||||
uint8_t s = 0; // stack pointer
|
||||
uint8_t p = 0; // processor status
|
||||
|
||||
PinLevel m_nmiLine = PinLevel::Low; // Active low
|
||||
PinLevel m_soLine = PinLevel::Low; // Active low
|
||||
PinLevel m_syncLine = PinLevel::Low; // Active high
|
||||
PinLevel m_rdyLine = PinLevel::Low; // Active high
|
||||
PinLevel m_nmiLine = PinLevel::Low; // In, Active low
|
||||
PinLevel m_soLine = PinLevel::Low; // In, Active low
|
||||
PinLevel m_syncLine = PinLevel::Low; // Out, Active high
|
||||
PinLevel m_rdyLine = PinLevel::Low; // In, Active high
|
||||
|
||||
register16_t m_intermediate;
|
||||
|
||||
bool m_handlingRESET = false;
|
||||
bool m_handlingNMI = false;
|
||||
bool m_handlingIRQ = false;
|
||||
bool m_handlingINT = false;
|
||||
};
|
||||
}
|
@ -4,18 +4,45 @@
|
||||
EightBit::MOS6502::MOS6502(Bus& bus)
|
||||
: LittleEndianProcessor(bus) {}
|
||||
|
||||
void EightBit::MOS6502::powerOn() {
|
||||
|
||||
LittleEndianProcessor::powerOn();
|
||||
|
||||
void EightBit::MOS6502::raisePOWER() {
|
||||
LittleEndianProcessor::raisePOWER();
|
||||
X() = Bit7;
|
||||
Y() = 0;
|
||||
A() = 0;
|
||||
P() = RF;
|
||||
S() = Mask8;
|
||||
lowerSYNC();
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::lowerNMI() {
|
||||
lower(NMI());
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::raiseNMI() {
|
||||
raise(NMI());
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::lowerSO() {
|
||||
lower(SO());
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::raiseSO() {
|
||||
raise(SO());
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::lowerSYNC() {
|
||||
lower(SYNC());
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::raiseSYNC() {
|
||||
raise(SYNC());
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::lowerRDY() {
|
||||
lower(RDY());
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::raiseRDY() {
|
||||
raise(RDY());
|
||||
}
|
||||
|
||||
@ -27,14 +54,14 @@ int EightBit::MOS6502::step() {
|
||||
if (UNLIKELY(lowered(SO())))
|
||||
handleSO();
|
||||
if (LIKELY(raised(RDY()))) {
|
||||
lower(SYNC()); // Instruction fetch beginning
|
||||
lowerSYNC(); // Instruction fetch beginning
|
||||
opcode() = BUS().read(PC()++); // can't use fetchByte
|
||||
if (UNLIKELY(lowered(RESET())))
|
||||
handleRESET();
|
||||
else if (UNLIKELY(lowered(NMI())))
|
||||
handleNMI();
|
||||
else if (UNLIKELY(lowered(IRQ()) && !interruptMasked()))
|
||||
handleIRQ();
|
||||
else if (UNLIKELY(lowered(INT()) && !interruptMasked()))
|
||||
handleINT();
|
||||
execute();
|
||||
}
|
||||
}
|
||||
@ -45,33 +72,33 @@ int EightBit::MOS6502::step() {
|
||||
// Interrupt (etc.) handlers
|
||||
|
||||
void EightBit::MOS6502::handleSO() {
|
||||
raise(SO());
|
||||
raiseSO();
|
||||
P() |= VF;
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::handleRESET() {
|
||||
raise(RESET());
|
||||
raiseRESET();
|
||||
m_handlingRESET = true;
|
||||
opcode() = 0x00; // BRK
|
||||
}
|
||||
|
||||
|
||||
void EightBit::MOS6502::handleNMI() {
|
||||
raise(NMI());
|
||||
raiseNMI();
|
||||
m_handlingNMI = true;
|
||||
opcode() = 0x00; // BRK
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::handleIRQ() {
|
||||
void EightBit::MOS6502::handleINT() {
|
||||
raise(INT());
|
||||
m_handlingIRQ = true;
|
||||
m_handlingINT = true;
|
||||
opcode() = 0x00; // BRK
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::interrupt() {
|
||||
const bool reset = m_handlingRESET;
|
||||
const bool nmi = m_handlingNMI;
|
||||
const bool irq = m_handlingIRQ;
|
||||
const bool irq = m_handlingINT;
|
||||
const bool hardware = nmi || irq || reset;
|
||||
const bool software = !hardware;
|
||||
if (reset) {
|
||||
@ -85,7 +112,7 @@ void EightBit::MOS6502::interrupt() {
|
||||
setFlag(P(), IF); // Disable IRQ
|
||||
const uint8_t vector = reset ? RSTvector : (nmi ? NMIvector : IRQvector);
|
||||
jump(getWordPaged(0xff, vector));
|
||||
m_handlingRESET = m_handlingNMI = m_handlingIRQ = false;
|
||||
m_handlingRESET = m_handlingNMI = m_handlingINT = false;
|
||||
}
|
||||
|
||||
//
|
||||
@ -104,7 +131,7 @@ uint8_t EightBit::MOS6502::busRead() {
|
||||
|
||||
int EightBit::MOS6502::execute() {
|
||||
|
||||
raise(SYNC()); // Instruction fetch has now completed
|
||||
raiseSYNC(); // Instruction fetch has now completed
|
||||
|
||||
switch (opcode()) {
|
||||
|
||||
|
@ -10,14 +10,19 @@
|
||||
Board::Board(const Configuration& configuration)
|
||||
: m_configuration(configuration) {}
|
||||
|
||||
void Board::powerOn() {
|
||||
EightBit::Bus::powerOn();
|
||||
CPU().powerOn();
|
||||
void Board::raisePOWER() {
|
||||
EightBit::Bus::raisePOWER();
|
||||
CPU().raisePOWER();
|
||||
CPU().raiseRESET();
|
||||
CPU().raiseINT();
|
||||
CPU().raiseNMI();
|
||||
CPU().raiseSO();
|
||||
CPU().raiseRDY();
|
||||
}
|
||||
|
||||
void Board::powerOff() {
|
||||
CPU().powerOff();
|
||||
EightBit::Bus::powerOff();
|
||||
void Board::lowerPOWER() {
|
||||
CPU().lowerPOWER();
|
||||
EightBit::Bus::lowerPOWER();
|
||||
}
|
||||
|
||||
void Board::initialise() {
|
||||
@ -53,7 +58,7 @@ void Board::initialise() {
|
||||
if (m_oldPC != pc) {
|
||||
m_oldPC = pc;
|
||||
} else {
|
||||
powerOff();
|
||||
lowerPOWER();
|
||||
auto test = peek(0x0200);
|
||||
std::cout << std::endl << "** Test=" << std::hex << (int)test;
|
||||
}
|
||||
|
@ -17,11 +17,12 @@ public:
|
||||
|
||||
EightBit::MOS6502& CPU() { return m_cpu; }
|
||||
|
||||
virtual void powerOn() final;
|
||||
virtual void powerOff() final;
|
||||
virtual void raisePOWER() final;
|
||||
virtual void lowerPOWER() final;
|
||||
|
||||
virtual void initialise() final;
|
||||
|
||||
protected:
|
||||
virtual void initialise() final;
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final {
|
||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
}
|
||||
|
@ -57,10 +57,34 @@ namespace EightBit {
|
||||
Signal<mc6809> ExecutingInstruction;
|
||||
Signal<mc6809> ExecutedInstruction;
|
||||
|
||||
Signal<EventArgs> RaisedNMI;
|
||||
Signal<EventArgs> LoweredNMI;
|
||||
|
||||
Signal<EventArgs> RaisedFIRQ;
|
||||
Signal<EventArgs> LoweredFIRQ;
|
||||
|
||||
Signal<EventArgs> RaisedHALT;
|
||||
Signal<EventArgs> LoweredHALT;
|
||||
|
||||
Signal<EventArgs> RaisedBA;
|
||||
Signal<EventArgs> LoweredBA;
|
||||
|
||||
Signal<EventArgs> RaisedBS;
|
||||
Signal<EventArgs> LoweredBS;
|
||||
|
||||
virtual int execute() final;
|
||||
virtual int step() final;
|
||||
|
||||
virtual void powerOn() final;
|
||||
virtual void raisePOWER() final;
|
||||
|
||||
virtual void lowerNMI();
|
||||
virtual void raiseNMI();
|
||||
|
||||
virtual void lowerFIRQ();
|
||||
virtual void raiseFIRQ();
|
||||
|
||||
virtual void lowerHALT();
|
||||
virtual void raiseHALT();
|
||||
|
||||
auto& D() { return m_d; }
|
||||
auto& A() { return D().high; }
|
||||
@ -75,8 +99,9 @@ namespace EightBit {
|
||||
auto& CC() { return m_cc; }
|
||||
const auto& CC() const { return m_cc; }
|
||||
|
||||
auto& NMI() { return m_nmiLine; } // In
|
||||
auto& FIRQ() { return m_firqLine; } // In
|
||||
[[nodiscard]] auto& NMI() noexcept { return m_nmiLine; } // In
|
||||
[[nodiscard]] auto& FIRQ() noexcept { return m_firqLine; } // In
|
||||
[[nodiscard]] auto& HALT() noexcept { return m_haltLine; } // In
|
||||
|
||||
// |---------------|-----------------------------------|
|
||||
// | MPU State | |
|
||||
@ -92,6 +117,10 @@ namespace EightBit {
|
||||
auto& BA() { return m_baLine; } // Out
|
||||
auto& BS() { return m_bsLine; } // Out
|
||||
|
||||
[[nodiscard]] auto halted() noexcept { return lowered(HALT()); }
|
||||
void halt() noexcept { --PC(); lowerHALT(); }
|
||||
void proceed() noexcept { ++PC(); raiseHALT(); }
|
||||
|
||||
protected:
|
||||
// Default push/pop handlers
|
||||
|
||||
@ -101,7 +130,15 @@ namespace EightBit {
|
||||
// Interrupt (etc.) handlers
|
||||
|
||||
virtual void handleRESET() final;
|
||||
virtual void handleIRQ() final;
|
||||
virtual void handleINT() final;
|
||||
|
||||
// Line handlers
|
||||
|
||||
virtual void lowerBA();
|
||||
virtual void raiseBA();
|
||||
|
||||
virtual void lowerBS();
|
||||
virtual void raiseBS();
|
||||
|
||||
private:
|
||||
const uint8_t RESETvector = 0xfe; // RESET vector
|
||||
@ -368,11 +405,12 @@ namespace EightBit {
|
||||
uint8_t m_dp = 0;
|
||||
uint8_t m_cc = 0;
|
||||
|
||||
PinLevel m_nmiLine = PinLevel::Low;
|
||||
PinLevel m_firqLine = PinLevel::Low;
|
||||
PinLevel m_nmiLine = PinLevel::Low; // In, Active low
|
||||
PinLevel m_firqLine = PinLevel::Low; // In, Active low
|
||||
PinLevel m_haltLine = PinLevel::Low; // In, Active low
|
||||
|
||||
PinLevel m_baLine = PinLevel::Low;
|
||||
PinLevel m_bsLine = PinLevel::Low;
|
||||
PinLevel m_baLine = PinLevel::Low; // Out, Bus available
|
||||
PinLevel m_bsLine = PinLevel::Low; // Out, Bus status
|
||||
|
||||
bool m_prefix10 = false;
|
||||
bool m_prefix11 = false;
|
||||
|
@ -108,7 +108,7 @@ bool EightBit::Disassembly::ignore() {
|
||||
|| CPU().lowered(CPU().RESET())
|
||||
|| CPU().lowered(CPU().NMI())
|
||||
|| (CPU().lowered(CPU().FIRQ()) && !(CPU().CC() & mc6809::FF))
|
||||
|| (CPU().lowered(CPU().IRQ()) && !(CPU().CC() & mc6809::IF));
|
||||
|| (CPU().lowered(CPU().INT()) && !(CPU().CC() & mc6809::IF));
|
||||
}
|
||||
|
||||
std::string EightBit::Disassembly::disassemble(uint16_t current) {
|
||||
|
@ -7,10 +7,60 @@
|
||||
EightBit::mc6809::mc6809(Bus& bus)
|
||||
: BigEndianProcessor(bus) {}
|
||||
|
||||
void EightBit::mc6809::powerOn() {
|
||||
BigEndianProcessor::powerOn();
|
||||
void EightBit::mc6809::raisePOWER() {
|
||||
BigEndianProcessor::raisePOWER();
|
||||
lowerBA();
|
||||
lowerBS();
|
||||
}
|
||||
|
||||
void EightBit::mc6809::lowerNMI() {
|
||||
lower(NMI());
|
||||
LoweredNMI.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::mc6809::raiseNMI() {
|
||||
raise(NMI());
|
||||
RaisedNMI.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::mc6809::lowerFIRQ() {
|
||||
lower(FIRQ());
|
||||
LoweredFIRQ.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::mc6809::raiseFIRQ() {
|
||||
raise(FIRQ());
|
||||
RaisedFIRQ.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::mc6809::lowerHALT() {
|
||||
lower(HALT());
|
||||
LoweredHALT.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::mc6809::raiseHALT() {
|
||||
raise(HALT());
|
||||
RaisedHALT.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::mc6809::lowerBA() {
|
||||
lower(BA());
|
||||
LoweredNMI.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::mc6809::raiseBA() {
|
||||
raise(BA());
|
||||
RaisedBA.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::mc6809::lowerBS() {
|
||||
lower(BS());
|
||||
LoweredBS.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::mc6809::raiseBS() {
|
||||
raise(BS());
|
||||
RaisedBS.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
int EightBit::mc6809::step() {
|
||||
@ -26,8 +76,8 @@ int EightBit::mc6809::step() {
|
||||
handleNMI();
|
||||
else if (UNLIKELY(lowered(FIRQ()) && !fastInterruptMasked()))
|
||||
handleFIRQ();
|
||||
else if (UNLIKELY(lowered(IRQ()) && !interruptMasked()))
|
||||
handleIRQ();
|
||||
else if (UNLIKELY(lowered(INT()) && !interruptMasked()))
|
||||
handleINT();
|
||||
else
|
||||
Processor::execute(fetchByte());
|
||||
}
|
||||
@ -38,15 +88,15 @@ int EightBit::mc6809::step() {
|
||||
// Interrupt (etc.) handlers
|
||||
|
||||
void EightBit::mc6809::handleHALT() {
|
||||
raise(BA());
|
||||
raise(BS());
|
||||
raiseBA();
|
||||
raiseBS();
|
||||
}
|
||||
|
||||
void EightBit::mc6809::handleRESET() {
|
||||
BigEndianProcessor::handleRESET();
|
||||
raise(NMI());
|
||||
lower(BA());
|
||||
raise(BS());
|
||||
raiseNMI();
|
||||
lowerBA();
|
||||
raiseBS();
|
||||
DP() = 0;
|
||||
setFlag(CC(), IF); // Disable IRQ
|
||||
setFlag(CC(), FF); // Disable FIRQ
|
||||
@ -55,9 +105,9 @@ void EightBit::mc6809::handleRESET() {
|
||||
}
|
||||
|
||||
void EightBit::mc6809::handleNMI() {
|
||||
raise(NMI());
|
||||
lower(BA());
|
||||
raise(BS());
|
||||
raiseNMI();
|
||||
lowerBA();
|
||||
raiseBS();
|
||||
saveEntireRegisterState();
|
||||
setFlag(CC(), IF); // Disable IRQ
|
||||
setFlag(CC(), FF); // Disable FIRQ
|
||||
@ -65,10 +115,10 @@ void EightBit::mc6809::handleNMI() {
|
||||
tick(12);
|
||||
}
|
||||
|
||||
void EightBit::mc6809::handleIRQ() {
|
||||
BigEndianProcessor::handleIRQ();
|
||||
lower(BA());
|
||||
raise(BS());
|
||||
void EightBit::mc6809::handleINT() {
|
||||
BigEndianProcessor::handleINT();
|
||||
lowerBA();
|
||||
raiseBS();
|
||||
saveEntireRegisterState();
|
||||
setFlag(CC(), IF); // Disable IRQ
|
||||
jump(getWordPaged(0xff, IRQvector));
|
||||
@ -76,9 +126,9 @@ void EightBit::mc6809::handleIRQ() {
|
||||
}
|
||||
|
||||
void EightBit::mc6809::handleFIRQ() {
|
||||
raise(FIRQ());
|
||||
lower(BA());
|
||||
raise(BS());
|
||||
raiseFIRQ();
|
||||
lowerBA();
|
||||
raiseBS();
|
||||
savePartialRegisterState();
|
||||
setFlag(CC(), IF); // Disable IRQ
|
||||
setFlag(CC(), FF); // Disable FIRQ
|
||||
@ -89,8 +139,8 @@ void EightBit::mc6809::handleFIRQ() {
|
||||
//
|
||||
|
||||
int EightBit::mc6809::execute() {
|
||||
lower(BA());
|
||||
lower(BS());
|
||||
lowerBA();
|
||||
lowerBS();
|
||||
const bool prefixed = m_prefix10 || m_prefix11;
|
||||
const bool unprefixed = !prefixed;
|
||||
if (unprefixed) {
|
||||
|
@ -4,29 +4,31 @@
|
||||
Board::Board(const Configuration& configuration)
|
||||
: m_configuration(configuration) {}
|
||||
|
||||
void Board::powerOn() {
|
||||
void Board::raisePOWER() {
|
||||
|
||||
EightBit::Bus::powerOn();
|
||||
EightBit::Bus::raisePOWER();
|
||||
|
||||
// Get the CPU ready for action
|
||||
CPU().powerOn();
|
||||
CPU().raise(CPU().NMI());
|
||||
CPU().raise(CPU().FIRQ());
|
||||
CPU().reset();
|
||||
CPU().raisePOWER();
|
||||
CPU().lowerRESET();
|
||||
CPU().raiseINT();
|
||||
CPU().raiseNMI();
|
||||
CPU().raiseFIRQ();
|
||||
CPU().raiseHALT();
|
||||
|
||||
// Get the ACIA ready for action
|
||||
ADDRESS() = 0b1010000000000000;
|
||||
ACIA().DATA() = EightBit::mc6850::CR0 | EightBit::mc6850::CR1; // Master reset
|
||||
updateAciaPinsWrite();
|
||||
ACIA().lower(ACIA().CTS());
|
||||
ACIA().powerOn();
|
||||
ACIA().raisePOWER();
|
||||
accessAcia();
|
||||
}
|
||||
|
||||
void Board::powerOff() {
|
||||
ACIA().powerOff();
|
||||
CPU().powerOff();
|
||||
EightBit::Bus::powerOff();
|
||||
void Board::lowerPOWER() {
|
||||
ACIA().lowerPOWER();
|
||||
CPU().lowerPOWER();
|
||||
EightBit::Bus::lowerPOWER();
|
||||
}
|
||||
|
||||
void Board::initialise() {
|
||||
@ -88,7 +90,7 @@ void Board::initialise() {
|
||||
assert(cpu.cycles() > 0);
|
||||
m_totalCycleCount += cpu.cycles();
|
||||
if (m_totalCycleCount > Configuration::TerminationCycles)
|
||||
powerOff();
|
||||
lowerPOWER();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -107,13 +109,12 @@ EightBit::MemoryMapping Board::mapping(uint16_t address) {
|
||||
return { m_rom, 0xc000, EightBit::Chip::Mask16, EightBit::MemoryMapping::AccessLevel::ReadOnly };
|
||||
}
|
||||
|
||||
void Board::updateAciaPins(const EightBit::Chip::PinLevel rw) {
|
||||
ACIA().RW() = rw;
|
||||
void Board::updateAciaPins() {
|
||||
ACIA().DATA() = DATA();
|
||||
ACIA().match(ACIA().RS(), ADDRESS().word & EightBit::Chip::Bit0);
|
||||
ACIA().match(ACIA().CS0(), ADDRESS().word & EightBit::Chip::Bit15);
|
||||
ACIA().match(ACIA().CS1(), ADDRESS().word & EightBit::Chip::Bit13);
|
||||
ACIA().match(ACIA().CS2(), ADDRESS().word & EightBit::Chip::Bit14);
|
||||
ADDRESS().word & EightBit::Chip::Bit0 ? ACIA().raise(ACIA().RS()) : ACIA().lower(ACIA().RS());
|
||||
ADDRESS().word & EightBit::Chip::Bit15 ? ACIA().raise(ACIA().CS0()) : ACIA().lower(ACIA().CS0());
|
||||
ADDRESS().word & EightBit::Chip::Bit13 ? ACIA().raise(ACIA().CS1()) : ACIA().lower(ACIA().CS1());
|
||||
ADDRESS().word & EightBit::Chip::Bit14 ? ACIA().raise(ACIA().CS2()) : ACIA().lower(ACIA().CS2());
|
||||
}
|
||||
|
||||
bool Board::accessAcia() {
|
||||
|
@ -19,11 +19,12 @@ public:
|
||||
auto& CPU() { return m_cpu; }
|
||||
auto& ACIA() { return m_acia; }
|
||||
|
||||
virtual void powerOn() final;
|
||||
virtual void powerOff() final;
|
||||
virtual void raisePOWER() final;
|
||||
virtual void lowerPOWER() final;
|
||||
|
||||
virtual void initialise() final;
|
||||
|
||||
protected:
|
||||
virtual void initialise() final;
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final;
|
||||
|
||||
private:
|
||||
@ -46,9 +47,17 @@ private:
|
||||
bool m_ignoreDisassembly = false;
|
||||
|
||||
// Use the bus data to update the ACIA access/address pins
|
||||
void updateAciaPinsRead() { updateAciaPins(EightBit::Chip::PinLevel::High); }
|
||||
void updateAciaPinsWrite() { updateAciaPins(EightBit::Chip::PinLevel::Low); }
|
||||
void updateAciaPins(EightBit::Chip::PinLevel rw);
|
||||
void updateAciaPinsRead() {
|
||||
ACIA().raise(ACIA().RW());
|
||||
updateAciaPins();
|
||||
}
|
||||
|
||||
void updateAciaPinsWrite() {
|
||||
ACIA().lower(ACIA().RW());
|
||||
updateAciaPins();
|
||||
}
|
||||
|
||||
void updateAciaPins();
|
||||
|
||||
bool accessAcia();
|
||||
};
|
||||
|
@ -6,17 +6,22 @@ Board::Board()
|
||||
m_disassembler(*this, m_cpu) {
|
||||
}
|
||||
|
||||
void Board::powerOn() {
|
||||
EightBit::Bus::powerOn();
|
||||
CPU().powerOn();
|
||||
CPU().raise(CPU().NMI());
|
||||
CPU().raise(CPU().FIRQ());
|
||||
CPU().reset();
|
||||
void Board::raisePOWER() {
|
||||
EightBit::Bus::raisePOWER();
|
||||
|
||||
CPU().raisePOWER();
|
||||
|
||||
CPU().lowerRESET();
|
||||
CPU().raiseINT();
|
||||
|
||||
CPU().raiseNMI();
|
||||
CPU().raiseFIRQ();
|
||||
CPU().raiseHALT();
|
||||
}
|
||||
|
||||
void Board::powerOff() {
|
||||
CPU().powerOff();
|
||||
EightBit::Bus::powerOff();
|
||||
void Board::lowerPOWER() {
|
||||
CPU().lowerPOWER();
|
||||
EightBit::Bus::lowerPOWER();
|
||||
}
|
||||
|
||||
void Board::initialise() {
|
||||
|
@ -11,11 +11,12 @@ public:
|
||||
|
||||
EightBit::mc6809& CPU() { return m_cpu; }
|
||||
|
||||
virtual void powerOn() final;
|
||||
virtual void powerOff() final;
|
||||
virtual void raisePOWER() final;
|
||||
virtual void lowerPOWER() final;
|
||||
|
||||
protected:
|
||||
virtual void initialise() final;
|
||||
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final;
|
||||
|
||||
private:
|
||||
|
@ -9,7 +9,7 @@
|
||||
TEST_CASE("Add Accumulator B to Index Register X Unsigned", "[ABX]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -70,7 +70,7 @@ TEST_CASE("Add Accumulator B to Index Register X Unsigned", "[ABX]") {
|
||||
TEST_CASE("Add Memory Plus Carry to Accumulator", "[ADC][ADCA]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -153,7 +153,7 @@ TEST_CASE("Add Memory Plus Carry to Accumulator", "[ADC][ADCA]") {
|
||||
TEST_CASE("Add Memory to Accumulator", "[ADD][ADDA][ADDB][ADDD]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -350,7 +350,7 @@ TEST_CASE("Add Memory to Accumulator", "[ADD][ADDA][ADDB][ADDD]") {
|
||||
TEST_CASE("Logical AND Accumulator", "[AND][ANDA]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -370,7 +370,7 @@ TEST_CASE("Logical AND Accumulator", "[AND][ANDA]") {
|
||||
TEST_CASE("Shift Accumulator or Memory Byte Left", "[ASL][ASLA]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -389,7 +389,7 @@ TEST_CASE("Shift Accumulator or Memory Byte Left", "[ASL][ASLA]") {
|
||||
TEST_CASE("Shift Accumulator or Memory Byte Right", "[ASR][ASRA]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -408,7 +408,7 @@ TEST_CASE("Shift Accumulator or Memory Byte Right", "[ASR][ASRA]") {
|
||||
TEST_CASE("Bit Test", "[BIT][BITA]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -427,7 +427,7 @@ TEST_CASE("Bit Test", "[BIT][BITA]") {
|
||||
TEST_CASE("Clear Accumulator or Memory", "[CLR][CLRA]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -447,7 +447,7 @@ TEST_CASE("Clear Accumulator or Memory", "[CLR][CLRA]") {
|
||||
TEST_CASE("Compare Memory with a Register", "[CMP][CMPA][CMPB][CMPX]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -544,7 +544,7 @@ TEST_CASE("Compare Memory with a Register", "[CMP][CMPA][CMPB][CMPX]") {
|
||||
TEST_CASE("Decrement Accumulator or Memory", "[DEC][DECA]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -593,7 +593,7 @@ TEST_CASE("Decrement Accumulator or Memory", "[DEC][DECA]") {
|
||||
TEST_CASE("Increment Accumulator or Memory Location by 1", "[INC][INCA]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -640,7 +640,7 @@ TEST_CASE("Increment Accumulator or Memory Location by 1", "[INC][INCA]") {
|
||||
TEST_CASE("Subtract Memory from Accumulator with Borrow (8-bit)", "[SBC][SBCA][SBCB]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -729,7 +729,7 @@ TEST_CASE("Subtract Memory from Accumulator with Borrow (8-bit)", "[SBC][SBCA][S
|
||||
TEST_CASE("Subtract Memory from Register", "[SUB][SUBA]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -826,7 +826,7 @@ TEST_CASE("Subtract Memory from Register", "[SUB][SUBA]") {
|
||||
TEST_CASE(" Branch if Greater Than Zero", "[BGT]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -847,7 +847,7 @@ TEST_CASE(" Branch if Greater Than Zero", "[BGT]") {
|
||||
REQUIRE(cpu.A() == 1);
|
||||
}
|
||||
|
||||
cpu.reset();
|
||||
cpu.lowerRESET();
|
||||
cpu.step();
|
||||
|
||||
SECTION("BGT2") {
|
||||
@ -858,7 +858,7 @@ TEST_CASE(" Branch if Greater Than Zero", "[BGT]") {
|
||||
REQUIRE(cpu.A() == 2);
|
||||
}
|
||||
|
||||
cpu.reset();
|
||||
cpu.lowerRESET();
|
||||
cpu.step();
|
||||
|
||||
SECTION("BGT3") {
|
||||
@ -869,7 +869,7 @@ TEST_CASE(" Branch if Greater Than Zero", "[BGT]") {
|
||||
REQUIRE(cpu.A() == 1);
|
||||
}
|
||||
|
||||
cpu.reset();
|
||||
cpu.lowerRESET();
|
||||
cpu.step();
|
||||
|
||||
SECTION("BGT4") {
|
||||
@ -880,7 +880,7 @@ TEST_CASE(" Branch if Greater Than Zero", "[BGT]") {
|
||||
REQUIRE(cpu.A() == 2);
|
||||
}
|
||||
|
||||
cpu.reset();
|
||||
cpu.lowerRESET();
|
||||
cpu.step();
|
||||
|
||||
SECTION("BGT5") {
|
||||
@ -895,7 +895,7 @@ TEST_CASE(" Branch if Greater Than Zero", "[BGT]") {
|
||||
TEST_CASE(" Branch if Higher", "[BHI]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -920,7 +920,7 @@ TEST_CASE(" Branch if Higher", "[BHI]") {
|
||||
TEST_CASE("Branch on Less than or Equal to Zero", "[BLE]") {
|
||||
|
||||
Board board;
|
||||
board.powerOn();
|
||||
board.raisePOWER();
|
||||
auto& cpu = board.CPU();
|
||||
cpu.step(); // Step over the reset
|
||||
|
||||
@ -941,7 +941,7 @@ TEST_CASE("Branch on Less than or Equal to Zero", "[BLE]") {
|
||||
REQUIRE(cpu.A() == 2);
|
||||
}
|
||||
|
||||
cpu.reset();
|
||||
cpu.lowerRESET();
|
||||
cpu.step();
|
||||
|
||||
SECTION("BLE2") {
|
||||
@ -952,7 +952,7 @@ TEST_CASE("Branch on Less than or Equal to Zero", "[BLE]") {
|
||||
REQUIRE(cpu.A() == 1);
|
||||
}
|
||||
|
||||
cpu.reset();
|
||||
cpu.lowerRESET();
|
||||
cpu.step();
|
||||
|
||||
SECTION("BLE3") {
|
||||
@ -963,7 +963,7 @@ TEST_CASE("Branch on Less than or Equal to Zero", "[BLE]") {
|
||||
REQUIRE(cpu.A() == 2);
|
||||
}
|
||||
|
||||
cpu.reset();
|
||||
cpu.lowerRESET();
|
||||
cpu.step();
|
||||
|
||||
SECTION("BLE4") {
|
||||
@ -974,7 +974,7 @@ TEST_CASE("Branch on Less than or Equal to Zero", "[BLE]") {
|
||||
REQUIRE(cpu.A() == 1);
|
||||
}
|
||||
|
||||
cpu.reset();
|
||||
cpu.lowerRESET();
|
||||
cpu.step();
|
||||
|
||||
SECTION("BLE5") {
|
||||
|
@ -8,7 +8,7 @@
|
||||
namespace EightBit {
|
||||
class mc6850 final : public ClockedChip {
|
||||
public:
|
||||
void powerOn() final;
|
||||
void raisePOWER() final;
|
||||
|
||||
// +--------+----------------------------------------------------------------------------------+
|
||||
// | | Buffer address |
|
||||
@ -271,10 +271,6 @@ namespace EightBit {
|
||||
void startTransmit();
|
||||
void completeReceive();
|
||||
|
||||
bool isInterruptRequired() const;
|
||||
bool isTransmitInterruptRequired() const;
|
||||
bool isReceiveInterruptRequired() const;
|
||||
|
||||
bool transmitInterruptEnabled() const { return m_transmitControl == ReadyLowInterruptEnabled; }
|
||||
bool receiveInterruptEnabled() const { return m_receiveControl == ReceiveInterruptEnable; }
|
||||
|
||||
|
Binary file not shown.
@ -10,15 +10,18 @@ Fuse::TestRunner::TestRunner(const Test& test, const ExpectedTestResult& expecte
|
||||
|
||||
//
|
||||
|
||||
void Fuse::TestRunner::powerOn() {
|
||||
EightBit::Bus::powerOn();
|
||||
m_cpu.powerOn();
|
||||
void Fuse::TestRunner::raisePOWER() {
|
||||
EightBit::Bus::raisePOWER();
|
||||
m_cpu.raisePOWER();
|
||||
m_cpu.raiseRESET();
|
||||
m_cpu.raiseINT();
|
||||
m_cpu.raiseNMI();
|
||||
initialiseRegisters();
|
||||
}
|
||||
|
||||
void Fuse::TestRunner::powerOff() {
|
||||
m_cpu.powerOff();
|
||||
EightBit::Bus::powerOff();
|
||||
void Fuse::TestRunner::lowerPOWER() {
|
||||
m_cpu.lowerPOWER();
|
||||
EightBit::Bus::lowerPOWER();
|
||||
}
|
||||
|
||||
void Fuse::TestRunner::initialise() {
|
||||
@ -327,8 +330,8 @@ void Fuse::TestRunner::checkMemory() {
|
||||
}
|
||||
|
||||
void Fuse::TestRunner::run() {
|
||||
|
||||
powerOn();
|
||||
raisePOWER();
|
||||
initialise();
|
||||
auto allowedCycles = m_test.registerState.tstates;
|
||||
try {
|
||||
m_cpu.run(allowedCycles);
|
||||
|
@ -35,7 +35,6 @@ namespace Fuse {
|
||||
EightBit::register16_t actual, EightBit::register16_t expected) const;
|
||||
|
||||
protected:
|
||||
virtual void initialise() final;
|
||||
virtual EightBit::MemoryMapping mapping(uint16_t address) final {
|
||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
}
|
||||
@ -47,7 +46,9 @@ namespace Fuse {
|
||||
bool failed() const { return m_failed; }
|
||||
bool unimplemented() const { return m_unimplemented; }
|
||||
|
||||
virtual void powerOn() final;
|
||||
virtual void powerOff() final;
|
||||
virtual void raisePOWER() final;
|
||||
virtual void lowerPOWER() final;
|
||||
|
||||
virtual void initialise() final;
|
||||
};
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
#include <Bus.h>
|
||||
#include <InputOutput.h>
|
||||
#include <IntelProcessor.h>
|
||||
#include <EventArgs.h>
|
||||
#include <Signal.h>
|
||||
#include <Register.h>
|
||||
#include <EightBitCompilerDefinitions.h>
|
||||
@ -51,12 +52,22 @@ namespace EightBit {
|
||||
Signal<Z80> ExecutingInstruction;
|
||||
Signal<Z80> ExecutedInstruction;
|
||||
|
||||
Signal<EventArgs> RaisedNMI;
|
||||
Signal<EventArgs> LoweredNMI;
|
||||
|
||||
Signal<EventArgs> RaisedM1;
|
||||
Signal<EventArgs> LoweredM1;
|
||||
|
||||
[[nodiscard]] auto& NMI() { return m_nmiLine; } // In
|
||||
[[nodiscard]] auto& M1() { return m_m1Line; } // Out
|
||||
|
||||
int execute() final;
|
||||
int step() final;
|
||||
void powerOn() final;
|
||||
|
||||
void raisePOWER() final;
|
||||
|
||||
void raiseNMI();
|
||||
void lowerNMI();
|
||||
|
||||
[[nodiscard]] register16_t& AF() final;
|
||||
[[nodiscard]] register16_t& BC() final;
|
||||
@ -90,8 +101,8 @@ namespace EightBit {
|
||||
void handleINT() final;
|
||||
|
||||
private:
|
||||
PinLevel m_nmiLine = PinLevel::Low;
|
||||
PinLevel m_m1Line = PinLevel::Low;
|
||||
PinLevel m_nmiLine = PinLevel::Low; // In, Active low
|
||||
PinLevel m_m1Line = PinLevel::Low; // Out, Active low
|
||||
|
||||
InputOutput& m_ports;
|
||||
|
||||
@ -121,6 +132,9 @@ namespace EightBit {
|
||||
int8_t m_displacement = 0;
|
||||
bool m_displaced = false;
|
||||
|
||||
void raiseM1();
|
||||
void lowerM1();
|
||||
|
||||
void handleNMI();
|
||||
|
||||
[[nodiscard]] uint16_t displacedAddress() {
|
||||
|
@ -24,12 +24,11 @@ EightBit::register16_t& EightBit::Z80::HL() {
|
||||
return m_registers[m_registerSet][HL_IDX];
|
||||
}
|
||||
|
||||
void EightBit::Z80::powerOn() {
|
||||
void EightBit::Z80::raisePOWER() {
|
||||
|
||||
IntelProcessor::powerOn();
|
||||
IntelProcessor::raisePOWER();
|
||||
|
||||
raise(NMI());
|
||||
raise(M1());
|
||||
raiseM1();
|
||||
|
||||
di();
|
||||
IM() = 0;
|
||||
@ -46,6 +45,26 @@ void EightBit::Z80::powerOn() {
|
||||
m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
|
||||
}
|
||||
|
||||
void EightBit::Z80::raiseNMI() {
|
||||
raise(NMI());
|
||||
RaisedNMI.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::Z80::lowerNMI() {
|
||||
lower(NMI());
|
||||
LoweredNMI.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::Z80::raiseM1() {
|
||||
raise(M1());
|
||||
RaisedM1.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::Z80::lowerM1() {
|
||||
lower(M1());
|
||||
LoweredM1.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::Z80::handleRESET() {
|
||||
IntelProcessor::handleRESET();
|
||||
di();
|
||||
@ -53,8 +72,8 @@ void EightBit::Z80::handleRESET() {
|
||||
}
|
||||
|
||||
void EightBit::Z80::handleNMI() {
|
||||
raise(NMI());
|
||||
raise(HALT());
|
||||
raiseNMI();
|
||||
raiseHALT();
|
||||
IFF1() = false;
|
||||
restart(0x66);
|
||||
tick(13);
|
||||
@ -62,12 +81,12 @@ void EightBit::Z80::handleNMI() {
|
||||
|
||||
void EightBit::Z80::handleINT() {
|
||||
IntelProcessor::handleINT();
|
||||
raise(HALT());
|
||||
raiseHALT();
|
||||
if (IFF1()) {
|
||||
di();
|
||||
switch (IM()) {
|
||||
case 0: // i8080 equivalent
|
||||
Processor::execute(BUS().DATA());
|
||||
IntelProcessor::execute(BUS().DATA());
|
||||
break;
|
||||
case 1:
|
||||
restart(7 << 3);
|
||||
@ -663,7 +682,7 @@ int EightBit::Z80::step() {
|
||||
ExecutingInstruction.fire(*this);
|
||||
if (LIKELY(powered())) {
|
||||
m_displaced = m_prefixCB = m_prefixDD = m_prefixED = m_prefixFD = false;
|
||||
lower(M1());
|
||||
lowerM1();
|
||||
if (UNLIKELY(lowered(RESET()))) {
|
||||
handleRESET();
|
||||
} else if (UNLIKELY(lowered(NMI()))) {
|
||||
@ -671,9 +690,9 @@ int EightBit::Z80::step() {
|
||||
} else if (UNLIKELY(lowered(INT()))) {
|
||||
handleINT();
|
||||
} else if (UNLIKELY(lowered(HALT()))) {
|
||||
Processor::execute(0); // NOP
|
||||
IntelProcessor::execute(0); // NOP
|
||||
} else {
|
||||
Processor::execute(fetchByte());
|
||||
IntelProcessor::execute(fetchByte());
|
||||
}
|
||||
}
|
||||
ExecutedInstruction.fire(*this);
|
||||
@ -686,7 +705,7 @@ int EightBit::Z80::execute() {
|
||||
|
||||
if (LIKELY(!(m_prefixCB && m_displaced))) {
|
||||
++REFRESH();
|
||||
raise(M1());
|
||||
raiseM1();
|
||||
}
|
||||
|
||||
const auto& decoded = getDecodedOpcode(opcode());
|
||||
@ -1363,8 +1382,8 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
|
||||
m_prefixCB = true;
|
||||
if (UNLIKELY(m_displaced))
|
||||
fetchDisplacement();
|
||||
lower(M1());
|
||||
Processor::execute(fetchByte());
|
||||
lowerM1();
|
||||
IntelProcessor::execute(fetchByte());
|
||||
break;
|
||||
case 2: // OUT (n),A
|
||||
writePort(fetchByte());
|
||||
@ -1413,18 +1432,18 @@ void EightBit::Z80::executeOther(const int x, const int y, const int z, const in
|
||||
break;
|
||||
case 1: // DD prefix
|
||||
m_displaced = m_prefixDD = true;
|
||||
lower(M1());
|
||||
Processor::execute(fetchByte());
|
||||
lowerM1();
|
||||
IntelProcessor::execute(fetchByte());
|
||||
break;
|
||||
case 2: // ED prefix
|
||||
m_prefixED = true;
|
||||
lower(M1());
|
||||
Processor::execute(fetchByte());
|
||||
lowerM1();
|
||||
IntelProcessor::execute(fetchByte());
|
||||
break;
|
||||
case 3: // FD prefix
|
||||
m_displaced = m_prefixFD = true;
|
||||
lower(M1());
|
||||
Processor::execute(fetchByte());
|
||||
lowerM1();
|
||||
IntelProcessor::execute(fetchByte());
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE;
|
||||
|
@ -4,15 +4,17 @@
|
||||
Board::Board(const Configuration& configuration)
|
||||
: m_configuration(configuration) {}
|
||||
|
||||
void Board::powerOn() {
|
||||
EightBit::Bus::powerOn();
|
||||
CPU().powerOn();
|
||||
CPU().reset();
|
||||
void Board::raisePOWER() {
|
||||
EightBit::Bus::raisePOWER();
|
||||
CPU().raisePOWER();
|
||||
CPU().raiseRESET();
|
||||
CPU().raiseINT();
|
||||
CPU().raiseNMI();
|
||||
}
|
||||
|
||||
void Board::powerOff() noexcept {
|
||||
CPU().powerOff();
|
||||
EightBit::Bus::powerOff();
|
||||
void Board::lowerPOWER() noexcept {
|
||||
CPU().lowerPOWER();
|
||||
EightBit::Bus::lowerPOWER();
|
||||
}
|
||||
|
||||
void Board::initialise() {
|
||||
@ -20,13 +22,15 @@ void Board::initialise() {
|
||||
auto romDirectory = m_configuration.getRomDirectory();
|
||||
m_ram.load(romDirectory + "/zexall.com", 0x100); // Cringle/Bartholomew
|
||||
|
||||
m_cpu.LoweredHALT.connect([this](EightBit::EventArgs) {
|
||||
lowerPOWER();
|
||||
});
|
||||
|
||||
m_cpu.ExecutingInstruction.connect([this] (EightBit::Z80& cpu) {
|
||||
if (UNLIKELY(EightBit::Chip::lowered(cpu.HALT())))
|
||||
powerOff();
|
||||
switch (cpu.PC().word) {
|
||||
case 0x0: // CP/M warm start
|
||||
if (++m_warmstartCount == 3) {
|
||||
powerOff();
|
||||
if (++m_warmstartCount == 2) {
|
||||
lowerPOWER();
|
||||
if (m_configuration.isProfileMode())
|
||||
m_profiler.dump();
|
||||
}
|
||||
|
@ -18,11 +18,12 @@ public:
|
||||
|
||||
EightBit::Z80& CPU() noexcept { return m_cpu; }
|
||||
|
||||
void powerOn() final;
|
||||
void powerOff() noexcept final;
|
||||
void raisePOWER() final;
|
||||
void lowerPOWER() noexcept final;
|
||||
|
||||
void initialise() final;
|
||||
|
||||
protected:
|
||||
void initialise() final;
|
||||
EightBit::MemoryMapping mapping(uint16_t address) noexcept final {
|
||||
return { m_ram, 0x0000, 0xffff, EightBit::MemoryMapping::AccessLevel::ReadWrite };
|
||||
}
|
||||
|
@ -48,12 +48,12 @@ namespace EightBit {
|
||||
write(value);
|
||||
}
|
||||
|
||||
virtual void powerOn();
|
||||
virtual void powerOff();
|
||||
virtual void raisePOWER();
|
||||
virtual void lowerPOWER();
|
||||
|
||||
protected:
|
||||
virtual void initialise() = 0;
|
||||
|
||||
protected:
|
||||
[[nodiscard]] uint8_t& reference(uint16_t address);
|
||||
[[nodiscard]] auto& reference(const register16_t address) { return reference(address.word); }
|
||||
[[nodiscard]] uint8_t& reference() { return reference(ADDRESS()); }
|
||||
|
14
inc/Device.h
14
inc/Device.h
@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "EventArgs.h"
|
||||
#include "Signal.h"
|
||||
|
||||
namespace EightBit {
|
||||
class Device {
|
||||
public:
|
||||
@ -12,20 +15,21 @@ namespace EightBit {
|
||||
static constexpr auto lowered(const PinLevel line) { return line == PinLevel::Low; }
|
||||
static void lower(PinLevel& line) noexcept { line = PinLevel::Low; }
|
||||
|
||||
static void match(PinLevel& line, int value);
|
||||
|
||||
virtual ~Device() {};
|
||||
|
||||
Signal<EventArgs> RaisedPOWER;
|
||||
Signal<EventArgs> LoweredPOWER;
|
||||
|
||||
[[nodiscard]] auto& POWER() noexcept { return m_powerLine; }
|
||||
|
||||
[[nodiscard]] auto powered() noexcept { return raised(POWER()); }
|
||||
virtual void powerOn();
|
||||
virtual void powerOff() { lower(POWER()); }
|
||||
virtual void raisePOWER();
|
||||
virtual void lowerPOWER();
|
||||
|
||||
protected:
|
||||
Device() {};
|
||||
|
||||
private:
|
||||
PinLevel m_powerLine = PinLevel::Low;
|
||||
PinLevel m_powerLine = PinLevel::Low; // In
|
||||
};
|
||||
}
|
||||
|
@ -6,7 +6,8 @@
|
||||
#include "Bus.h"
|
||||
#include "LittleEndianProcessor.h"
|
||||
#include "Register.h"
|
||||
|
||||
#include "EventArgs.h"
|
||||
#include "Signal.h"
|
||||
#include "EightBitCompilerDefinitions.h"
|
||||
|
||||
namespace EightBit {
|
||||
@ -33,6 +34,11 @@ namespace EightBit {
|
||||
|
||||
~IntelProcessor() = default;
|
||||
|
||||
Signal<EventArgs> RaisedHALT;
|
||||
Signal<EventArgs> LoweredHALT;
|
||||
|
||||
[[nodiscard]] auto& HALT() noexcept { return m_haltLine; }
|
||||
|
||||
[[nodiscard]] const auto& getDecodedOpcode(const size_t i) const noexcept {
|
||||
return m_decodedOpcodes[i];
|
||||
}
|
||||
@ -57,7 +63,7 @@ namespace EightBit {
|
||||
[[nodiscard]] auto& H() { return HL().high; }
|
||||
[[nodiscard]] auto& L() { return HL().low; }
|
||||
|
||||
void powerOn() override;
|
||||
void raisePOWER() override;
|
||||
|
||||
protected:
|
||||
IntelProcessor(Bus& bus);
|
||||
@ -117,6 +123,8 @@ namespace EightBit {
|
||||
return m_halfCarryTableSub[index & Mask3];
|
||||
}
|
||||
|
||||
void handleRESET() override;
|
||||
|
||||
void push(uint8_t value) final;
|
||||
[[nodiscard]] uint8_t pop() final;
|
||||
|
||||
@ -164,9 +172,18 @@ namespace EightBit {
|
||||
|
||||
void ret() final;
|
||||
|
||||
[[nodiscard]] auto halted() noexcept { return lowered(HALT()); }
|
||||
void halt() noexcept { --PC(); lowerHALT(); }
|
||||
void proceed() noexcept { ++PC(); raiseHALT(); }
|
||||
|
||||
virtual void lowerHALT();
|
||||
virtual void raiseHALT();
|
||||
|
||||
private:
|
||||
std::array<opcode_decoded_t, 0x100> m_decodedOpcodes;
|
||||
register16_t m_sp = Mask16;
|
||||
register16_t m_memptr;
|
||||
|
||||
PinLevel m_haltLine = PinLevel::Low; // Out, Active low
|
||||
};
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "ClockedChip.h"
|
||||
#include "Bus.h"
|
||||
#include "Register.h"
|
||||
#include "EventArgs.h"
|
||||
#include "Signal.h"
|
||||
|
||||
#include "EightBitCompilerDefinitions.h"
|
||||
|
||||
@ -17,15 +19,22 @@ namespace EightBit {
|
||||
|
||||
~Processor() {};
|
||||
|
||||
Signal<EventArgs> RaisedRESET;
|
||||
Signal<EventArgs> LoweredRESET;
|
||||
|
||||
Signal<EventArgs> RaisedINT;
|
||||
Signal<EventArgs> LoweredINT;
|
||||
|
||||
[[nodiscard]] auto& PC() noexcept { return m_pc; }
|
||||
|
||||
[[nodiscard]] auto& RESET() noexcept { return m_resetLine; }
|
||||
[[nodiscard]] auto& HALT() noexcept { return m_haltLine; }
|
||||
[[nodiscard]] auto& INT() noexcept { return m_intLine; }
|
||||
[[nodiscard]] auto& IRQ() noexcept { return INT(); } // Synonym
|
||||
|
||||
void powerOn() override;
|
||||
void reset() noexcept { lower(RESET()); }
|
||||
virtual void lowerRESET();
|
||||
virtual void raiseRESET();
|
||||
|
||||
virtual void lowerINT();
|
||||
virtual void raiseINT();
|
||||
|
||||
int run(int limit);
|
||||
virtual int step() = 0;
|
||||
@ -41,13 +50,8 @@ namespace EightBit {
|
||||
[[nodiscard]] auto& opcode() noexcept { return m_opcode; }
|
||||
[[nodiscard]] auto& BUS() noexcept { return m_bus; }
|
||||
|
||||
[[nodiscard]] auto halted() noexcept { return lowered(HALT()); }
|
||||
void halt() noexcept { --PC(); lower(HALT()); }
|
||||
void proceed() noexcept { ++PC(); raise(HALT()); }
|
||||
|
||||
virtual void handleRESET();
|
||||
virtual void handleINT();
|
||||
virtual void handleIRQ();
|
||||
|
||||
void busWrite(register16_t address, uint8_t data);
|
||||
void busWrite(uint8_t data);
|
||||
@ -108,8 +112,7 @@ namespace EightBit {
|
||||
uint8_t m_opcode = Mask8;
|
||||
register16_t m_pc;
|
||||
|
||||
PinLevel m_intLine = PinLevel::Low;
|
||||
PinLevel m_haltLine = PinLevel::Low;
|
||||
PinLevel m_resetLine = PinLevel::Low;
|
||||
PinLevel m_intLine = PinLevel::Low; // In
|
||||
PinLevel m_resetLine = PinLevel::Low; // In
|
||||
};
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ namespace EightBit {
|
||||
m_totalCycles = m_instructions = 0L;
|
||||
m_startHostCycles = currentHostCycles();
|
||||
|
||||
m_board.powerOn();
|
||||
m_board.initialise();
|
||||
m_board.raisePOWER();
|
||||
|
||||
auto& cpu = m_board.CPU();
|
||||
|
||||
|
@ -8,11 +8,9 @@
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
void EightBit::Bus::powerOn() {
|
||||
initialise();
|
||||
}
|
||||
void EightBit::Bus::raisePOWER() {}
|
||||
|
||||
void EightBit::Bus::powerOff() {}
|
||||
void EightBit::Bus::lowerPOWER() {}
|
||||
|
||||
uint8_t EightBit::Bus::read() {
|
||||
ReadingByte.fire(EventArgs::empty());
|
||||
|
@ -1,10 +1,12 @@
|
||||
#include "stdafx.h"
|
||||
#include "Device.h"
|
||||
|
||||
void EightBit::Device::powerOn() {
|
||||
void EightBit::Device::raisePOWER() {
|
||||
raise(POWER());
|
||||
RaisedPOWER.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::Device::match(PinLevel& line, int value) {
|
||||
value ? raise(line) : lower(line);
|
||||
void EightBit::Device::lowerPOWER() {
|
||||
lower(POWER());
|
||||
LoweredPOWER.fire(EventArgs::empty());
|
||||
}
|
||||
|
@ -7,11 +7,27 @@ EightBit::IntelProcessor::IntelProcessor(Bus& bus)
|
||||
m_decodedOpcodes[i] = i;
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::powerOn() {
|
||||
Processor::powerOn();
|
||||
void EightBit::IntelProcessor::raisePOWER() {
|
||||
Processor::raisePOWER();
|
||||
raiseHALT();
|
||||
SP() = AF() = BC() = DE() = HL() = Mask16;
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::lowerHALT() {
|
||||
lower(HALT());
|
||||
LoweredHALT.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::raiseHALT() {
|
||||
raise(HALT());
|
||||
RaisedHALT.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::handleRESET() {
|
||||
Processor::handleRESET();
|
||||
PC() = 0;
|
||||
}
|
||||
|
||||
void EightBit::IntelProcessor::push(const uint8_t value) {
|
||||
BUS().write(--SP(), value);
|
||||
}
|
||||
|
@ -5,24 +5,32 @@ EightBit::Processor::Processor(Bus& bus)
|
||||
: m_bus(bus) {
|
||||
}
|
||||
|
||||
void EightBit::Processor::powerOn() {
|
||||
Chip::powerOn();
|
||||
void EightBit::Processor::lowerRESET() {
|
||||
lower(RESET());
|
||||
LoweredRESET.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::Processor::raiseRESET() {
|
||||
raise(RESET());
|
||||
raise(HALT());
|
||||
RaisedRESET.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::Processor::lowerINT() {
|
||||
lower(INT());
|
||||
LoweredINT.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::Processor::raiseINT() {
|
||||
raise(INT());
|
||||
RaisedINT.fire(EventArgs::empty());
|
||||
}
|
||||
|
||||
void EightBit::Processor::handleRESET() {
|
||||
raise(RESET());
|
||||
PC() = 0;
|
||||
raiseRESET();
|
||||
}
|
||||
|
||||
void EightBit::Processor::handleINT() {
|
||||
raise(INT());
|
||||
}
|
||||
|
||||
void EightBit::Processor::handleIRQ() {
|
||||
raise(IRQ());
|
||||
raiseINT();
|
||||
}
|
||||
|
||||
void EightBit::Processor::busWrite(const register16_t address, const uint8_t data) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user