1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-03 11:30:02 +00:00

Takes a minor first step towards actually performing 65816 instructions.

This commit is contained in:
Thomas Harte 2020-09-27 22:20:58 -04:00
parent b96cd4d18b
commit 5645f90abe
5 changed files with 98 additions and 35 deletions

View File

@ -1342,6 +1342,7 @@
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>"; };
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>"; };
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>"; };
@ -3330,6 +3331,7 @@
4BB73E951B587A5100552FC2 = {
isa = PBXGroup;
children = (
4BB023FF25212888009F8D90 /* 65816Implementation.hpp */,
4B51F70820A521D700AFA2C1 /* Activity */,
4B8944E2201967B4007DE474 /* Analyser */,
4BB73EA01B587A5100552FC2 /* Clock Signal */,

View File

@ -13,21 +13,25 @@
#include <vector>
#include "../RegisterSizes.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace CPU {
namespace WDC65816 {
enum class Personality {
WDC65816,
WDC65802
};
#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"
}
}

View 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);
}
}
}

View File

@ -108,8 +108,15 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
void set_exception_generator(Generator generator) {
const auto key = std::make_pair(AccessType::Read, generator);
const auto map_entry = installed_patterns.find(key);
storage_.instructions[512].program_offset = uint16_t(map_entry->second.first);
storage_.instructions[512].operation = BRK;
storage_.instructions[size_t(ProcessorStorage::OperationSlot::Exception)].program_offset = uint16_t(map_entry->second.first);
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
constructor.set_exception_generator(&ProcessorStorageConstructor::stack_exception);
constructor.install_fetch_decode_execute();
#ifndef NDEBUG
assert(micro_ops_.size() < 65536);

View File

@ -103,7 +103,10 @@ enum MicroOp: uint8_t {
OperationPrepareException,
/// 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 {
@ -165,40 +168,59 @@ enum Operation: uint8_t {
class ProcessorStorageConstructor;
class ProcessorStorage {
public:
ProcessorStorage();
struct ProcessorStorage {
ProcessorStorage();
// Frustratingly, there is not quite enough space in 16 bits to store both
// the program offset and the operation as currently defined.
struct Instruction {
uint16_t program_offset;
Operation operation;
};
Instruction instructions[513]; // Arranged as:
// 256 entries: emulation-mode instructions;
// 256 entries: 16-bit instructions; and
// the entry for 'exceptions' (i.e. reset, irq, nmi).
// Frustratingly, there is not quite enough space in 16 bits to store both
// the program offset and the operation as currently defined.
struct Instruction {
uint16_t program_offset;
Operation operation;
};
Instruction instructions[514]; // Arranged as:
// 256 entries: emulation-mode instructions;
// 256 entries: 16-bit instructions;
// the entry for 'exceptions' (i.e. reset, irq, nmi); and
// the entry for fetch-decode-execute.
enum class OperationSlot {
Exception = 512,
FetchDecodeExecute
};
private:
friend ProcessorStorageConstructor;
void set_power_on_state() {
// 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_ = &micro_ops_[c];
break;
}
}
// Registers.
RegisterPair16 a_;
RegisterPair16 x_, y_;
uint16_t pc_, s_;
pending_exceptions_ = PowerOn;
}
// I.e. the offset for direct addressing (outside of emulation mode).
uint16_t direct_;
// Registers.
RegisterPair16 a_;
RegisterPair16 x_, y_;
uint16_t pc_, s_;
// Banking registers are all stored with the relevant byte
// shifted up bits 1623.
uint32_t data_bank_; // i.e. DBR.
uint32_t program_bank_; // i.e. PBR.
// I.e. the offset for direct addressing (outside of emulation mode).
uint16_t direct_;
// Banking registers are all stored with the relevant byte
// shifted up bits 1623.
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 */