mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-03-13 07:33:34 +00:00
Have a stab at sorting out processor pin handling.
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
parent
17c46264e9
commit
c105ee37bf
@ -39,10 +39,12 @@ namespace EightBit {
|
||||
uint8_t& S() { return s; }
|
||||
uint8_t& P() { return p; }
|
||||
|
||||
PinLevel& NMI() { return m_nmiLine; } // In
|
||||
PinLevel& SO() { return m_soLine; } // In
|
||||
|
||||
protected:
|
||||
virtual void reset() final;
|
||||
virtual void handleRESET() final;
|
||||
virtual void handleIRQ() final;
|
||||
|
||||
virtual uint8_t SUB(uint8_t operand, uint8_t data, int borrow = 0);
|
||||
uint8_t SBC(uint8_t operand, uint8_t data);
|
||||
@ -55,6 +57,10 @@ namespace EightBit {
|
||||
uint8_t ADD_d(uint8_t operand, uint8_t data, int carry);
|
||||
|
||||
private:
|
||||
void handleNMI();
|
||||
void handleSO();
|
||||
void handleHALT();
|
||||
|
||||
void interrupt(uint8_t vector);
|
||||
|
||||
void adjustZero(uint8_t datum) { clearFlag(P(), ZF, datum); }
|
||||
@ -324,6 +330,7 @@ namespace EightBit {
|
||||
uint8_t s = 0; // stack pointer
|
||||
uint8_t p = 0; // processor status
|
||||
|
||||
PinLevel m_nmiLine = Low;
|
||||
PinLevel m_soLine = Low;
|
||||
|
||||
register16_t m_intermediate;
|
||||
|
@ -17,37 +17,56 @@ void EightBit::MOS6502::powerOn() {
|
||||
raise(SO());
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::handleSO() {
|
||||
raise(SO());
|
||||
P() |= VF;
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::handleRESET() {
|
||||
Processor::handleRESET();
|
||||
jump(getWordPaged(0xff, RSTvector));
|
||||
addCycles(4); // ?? TBC
|
||||
}
|
||||
|
||||
|
||||
void EightBit::MOS6502::handleNMI() {
|
||||
raise(NMI());
|
||||
interrupt(NMIvector);
|
||||
addCycles(4); // ?? TBC
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::handleIRQ() {
|
||||
Processor::handleIRQ();
|
||||
interrupt(IRQvector);
|
||||
addCycles(4); // ?? TBC
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::handleHALT() {
|
||||
execute(0xea); // NOP
|
||||
addCycles(2);
|
||||
}
|
||||
|
||||
int EightBit::MOS6502::step() {
|
||||
resetCycles();
|
||||
auto returned = 0;
|
||||
if (LIKELY(powered())) {
|
||||
ExecutingInstruction.fire(*this);
|
||||
if (UNLIKELY(lowered(SO()))) {
|
||||
P() |= VF;
|
||||
raise(SO());
|
||||
handleSO();
|
||||
}
|
||||
if (UNLIKELY(lowered(NMI()))) {
|
||||
raise(NMI());
|
||||
interrupt(NMIvector);
|
||||
returned = 4; // ?? TBC
|
||||
} else if (UNLIKELY(lowered(INT()))) {
|
||||
raise(INT());
|
||||
interrupt(IRQvector);
|
||||
returned = 4; // ?? TBC
|
||||
if (lowered(RESET())) {
|
||||
handleRESET();
|
||||
} else if (UNLIKELY(lowered(NMI()))) {
|
||||
handleNMI();
|
||||
} else if (UNLIKELY(lowered(IRQ()))) {
|
||||
handleIRQ();
|
||||
} else if (UNLIKELY(lowered(HALT()))) {
|
||||
execute(0xea); // NOP
|
||||
returned = 2; //
|
||||
handleHALT();
|
||||
} else {
|
||||
returned = execute(fetchByte());
|
||||
execute(fetchByte());
|
||||
}
|
||||
ExecutedInstruction.fire(*this);
|
||||
}
|
||||
return returned;
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::reset() {
|
||||
Processor::reset();
|
||||
jump(getWordPaged(0xff, RSTvector));
|
||||
return cycles();
|
||||
}
|
||||
|
||||
void EightBit::MOS6502::interrupt(uint8_t vector) {
|
||||
|
@ -21,7 +21,7 @@ void Board::initialise() {
|
||||
|
||||
switch (m_configuration.getLoadMethod()) {
|
||||
case Configuration::LoadMethod::Ram:
|
||||
m_ram.load(programPath, loadAddress);
|
||||
m_ram.load(programPath, loadAddress.word);
|
||||
break;
|
||||
case Configuration::LoadMethod::Rom:
|
||||
// m_rom.load(programPath, loadAddress);
|
||||
@ -58,7 +58,10 @@ void Board::initialise() {
|
||||
m_pollInterval = m_configuration.getPollInterval();
|
||||
|
||||
CPU().powerOn();
|
||||
CPU().PC().word = m_configuration.getStartAddress();
|
||||
|
||||
poke(0x00, 0x4c);
|
||||
poke(0x01, m_configuration.getStartAddress().low);
|
||||
poke(0x02, m_configuration.getStartAddress().high);
|
||||
}
|
||||
|
||||
void Board::Cpu_ExecutingInstruction_Profile(const EightBit::MOS6502& cpu) {
|
||||
@ -101,14 +104,14 @@ void Board::Cpu_ExecutingInstruction_Debug(EightBit::MOS6502& cpu) {
|
||||
}
|
||||
|
||||
void Board::Memory_ReadingByte_Input(EightBit::EventArgs) {
|
||||
if (ADDRESS().word == m_configuration.getInputAddress()) {
|
||||
if (ADDRESS().word == m_configuration.getInputAddress().word) {
|
||||
if (!!DATA())
|
||||
write(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Board::Memory_WrittenByte_Output(EightBit::EventArgs) {
|
||||
if (ADDRESS().word == m_configuration.getOutputAddress()) {
|
||||
if (ADDRESS().word == m_configuration.getOutputAddress().word) {
|
||||
#ifdef _MSC_VER
|
||||
_putch(DATA());
|
||||
#endif
|
||||
@ -125,6 +128,6 @@ void Board::Cpu_ExecutedInstruction_Poll(const EightBit::MOS6502& cpu) {
|
||||
void Board::pollKeyboard() {
|
||||
#ifdef _MSC_VER
|
||||
if (_kbhit())
|
||||
poke(m_configuration.getInputAddress(), _getch());
|
||||
poke(m_configuration.getInputAddress().word, _getch());
|
||||
#endif
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "Configuration.h"
|
||||
|
||||
Configuration::Configuration()
|
||||
: m_debugMode(false),
|
||||
m_profileMode(false),
|
||||
m_loadAddress(0x400),
|
||||
m_startAddress(0x400),
|
||||
m_allowInput(false),
|
||||
m_inputAddress(0xbff0),
|
||||
m_allowOutput(false),
|
||||
m_outputAddress(0xbff0),
|
||||
m_pollInterval(2000000 / 50), // 2Mhz, 50 times a second;
|
||||
m_stopCondition(StopCondition::Loop),
|
||||
m_romDirectory("roms"),
|
||||
m_program("6502_functional_test.bin"),
|
||||
m_loadMethod(LoadMethod::Ram) {
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <Register.h>
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
@ -15,7 +16,7 @@ public:
|
||||
Rom
|
||||
};
|
||||
|
||||
Configuration();
|
||||
Configuration() = default;
|
||||
|
||||
bool isDebugMode() const { return m_debugMode; }
|
||||
void setDebugMode(bool value) { m_debugMode = value; }
|
||||
@ -23,14 +24,14 @@ public:
|
||||
bool isProfileMode() const { return m_profileMode; }
|
||||
void setProfileMode(bool value) { m_profileMode = value; }
|
||||
|
||||
uint16_t getLoadAddress() const { return m_loadAddress; }
|
||||
uint16_t getStartAddress() const { return m_startAddress; }
|
||||
EightBit::register16_t getLoadAddress() const { return m_loadAddress; }
|
||||
EightBit::register16_t getStartAddress() const { return m_startAddress; }
|
||||
|
||||
bool allowInput() const { return m_allowInput; }
|
||||
uint16_t getInputAddress() const { return m_inputAddress; }
|
||||
EightBit::register16_t getInputAddress() const { return m_inputAddress; }
|
||||
|
||||
bool allowOutput() const { return m_allowOutput; }
|
||||
uint16_t getOutputAddress() const { return m_outputAddress; }
|
||||
EightBit::register16_t getOutputAddress() const { return m_outputAddress; }
|
||||
|
||||
uint64_t getPollInterval() const { return m_pollInterval; }
|
||||
|
||||
@ -42,17 +43,17 @@ public:
|
||||
LoadMethod getLoadMethod() const { return m_loadMethod; }
|
||||
|
||||
private:
|
||||
bool m_debugMode;
|
||||
bool m_profileMode;
|
||||
uint16_t m_loadAddress;
|
||||
uint16_t m_startAddress;
|
||||
bool m_allowInput;
|
||||
uint16_t m_inputAddress;
|
||||
bool m_allowOutput;
|
||||
uint16_t m_outputAddress;
|
||||
uint64_t m_pollInterval;
|
||||
StopCondition m_stopCondition;
|
||||
std::string m_romDirectory;
|
||||
std::string m_program;
|
||||
LoadMethod m_loadMethod;
|
||||
bool m_debugMode = false;
|
||||
bool m_profileMode = false;
|
||||
EightBit::register16_t m_loadAddress = 0x400;
|
||||
EightBit::register16_t m_startAddress = 0x400;
|
||||
bool m_allowInput = false;
|
||||
EightBit::register16_t m_inputAddress = 0xbff0;
|
||||
bool m_allowOutput = false;
|
||||
EightBit::register16_t m_outputAddress = 0xbff0;
|
||||
uint64_t m_pollInterval = 2000000 / 50;
|
||||
StopCondition m_stopCondition = StopCondition::Loop;
|
||||
std::string m_romDirectory = "roms";
|
||||
std::string m_program = "6502_functional_test.bin";
|
||||
LoadMethod m_loadMethod = LoadMethod::Ram;
|
||||
};
|
||||
|
@ -154,7 +154,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Board.cpp" />
|
||||
<ClCompile Include="Configuration.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
|
@ -31,8 +31,5 @@
|
||||
<ClCompile Include="Board.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Configuration.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -70,10 +70,11 @@ namespace EightBit {
|
||||
uint8_t& DP() { return m_dp; }
|
||||
uint8_t& CC() { return m_cc; }
|
||||
|
||||
PinLevel& IRQ() { return INT(); }
|
||||
PinLevel& FIRQ() { return m_firq; }
|
||||
PinLevel& NMI() { return m_nmiLine; } // In
|
||||
PinLevel& FIRQ() { return m_firqLine; } // In
|
||||
|
||||
protected:
|
||||
virtual void powerOn() final;
|
||||
|
||||
// Default push/pop handlers
|
||||
|
||||
@ -83,7 +84,7 @@ namespace EightBit {
|
||||
// Interrupt (etc.) handlers
|
||||
|
||||
virtual void handleRESET() final;
|
||||
virtual void handleNMI() final;
|
||||
virtual void handleIRQ() final;
|
||||
|
||||
private:
|
||||
const uint8_t RESETvector = 0xfe; // RESET vector
|
||||
@ -124,7 +125,7 @@ namespace EightBit {
|
||||
|
||||
// Interrupt (etc.) handlers
|
||||
|
||||
void handleIRQ();
|
||||
void handleNMI();
|
||||
void handleFIRQ();
|
||||
|
||||
// Execution helpers
|
||||
@ -322,7 +323,8 @@ namespace EightBit {
|
||||
uint8_t m_dp;
|
||||
uint8_t m_cc;
|
||||
|
||||
PinLevel m_firq;
|
||||
PinLevel m_nmiLine = Low;
|
||||
PinLevel m_firqLine = Low;
|
||||
|
||||
bool m_prefix10 = false;
|
||||
bool m_prefix11 = false;
|
||||
|
@ -7,6 +7,12 @@
|
||||
EightBit::mc6809::mc6809(Bus& bus)
|
||||
: BigEndianProcessor(bus) {}
|
||||
|
||||
void EightBit::mc6809::powerOn() {
|
||||
Processor::powerOn();
|
||||
raise(NMI());
|
||||
raise(FIRQ());
|
||||
}
|
||||
|
||||
int EightBit::mc6809::step() {
|
||||
resetCycles();
|
||||
if (LIKELY(powered())) {
|
||||
@ -33,21 +39,21 @@ void EightBit::mc6809::handleRESET() {
|
||||
Processor::handleRESET();
|
||||
raise(NMI());
|
||||
DP() = 0;
|
||||
setFlag(CC(), IF | FF);
|
||||
setFlag(CC(), IF | FF); // Disable all IRQs
|
||||
jump(getWordPaged(0xff, RESETvector));
|
||||
}
|
||||
|
||||
void EightBit::mc6809::handleNMI() {
|
||||
Processor::handleNMI();
|
||||
raise(NMI());
|
||||
saveEntireRegisterState();
|
||||
jump(getWordPaged(0xff, NMIvector));
|
||||
addCycles(21);
|
||||
}
|
||||
|
||||
void EightBit::mc6809::handleIRQ() {
|
||||
Processor::handleINT(); // Synonymous
|
||||
Processor::handleIRQ();
|
||||
saveEntireRegisterState();
|
||||
setFlag(CC(), IF);
|
||||
setFlag(CC(), IF); // Disable IRQ
|
||||
jump(getWordPaged(0xff, IRQvector));
|
||||
addCycles(21);
|
||||
}
|
||||
@ -57,7 +63,7 @@ void EightBit::mc6809::handleFIRQ() {
|
||||
clearFlag(CC(), EF);
|
||||
pushWordS(PC());
|
||||
pushS(CC());
|
||||
setFlag(CC(), IF | FF);
|
||||
setFlag(CC(), IF | FF); // Disable all IRQs
|
||||
jump(getWordPaged(0xff, FIRQvector));
|
||||
addCycles(12);
|
||||
}
|
||||
@ -65,17 +71,12 @@ void EightBit::mc6809::handleFIRQ() {
|
||||
//
|
||||
|
||||
int EightBit::mc6809::execute(uint8_t opcode) {
|
||||
const bool prefixed = m_prefix10 || m_prefix11;
|
||||
if (LIKELY(!prefixed)) {
|
||||
if (m_prefix10)
|
||||
execute10(opcode);
|
||||
else if (m_prefix11)
|
||||
execute11(opcode);
|
||||
else
|
||||
executeUnprefixed(opcode);
|
||||
} else {
|
||||
if (m_prefix10)
|
||||
execute10(opcode);
|
||||
else if (m_prefix11)
|
||||
execute11(opcode);
|
||||
else
|
||||
UNREACHABLE;
|
||||
}
|
||||
assert(cycles() > 0);
|
||||
return cycles();
|
||||
}
|
||||
|
@ -10,8 +10,6 @@ namespace EightBit {
|
||||
Ricoh2A03(Bus& bus);
|
||||
virtual ~Ricoh2A03() = default;
|
||||
|
||||
int clockCycles() const { return cycles(); }
|
||||
|
||||
protected:
|
||||
virtual uint8_t SUB(uint8_t operand, uint8_t data, int borrow) final;
|
||||
virtual uint8_t ADD(uint8_t operand, uint8_t data, int carry) final;
|
||||
|
@ -51,6 +51,7 @@ namespace EightBit {
|
||||
Signal<Z80> ExecutingInstruction;
|
||||
Signal<Z80> ExecutedInstruction;
|
||||
|
||||
PinLevel& NMI() { return m_nmiLine; } // In
|
||||
PinLevel& M1() { return m_m1Line; } // Out
|
||||
|
||||
virtual int execute(uint8_t opcode) final;
|
||||
@ -86,10 +87,10 @@ namespace EightBit {
|
||||
|
||||
protected:
|
||||
virtual void handleRESET() final;
|
||||
virtual void handleNMI() final;
|
||||
virtual void handleINT() final;
|
||||
|
||||
private:
|
||||
PinLevel m_nmiLine = Low;
|
||||
PinLevel m_m1Line = Low;
|
||||
|
||||
InputOutput& m_ports;
|
||||
@ -120,6 +121,8 @@ namespace EightBit {
|
||||
int8_t m_displacement = 0;
|
||||
bool m_displaced = false;
|
||||
|
||||
void handleNMI();
|
||||
|
||||
uint16_t displacedAddress() {
|
||||
assert(m_displaced);
|
||||
return MEMPTR().word = (m_prefixDD ? IX() : IY()).word + m_displacement;
|
||||
|
@ -51,7 +51,7 @@ void EightBit::Z80::handleRESET() {
|
||||
}
|
||||
|
||||
void EightBit::Z80::handleNMI() {
|
||||
Processor::handleNMI();
|
||||
raise(NMI());
|
||||
raise(HALT());
|
||||
IFF1() = false;
|
||||
restart(0x66);
|
||||
|
@ -74,7 +74,7 @@ namespace EightBit {
|
||||
PinLevel& RESET() { return m_resetLine; }
|
||||
PinLevel& HALT() { return m_haltLine; }
|
||||
PinLevel& INT() { return m_intLine; }
|
||||
PinLevel& NMI() { return m_nmiLine; }
|
||||
PinLevel& IRQ() { return INT(); } // Synonym
|
||||
PinLevel& POWER() { return m_powerLine; }
|
||||
|
||||
bool powered() { return raised(POWER()); }
|
||||
@ -84,9 +84,10 @@ namespace EightBit {
|
||||
|
||||
int run(int limit);
|
||||
virtual int step() = 0;
|
||||
|
||||
virtual int execute(uint8_t opcode) = 0;
|
||||
|
||||
int cycles() const { return m_cycles; }
|
||||
|
||||
protected:
|
||||
static void clearFlag(uint8_t& f, const int flag) { f &= ~flag; }
|
||||
static void setFlag(uint8_t& f, const int flag) { f |= flag; }
|
||||
@ -107,8 +108,8 @@ namespace EightBit {
|
||||
void proceed() { ++PC(); raise(HALT()); }
|
||||
|
||||
virtual void handleRESET();
|
||||
virtual void handleNMI();
|
||||
virtual void handleINT();
|
||||
virtual void handleIRQ();
|
||||
|
||||
uint8_t getBytePaged(uint8_t page, uint8_t offset) {
|
||||
return BUS().read(register16_t(offset, page));
|
||||
@ -159,7 +160,6 @@ namespace EightBit {
|
||||
jump(popWord());
|
||||
}
|
||||
|
||||
int cycles() const { return m_cycles; }
|
||||
void resetCycles() { m_cycles = 0; }
|
||||
void addCycles(const int extra) { m_cycles += extra; }
|
||||
void addCycle() { ++m_cycles; }
|
||||
@ -170,7 +170,6 @@ namespace EightBit {
|
||||
register16_t m_pc;
|
||||
|
||||
PinLevel m_intLine = Low;
|
||||
PinLevel m_nmiLine = Low;
|
||||
PinLevel m_haltLine = Low;
|
||||
PinLevel m_resetLine = Low;
|
||||
PinLevel m_powerLine = Low;
|
||||
|
@ -9,7 +9,6 @@ void EightBit::Processor::powerOn() {
|
||||
raise(RESET());
|
||||
raise(HALT());
|
||||
raise(INT());
|
||||
raise(NMI());
|
||||
raise(POWER());
|
||||
}
|
||||
|
||||
@ -18,14 +17,14 @@ void EightBit::Processor::handleRESET() {
|
||||
PC() = 0;
|
||||
}
|
||||
|
||||
void EightBit::Processor::handleNMI() {
|
||||
raise(NMI());
|
||||
}
|
||||
|
||||
void EightBit::Processor::handleINT() {
|
||||
raise(INT());
|
||||
}
|
||||
|
||||
void EightBit::Processor::handleIRQ() {
|
||||
raise(IRQ());
|
||||
}
|
||||
|
||||
int EightBit::Processor::run(const int limit) {
|
||||
int current = 0;
|
||||
while (LIKELY(powered()) && current < limit)
|
||||
|
Loading…
x
Reference in New Issue
Block a user