2020-09-28 22:43:53 +00:00
|
|
|
//
|
|
|
|
// 6502Esque.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 28/09/2020.
|
|
|
|
// Copyright © 2020 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
2024-01-17 04:34:46 +00:00
|
|
|
#pragma once
|
2020-09-28 22:43:53 +00:00
|
|
|
|
2020-10-06 02:23:33 +00:00
|
|
|
#include "../../ClockReceiver/ClockReceiver.hpp"
|
|
|
|
|
2020-09-28 22:43:53 +00:00
|
|
|
/*
|
|
|
|
This file defines how the CPU-controlled part of a bus looks for the 6502 and
|
|
|
|
for other processors with a sufficiently-similar bus.
|
|
|
|
|
|
|
|
I'm not yet a big fan of the name I've used here, and I'm still on the fence
|
|
|
|
about what to do when eventually I get around to the 6800 and/or 6809, which have
|
|
|
|
very similar bus characteristics.
|
|
|
|
|
|
|
|
So: this is _very_ provisional stuff.
|
|
|
|
*/
|
2023-05-10 21:02:18 +00:00
|
|
|
namespace CPU::MOS6502Esque {
|
2020-09-28 22:43:53 +00:00
|
|
|
|
2020-09-29 01:35:46 +00:00
|
|
|
/*
|
2023-05-10 23:53:38 +00:00
|
|
|
The list of registers that can be accessed via @c value_of(Register) and @c set_value_of(Register, value).
|
2020-09-29 01:35:46 +00:00
|
|
|
*/
|
|
|
|
enum Register {
|
|
|
|
LastOperationAddress,
|
|
|
|
ProgramCounter,
|
|
|
|
StackPointer,
|
|
|
|
Flags,
|
|
|
|
A,
|
|
|
|
X,
|
2020-10-14 01:38:30 +00:00
|
|
|
Y,
|
|
|
|
|
2024-03-04 18:25:40 +00:00
|
|
|
// These `ex`ist on a 65816 only.
|
2020-10-14 01:38:30 +00:00
|
|
|
EmulationFlag,
|
|
|
|
DataBank,
|
|
|
|
ProgramBank,
|
|
|
|
Direct
|
2020-09-29 01:35:46 +00:00
|
|
|
};
|
|
|
|
|
2020-10-06 02:23:33 +00:00
|
|
|
/*
|
2023-05-10 23:53:38 +00:00
|
|
|
Flags as defined on the 6502; can be used to decode the result of @c value_of(Flags) or to form a value for
|
2020-10-06 02:23:33 +00:00
|
|
|
the corresponding set.
|
|
|
|
*/
|
|
|
|
enum Flag: uint8_t {
|
|
|
|
Sign = 0x80,
|
|
|
|
Overflow = 0x40,
|
|
|
|
Always = 0x20,
|
|
|
|
Break = 0x10,
|
|
|
|
Decimal = 0x08,
|
|
|
|
Interrupt = 0x04,
|
|
|
|
Zero = 0x02,
|
2020-10-11 01:23:59 +00:00
|
|
|
Carry = 0x01,
|
|
|
|
|
|
|
|
// These are available on a 65816 only.
|
|
|
|
MemorySize = 0x20,
|
|
|
|
IndexSize = 0x10,
|
2020-10-06 02:23:33 +00:00
|
|
|
};
|
|
|
|
|
2020-09-28 22:43:53 +00:00
|
|
|
/*!
|
|
|
|
Bus handlers will be given the task of performing bus operations, allowing them to provide whatever interface they like
|
2020-10-16 01:35:01 +00:00
|
|
|
between a 6502-esque chip and the rest of the system. @c BusOperation lists the types of bus operation that may be requested.
|
2020-09-28 22:43:53 +00:00
|
|
|
*/
|
|
|
|
enum BusOperation {
|
2020-10-16 01:35:01 +00:00
|
|
|
/// 6502: indicates that a read was signalled.
|
|
|
|
/// 65816: indicates that a read was signalled with VDA.
|
2020-10-11 19:25:13 +00:00
|
|
|
Read,
|
2020-10-16 01:35:01 +00:00
|
|
|
/// 6502: indicates that a read was signalled with SYNC.
|
|
|
|
/// 65816: indicates that a read was signalled with VDA and VPA.
|
2020-10-11 19:25:13 +00:00
|
|
|
ReadOpcode,
|
2020-10-16 01:35:01 +00:00
|
|
|
/// 6502: never signalled.
|
|
|
|
/// 65816: indicates that a read was signalled with VPA.
|
|
|
|
ReadProgram,
|
|
|
|
/// 6502: never signalled.
|
2022-06-24 14:37:39 +00:00
|
|
|
/// 65816: indicates that a read was signalled with VPB and VDA.
|
2020-10-16 01:35:01 +00:00
|
|
|
ReadVector,
|
2020-10-17 01:56:20 +00:00
|
|
|
/// 6502: never signalled.
|
|
|
|
/// 65816: indicates that a read was signalled, but neither VDA nor VPA were active.
|
|
|
|
InternalOperationRead,
|
2020-10-16 01:35:01 +00:00
|
|
|
|
2020-10-17 01:56:20 +00:00
|
|
|
/// All processors: indicates that the processor is paused due to the RDY input.
|
2020-10-16 01:35:01 +00:00
|
|
|
/// 65C02 and 65816: indicates a WAI is ongoing.
|
2020-10-11 19:25:13 +00:00
|
|
|
Ready,
|
2020-10-16 01:35:01 +00:00
|
|
|
|
|
|
|
/// 65C02 and 65816: indicates a STP condition.
|
|
|
|
None,
|
2020-11-04 01:17:09 +00:00
|
|
|
|
|
|
|
/// 6502: indicates that a write was signalled.
|
|
|
|
/// 65816: indicates that a write was signalled with VDA.
|
|
|
|
Write,
|
|
|
|
/// 6502: never signalled.
|
|
|
|
/// 65816: indicates that a write was signalled, but neither VDA nor VPA were active.
|
|
|
|
InternalOperationWrite,
|
2020-09-28 22:43:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*!
|
2020-10-17 01:56:20 +00:00
|
|
|
For a machine watching only the RWB line, evaluates to @c true if the operation should be treated as a read; @c false otherwise.
|
2020-09-28 22:43:53 +00:00
|
|
|
*/
|
2020-10-18 02:27:04 +00:00
|
|
|
#define isReadOperation(v) (v <= CPU::MOS6502Esque::InternalOperationRead)
|
2020-09-28 22:43:53 +00:00
|
|
|
|
2020-10-16 01:35:01 +00:00
|
|
|
/*!
|
2020-10-17 01:56:20 +00:00
|
|
|
For a machine watching only the RWB line, evaluates to @c true if the operation is any sort of write; @c false otherwise.
|
2020-10-16 01:35:01 +00:00
|
|
|
*/
|
2020-11-04 01:17:09 +00:00
|
|
|
#define isWriteOperation(v) (v >= CPU::MOS6502Esque::Write)
|
2020-10-16 01:35:01 +00:00
|
|
|
|
|
|
|
/*!
|
2020-10-17 01:56:20 +00:00
|
|
|
Evaluates to @c true if the operation actually expects a response; @c false otherwise.
|
2020-10-16 01:35:01 +00:00
|
|
|
*/
|
2020-11-04 01:17:09 +00:00
|
|
|
#define isAccessOperation(v) ((v <= CPU::MOS6502Esque::ReadVector) || (v == CPU::MOS6502Esque::Write))
|
2020-10-16 01:35:01 +00:00
|
|
|
|
2020-09-28 22:43:53 +00:00
|
|
|
/*!
|
|
|
|
A class providing empty implementations of the methods a 6502 uses to access the bus. To wire the 6502 to a bus,
|
|
|
|
machines should subclass BusHandler and then declare a realisation of the 6502 template, suplying their bus
|
|
|
|
handler.
|
|
|
|
*/
|
2020-10-18 19:08:21 +00:00
|
|
|
template <typename addr_t> class BusHandler {
|
2020-09-28 22:43:53 +00:00
|
|
|
public:
|
2020-10-18 19:08:21 +00:00
|
|
|
using AddressType = addr_t;
|
|
|
|
|
2020-09-28 22:43:53 +00:00
|
|
|
/*!
|
|
|
|
Announces that the 6502 has performed the cycle defined by operation, address and value. On the 6502,
|
|
|
|
all bus cycles take one clock cycle so the amoutn of time advanced is implicit.
|
|
|
|
|
|
|
|
@param operation The type of bus cycle: read, read opcode (i.e. read, with sync active),
|
|
|
|
write or ready.
|
|
|
|
@param address The value of the address bus during this bus cycle.
|
|
|
|
@param value If this is a cycle that puts a value onto the data bus, *value is that value. If this is
|
|
|
|
a cycle that reads the bus, the bus handler should write a value to *value. Writing to *value during
|
|
|
|
a read cycle will produce undefined behaviour.
|
|
|
|
|
|
|
|
@returns The number of cycles that passed in objective time while this 6502 bus cycle was ongoing.
|
|
|
|
On an archetypal machine this will be Cycles(1) but some architectures may choose not to clock the 6502
|
|
|
|
during some periods; one way to simulate that is to have the bus handler return a number other than
|
|
|
|
Cycles(1) to describe lengthened bus cycles.
|
|
|
|
*/
|
2020-10-18 19:08:21 +00:00
|
|
|
Cycles perform_bus_operation([[maybe_unused]] BusOperation operation, [[maybe_unused]] addr_t address, [[maybe_unused]] uint8_t *value) {
|
2020-09-28 22:43:53 +00:00
|
|
|
return Cycles(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|