Have a stab at sorting out processor pin handling.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2018-08-25 12:09:26 +01:00
parent 17c46264e9
commit c105ee37bf
14 changed files with 110 additions and 100 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -31,8 +31,5 @@
<ClCompile Include="Board.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Configuration.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

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

View File

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

View File

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

View File

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

View File

@ -51,7 +51,7 @@ void EightBit::Z80::handleRESET() {
}
void EightBit::Z80::handleNMI() {
Processor::handleNMI();
raise(NMI());
raise(HALT());
IFF1() = false;
restart(0x66);

View File

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

View File

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