1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-23 20:29:42 +00:00

Introduces 6502Selector, for picking either a 6502 or a 65816 based on a single template parameter.

This commit is contained in:
Thomas Harte 2020-09-28 21:35:46 -04:00
parent 6635876e7e
commit ef1a514785
13 changed files with 156 additions and 41 deletions

View File

@ -424,8 +424,8 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
!tape_player_.get_tape()->is_at_end()) {
uint8_t next_byte = tape_player_.get_next_byte(!ram_[tape_speed_address_]);
m6502_.set_value_of_register(CPU::MOS6502::A, next_byte);
m6502_.set_value_of_register(CPU::MOS6502::Flags, next_byte ? 0 : CPU::MOS6502::Flag::Zero);
m6502_.set_value_of_register(CPU::MOS6502Esque::A, next_byte);
m6502_.set_value_of_register(CPU::MOS6502Esque::Flags, next_byte ? 0 : CPU::MOS6502::Flag::Zero);
*value = 0x60; // i.e. RTS
}
} else {

View File

@ -210,6 +210,9 @@
4B4B1A3D200198CA00A0F866 /* KonamiSCC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4B1A3A200198C900A0F866 /* KonamiSCC.cpp */; };
4B4DC8211D2C2425003C5BF8 /* Vic20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */; };
4B4DC82B1D2C27A4003C5BF8 /* SerialBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */; };
4B4DEBED2522C03F004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEBEC2522C03F004583AC /* 65816Base.cpp */; };
4B4DEBEE2522C03F004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEBEC2522C03F004583AC /* 65816Base.cpp */; };
4B4DEBEF2522C03F004583AC /* 65816Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DEBEC2522C03F004583AC /* 65816Base.cpp */; };
4B50AF80242817F40099BBD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B50AF7F242817F40099BBD7 /* QuartzCore.framework */; };
4B54C0BC1F8D8E790050900F /* KeyboardMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BB1F8D8E790050900F /* KeyboardMachine.cpp */; };
4B54C0BF1F8D8F450050900F /* Keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B54C0BD1F8D8F450050900F /* Keyboard.cpp */; };
@ -1119,6 +1122,7 @@
4B4DC8271D2C2470003C5BF8 /* C1540.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = C1540.hpp; sourceTree = "<group>"; };
4B4DC8291D2C27A4003C5BF8 /* SerialBus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SerialBus.cpp; sourceTree = "<group>"; };
4B4DC82A1D2C27A4003C5BF8 /* SerialBus.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SerialBus.hpp; sourceTree = "<group>"; };
4B4DEBEC2522C03F004583AC /* 65816Base.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = 65816Base.cpp; path = ../../Processors/65816/Implementation/65816Base.cpp; sourceTree = "<group>"; };
4B4F2B7024DF99D4000DA6B0 /* CSScanTarget+CppScanTarget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CSScanTarget+CppScanTarget.h"; sourceTree = "<group>"; };
4B50AF7F242817F40099BBD7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
4B51F70920A521D700AFA2C1 /* Source.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Source.hpp; sourceTree = "<group>"; };
@ -1344,6 +1348,7 @@
4BAF2B4D2004580C00480230 /* DMK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DMK.hpp; sourceTree = "<group>"; };
4BB023FF25212888009F8D90 /* 65816Implementation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = 65816Implementation.hpp; path = ../../Processors/65816/Implementation/65816Implementation.hpp; sourceTree = "<group>"; };
4BB0240425229C6E009F8D90 /* 6502Esque.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = 6502Esque.hpp; sourceTree = "<group>"; };
4BB024092522B7BE009F8D90 /* 6502Selector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = 6502Selector.hpp; sourceTree = "<group>"; };
4BB06B211F316A3F00600C7A /* ForceInline.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ForceInline.hpp; sourceTree = "<group>"; };
4BB0A6592044FD3000FB3688 /* SN76489.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SN76489.cpp; sourceTree = "<group>"; };
4BB0A65A2044FD3000FB3688 /* SN76489.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SN76489.hpp; sourceTree = "<group>"; };
@ -3332,6 +3337,7 @@
4BB73E951B587A5100552FC2 = {
isa = PBXGroup;
children = (
4B4DEBEC2522C03F004583AC /* 65816Base.cpp */,
4BB023FF25212888009F8D90 /* 65816Implementation.hpp */,
4B51F70820A521D700AFA2C1 /* Activity */,
4B8944E2201967B4007DE474 /* Analyser */,
@ -3491,6 +3497,7 @@
children = (
4BFCA1211ECBDCAF00AC40C1 /* AllRAMProcessor.cpp */,
4BB0240425229C6E009F8D90 /* 6502Esque.hpp */,
4BB024092522B7BE009F8D90 /* 6502Selector.hpp */,
4BFCA1221ECBDCAF00AC40C1 /* AllRAMProcessor.hpp */,
4B2C455C1EC9442600FC74DD /* RegisterSizes.hpp */,
4B1414561B58879D00E04248 /* 6502 */,
@ -4496,6 +4503,7 @@
4BDACBED22FFA5D20045EF7E /* ncr5380.cpp in Sources */,
4BC131772346DE9100E4FF3D /* StaticAnalyser.cpp in Sources */,
4B055ACF1FAE9B030060FFFF /* SoundGenerator.cpp in Sources */,
4B4DEBEF2522C03F004583AC /* 65816Base.cpp in Sources */,
4B894519201967B4007DE474 /* ConfidenceCounter.cpp in Sources */,
4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */,
4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */,
@ -4778,6 +4786,7 @@
4BEBFB4D2002C4BF000708CC /* MSXDSK.cpp in Sources */,
4BBFBB6C1EE8401E00C01E7A /* ZX8081.cpp in Sources */,
4B83348A1F5DB94B0097E338 /* IRQDelegatePortHandler.cpp in Sources */,
4B4DEBED2522C03F004583AC /* 65816Base.cpp in Sources */,
4B894524201967B4007DE474 /* Tape.cpp in Sources */,
4B7136891F78725F008B8ED9 /* Shifter.cpp in Sources */,
4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */,
@ -4925,6 +4934,7 @@
4B778F4123A5F19A0000D260 /* MemoryPacker.cpp in Sources */,
4B778F4423A5F1BE0000D260 /* CommodoreGCR.cpp in Sources */,
4B778EF923A5EB740000D260 /* MSA.cpp in Sources */,
4B4DEBEE2522C03F004583AC /* 65816Base.cpp in Sources */,
4B778F2323A5EDE40000D260 /* Tape.cpp in Sources */,
4B778F4F23A5F21C0000D260 /* StaticAnalyser.cpp in Sources */,
4B778EEF23A5D6680000D260 /* AsyncTaskQueue.cpp in Sources */,

View File

@ -42,14 +42,13 @@ static CPU::MOS6502::Register registerForRegister(CSTestMachine6502Register reg)
if(self) {
switch(processor) {
case CSTestMachine6502Processor6502:
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502::Personality::P6502);
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::T6502);
break;
case CSTestMachine6502Processor65C02:
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502::Personality::PWDC65C02);
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::TWDC65C02);
break;
default:
assert(false); // TODO
case CSTestMachine6502Processor65816:
_processor = CPU::MOS6502::AllRAMProcessor::Processor(CPU::MOS6502Esque::Type::TWDC65816);
}
}

