1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Attempt DBcc.

This commit is contained in:
Thomas Harte 2022-05-20 11:32:06 -04:00
parent 452dd3ccfd
commit 860cc63e21
2 changed files with 59 additions and 1 deletions

View File

@ -86,6 +86,11 @@ enum ExecutionState: int {
Scc_Dn, Scc_Dn,
Scc_Dn_did_not_set, Scc_Dn_did_not_set,
Scc_Dn_did_set, Scc_Dn_did_set,
DBcc,
DBcc_branch_taken,
DBcc_condition_true,
DBcc_counter_overflow,
}; };
// MARK: - The state machine. // MARK: - The state machine.
@ -516,6 +521,8 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
} }
}); });
StdCASE(DBcc, perform_state_ = DBcc);
default: default:
assert(false); assert(false);
} }
@ -1092,6 +1099,44 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
next_operand_ = 0; next_operand_ = 0;
MoveToState(StoreOperand); MoveToState(StoreOperand);
//
// DBcc
//
BeginState(DBcc):
InstructionSet::M68k::perform<
InstructionSet::M68k::Model::M68000,
ProcessorBase,
InstructionSet::M68k::Operation::DBcc
>(
instruction_, operand_[0], operand_[1], status_, *static_cast<ProcessorBase *>(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. // 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; 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. // MARK: - External state.
template <class BusHandler, bool dtack_is_implicit, bool permit_overrun, bool signal_will_perform> template <class BusHandler, bool dtack_is_implicit, bool permit_overrun, bool signal_will_perform>

View File

@ -109,7 +109,7 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
inline void did_bit_op(int) {} inline void did_bit_op(int) {}
inline void did_update_status(); inline void did_update_status();
template <typename IntT> void complete_bcc(bool, IntT) {} template <typename IntT> 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 bsr(uint32_t) {}
inline void jsr(uint32_t) {} inline void jsr(uint32_t) {}
inline void jmp(uint32_t) {} inline void jmp(uint32_t) {}