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

Add DIVU/DIVS, at least as far as getting the correct numeric result.

This commit is contained in:
Thomas Harte 2022-05-21 15:56:09 -04:00
parent 176c8355cb
commit f97d2a0eb9
2 changed files with 60 additions and 9 deletions

View File

@ -158,6 +158,8 @@ enum ExecutionState: int {
MOVEMtoM_l_write, MOVEMtoM_w_write, MOVEMtoM_l_write, MOVEMtoM_w_write,
MOVEMtoM_l_write_predec, MOVEMtoM_w_write_predec, MOVEMtoM_l_write_predec, MOVEMtoM_w_write_predec,
MOVEMtoM_finish, MOVEMtoM_finish,
DIVU_DIVS,
}; };
// MARK: - The state machine. // MARK: - The state machine.
@ -685,6 +687,9 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
StdCASE(TSTw, perform_state_ = Perform_np); StdCASE(TSTw, perform_state_ = Perform_np);
StdCASE(TSTl, perform_state_ = Perform_np); StdCASE(TSTl, perform_state_ = Perform_np);
StdCASE(DIVU, perform_state_ = DIVU_DIVS);
StdCASE(DIVS, perform_state_ = DIVU_DIVS);
default: default:
assert(false); assert(false);
} }
@ -1521,7 +1526,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
InstructionSet::M68k::perform<InstructionSet::M68k::Model::M68000>( InstructionSet::M68k::perform<InstructionSet::M68k::Model::M68000>(
instruction_, operand_[0], operand_[1], status_, *static_cast<ProcessorBase *>(this)); instruction_, operand_[0], operand_[1], status_, *static_cast<ProcessorBase *>(this));
IdleBus(1 + did_bit_op_high_); IdleBus(1 + dynamic_instruction_length_);
registers_[instruction_.reg(1)] = operand_[1]; registers_[instruction_.reg(1)] = operand_[1];
MoveToState(Decode); MoveToState(Decode);
@ -1533,7 +1538,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
>( >(
instruction_, operand_[0], operand_[1], status_, *static_cast<ProcessorBase *>(this)); instruction_, operand_[0], operand_[1], status_, *static_cast<ProcessorBase *>(this));
IdleBus(2 + did_bit_op_high_); IdleBus(2 + dynamic_instruction_length_);
registers_[instruction_.reg(1)] = operand_[1]; registers_[instruction_.reg(1)] = operand_[1];
MoveToState(Decode); MoveToState(Decode);
@ -1828,6 +1833,32 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
Prefetch(); // np Prefetch(); // np
MoveToState(Decode); MoveToState(Decode);
//
// DIVU and DIVUS
//
BeginState(DIVU_DIVS):
// Set a no-interrupt-occurred sentinel.
exception_vector_ = -1;
// Perform the instruction.
InstructionSet::M68k::perform<InstructionSet::M68k::Model::M68000>(
instruction_, operand_[0], operand_[1], status_, *static_cast<ProcessorBase *>(this));
// Delay the correct amount of time.
IdleBus(dynamic_instruction_length_);
// Either dispatch an exception or don't.
if(exception_vector_ >= 0) {
MoveToState(StandardException);
}
// DIVU and DIVS are always to a register, so just write back here
// to save on dispatch costs.
registers_[instruction_.reg(1)] = operand_[1];
Prefetch(); // np
MoveToState(Decode);
// //
// Various states TODO. // Various states TODO.
// //
@ -1911,7 +1942,26 @@ void ProcessorBase::bsr(uint32_t offset) {
} }
void ProcessorBase::did_bit_op(int bit_position) { void ProcessorBase::did_bit_op(int bit_position) {
did_bit_op_high_ = bit_position > 15; dynamic_instruction_length_ = int(bit_position > 15);
}
template <bool did_overflow> void ProcessorBase::did_divu(uint32_t, uint32_t) {
// TODO: calculate cost.
}
template <bool did_overflow> void ProcessorBase::did_divs(int32_t, int32_t) {
// TODO: calculate cost.
}
template <bool use_current_instruction_pc> void ProcessorBase::raise_exception(int vector) {
// No overt action is taken here; instructions that might throw an exception are required
// to check-in after the fact.
//
// As implemented above, that means:
//
// * DIVU;
// * DIVS.
exception_vector_ = vector;
} }
// MARK: - External state. // MARK: - External state.

View File

@ -95,9 +95,10 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
/// Transient storage for exception processing. /// Transient storage for exception processing.
SlicedInt16 captured_status_; SlicedInt16 captured_status_;
/// An internal flag used during BCHG, BSET and BCLR processing to /// An internal flag used during various dynamically-sized instructions
/// determine total operation cost. /// (e.g. BCHG, DIVU) to indicate how much additional processing happened;
bool did_bit_op_high_ = false; /// this is measured in microcycles.
int dynamic_instruction_length_ = 0;
/// Two bits of state for MOVEM, being the curent register and what to /// Two bits of state for MOVEM, being the curent register and what to
/// add to it to get to the next register. /// add to it to get to the next register.
@ -126,8 +127,8 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
inline void did_chk(bool, bool); inline void did_chk(bool, bool);
inline void did_scc(bool); inline void did_scc(bool);
inline void did_shift(int) {} // inline void did_shift(int) {} //
template <bool did_overflow> void did_divu(uint32_t, uint32_t) {} // template <bool did_overflow> void did_divu(uint32_t, uint32_t);
template <bool did_overflow> void did_divs(int32_t, int32_t) {} // template <bool did_overflow> void did_divs(int32_t, int32_t);
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);
@ -146,7 +147,7 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
inline void move_to_usp(uint32_t) {} // inline void move_to_usp(uint32_t) {} //
inline void move_from_usp(uint32_t &) {} // inline void move_from_usp(uint32_t &) {} //
inline void tas(Preinstruction, uint32_t) {} // inline void tas(Preinstruction, uint32_t) {} //
template <bool use_current_instruction_pc = true> void raise_exception(int) {} template <bool use_current_instruction_pc = true> void raise_exception(int);
// These aren't implemented because the specific details of the implementation // These aren't implemented because the specific details of the implementation
// mean that the performer call-out isn't necessary. // mean that the performer call-out isn't necessary.