View File

@ -22,19 +22,7 @@ namespace MOS6502 {
using BusOperation = CPU::MOS6502Esque::BusOperation;
using BusHandler = CPU::MOS6502Esque::BusHandler<uint16_t>;
/*
The list of registers that can be accessed via @c set_value_of_register and @c set_value_of_register.
*/
enum Register {
LastOperationAddress,
ProgramCounter,
StackPointer,
Flags,
A,
X,
Y
};
using Register = CPU::MOS6502Esque::Register;
/*
The list of 6502 variants supported by this implementation.

View File

@ -15,7 +15,9 @@ using namespace CPU::MOS6502;
namespace {
template <Personality personality> class ConcreteAllRAMProcessor: public AllRAMProcessor, public BusHandler {
using Type = CPU::MOS6502Esque::Type;
template <Type type> class ConcreteAllRAMProcessor: public AllRAMProcessor, public BusHandler {
public:
ConcreteAllRAMProcessor() :
mos6502_(*this) {
@ -63,20 +65,21 @@ template <Personality personality> class ConcreteAllRAMProcessor: public AllRAMP
}
private:
CPU::MOS6502::Processor<personality, ConcreteAllRAMProcessor, false> mos6502_;
CPU::MOS6502Esque::Processor<type, ConcreteAllRAMProcessor, false> mos6502_;
};
}
AllRAMProcessor *AllRAMProcessor::Processor(Personality personality) {
AllRAMProcessor *AllRAMProcessor::Processor(Type type) {
#define Bind(p) case p: return new ConcreteAllRAMProcessor<p>();
switch(personality) {
switch(type) {
default:
Bind(Personality::P6502)
Bind(Personality::PNES6502)
Bind(Personality::PSynertek65C02)
Bind(Personality::PWDC65C02)
Bind(Personality::PRockwell65C02)
Bind(Type::T6502)
Bind(Type::TNES6502)
Bind(Type::TSynertek65C02)
Bind(Type::TWDC65C02)
Bind(Type::TRockwell65C02)
Bind(Type::TWDC65816)
}
#undef Bind
}

View File

@ -9,7 +9,7 @@
#ifndef MOS6502AllRAM_cpp
#define MOS6502AllRAM_cpp
#include "../6502.hpp"
#include "../../6502Selector.hpp"
#include "../../AllRAMProcessor.hpp"
namespace CPU {
@ -17,9 +17,8 @@ namespace MOS6502 {
class AllRAMProcessor:
public ::CPU::AllRAMProcessor {
public:
static AllRAMProcessor *Processor(Personality personality);
static AllRAMProcessor *Processor(CPU::MOS6502Esque::Type type);
virtual ~AllRAMProcessor() {}
virtual void run_for(const Cycles cycles) = 0;

View File

@ -8,8 +8,6 @@
#include "../6502.hpp"
#include <cassert>
using namespace CPU::MOS6502;
const uint8_t CPU::MOS6502::JamOpcode = 0xf2;

View File

@ -22,6 +22,19 @@
namespace CPU {
namespace MOS6502Esque {
/*
The list of registers that can be accessed via @c set_value_of_register and @c set_value_of_register.
*/
enum Register {
LastOperationAddress,
ProgramCounter,
StackPointer,
Flags,
A,
X,
Y
};
/*!
Bus handlers will be given the task of performing bus operations, allowing them to provide whatever interface they like
between a 6502 and the rest of the system. @c BusOperation lists the types of bus operation that may be requested.

View File

@ -0,0 +1,46 @@
//
// 6502Selector.hpp
// Clock Signal
//
// Created by Thomas Harte on 28/09/2020.
// Copyright © 2020 Thomas Harte. All rights reserved.
//
#ifndef _502Selector_h
#define _502Selector_h
#include "6502/6502.hpp"
#include "65816/65816.hpp"
namespace CPU {
namespace MOS6502Esque {
enum class Type {
TNES6502, // the NES's 6502, which is like a 6502 but lacks decimal mode (though it retains the decimal flag)
T6502, // the original [NMOS] 6502, replete with various undocumented instructions
TSynertek65C02, // a 6502 extended with BRA, P[H/L][X/Y], STZ, TRB, TSB and the (zp) addressing mode and a few other additions
TRockwell65C02, // like the Synertek, but with BBR, BBS, RMB and SMB
TWDC65C02, // like the Rockwell, but with STP and WAI
TWDC65816, // the slightly 16-bit follow-up to the 6502
};
/*
Machines that can use either a 6502 or a 65816 can use CPU::MOS6502Esque::Processor in order to select the proper
class in much the same way that a raw user of CPU::MOS6502::Processor would set the personality. Just provide one
of the type enums as above as the appropriate template parameter.
*/
template <Type processor_type, typename BusHandler, bool uses_ready_line> class Processor:
public CPU::MOS6502::Processor<CPU::MOS6502::Personality(processor_type), BusHandler, uses_ready_line> {
using CPU::MOS6502::Processor<CPU::MOS6502::Personality(processor_type), BusHandler, uses_ready_line>::Processor;
};
template <typename BusHandler, bool uses_ready_line> class Processor<Type::TWDC65816, BusHandler, uses_ready_line>:
public CPU::WDC65816::Processor<BusHandler> {
using CPU::WDC65816::Processor<BusHandler>::Processor;
};
}
}
#endif /* _502Selector_h */

