mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-29 12:50:28 +00:00
Attempts to complete all 65816 bus signalling.
This commit is contained in:
parent
096add7551
commit
3b398f7a9a
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user