2020-09-24 02:14:42 +00:00
|
|
|
|
//
|
|
|
|
|
// 65816Implementation.hpp
|
|
|
|
|
// Clock Signal
|
|
|
|
|
//
|
|
|
|
|
// Created by Thomas Harte on 23/09/2020.
|
|
|
|
|
// Copyright © 2020 Thomas Harte. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#ifndef WDC65816Implementation_h
|
|
|
|
|
#define WDC65816Implementation_h
|
|
|
|
|
|
2020-09-25 02:27:20 +00:00
|
|
|
|
enum MicroOp: uint8_t {
|
|
|
|
|
/// Fetches a byte from the program counter to the instruction buffer and increments the program counter.
|
|
|
|
|
CycleFetchIncrementPC,
|
|
|
|
|
/// Fetches a byte from the program counter without incrementing it, and throws it away.
|
|
|
|
|
CycleFetchPC,
|
|
|
|
|
|
|
|
|
|
/// Fetches a byte from the data address to the data buffer.
|
|
|
|
|
CycleFetchData,
|
|
|
|
|
/// Fetches a byte from the data address to the data buffer and increments the data address.
|
|
|
|
|
CycleFetchIncrementData,
|
2020-09-26 01:16:36 +00:00
|
|
|
|
/// Fetches from the address formed by the low byte of the data address and the high byte
|
|
|
|
|
/// of the instruction buffer, throwing the result away.
|
|
|
|
|
CycleFetchIncorrectDataAddress,
|
2020-09-25 02:27:20 +00:00
|
|
|
|
|
2020-09-26 01:49:03 +00:00
|
|
|
|
// Dedicated block-move cycles; these use the data buffer as an intermediary.
|
|
|
|
|
CycleFetchBlockX,
|
|
|
|
|
CycleFetchBlockY,
|
|
|
|
|
CycleStoreBlockY,
|
|
|
|
|
|
2020-09-25 02:27:20 +00:00
|
|
|
|
/// Stores a byte from the data buffer.
|
|
|
|
|
CycleStoreData,
|
|
|
|
|
/// Stores a byte to the data address from the data buffer and increments the data address.
|
|
|
|
|
CycleStoreIncrementData,
|
|
|
|
|
/// Stores a byte to the data address from the data buffer and decrements the data address.
|
|
|
|
|
CycleStoreDecrementData,
|
|
|
|
|
|
|
|
|
|
/// Pushes a single byte from the data buffer to the stack.
|
|
|
|
|
CyclePush,
|
2020-09-25 22:35:00 +00:00
|
|
|
|
/// Fetches from the current stack location and throws the result away.
|
|
|
|
|
CycleAccessStack,
|
2020-09-25 02:27:20 +00:00
|
|
|
|
|
|
|
|
|
/// Sets the data address by copying the final two bytes of the instruction buffer.
|
|
|
|
|
OperationConstructAbsolute,
|
2020-09-25 22:35:00 +00:00
|
|
|
|
/// Sets the data address to the result of (a, x).
|
|
|
|
|
/// TODO: explain better once implemented.
|
2020-09-25 02:27:20 +00:00
|
|
|
|
OperationConstructAbsoluteIndexedIndirect,
|
2020-09-25 23:27:17 +00:00
|
|
|
|
OperationConstructAbsoluteLongX,
|
2020-09-25 02:27:20 +00:00
|
|
|
|
|
2020-09-26 01:16:36 +00:00
|
|
|
|
/// Calculates an a, x address; if:
|
|
|
|
|
/// there was no carry into the top byte of the address; and
|
|
|
|
|
/// the process or in emulation or 8-bit index mode;
|
|
|
|
|
/// then it also skips the next micro-op.
|
|
|
|
|
OperationConstructAbsoluteXRead,
|
|
|
|
|
|
|
|
|
|
/// Calculates an a, x address.
|
|
|
|
|
OperationConstructAbsoluteX,
|
|
|
|
|
|
|
|
|
|
// These are analogous to the X versions above.
|
|
|
|
|
OperationConstructAbsoluteY,
|
|
|
|
|
OperationConstructAbsoluteYRead,
|
|
|
|
|
|
2020-09-26 02:01:36 +00:00
|
|
|
|
/// Constructs the current direct address using the value in the instruction buffer.
|
|
|
|
|
/// Skips the next micro-op if the low byte of the direct register is 0.
|
|
|
|
|
OperationConstructDirect,
|
|
|
|
|
|
2020-09-26 02:22:30 +00:00
|
|
|
|
// These follow similar skip-one-if-possible logic to OperationConstructDirect.
|
|
|
|
|
OperationConstructDirectIndexedIndirect,
|
|
|
|
|
OperationConstructDirectIndirect,
|
|
|
|
|
|
2020-09-25 02:27:20 +00:00
|
|
|
|
/// Performs whatever operation goes with this program.
|
|
|
|
|
OperationPerform,
|
|
|
|
|
|
2020-09-25 02:37:31 +00:00
|
|
|
|
/// Copies the current program counter to the data buffer.
|
|
|
|
|
OperationCopyPCToData,
|
|
|
|
|
|
2020-09-25 22:35:00 +00:00
|
|
|
|
/// Copies the current PBR to the data buffer.
|
|
|
|
|
OperationCopyPBRToData,
|
|
|
|
|
|
2020-09-26 01:16:36 +00:00
|
|
|
|
OperationCopyAToData,
|
|
|
|
|
OperationCopyDataToA,
|
|
|
|
|
|
2020-09-25 02:27:20 +00:00
|
|
|
|
/// Complete this set of micr-ops.
|
|
|
|
|
OperationMoveToNextProgram
|
|
|
|
|
};
|
2020-09-24 02:23:23 +00:00
|
|
|
|
|
2020-09-25 21:18:25 +00:00
|
|
|
|
enum Operation: uint8_t {
|
|
|
|
|
// 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,
|
|
|
|
|
|
|
|
|
|
// These load the respective register from the data buffer;
|
|
|
|
|
// they are implicitly AccessType::Read.
|
|
|
|
|
LDA, LDX, LDY,
|
|
|
|
|
|
|
|
|
|
// These move the respective register (or value) to the data buffer;
|
|
|
|
|
// they are implicitly AccessType::Write.
|
|
|
|
|
STA, STX, STY, STZ,
|
|
|
|
|
|
2020-09-26 01:16:36 +00:00
|
|
|
|
// These modify the value in the data buffer as part of a read-modify-write.
|
|
|
|
|
ASL, DEC, INC, LSR, ROL, ROR, TRB, TSB,
|
|
|
|
|
|
2020-09-26 01:49:03 +00:00
|
|
|
|
// These merely decrement A, increment or decrement X and Y, and regress
|
|
|
|
|
// the program counter only if appropriate.
|
|
|
|
|
MVN, MVP,
|
|
|
|
|
|
2020-09-25 21:18:25 +00:00
|
|
|
|
/// Loads the PC with the operand from the data buffer.
|
|
|
|
|
JMP,
|
|
|
|
|
|
2020-09-25 22:00:02 +00:00
|
|
|
|
/// Loads the PC and PBR with the operand from the data buffer.
|
|
|
|
|
JML,
|
|
|
|
|
|
2020-09-25 22:35:00 +00:00
|
|
|
|
/// Loads the PC with the operand from the data buffer, replacing
|
2020-09-25 21:18:25 +00:00
|
|
|
|
/// it with the old PC.
|
|
|
|
|
JSR,
|
2020-09-25 22:35:00 +00:00
|
|
|
|
|
|
|
|
|
/// Loads the PC and the PBR with the operand from the data buffer,
|
|
|
|
|
/// replacing it with the old PC (and only the PC; PBR not included).
|
|
|
|
|
JSL,
|
2020-09-25 02:27:20 +00:00
|
|
|
|
};
|
2020-09-24 02:14:42 +00:00
|
|
|
|
|
2020-09-25 02:27:20 +00:00
|
|
|
|
class ProcessorStorageConstructor;
|
2020-09-24 02:14:42 +00:00
|
|
|
|
|
2020-09-25 02:27:20 +00:00
|
|
|
|
class ProcessorStorage {
|
|
|
|
|
public:
|
|
|
|
|
ProcessorStorage();
|
2020-09-24 02:14:42 +00:00
|
|
|
|
|
|
|
|
|
struct Instruction {
|
|
|
|
|
size_t program_offset;
|
|
|
|
|
Operation operation;
|
|
|
|
|
};
|
2020-09-25 21:18:25 +00:00
|
|
|
|
Instruction instructions[512 + 3]; // Arranged as:
|
|
|
|
|
// 256 entries: emulation-mode instructions;
|
|
|
|
|
// 256 entries: 16-bit instructions;
|
|
|
|
|
// reset
|
|
|
|
|
// NMI
|
|
|
|
|
// IRQ
|
2020-09-24 02:14:42 +00:00
|
|
|
|
|
|
|
|
|
private:
|
2020-09-25 21:18:25 +00:00
|
|
|
|
friend ProcessorStorageConstructor;
|
2020-09-24 02:14:42 +00:00
|
|
|
|
|
2020-09-25 22:00:02 +00:00
|
|
|
|
// Registers.
|
|
|
|
|
RegisterPair16 a_;
|
|
|
|
|
RegisterPair16 x_, y_;
|
|
|
|
|
uint16_t pc_, s_;
|
|
|
|
|
|
|
|
|
|
// Not
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
2020-09-25 21:18:25 +00:00
|
|
|
|
std::vector<MicroOp> micro_ops_;
|
2020-09-24 02:14:42 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif /* WDC65816Implementation_h */
|