mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-26 09:29:45 +00:00
Add DIVU/DIVS, at least as far as getting the correct numeric result.
This commit is contained in:
parent
176c8355cb
commit
f97d2a0eb9
@ -158,6 +158,8 @@ enum ExecutionState: int {
|
||||
MOVEMtoM_l_write, MOVEMtoM_w_write,
|
||||
MOVEMtoM_l_write_predec, MOVEMtoM_w_write_predec,
|
||||
MOVEMtoM_finish,
|
||||
|
||||
DIVU_DIVS,
|
||||
};
|
||||
|
||||
// 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(TSTl, perform_state_ = Perform_np);
|
||||
|
||||
StdCASE(DIVU, perform_state_ = DIVU_DIVS);
|
||||
StdCASE(DIVS, perform_state_ = DIVU_DIVS);
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
@ -1521,7 +1526,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
||||
InstructionSet::M68k::perform<InstructionSet::M68k::Model::M68000>(
|
||||
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];
|
||||
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));
|
||||
|
||||
IdleBus(2 + did_bit_op_high_);
|
||||
IdleBus(2 + dynamic_instruction_length_);
|
||||
registers_[instruction_.reg(1)] = operand_[1];
|
||||
MoveToState(Decode);
|
||||
|
||||
@ -1828,6 +1833,32 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
||||
Prefetch(); // np
|
||||
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.
|
||||
//
|
||||
@ -1911,7 +1942,26 @@ void ProcessorBase::bsr(uint32_t offset) {
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -95,9 +95,10 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
|
||||
/// Transient storage for exception processing.
|
||||
SlicedInt16 captured_status_;
|
||||
|
||||
/// An internal flag used during BCHG, BSET and BCLR processing to
|
||||
/// determine total operation cost.
|
||||
bool did_bit_op_high_ = false;
|
||||
/// An internal flag used during various dynamically-sized instructions
|
||||
/// (e.g. BCHG, DIVU) to indicate how much additional processing happened;
|
||||
/// this is measured in microcycles.
|
||||
int dynamic_instruction_length_ = 0;
|
||||
|
||||
/// Two bits of state for MOVEM, being the curent register and what to
|
||||
/// 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_scc(bool);
|
||||
inline void did_shift(int) {} //
|
||||
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_divu(uint32_t, uint32_t);
|
||||
template <bool did_overflow> void did_divs(int32_t, int32_t);
|
||||
inline void did_bit_op(int);
|
||||
inline void did_update_status();
|
||||
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_from_usp(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
|
||||
// mean that the performer call-out isn't necessary.
|
||||
|
Loading…
Reference in New Issue
Block a user