mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Ensure IO cycles don't produce an address of (PC+1).
This commit is contained in:
parent
ab0c290489
commit
ec98736bd7
@ -99,6 +99,10 @@ template <typename BusHandler, bool uses_ready_line> void Processor<BusHandler,
|
|||||||
perform_bus(registers_.pc | registers_.program_bank, &bus_throwaway_, MOS6502Esque::InternalOperationRead);
|
perform_bus(registers_.pc | registers_.program_bank, &bus_throwaway_, MOS6502Esque::InternalOperationRead);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CycleFetchPreviousPCThrowaway:
|
||||||
|
perform_bus(((registers_.pc - 1) & 0xffff) | registers_.program_bank, &bus_throwaway_, MOS6502Esque::InternalOperationRead);
|
||||||
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Data fetches and stores.
|
// Data fetches and stores.
|
||||||
//
|
//
|
||||||
|
@ -387,7 +387,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
|
|
||||||
// 8. Accumulator; A.
|
// 8. Accumulator; A.
|
||||||
static void accumulator(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
static void accumulator(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
// TODO: seriously consider a-specific versions of all relevant operations;
|
// TODO: seriously consider a-specific versions of all relevant operations;
|
||||||
// the cost of interpreting three things here is kind of silly.
|
// the cost of interpreting three things here is kind of silly.
|
||||||
@ -416,10 +416,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(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
read_write(type, is8bit, target);
|
read_write(type, is8bit, target);
|
||||||
}
|
}
|
||||||
@ -430,7 +430,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // DO.
|
target(CycleFetchIncrementPC); // DO.
|
||||||
|
|
||||||
target(OperationConstructDirect);
|
target(OperationConstructDirect);
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
read_modify_write(is8bit, target);
|
read_modify_write(is8bit, target);
|
||||||
}
|
}
|
||||||
@ -440,9 +440,9 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // DO.
|
target(CycleFetchIncrementPC); // DO.
|
||||||
|
|
||||||
target(OperationConstructDirectIndexedIndirect);
|
target(OperationConstructDirectIndexedIndirect);
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CycleFetchIncrementData); // AAL.
|
target(CycleFetchIncrementData); // AAL.
|
||||||
target(CycleFetchData); // AAH.
|
target(CycleFetchData); // AAH.
|
||||||
@ -458,7 +458,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // DO.
|
target(CycleFetchIncrementPC); // DO.
|
||||||
|
|
||||||
target(OperationConstructDirect);
|
target(OperationConstructDirect);
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CycleFetchIncrementData); // AAL.
|
target(CycleFetchIncrementData); // AAL.
|
||||||
target(CycleFetchData); // AAH.
|
target(CycleFetchData); // AAH.
|
||||||
@ -473,7 +473,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // DO.
|
target(CycleFetchIncrementPC); // DO.
|
||||||
|
|
||||||
target(OperationConstructDirect);
|
target(OperationConstructDirect);
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CycleFetchIncrementData); // AAL.
|
target(CycleFetchIncrementData); // AAL.
|
||||||
target(CycleFetchData); // AAH.
|
target(CycleFetchData); // AAH.
|
||||||
@ -490,7 +490,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // DO.
|
target(CycleFetchIncrementPC); // DO.
|
||||||
|
|
||||||
target(OperationConstructDirect);
|
target(OperationConstructDirect);
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CycleFetchIncrementData); // AAL.
|
target(CycleFetchIncrementData); // AAL.
|
||||||
target(CycleFetchIncrementData); // AAH.
|
target(CycleFetchIncrementData); // AAH.
|
||||||
@ -506,7 +506,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // DO.
|
target(CycleFetchIncrementPC); // DO.
|
||||||
|
|
||||||
target(OperationConstructDirectLong);
|
target(OperationConstructDirectLong);
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CycleFetchIncrementData); // AAL.
|
target(CycleFetchIncrementData); // AAL.
|
||||||
target(CycleFetchIncrementData); // AAH.
|
target(CycleFetchIncrementData); // AAH.
|
||||||
@ -522,9 +522,9 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // DO.
|
target(CycleFetchIncrementPC); // DO.
|
||||||
|
|
||||||
target(OperationConstructDirectX);
|
target(OperationConstructDirectX);
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
read_write(type, is8bit, target);
|
read_write(type, is8bit, target);
|
||||||
}
|
}
|
||||||
@ -534,9 +534,9 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // DO.
|
target(CycleFetchIncrementPC); // DO.
|
||||||
|
|
||||||
target(OperationConstructDirectX);
|
target(OperationConstructDirectX);
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
read_modify_write(is8bit, target);
|
read_modify_write(is8bit, target);
|
||||||
}
|
}
|
||||||
@ -546,9 +546,9 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // DO.
|
target(CycleFetchIncrementPC); // DO.
|
||||||
|
|
||||||
target(OperationConstructDirectY);
|
target(OperationConstructDirectY);
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
read_write(type, is8bit, target);
|
read_write(type, is8bit, target);
|
||||||
}
|
}
|
||||||
@ -563,20 +563,20 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
|
|
||||||
static void immediate_rep_sep(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
static void immediate_rep_sep(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchIncrementPC); // IDL.
|
target(CycleFetchIncrementPC); // IDL.
|
||||||
target(CycleFetchPCThrowaway); // "Add 1 cycle for REP and SEP"
|
target(CycleFetchPreviousPCThrowaway); // "Add 1 cycle for REP and SEP"
|
||||||
target(OperationPerform);
|
target(OperationPerform);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 19a. Implied; i.
|
// 19a. Implied; i.
|
||||||
static void implied(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
static void implied(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
target(OperationPerform);
|
target(OperationPerform);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 19b. Implied; i; XBA.
|
// 19b. Implied; i; XBA.
|
||||||
static void implied_xba(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
static void implied_xba(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
target(OperationPerform);
|
target(OperationPerform);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,8 +584,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
// 19d. Wait for interrupt.
|
// 19d. Wait for interrupt.
|
||||||
static void stp_wai(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
static void stp_wai(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(OperationPerform); // Establishes the termination condition.
|
target(OperationPerform); // Establishes the termination condition.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
target(CycleRepeatingNone); // This will first check whether the STP/WAI exit
|
target(CycleRepeatingNone); // This will first check whether the STP/WAI exit
|
||||||
// condition has occurred; if not then it'll issue
|
// condition has occurred; if not then it'll issue
|
||||||
// either a BusOperation::None or ::Ready and then
|
// either a BusOperation::None or ::Ready and then
|
||||||
@ -594,34 +594,34 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
|
|
||||||
// 20. Relative; r.
|
// 20. Relative; r.
|
||||||
static void relative(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
static void relative(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchIncrementPC); // Offset.
|
target(CycleFetchIncrementPC); // Offset.
|
||||||
|
|
||||||
target(OperationPerform); // The branch instructions will all skip one or three
|
target(OperationPerform); // The branch instructions will all skip one or three
|
||||||
// of the next cycles, depending on the effect of
|
// of the next cycles, depending on the effect of
|
||||||
// the jump. It'll also calculate the correct target
|
// the jump. It'll also calculate the correct target
|
||||||
// address, placing it into the data buffer.
|
// address, placing it into the data buffer.
|
||||||
|
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(OperationCopyDataToPC); // Install the address that was calculated above.
|
target(OperationCopyDataToPC); // Install the address that was calculated above.
|
||||||
}
|
}
|
||||||
|
|
||||||
// 21. Relative long; rl.
|
// 21. Relative long; rl.
|
||||||
static void relative_long(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
static void relative_long(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchIncrementPC); // Offset low.
|
target(CycleFetchIncrementPC); // Offset low.
|
||||||
target(CycleFetchIncrementPC); // Offset high.
|
target(CycleFetchIncrementPC); // Offset high.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(OperationPerform); // [BRL]
|
target(OperationPerform); // [BRL]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 22a. Stack; s, abort/irq/nmi/res.
|
// 22a. Stack; s, abort/irq/nmi/res.
|
||||||
//
|
//
|
||||||
// Combined here with reset, which is the same sequence but with a different stack access.
|
// Combined here with reset, which is the same sequence but with a different stack access.
|
||||||
static void stack_exception_impl(AccessType, bool, const std::function<void(MicroOp)> &target, MicroOp stack_op) {
|
static void stack_exception_impl(AccessType, bool, const std::function<void(MicroOp)> &target, MicroOp stack_op) {
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(OperationPrepareException); // Populates the data buffer; if the exception is a
|
target(OperationPrepareException); // Populates the data buffer; if the exception is a
|
||||||
// reset then switches to the reset tail program.
|
// reset then switches to the reset tail program.
|
||||||
@ -654,8 +654,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
|
|
||||||
// 22b. Stack; s, PLx.
|
// 22b. Stack; s, PLx.
|
||||||
static void stack_pull(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
|
static void stack_pull(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
if(!is8bit) target(CyclePull); // REG low.
|
if(!is8bit) target(CyclePull); // REG low.
|
||||||
target(CyclePull); // REG [high].
|
target(CyclePull); // REG [high].
|
||||||
@ -665,7 +665,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
|
|
||||||
// 22c. Stack; s, PHx.
|
// 22c. Stack; s, PHx.
|
||||||
static void stack_push(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
|
static void stack_push(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(OperationPerform);
|
target(OperationPerform);
|
||||||
|
|
||||||
@ -689,7 +689,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
target(CycleFetchIncrementPC); // DO.
|
target(CycleFetchIncrementPC); // DO.
|
||||||
|
|
||||||
target(OperationConstructDirect);
|
target(OperationConstructDirect);
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CycleFetchIncrementData); // AAL.
|
target(CycleFetchIncrementData); // AAL.
|
||||||
target(CycleFetchData); // AAH.
|
target(CycleFetchData); // AAH.
|
||||||
@ -701,7 +701,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
static void stack_per(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
static void stack_per(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchIncrementPC); // Offset low.
|
target(CycleFetchIncrementPC); // Offset low.
|
||||||
target(CycleFetchIncrementPC); // Offset high.
|
target(CycleFetchIncrementPC); // Offset high.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(OperationConstructPER);
|
target(OperationConstructPER);
|
||||||
|
|
||||||
@ -711,8 +711,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
|
|
||||||
// 22g. Stack; s, RTI.
|
// 22g. Stack; s, RTI.
|
||||||
static void stack_rti(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
static void stack_rti(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CyclePull); // P.
|
target(CyclePull); // P.
|
||||||
target(CyclePull); // New PCL.
|
target(CyclePull); // New PCL.
|
||||||
@ -724,8 +724,8 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
|
|
||||||
// 22h. Stack; s, RTS.
|
// 22h. Stack; s, RTS.
|
||||||
static void stack_rts(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
static void stack_rts(AccessType, bool, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(CyclePull); // PCL.
|
target(CyclePull); // PCL.
|
||||||
target(CyclePull); // PCH.
|
target(CyclePull); // PCH.
|
||||||
@ -772,7 +772,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
// 23. Stack Relative; d, s.
|
// 23. Stack Relative; d, s.
|
||||||
static void stack_relative(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) {
|
static void stack_relative(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchIncrementPC); // SO.
|
target(CycleFetchIncrementPC); // SO.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(OperationConstructStackRelative);
|
target(OperationConstructStackRelative);
|
||||||
read_write(type, is8bit, target);
|
read_write(type, is8bit, target);
|
||||||
@ -781,7 +781,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
|
|||||||
// 24. Stack Relative Indirect Indexed (d, s), y.
|
// 24. Stack Relative Indirect Indexed (d, s), y.
|
||||||
static void stack_relative_indexed_indirect(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) {
|
static void stack_relative_indexed_indirect(AccessType type, bool is8bit, const std::function<void(MicroOp)> &target) {
|
||||||
target(CycleFetchIncrementPC); // SO.
|
target(CycleFetchIncrementPC); // SO.
|
||||||
target(CycleFetchPCThrowaway); // IO.
|
target(CycleFetchPreviousPCThrowaway); // IO.
|
||||||
|
|
||||||
target(OperationConstructStackRelative);
|
target(OperationConstructStackRelative);
|
||||||
target(CycleFetchIncrementData); // AAL.
|
target(CycleFetchIncrementData); // AAL.
|
||||||
|
@ -13,6 +13,8 @@ enum MicroOp: uint8_t {
|
|||||||
CycleFetchPC,
|
CycleFetchPC,
|
||||||
/// Fetches a byte from the program counter without incrementing it, and throws it away.
|
/// Fetches a byte from the program counter without incrementing it, and throws it away.
|
||||||
CycleFetchPCThrowaway,
|
CycleFetchPCThrowaway,
|
||||||
|
/// Fetches a byte from (PC - 1), and throws it away; useful for IO cycles that immediately follow incremented PCs.
|
||||||
|
CycleFetchPreviousPCThrowaway,
|
||||||
/// The same as CycleFetchIncrementPC but indicates valid program address rather than valid data address.
|
/// The same as CycleFetchIncrementPC but indicates valid program address rather than valid data address.
|
||||||
CycleFetchOpcode,
|
CycleFetchOpcode,
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user