1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-01 11:49:58 +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. /// 6502: never signalled.
/// 65816: indicates that a read was signalled with VPB. /// 65816: indicates that a read was signalled with VPB.
ReadVector, 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. /// 6502: indicates that a write was signalled.
/// 65816: indicates that a write was signalled with VDA. /// 65816: indicates that a write was signalled with VDA.
Write, 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. /// 65C02 and 65816: indicates a WAI is ongoing.
Ready, 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. /// 65C02 and 65816: indicates a STP condition.
None, 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, 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. // PC fetches.
// //
case CycleFetchIncrementPC:
read(registers_.pc | registers_.program_bank, instruction_buffer_.next_input());
++registers_.pc;
break;
case CycleFetchOpcode: case CycleFetchOpcode:
perform_bus(registers_.pc | registers_.program_bank, instruction_buffer_.next_input(), MOS6502Esque::ReadOpcode); perform_bus(registers_.pc | registers_.program_bank, instruction_buffer_.next_input(), MOS6502Esque::ReadOpcode);
++registers_.pc; ++registers_.pc;
break; break;
case CycleFetchIncrementPC:
perform_bus(registers_.pc | registers_.program_bank, instruction_buffer_.next_input(), MOS6502Esque::ReadProgram);
++registers_.pc;
break;
case CycleFetchPC: 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; break;
case CycleFetchPCThrowaway: case CycleFetchPCThrowaway:
read(registers_.pc | registers_.program_bank, &bus_throwaway_); perform_bus(registers_.pc | registers_.program_bank, &bus_throwaway_, MOS6502Esque::InternalOperationRead);
break; break;
// //
@ -101,11 +101,11 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
break; break;
case CycleFetchDataThrowaway: case CycleFetchDataThrowaway:
read(data_address_, &bus_throwaway_); perform_bus(data_address_, &bus_throwaway_, MOS6502Esque::InternalOperationRead);
break; break;
case CycleFetchIncorrectDataAddress: case CycleFetchIncorrectDataAddress:
read(incorrect_data_address_, &bus_throwaway_); perform_bus(incorrect_data_address_, &bus_throwaway_, MOS6502Esque::InternalOperationRead);
break; break;
case CycleFetchIncrementData: case CycleFetchIncrementData:
@ -113,12 +113,21 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
increment_data_address(); increment_data_address();
break; 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: case CycleStoreData:
write(data_address_, data_buffer_.next_output()); write(data_address_, data_buffer_.next_output());
break; break;
case CycleStoreDataThrowaway: case CycleStoreDataThrowaway:
write(data_address_, data_buffer_.preview_output()); perform_bus(data_address_, data_buffer_.preview_output(), MOS6502Esque::InternalOperationWrite);
break; break;
case CycleStoreIncrementData: case CycleStoreIncrementData:
@ -136,7 +145,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
break; break;
case CycleFetchBlockY: case CycleFetchBlockY:
read(((instruction_buffer_.value & 0xff00) << 8) | y(), &bus_throwaway_); perform_bus(((instruction_buffer_.value & 0xff00) << 8) | y(), &bus_throwaway_, MOS6502Esque::InternalOperationRead);
break; break;
case CycleStoreBlockY: case CycleStoreBlockY:
@ -172,7 +181,7 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
break; break;
case CycleAccessStack: case CycleAccessStack:
stack_access(&bus_throwaway_, MOS6502Esque::Read); stack_access(&bus_throwaway_, MOS6502Esque::InternalOperationRead);
break; break;
#undef stack_access #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) { 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. if(!is8bit) target(CycleFetchIncrementData); // Data low.
target(CycleFetchData); // Data [high]. 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. if(!is8bit) target(CycleFetchDataThrowaway); // 16-bit: reread final byte of data.
else target(CycleStoreDataThrowaway); // 8-bit rewrite 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. // 1b. Absolute; a, JMP.
static void 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(CycleFetchPC); // New PCH. target(CycleFetchPC); // New PCH.
target(OperationPerform); // [JMP] target(OperationPerform); // [JMP]
} }
@ -199,9 +198,9 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
// 1d. Absolute; a, read-modify-write. // 1d. Absolute; a, read-modify-write.
static void 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.
read_modify_write(is8bit, target); read_modify_write(is8bit, target);
} }
@ -382,10 +381,10 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
// 10a. Direct; d. // 10a. Direct; d.
// (That's zero page in 6502 terms) // (That's zero page in 6502 terms)
static void direct(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) { static void direct(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) {
target(CycleFetchIncrementPC); // DO. target(CycleFetchIncrementPC); // DO.
target(OperationConstructDirect); target(OperationConstructDirect);
target(CycleFetchPCThrowaway); // IO. target(CycleFetchPCThrowaway); // IO.
read_write(type, is8bit, target); read_write(type, is8bit, target);
} }
@ -594,9 +593,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
target(CyclePush); // PCL target(CyclePush); // PCL
target(CyclePush); // P target(CyclePush); // P
// TODO: I think I need a seperate vector fetch here, to signal vector pull? target(CycleFetchIncrementVector); // AAVL
target(CycleFetchIncrementData); // AAVL target(CycleFetchVector); // AAVH
target(CycleFetchData); // AAVH
target(OperationPerform); // Jumps to the vector address. target(OperationPerform); // Jumps to the vector address.
} }
@ -704,9 +702,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
target(CyclePush); // PCL target(CyclePush); // PCL
target(CyclePush); // P target(CyclePush); // P
// TODO: I think I need a seperate vector fetch here, to signal vector pull? target(CycleFetchIncrementVector); // AAVL
target(CycleFetchIncrementData); // AAVL target(CycleFetchVector); // AAVH
target(CycleFetchData); // AAVH
target(OperationPerform); // Jumps to the vector address. target(OperationPerform); // Jumps to the vector address.
} }

View File

@ -25,6 +25,10 @@ enum MicroOp: uint8_t {
CycleFetchIncorrectDataAddress, CycleFetchIncorrectDataAddress,
/// Fetches a byte from the data address and throws it away. /// Fetches a byte from the data address and throws it away.
CycleFetchDataThrowaway, 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. // Dedicated block-move cycles; these use the data buffer as an intermediary.
CycleFetchBlockX, CycleFetchBlockX,