mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-27 00:30:26 +00:00
Takes a minor first step towards actually performing 65816 instructions.
This commit is contained in:
parent
b96cd4d18b
commit
5645f90abe
@ -1342,6 +1342,7 @@
|
|||||||
4BAB62AE1D32730D00DF5BA0 /* Storage.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Storage.hpp; sourceTree = "<group>"; };
|
4BAB62AE1D32730D00DF5BA0 /* Storage.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Storage.hpp; sourceTree = "<group>"; };
|
||||||
4BAF2B4C2004580C00480230 /* DMK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DMK.cpp; sourceTree = "<group>"; };
|
4BAF2B4C2004580C00480230 /* DMK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DMK.cpp; sourceTree = "<group>"; };
|
||||||
4BAF2B4D2004580C00480230 /* DMK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DMK.hpp; sourceTree = "<group>"; };
|
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>"; };
|
||||||
4BB06B211F316A3F00600C7A /* ForceInline.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ForceInline.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>"; };
|
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>"; };
|
4BB0A65A2044FD3000FB3688 /* SN76489.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SN76489.hpp; sourceTree = "<group>"; };
|
||||||
@ -3330,6 +3331,7 @@
|
|||||||
4BB73E951B587A5100552FC2 = {
|
4BB73E951B587A5100552FC2 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
4BB023FF25212888009F8D90 /* 65816Implementation.hpp */,
|
||||||
4B51F70820A521D700AFA2C1 /* Activity */,
|
4B51F70820A521D700AFA2C1 /* Activity */,
|
||||||
4B8944E2201967B4007DE474 /* Analyser */,
|
4B8944E2201967B4007DE474 /* Analyser */,
|
||||||
4BB73EA01B587A5100552FC2 /* Clock Signal */,
|
4BB73EA01B587A5100552FC2 /* Clock Signal */,
|
||||||
|
@ -13,21 +13,25 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../RegisterSizes.hpp"
|
#include "../RegisterSizes.hpp"
|
||||||
|
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||||
|
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
namespace WDC65816 {
|
namespace WDC65816 {
|
||||||
|
|
||||||
enum class Personality {
|
|
||||||
WDC65816,
|
|
||||||
WDC65802
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "Implementation/65816Storage.hpp"
|
#include "Implementation/65816Storage.hpp"
|
||||||
|
|
||||||
template <Personality personality> class Processor: public ProcessorStorage {
|
template <typename BusHandler> class Processor: private ProcessorStorage {
|
||||||
|
public:
|
||||||
|
Processor(BusHandler &bus_handler) : bus_handler_(bus_handler) {}
|
||||||
|
|
||||||
|
void run_for(const Cycles cycles);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BusHandler &bus_handler_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include "Implementation/65816Implementation.hpp"
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
Processors/65816/Implementation/65816Implementation.hpp
Normal file
27
Processors/65816/Implementation/65816Implementation.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// 65816Implementation.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 27/09/2020.
|
||||||
|
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename BusHandler> void Processor<BusHandler>::run_for(const Cycles cycles) {
|
||||||
|
auto int_cycles = cycles.as_integral();
|
||||||
|
while(int_cycles--) {
|
||||||
|
const MicroOp operation = *next_op_;
|
||||||
|
++next_op_;
|
||||||
|
|
||||||
|
switch(operation) {
|
||||||
|
case OperationMoveToNextProgram:
|
||||||
|
// 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_ = &instructions[pending_exceptions_ ? size_t(OperationSlot::Exception) : size_t(OperationSlot::FetchDecodeExecute)];
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -108,8 +108,15 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
void set_exception_generator(Generator generator) {
|
void set_exception_generator(Generator generator) {
|
||||||
const auto key = std::make_pair(AccessType::Read, generator);
|
const auto key = std::make_pair(AccessType::Read, generator);
|
||||||
const auto map_entry = installed_patterns.find(key);
|
const auto map_entry = installed_patterns.find(key);
|
||||||
storage_.instructions[512].program_offset = uint16_t(map_entry->second.first);
|
storage_.instructions[size_t(ProcessorStorage::OperationSlot::Exception)].program_offset = uint16_t(map_entry->second.first);
|
||||||
storage_.instructions[512].operation = BRK;
|
storage_.instructions[size_t(ProcessorStorage::OperationSlot::Exception)].operation = BRK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void install_fetch_decode_execute() {
|
||||||
|
storage_.instructions[size_t(ProcessorStorage::OperationSlot::FetchDecodeExecute)].program_offset = uint16_t(storage_.micro_ops_.size());
|
||||||
|
storage_.instructions[size_t(ProcessorStorage::OperationSlot::FetchDecodeExecute)].operation = NOP;
|
||||||
|
storage_.micro_ops_.push_back(CycleFetchIncrementPC);
|
||||||
|
storage_.micro_ops_.push_back(OperationDecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -979,6 +986,7 @@ ProcessorStorage::ProcessorStorage() {
|
|||||||
#undef op
|
#undef op
|
||||||
|
|
||||||
constructor.set_exception_generator(&ProcessorStorageConstructor::stack_exception);
|
constructor.set_exception_generator(&ProcessorStorageConstructor::stack_exception);
|
||||||
|
constructor.install_fetch_decode_execute();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
assert(micro_ops_.size() < 65536);
|
assert(micro_ops_.size() < 65536);
|
||||||
|
@ -103,7 +103,10 @@ enum MicroOp: uint8_t {
|
|||||||
OperationPrepareException,
|
OperationPrepareException,
|
||||||
|
|
||||||
/// Complete this set of micr-ops.
|
/// Complete this set of micr-ops.
|
||||||
OperationMoveToNextProgram
|
OperationMoveToNextProgram,
|
||||||
|
|
||||||
|
/// Inspects the instruction buffer and thereby selects the next set of micro-ops to schedule.
|
||||||
|
OperationDecode,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Operation: uint8_t {
|
enum Operation: uint8_t {
|
||||||
@ -165,40 +168,59 @@ enum Operation: uint8_t {
|
|||||||
|
|
||||||
class ProcessorStorageConstructor;
|
class ProcessorStorageConstructor;
|
||||||
|
|
||||||
class ProcessorStorage {
|
struct ProcessorStorage {
|
||||||
public:
|
ProcessorStorage();
|
||||||
ProcessorStorage();
|
|
||||||
|
|
||||||
// Frustratingly, there is not quite enough space in 16 bits to store both
|
// Frustratingly, there is not quite enough space in 16 bits to store both
|
||||||
// the program offset and the operation as currently defined.
|
// the program offset and the operation as currently defined.
|
||||||
struct Instruction {
|
struct Instruction {
|
||||||
uint16_t program_offset;
|
uint16_t program_offset;
|
||||||
Operation operation;
|
Operation operation;
|
||||||
};
|
};
|
||||||
Instruction instructions[513]; // Arranged as:
|
Instruction instructions[514]; // Arranged as:
|
||||||
// 256 entries: emulation-mode instructions;
|
// 256 entries: emulation-mode instructions;
|
||||||
// 256 entries: 16-bit instructions; and
|
// 256 entries: 16-bit instructions;
|
||||||
// the entry for 'exceptions' (i.e. reset, irq, nmi).
|
// the entry for 'exceptions' (i.e. reset, irq, nmi); and
|
||||||
|
// the entry for fetch-decode-execute.
|
||||||
|
|
||||||
|
enum class OperationSlot {
|
||||||
|
Exception = 512,
|
||||||
|
FetchDecodeExecute
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
void set_power_on_state() {
|
||||||
friend ProcessorStorageConstructor;
|
// Set next_op_ to any instance of OperationMoveToNextProgram.
|
||||||
|
for(size_t c = 0; c < micro_ops_.size(); ++c) {
|
||||||
|
if(micro_ops_[c] == OperationMoveToNextProgram) {
|
||||||
|
next_op_ = µ_ops_[c];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Registers.
|
pending_exceptions_ = PowerOn;
|
||||||
RegisterPair16 a_;
|
}
|
||||||
RegisterPair16 x_, y_;
|
|
||||||
uint16_t pc_, s_;
|
|
||||||
|
|
||||||
// I.e. the offset for direct addressing (outside of emulation mode).
|
// Registers.
|
||||||
uint16_t direct_;
|
RegisterPair16 a_;
|
||||||
|
RegisterPair16 x_, y_;
|
||||||
|
uint16_t pc_, s_;
|
||||||
|
|
||||||
// Banking registers are all stored with the relevant byte
|
// I.e. the offset for direct addressing (outside of emulation mode).
|
||||||
// shifted up bits 16–23.
|
uint16_t direct_;
|
||||||
uint32_t data_bank_; // i.e. DBR.
|
|
||||||
uint32_t program_bank_; // i.e. PBR.
|
|
||||||
|
|
||||||
|
// Banking registers are all stored with the relevant byte
|
||||||
|
// shifted up bits 16–23.
|
||||||
|
uint32_t data_bank_; // i.e. DBR.
|
||||||
|
uint32_t program_bank_; // i.e. PBR.
|
||||||
|
|
||||||
std::vector<MicroOp> micro_ops_;
|
static constexpr int PowerOn = 1 << 0;
|
||||||
|
static constexpr int Reset = 1 << 1;
|
||||||
|
static constexpr int IRQ = 1 << 2;
|
||||||
|
static constexpr int NMI = 1 << 3;
|
||||||
|
int pending_exceptions_ = 0;
|
||||||
|
|
||||||
|
std::vector<MicroOp> micro_ops_;
|
||||||
|
MicroOp *next_op_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* WDC65816Implementation_h */
|
#endif /* WDC65816Implementation_h */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user