mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-25 16:31:42 +00:00
Attempt DBcc.
This commit is contained in:
parent
452dd3ccfd
commit
860cc63e21
@ -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<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
||||
}
|
||||
});
|
||||
|
||||
StdCASE(DBcc, perform_state_ = DBcc);
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
@ -1092,6 +1099,44 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
||||
next_operand_ = 0;
|
||||
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.
|
||||
//
|
||||
@ -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 <class BusHandler, bool dtack_is_implicit, bool permit_overrun, bool signal_will_perform>
|
||||
|
@ -109,7 +109,7 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
|
||||
inline void did_bit_op(int) {}
|
||||
inline void did_update_status();
|
||||
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 jsr(uint32_t) {}
|
||||
inline void jmp(uint32_t) {}
|
||||
|
Loading…
Reference in New Issue
Block a user