1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-16 22:28:57 +00:00

Switches to generators with stable pointers; adds 2a.

This commit is contained in:
Thomas Harte 2020-09-24 22:27:20 -04:00
parent 5c9192e5e6
commit d707c5ac95
2 changed files with 137 additions and 93 deletions

View File

@ -6,20 +6,11 @@
// Copyright © 2020 Thomas Harte. All rights reserved. // Copyright © 2020 Thomas Harte. All rights reserved.
// //
#include <cstdint> #include "../65816.hpp"
#include <vector>
#include "65816Storage.hpp" using namespace CPU::WDC65816;
namespace { struct CPU::WDC65816::ProcessorStorageConstructor {
enum class AccessType {
Read, Write, ReadModifyWrite
};
}
ProcessorStorage::ProcessorStorage() {
/* /*
Code below is structured to ease translation from Table 5-7 of the 2018 Code below is structured to ease translation from Table 5-7 of the 2018
edition of the WDC 65816 datasheet. edition of the WDC 65816 datasheet.
@ -39,7 +30,7 @@ ProcessorStorage::ProcessorStorage() {
*/ */
// 1a. Absolute a. // 1a. Absolute a.
auto absolute = [] (AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) { static void absolute(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // AAL. target(CycleFetchIncrementPC); // AAL.
target(CycleFetchIncrementPC); // AAH. target(CycleFetchIncrementPC); // AAH.
target(OperationConstructAbsolute); // Calculate data address. target(OperationConstructAbsolute); // Calculate data address.
@ -56,24 +47,26 @@ ProcessorStorage::ProcessorStorage() {
}; };
// 1b. Absolute a, JMP. // 1b. Absolute a, JMP.
auto absolute_jmp = [] (AccessType, bool, const std::function<void(MicroOp)> &target) { static void absolute_jmp(AccessType, bool, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // New PCL. target(CycleFetchIncrementPC); // New PCL.
target(CycleFetchIncrementPC); // New PCH. target(CycleFetchPC); // New PCH.
target(OperationConstructAbsolute); // Calculate data address.
target(OperationPerform); // [JMP] target(OperationPerform); // [JMP]
}; };
// 1c. Absolute a, JSR. // 1c. Absolute a, JSR.
auto absolute_jsr = [] (AccessType, bool, const std::function<void(MicroOp)> &target) { static void absolute_jsr(AccessType, bool, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // New PCL. target(CycleFetchIncrementPC); // New PCL.
target(CycleFetchIncrementPC); // New PCH. target(CycleFetchPC); // New PCH.
target(CycleFetchPCDiscard); // IO target(CycleFetchPC); // IO
target(OperationConstructAbsolute); // Calculate data address.
target(OperationPerform); // [JSR] target(OperationPerform); // [JSR]
target(CyclePush); // PCH target(CyclePush); // PCH
target(CyclePush); // PCL target(CyclePush); // PCL
}; };
// 1d. Absolute read-modify-write. // 1d. Absolute read-modify-write.
auto absolute_rmw = [] (AccessType, bool is8bit, const std::function<void(MicroOp)> &target) { static void absolute_rmw(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // AAL. target(CycleFetchIncrementPC); // AAL.
target(CycleFetchIncrementPC); // AAH. target(CycleFetchIncrementPC); // AAH.
target(OperationConstructAbsolute); // Calculate data address. target(OperationConstructAbsolute); // Calculate data address.
@ -90,8 +83,57 @@ ProcessorStorage::ProcessorStorage() {
target(CycleStoreData); // Data [low]. target(CycleStoreData); // Data [low].
}; };
// 2a. Absolute Indexed Indirect (a, x), JMP.
static void absolute_indexed_indirect_jmp(AccessType, bool, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // AAL.
target(CycleFetchPC); // AAH.
target(CycleFetchPC); // IO.
target(OperationConstructAbsoluteIndexedIndirect); // Calculate data address.
target(CycleFetchIncrementData); // New PCL
target(CycleFetchData); // New PCH.
target(OperationPerform); // [JMP]
};
// 2b. Absolute Indexed Indirect (a, x), JSR.
};
AccessType ProcessorStorage::access_type_for_operation(Operation operation) {
switch(operation) {
case ADC: case AND: case BIT: case CMP:
case CPX: case CPY: case EOR: case ORA:
case SBC:
case LDA: case LDX: case LDY:
case JMP: case JSR:
return AccessType::Read;
case STA: case STX: case STY: case STZ:
return AccessType::Write;
}
}
void ProcessorStorage::install(void (* generator)(AccessType, bool, const std::function<void(MicroOp)>&), Operation operation, ProcessorStorageConstructor &) {
const AccessType access_type = access_type_for_operation(operation);
(*generator)(access_type, true, [] (MicroOp) {});
// TODO:
// (1) use [hash of] pointer to generator to determine whether operation tables have already been built;
// (2) if not, build them in both 8- and 16-bit variations;
// (3) insert appropriate entries into an instruction table for the current instruction; and
// (4) increment the instruction counter.
//
// Additional observation: temporary storage would be helpful, so load that into ProcessorStorageConstructor.
}
ProcessorStorage::ProcessorStorage() {
ProcessorStorageConstructor constructor;
// Install the instructions. // Install the instructions.
#define op set_instruction #define op(x, y) install(&ProcessorStorageConstructor::x, y, constructor)
/* 0x00 BRK s */ /* 0x00 BRK s */
/* 0x01 ORA (d, x) */ /* 0x01 ORA (d, x) */
/* 0x02 COP s */ /* 0x02 COP s */
@ -105,7 +147,7 @@ ProcessorStorage::ProcessorStorage() {
/* 0x0a ASL a */ /* 0x0a ASL a */
/* 0x0b PHD s */ /* 0x0b PHD s */
/* 0x0c TSB a */ /* 0x0c TSB a */
/* 0x0d ORA a */ // op(0x0d, absolute_read, ORA); /* 0x0d ORA a */ op(absolute, ORA);
/* 0x0e ASL a */ /* 0x0e ASL a */
/* 0x0f ORA al */ /* 0x0f ORA al */
@ -126,7 +168,7 @@ ProcessorStorage::ProcessorStorage() {
/* 0x1e ASL a, x */ /* 0x1e ASL a, x */
/* 0x1f ORA al, x */ /* 0x1f ORA al, x */
/* 0x20 JSR a */ // op(0x20, absolute_jsr, JSR); /* 0x20 JSR a */ op(absolute_jsr, JSR);
/* 0x21 ORA (d), y */ /* 0x21 ORA (d), y */
/* 0x22 AND (d, x) */ /* 0x22 AND (d, x) */
/* 0x23 JSL al */ /* 0x23 JSL al */
@ -138,8 +180,8 @@ ProcessorStorage::ProcessorStorage() {
/* 0x29 AND # */ /* 0x29 AND # */
/* 0x2a ROL A */ /* 0x2a ROL A */
/* 0x2b PLD s */ /* 0x2b PLD s */
/* 0x2c BIT a */ // op(0x2c, absolute_read, BIT); /* 0x2c BIT a */ op(absolute, BIT);
/* 0x2d AND a */ // op(0x2d, absolute_read, AND); /* 0x2d AND a */ op(absolute, AND);
/* 0x2e ROL a */ /* 0x2e ROL a */
/* 0x2f AND al */ /* 0x2f AND al */
@ -172,8 +214,8 @@ ProcessorStorage::ProcessorStorage() {
/* 0x49 EOR # */ /* 0x49 EOR # */
/* 0x4a LSR A */ /* 0x4a LSR A */
/* 0x4b PHK s */ /* 0x4b PHK s */
/* 0x4c JMP a */ // op(0x4c, absolute_jmp, JMP); /* 0x4c JMP a */ op(absolute, JMP);
/* 0x4d EOR a */ // op(0x4d, absolute_read, EOR); /* 0x4d EOR a */ op(absolute, EOR);
/* 0x4e LSR a */ /* 0x4e LSR a */
/* 0x4f EOR Al */ /* 0x4f EOR Al */
@ -207,7 +249,7 @@ ProcessorStorage::ProcessorStorage() {
/* 0x6a ROR A */ /* 0x6a ROR A */
/* 0x6b RTL s */ /* 0x6b RTL s */
/* 0x6c JMP (a) */ /* 0x6c JMP (a) */
/* 0x6d ADC a */ // op(0x6d, absolute_read, ADC); /* 0x6d ADC a */ op(absolute, ADC);
/* 0x6e ROR a */ /* 0x6e ROR a */
/* 0x6f ADC al */ /* 0x6f ADC al */
@ -223,7 +265,7 @@ ProcessorStorage::ProcessorStorage() {
/* 0x79 ADC a, y */ /* 0x79 ADC a, y */
/* 0x7a PLY s */ /* 0x7a PLY s */
/* 0x7b TDC i */ /* 0x7b TDC i */
/* 0x7c JMP (a, x) */ /* 0x7c JMP (a, x) */ op(absolute_indexed_indirect_jmp, JMP);
/* 0x7d ADC a, x */ /* 0x7d ADC a, x */
/* 0x7e ROR a, x */ /* 0x7e ROR a, x */
/* 0x7f ADC al, x */ /* 0x7f ADC al, x */
@ -240,9 +282,9 @@ ProcessorStorage::ProcessorStorage() {
/* 0x89 BIT # */ /* 0x89 BIT # */
/* 0x8a TXA i */ /* 0x8a TXA i */
/* 0x8b PHB s */ /* 0x8b PHB s */
/* 0x8c STY a */ // op(0x8c, absolute_write, STY); /* 0x8c STY a */ op(absolute, STY);
/* 0x8d STA a */ // op(0x8d, absolute_write, STA); /* 0x8d STA a */ op(absolute, STA);
/* 0x8e STX a */ // op(0x8e, absolute_write, STX); /* 0x8e STX a */ op(absolute, STX);
/* 0x8f STA al */ /* 0x8f STA al */
/* 0x90 BCC r */ /* 0x90 BCC r */
@ -257,7 +299,7 @@ ProcessorStorage::ProcessorStorage() {
/* 0x99 STA a, y */ /* 0x99 STA a, y */
/* 0x9a TXS i */ /* 0x9a TXS i */
/* 0x9b TXY i */ /* 0x9b TXY i */
/* 0x9c STZ a */ // op(0x9c, absolute_write, STZ); /* 0x9c STZ a */ op(absolute, STZ);
/* 0x9d STA a, x */ /* 0x9d STA a, x */
/* 0x9e STZ a, x */ /* 0x9e STZ a, x */
/* 0x9f STA al, x */ /* 0x9f STA al, x */
@ -274,9 +316,9 @@ ProcessorStorage::ProcessorStorage() {
/* 0xa9 LDA # */ /* 0xa9 LDA # */
/* 0xaa TAX i */ /* 0xaa TAX i */
/* 0xab PLB s */ /* 0xab PLB s */
/* 0xac LDY a */ // op(0xac, absolute_read, LDY); /* 0xac LDY a */ op(absolute, LDY);
/* 0xad LDA a */ // op(0xad, absolute_read, LDA); /* 0xad LDA a */ op(absolute, LDA);
/* 0xae LDX a */ // op(0xae, absolute_read, LDX); /* 0xae LDX a */ op(absolute, LDX);
/* 0xaf LDA al */ /* 0xaf LDA al */
/* 0xb0 BCS r */ /* 0xb0 BCS r */
@ -308,8 +350,8 @@ ProcessorStorage::ProcessorStorage() {
/* 0xc9 CMP # */ /* 0xc9 CMP # */
/* 0xca DEX i */ /* 0xca DEX i */
/* 0xcb WAI i */ /* 0xcb WAI i */
/* 0xcc CPY a */ // op(0xcd, absolute_read, CPY); /* 0xcc CPY a */ op(absolute, CPY);
/* 0xcd CMP a */ // op(0xcd, absolute_read, CMP); /* 0xcd CMP a */ op(absolute, CMP);
/* 0xce DEC a */ /* 0xce DEC a */
/* 0xcf CMP al */ /* 0xcf CMP al */
@ -342,8 +384,8 @@ ProcessorStorage::ProcessorStorage() {
/* 0xe9 SBC # */ /* 0xe9 SBC # */
/* 0xea NOP i */ /* 0xea NOP i */
/* 0xeb XBA i */ /* 0xeb XBA i */
/* 0xec CPX a */ // op(0xec, absolute_read, CPX); /* 0xec CPX a */ op(absolute, CPX);
/* 0xed SBC a */ // op(0xed, absolute_read, SBC); /* 0xed SBC a */ op(absolute, SBC);
/* 0xee INC a */ /* 0xee INC a */
/* 0xef SBC al */ /* 0xef SBC al */

View File

@ -9,15 +9,11 @@
#ifndef WDC65816Implementation_h #ifndef WDC65816Implementation_h
#define WDC65816Implementation_h #define WDC65816Implementation_h
class ProcessorStorage { enum MicroOp: uint8_t {
public:
ProcessorStorage();
enum MicroOp: uint8_t {
/// Fetches a byte from the program counter to the instruction buffer and increments the program counter. /// Fetches a byte from the program counter to the instruction buffer and increments the program counter.
CycleFetchIncrementPC, CycleFetchIncrementPC,
/// Fetches a byte from the program counter without incrementing it, and throws it away. /// Fetches a byte from the program counter without incrementing it, and throws it away.
CycleFetchPCDiscard, CycleFetchPC,
/// Fetches a byte from the data address to the data buffer. /// Fetches a byte from the data address to the data buffer.
CycleFetchData, CycleFetchData,
@ -36,29 +32,44 @@ class ProcessorStorage {
/// Sets the data address by copying the final two bytes of the instruction buffer. /// Sets the data address by copying the final two bytes of the instruction buffer.
OperationConstructAbsolute, OperationConstructAbsolute,
/// Sets the data address
OperationConstructAbsoluteIndexedIndirect,
/// Performs whatever operation goes with this program. /// Performs whatever operation goes with this program.
OperationPerform, OperationPerform,
/// Complete this set of micr-ops. /// Complete this set of micr-ops.
OperationMoveToNextProgram OperationMoveToNextProgram
}; };
enum class AccessType {
Read, Write
};
class ProcessorStorageConstructor;
class ProcessorStorage {
public:
ProcessorStorage();
enum Operation: uint8_t { enum Operation: uint8_t {
// These perform the named operation using the value in the data buffer. // These perform the named operation using the value in the data buffer;
// they are implicitly AccessType::Read.
ADC, AND, BIT, CMP, CPX, CPY, EOR, ORA, SBC, ADC, AND, BIT, CMP, CPX, CPY, EOR, ORA, SBC,
// These load the respective register from the data buffer. // These load the respective register from the data buffer;
// they are implicitly AccessType::Read.
LDA, LDX, LDY, LDA, LDX, LDY,
// These move the respective register (or value) to the data buffer. // These move the respective register (or value) to the data buffer;
// they are implicitly AccessType::Write.
STA, STX, STY, STZ, STA, STX, STY, STZ,
/// Loads the PC with the operand from the instruction buffer. /// Loads the PC with the operand from the data buffer.
JMP, JMP,
/// Loads the PC with the operand from the instruction buffer, placing /// Loads the PC with the operand from the daa buffer, replacing
/// the old PC into the data buffer. /// it with the old PC.
JSR, JSR,
}; };
@ -71,17 +82,8 @@ class ProcessorStorage {
private: private:
std::vector<MicroOp> micro_ops_; std::vector<MicroOp> micro_ops_;
size_t install_ops(std::initializer_list<MicroOp> ops) { AccessType access_type_for_operation(Operation);
// Just copy into place and return the index at which copying began. void install(void (* generator)(AccessType, bool, const std::function<void(MicroOp)>&), Operation, ProcessorStorageConstructor &);
const size_t index = micro_ops_.size();
micro_ops_.insert(micro_ops_.end(), ops.begin(), ops.end());
return index;
}
void set_instruction(uint8_t opcode, size_t micro_ops, Operation operation) {
instructions[opcode].program_offset = micro_ops;
instructions[opcode].operation = operation;
}
}; };
#endif /* WDC65816Implementation_h */ #endif /* WDC65816Implementation_h */