View File

@ -14,16 +14,30 @@
#include "../RegisterSizes.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../6502Esque.hpp"
namespace CPU {
namespace WDC65816 {
using BusOperation = CPU::MOS6502Esque::BusOperation;
using Register = CPU::MOS6502Esque::Register;
#include "Implementation/65816Storage.hpp"
template <typename BusHandler> class Processor: private ProcessorStorage {
class ProcessorBase: protected ProcessorStorage {
public:
inline void set_power_on(bool);
inline void set_irq_line(bool);
inline void set_nmi_line(bool);
void set_value_of_register(Register r, uint16_t value);
inline bool is_jammed() const;
uint16_t get_value_of_register(Register r) const;
};
template <typename BusHandler> class Processor: public ProcessorBase {
public:
Processor(BusHandler &bus_handler) : bus_handler_(bus_handler) {}
void run_for(const Cycles cycles);
private:

View File

@ -0,0 +1,36 @@
//
// 65816Base.cpp
// Clock Signal
//
// Created by Thomas Harte on 28/09/2020.
// Copyright © 2020 Thomas Harte. All rights reserved.
//
#include "../65816.hpp"
using namespace CPU::WDC65816;
uint16_t ProcessorBase::get_value_of_register(Register r) const {
switch (r) {
// case Register::ProgramCounter: return pc_.full;
// case Register::LastOperationAddress: return last_operation_pc_.full;
// case Register::StackPointer: return s_;
// case Register::Flags: return get_flags();
// case Register::A: return a_;
// case Register::X: return x_;
// case Register::Y: return y_;
default: return 0;
}
}
void ProcessorBase::set_value_of_register(Register r, uint16_t value) {
switch (r) {
// case Register::ProgramCounter: pc_.full = value; break;
// case Register::StackPointer: s_ = uint8_t(value); break;
// case Register::Flags: set_flags(uint8_t(value)); break;
// case Register::A: a_ = uint8_t(value); break;
// case Register::X: x_ = uint8_t(value); break;
// case Register::Y: y_ = uint8_t(value); break;
default: break;
}
}

View File

@ -17,7 +17,7 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
// The exception program will determine the appropriate way to respond
// based on the pending exception if one exists; otherwise just do a
// standard fetch-decode-execute.
next_op_ = &micro_ops_[&instructions[pending_exceptions_ ? size_t(OperationSlot::Exception) : size_t(OperationSlot::FetchDecodeExecute)].program_offset];
next_op_ = &micro_ops_[instructions[pending_exceptions_ ? size_t(OperationSlot::Exception) : size_t(OperationSlot::FetchDecodeExecute)].program_offset];
// TODO: reset instruction buffer.
continue;
@ -27,3 +27,8 @@ template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles
}
}
}
void ProcessorBase::set_power_on(bool) {}
void ProcessorBase::set_irq_line(bool) {}
void ProcessorBase::set_nmi_line(bool) {}
bool ProcessorBase::is_jammed() const { return false; }

View File

@ -185,10 +185,14 @@ struct ProcessorStorage {
FetchDecodeExecute
};
void set_power_on_state() {
// Set next_op_ to start the exception program.
next_op_ = &micro_ops_[instructions[size_t(OperationSlot::Exception)].program_offset];
pending_exceptions_ = PowerOn;
void set_power_on(bool power_on) {
if(power_on) {
// Set next_op_ to start the exception program.
next_op_ = &micro_ops_[instructions[size_t(OperationSlot::Exception)].program_offset];
pending_exceptions_ = PowerOn;
} else {
pending_exceptions_ &= ~PowerOn;
}
}
// Registers.