1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

Attempts to complete all 65816 bus signalling.

This commit is contained in:
Thomas Harte 2020-10-16 21:56:20 -04:00
parent 096add7551
commit 3b398f7a9a
4 changed files with 49 additions and 37 deletions

View File

@ -79,37 +79,39 @@ enum BusOperation {
/// 6502: never signalled.
/// 65816: indicates that a read was signalled with VPB.
ReadVector,
/// 6502: never signalled.
/// 65816: indicates that a read was signalled, but neither VDA nor VPA were active.
InternalOperationRead,
/// 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,
/// All processors: indicates that the processor is holding state due to the RDY input.
/// All processors: indicates that the processor is paused due to the RDY input.
/// 65C02 and 65816: indicates a WAI is ongoing.
Ready,
/// 6502: never signalled.
/// 65816: indicates that a read was signalled, but neither VDA or VPA were active.
InternalOperation,
/// 65C02 and 65816: indicates a STP condition.
None,
};
/*!
Evaluates to @c true if the operation is any sort of read; @c false otherwise.
For a machine watching only the RWB line, evaluates to @c true if the operation should be treated as a read; @c false otherwise.
*/
#define isReadOperation(v) (v < CPU::MOS6502Esque::BusOperation::Write)
#define isReadOperation(v) (v < CPU::MOS6502Esque::Write)
/*!
Evaluates to @c true if the operation is any sort of write; @c false otherwise.
For a machine watching only the RWB line, evaluates to @c true if the operation is any sort of write; @c false otherwise.
*/
#define isWriteOperation(v) (v == CPU::MOS6502Esque::BusOperation::Write)
#define isWriteOperation(v) (v == CPU::MOS6502Esque::Write || v == CPU::MOS6502Esque::InternalOperationWrite)
/*!
Evaluates to @c true if the operation is any sort of memory access; @c false otherwise.
Evaluates to @c true if the operation actually expects a response; @c false otherwise.
*/
#define isAccessOperation(v) (v < CPU::MOS6502Esque::BusOperation::Ready)
#define isAccessOperation(v) ((v < CPU::MOS6502Esque::Ready) && (v != CPU::MOS6502Esque::InternalOperationRead) && (v != CPU::MOS6502Esque::InternalOperationWrite))
/*!
A class providing empty implementations of the methods a 6502 uses to access the bus. To wire the 6502 to a bus,

View File

@ -70,22 +70,22 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
// PC fetches.
//
case CycleFetchIncrementPC:
read(registers_.pc | registers_.program_bank, instruction_buffer_.next_input());
++registers_.pc;
break;
case CycleFetchOpcode:
perform_bus(registers_.pc | registers_.program_bank, instruction_buffer_.next_input(), MOS6502Esque::ReadOpcode);
++registers_.pc;
break;
case CycleFetchIncrementPC:
perform_bus(registers_.pc | registers_.program_bank, instruction_buffer_.next_input(), MOS6502Esque::ReadProgram);
++registers_.pc;
break;
case CycleFetchPC:
read(registers_.pc | registers_.program_bank, instruction_buffer_.next_input());
perform_bus(registers_.pc | registers_.program_bank, instruction_buffer_.next_input(), MOS6502Esque::ReadProgram);
break;
case CycleFetchPCThrowaway:
read(registers_.pc | registers_.program_bank, &bus_throwaway_);
perform_bus(registers_.pc | registers_.program_bank, &bus_throwaway_, MOS6502Esque::InternalOperationRead);
break;
//
@ -101,11 +101,11 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
break;
case CycleFetchDataThrowaway:
read(data_address_, &bus_throwaway_);
perform_bus(data_address_, &bus_throwaway_, MOS6502Esque::InternalOperationRead);
break;
case CycleFetchIncorrectDataAddress:
read(incorrect_data_address_, &bus_throwaway_);
perform_bus(incorrect_data_address_, &bus_throwaway_, MOS6502Esque::InternalOperationRead);
break;
case CycleFetchIncrementData:
@ -113,12 +113,21 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
increment_data_address();
break;
case CycleFetchVector:
perform_bus(data_address_, data_buffer_.next_input(), MOS6502Esque::ReadVector);
break;
case CycleFetchIncrementVector:
perform_bus(data_address_, data_buffer_.next_input(), MOS6502Esque::ReadVector);
increment_data_address();
break;
case CycleStoreData:
write(data_address_, data_buffer_.next_output());
break;
case CycleStoreDataThrowaway:
write(data_address_, data_buffer_.preview_output());
perform_bus(data_address_, data_buffer_.preview_output(), MOS6502Esque::InternalOperationWrite);
break;
case CycleStoreIncrementData:
@ -136,7 +145,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
break;
case CycleFetchBlockY:
read(((instruction_buffer_.value & 0xff00) << 8) | y(), &bus_throwaway_);
perform_bus(((instruction_buffer_.value & 0xff00) << 8) | y(), &bus_throwaway_, MOS6502Esque::InternalOperationRead);
break;
case CycleStoreBlockY:
@ -172,7 +181,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
break;
case CycleAccessStack:
stack_access(&bus_throwaway_, MOS6502Esque::Read);
stack_access(&bus_throwaway_, MOS6502Esque::InternalOperationRead);
break;
#undef stack_access

View File

@ -156,12 +156,11 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
}
static void read_modify_write(bool is8bit, const std::function<void(MicroOp)> &target) {
target(OperationSetMemoryLock);
target(OperationSetMemoryLock); // Set the memory lock output until the end of this instruction.
if(!is8bit) target(CycleFetchIncrementData); // Data low.
target(CycleFetchData); // Data [high].
// TODO: does this look like another read? Or if VDA and VPA are both low, does the 65816 actually do no access?
if(!is8bit) target(CycleFetchDataThrowaway); // 16-bit: reread final byte of data.
else target(CycleStoreDataThrowaway); // 8-bit rewrite final byte of data.
@ -182,7 +181,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
// 1b. Absolute; a, JMP.
static void absolute_jmp(AccessType, bool, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // New PCL.
target(CycleFetchIncrementPC); // New PCL.]
target(CycleFetchPC); // New PCH.
target(OperationPerform); // [JMP]
}
@ -199,9 +198,9 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
// 1d. Absolute; a, read-modify-write.
static void absolute_rmw(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // AAL.
target(CycleFetchIncrementPC); // AAH.
target(OperationConstructAbsolute); // Calculate data address.
target(CycleFetchIncrementPC); // AAL.
target(CycleFetchIncrementPC); // AAH.
target(OperationConstructAbsolute); // Calculate data address.
read_modify_write(is8bit, target);
}
@ -382,10 +381,10 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
// 10a. Direct; d.
// (That's zero page in 6502 terms)
static void direct(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // DO.
target(CycleFetchIncrementPC); // DO.
target(OperationConstructDirect);
target(CycleFetchPCThrowaway); // IO.
target(CycleFetchPCThrowaway); // IO.
read_write(type, is8bit, target);
}
@ -594,9 +593,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
target(CyclePush); // PCL
target(CyclePush); // P
// TODO: I think I need a seperate vector fetch here, to signal vector pull?
target(CycleFetchIncrementData); // AAVL
target(CycleFetchData); // AAVH
target(CycleFetchIncrementVector); // AAVL
target(CycleFetchVector); // AAVH
target(OperationPerform); // Jumps to the vector address.
}
@ -704,9 +702,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
target(CyclePush); // PCL
target(CyclePush); // P
// TODO: I think I need a seperate vector fetch here, to signal vector pull?
target(CycleFetchIncrementData); // AAVL
target(CycleFetchData); // AAVH
target(CycleFetchIncrementVector); // AAVL
target(CycleFetchVector); // AAVH
target(OperationPerform); // Jumps to the vector address.
}

View File

@ -25,6 +25,10 @@ enum MicroOp: uint8_t {
CycleFetchIncorrectDataAddress,
/// Fetches a byte from the data address and throws it away.
CycleFetchDataThrowaway,
/// Fetches a byte from the data address to the data buffer, signalling VPB .
CycleFetchVector,
/// Fetches a byte from the data address to the data buffer and increments the data address, signalling VPB.
CycleFetchIncrementVector,
// Dedicated block-move cycles; these use the data buffer as an intermediary.
CycleFetchBlockX,