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>"; };
|
||||
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 */,
|
||||
|
@ -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"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
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) {
|
||||
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);
|
||||
|
@ -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_ = µ_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 16–23.
|
||||
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 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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user