From 860cc63e215e18dbdfd5ebd4483830722f09fe95 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 20 May 2022 11:32:06 -0400 Subject: [PATCH] Attempt DBcc. --- .../Implementation/68000Mk2Implementation.hpp | 58 +++++++++++++++++++ .../Implementation/68000Mk2Storage.hpp | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp b/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp index 3e7b77ab3..71aa392ca 100644 --- a/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp +++ b/Processors/68000Mk2/Implementation/68000Mk2Implementation.hpp @@ -86,6 +86,11 @@ enum ExecutionState: int { Scc_Dn, Scc_Dn_did_not_set, Scc_Dn_did_set, + + DBcc, + DBcc_branch_taken, + DBcc_condition_true, + DBcc_counter_overflow, }; // MARK: - The state machine. @@ -516,6 +521,8 @@ void Processor( + instruction_, operand_[0], operand_[1], status_, *static_cast(this)); + // Next state is set by complete_dbcc + break; + + BeginState(DBcc_branch_taken): + IdleBus(1); // n + Prefetch(); // np + Prefetch(); // np + MoveToState(Decode); + + BeginState(DBcc_condition_true): + IdleBus(2); // n n + Prefetch(); // np + Prefetch(); // np + MoveToState(Decode); + + BeginState(DBcc_counter_overflow): + IdleBus(1); // n + + // Yacht lists an extra np here; I'm assuming it's a read from where + // the PC would have gone, had the branch been taken. So do that, + // but then reset the PC to where it would have been. + Prefetch(); + + program_counter_.l = instruction_address_.l + 4; + Prefetch(); // np + Prefetch(); // np + MoveToState(Decode); + // // Various states TODO. // @@ -1145,6 +1190,19 @@ void ProcessorBase::did_scc(bool did_set_ff) { state_ = did_set_ff ? Scc_Dn_did_set : Scc_Dn_did_not_set; } +void ProcessorBase::complete_dbcc(bool matched_condition, bool overflowed, int16_t offset) { + // The actual DBcc rule is: branch if !matched_condition and !overflowed; but I think + // that a spurious read from the intended destination PC occurs if overflowed, so update + // the PC for any case of !matched_condition and rely on the DBcc_counter_overflow to + // set it back. + if(!matched_condition) { + state_ = overflowed ? DBcc_counter_overflow : DBcc_branch_taken; + program_counter_.l = instruction_address_.l + uint32_t(offset) + 2; + return; + } + state_ = DBcc_condition_true; +} + // MARK: - External state. template diff --git a/Processors/68000Mk2/Implementation/68000Mk2Storage.hpp b/Processors/68000Mk2/Implementation/68000Mk2Storage.hpp index 7af820c99..2c06d4c8f 100644 --- a/Processors/68000Mk2/Implementation/68000Mk2Storage.hpp +++ b/Processors/68000Mk2/Implementation/68000Mk2Storage.hpp @@ -109,7 +109,7 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController { inline void did_bit_op(int) {} inline void did_update_status(); template void complete_bcc(bool, IntT) {} - inline void complete_dbcc(bool, bool, int16_t) {} + inline void complete_dbcc(bool, bool, int16_t); inline void bsr(uint32_t) {} inline void jsr(uint32_t) {} inline void jmp(uint32_t) {}