1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-04-20 10:17:05 +00:00

Start transferring 6502 precepts.

This commit is contained in:
Thomas Harte
2025-10-18 22:31:00 -04:00
parent 564542420b
commit 294893b7da
2 changed files with 180 additions and 0 deletions
@@ -1801,6 +1801,7 @@
4B882F582C2F9C6900D84031 /* CPCShakerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CPCShakerTests.mm; sourceTree = "<group>"; };
4B882F5A2C2F9C7700D84031 /* Shaker */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Shaker; sourceTree = "<group>"; };
4B884C6F2EA28E0F00073840 /* CompileTimeCounter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CompileTimeCounter.hpp; sourceTree = "<group>"; };
4B884C722EA47FCC00073840 /* 6502Mk2.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = 6502Mk2.hpp; sourceTree = "<group>"; };
4B88559C2E8185BF00E251DD /* SizedInt.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SizedInt.hpp; sourceTree = "<group>"; };
4B8855A22E84D51B00E251DD /* SAA5050.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = SAA5050.hpp; sourceTree = "<group>"; };
4B8855A32E84D51B00E251DD /* SAA5050.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SAA5050.cpp; sourceTree = "<group>"; };
@@ -3859,6 +3860,14 @@
path = Data;
sourceTree = "<group>";
};
4B884C732EA47FCC00073840 /* 6502Mk2 */ = {
isa = PBXGroup;
children = (
4B884C722EA47FCC00073840 /* 6502Mk2.hpp */,
);
path = 6502Mk2;
sourceTree = "<group>";
};
4B8855A42E84D51B00E251DD /* SAA5050 */ = {
isa = PBXGroup;
children = (
@@ -4900,6 +4909,7 @@
4BFCA1221ECBDCAF00AC40C1 /* AllRAMProcessor.hpp */,
4B1414561B58879D00E04248 /* 6502 */,
4B4DEC15252BFA9C004583AC /* 6502Esque */,
4B884C732EA47FCC00073840 /* 6502Mk2 */,
4BF8D4CC251C0C9C00BBE21B /* 65816 */,
42AD552D2A0C4D5000ACE410 /* 68000 */,
4B77069E1EC9045B0053B588 /* Z80 */,
+170
View File
@@ -0,0 +1,170 @@
//
// 6502Mk2.hpp
// Clock Signal
//
// Created by Thomas Harte on 18/10/2025.
// Copyright © 2025 Thomas Harte. All rights reserved.
//
#pragma once
namespace CPU::MOS6502Mk2 {
// MARK: - Address resolvers.
namespace Address {
struct Literal {
constexpr LiteralAddress(const uint16_t address) noexcept : address_(address);
operator uint16_t() const {
return address_;
}
private:
uint16_t address_;
};
struct ZeroPage {
constexpr ZeroPage(const uint8_t address) noexcept : address_(address);
operator uint16_t() const {
return address_;
}
private:
uint8_t address_;
};
struct Stack {
constexpr ZeroPage(const uint8_t address) noexcept : address_(address);
operator uint16_t() const {
return 0x0100 | address_;
}
private:
uint8_t address_;
};
struct Vector {
constexpr ZeroPage(const uint8_t address) noexcept : address_(address);
operator uint16_t() const {
return 0xff00 | address_;
}
private:
uint8_t address_;
};
} // namespace Address
namespace Data {
struct NoValue {
operator uint8_t() const { return 0xff; }
};
/*!
Bus handlers perform bus transactions, connecting the 6502-esque chip to the rest of the syste.
@c BusOperation provides the type of operation.
*/
enum class BusOperation {
/// 6502: a read was signalled.
/// 65816: a read was signalled with VDA.
Read,
/// 6502: a read was signalled with SYNC.
/// 65816: a read was signalled with VDA and VPA.
ReadOpcode,
/// 6502: never signalled.
/// 65816: a read was signalled with VPA.
ReadProgram,
/// 6502: never signalled.
/// 65816: a read was signalled with VPB and VDA.
ReadVector,
/// 6502: never signalled.
/// 65816: a read was signalled, but neither VDA nor VPA were active.
InternalOperationRead,
/// All processors: indicates that the processor is paused due to the RDY input.
/// 65C02 and 65816: indicates a WAI is ongoing.
Ready,
/// 65C02 and 65816: indicates a STP condition.
None,
/// 6502: a write was signalled.
/// 65816: a write was signalled with VDA.
Write,
/// 6502: never signalled.
/// 65816: a write was signalled, but neither VDA nor VPA were active.
InternalOperationWrite,
};
constexpr bool is_read(const BusOperation op) { return op <= BusOperation::InternalOperationRead; }
constexpr bool is_write(const BusOperation op) { return op >= BusOperation::Write; }
constexpr bool is_access(const BusOperation op) { return op <= BusOperation::ReadVector || op == BusOperation::Write; }
constexpr bool is_dataless(const BusOperation op) { return !is_read(op) && !is_write(op); }
template <BusOperation, typename Enable = void> struct Value;
template <BusOperation operation> struct Value<operation, std::enable_if_t<is_read(operation)> {
using type = uint8_t &;
};
template <BusOperation operation> struct Value<operation, std::enable_if_t<is_write(operation)> {
using type = const uint8_t;
};
template <BusOperation operation> struct Value<operation, std::enable_if_t<is_dataless(operation)> {
using type = const NoValue;
};
} // namespace Data
/*
The list of registers that can be accessed via @c value_of(Register) and @c set_value_of(Register, value).
*/
enum class Register {
LastOperationAddress,
ProgramCounter,
StackPointer,
Flags,
A,
X,
Y,
//
// 65816 only.
//
EmulationFlag,
DataBank,
ProgramBank,
Direct
};
/*
Flags as defined on the 6502; can be used to decode the result of @c value_of(Flags) or to form a value for
the corresponding set.
*/
enum Flag: uint8_t {
Sign = 0b1000'0000,
Overflow = 0b0100'0000,
Always = 0b0010'0000,
Break = 0b0001'0000,
Decimal = 0b0000'1000,
Interrupt = 0b0000'0100,
Zero = 0b0000'0010,
Carry = 0b0000'0001,
//
// 65816 only.
//
MemorySize = Always,
IndexSize = Break,
};
enum Personality {
PNES6502, // The NES's 6502; like a 6502 but lacking decimal mode (though it retains the decimal flag).
P6502, // NMOS 6502.
PSynertek65C02, // A 6502 extended with BRA, P[H/L][X/Y], STZ, TRB, TSB and the (zp) addressing mode, and more.
PRockwell65C02, // The Synertek extended with BBR, BBS, RMB and SMB.
PWDC65C02, // The Rockwell extended with STP and WAI.
P65816, // The "16-bit" successor to the 6502.
};
}