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:
parent
096add7551
commit
3b398f7a9a
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user