mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-06 10:38:16 +00:00
Add bus and address error, and VPA checks.
This commit is contained in:
parent
b037c76da6
commit
523cdd859b
@ -400,8 +400,37 @@ class Processor: private ProcessorBase {
|
||||
CPU::MC68000Mk2::State get_state();
|
||||
void set_state(const CPU::MC68000Mk2::State &);
|
||||
|
||||
// TODO: DTACK, VPA, BERR, interrupt input, bus ack/grant, halt,
|
||||
// get E clock phase (and the E clock in general).
|
||||
// TODO: bus ack/grant, halt,
|
||||
|
||||
/// Sets the DTack line — @c true for active, @c false for inactive.
|
||||
inline void set_dtack(bool dtack) {
|
||||
dtack_ = dtack;
|
||||
}
|
||||
|
||||
/// Sets the VPA (valid peripheral address) line — @c true for active, @c false for inactive.
|
||||
inline void set_is_peripheral_address(bool is_peripheral_address) {
|
||||
vpa_ = is_peripheral_address;
|
||||
}
|
||||
|
||||
/// Sets the bus error line — @c true for active, @c false for inactive.
|
||||
inline void set_bus_error(bool bus_error) {
|
||||
berr_ = bus_error;
|
||||
}
|
||||
|
||||
/// Sets the interrupt lines, IPL0, IPL1 and IPL2.
|
||||
inline void set_interrupt_level(int interrupt_level) {
|
||||
bus_interrupt_level_ = interrupt_level;
|
||||
}
|
||||
|
||||
/// @returns The current phase of the E clock; this will be a number of
|
||||
/// half-cycles between 0 and 19 inclusive, indicating how far the 68000
|
||||
/// is into the current E cycle.
|
||||
///
|
||||
/// This is guaranteed to be 0 at initial 68000 construction. It is not guaranteed
|
||||
/// to return the correct result if called during a bus transaction.
|
||||
HalfCycles get_e_clock_phase() {
|
||||
return e_clock_phase_;
|
||||
}
|
||||
|
||||
private:
|
||||
BusHandler &bus_handler_;
|
||||
|
@ -188,6 +188,7 @@ enum ExecutionState: int {
|
||||
template <class BusHandler, bool dtack_is_implicit, bool permit_overrun, bool signal_will_perform>
|
||||
void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perform>::run_for(HalfCycles duration) {
|
||||
// Accumulate the newly paid-in cycles. If this instance remains in deficit, exit.
|
||||
e_clock_phase_ += duration;
|
||||
time_remaining_ += duration;
|
||||
if(time_remaining_ < HalfCycles(0)) return;
|
||||
|
||||
@ -262,12 +263,22 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
||||
|
||||
// Performs the bus operation provided, which will be one with a
|
||||
// SelectWord or SelectByte operation, stretching it to match the E
|
||||
// bus if VPA is currently asserted.
|
||||
// bus if VPA is currently asserted or seguing elsewhere if a bus
|
||||
// error is signalled or an adress error observed.
|
||||
//
|
||||
// TODO: If BERR is asserted, stop here and perform a bus error exception.
|
||||
// E clock behaviour implemented, which I think is correct:
|
||||
//
|
||||
// TODO: If VPA is asserted, stretch this cycle.
|
||||
// (1) wait until end of current 10-cycle window;
|
||||
// (2) run for the next 10-cycle window.
|
||||
#define CompleteAccess(x) \
|
||||
if(berr_ || (*x.address & (x.operation >> 1) & 1)) { \
|
||||
MoveToStateSpecific(BusOrAddressErrorException); \
|
||||
} \
|
||||
if(vpa_) { \
|
||||
x.length = HalfCycles(20) + (HalfCycles(20) + (e_clock_phase_ - time_remaining_) % HalfCycles(20)) % HalfCycles(20); \
|
||||
} else { \
|
||||
x.length = HalfCycles(4); \
|
||||
} \
|
||||
PerformBusOperation(x)
|
||||
|
||||
// Performs the memory access implied by the announce, perform pair,
|
||||
|
Loading…
x
Reference in New Issue
Block a user