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:
parent
176c8355cb
commit
f97d2a0eb9
@ -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.
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user