mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-29 12:50:28 +00:00
Make an attempt at bus/address error.
This commit is contained in:
parent
780954f27b
commit
01e93ba916
@ -17,7 +17,7 @@
|
|||||||
namespace CPU {
|
namespace CPU {
|
||||||
namespace MC68000Mk2 {
|
namespace MC68000Mk2 {
|
||||||
|
|
||||||
// TODO: obeyance of the trace flag, the address/bus error exception.
|
// TODO: obeyance of the trace flag.
|
||||||
|
|
||||||
/// States for the state machine which are named by
|
/// States for the state machine which are named by
|
||||||
/// me for their purpose rather than automatically by file position.
|
/// me for their purpose rather than automatically by file position.
|
||||||
@ -270,6 +270,8 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
// (2) run for the next 10-cycle window.
|
// (2) run for the next 10-cycle window.
|
||||||
#define CompleteAccess(x) \
|
#define CompleteAccess(x) \
|
||||||
if(berr_ || (*x.address & (x.operation >> 1) & 1)) { \
|
if(berr_ || (*x.address & (x.operation >> 1) & 1)) { \
|
||||||
|
bus_error_ = x; \
|
||||||
|
exception_vector_ = berr_ ? InstructionSet::M68k::AccessFault : InstructionSet::M68k::AddressError; \
|
||||||
MoveToStateSpecific(BusOrAddressErrorException); \
|
MoveToStateSpecific(BusOrAddressErrorException); \
|
||||||
} \
|
} \
|
||||||
if(vpa_) { \
|
if(vpa_) { \
|
||||||
@ -375,9 +377,10 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
BeginState(StandardException):
|
BeginState(StandardException):
|
||||||
captured_status_.w = status_.status();
|
captured_status_.w = status_.status();
|
||||||
|
|
||||||
// Switch to supervisor mode.
|
// Switch to supervisor mode, disable interrupts.
|
||||||
status_.is_supervisor = true;
|
status_.is_supervisor = true;
|
||||||
status_.trace_flag = 0;
|
status_.trace_flag = 0;
|
||||||
|
status_.interrupt_level = 7;
|
||||||
did_update_status();
|
did_update_status();
|
||||||
|
|
||||||
SetupDataAccess(0, Microcycle::SelectWord);
|
SetupDataAccess(0, Microcycle::SelectWord);
|
||||||
@ -412,6 +415,91 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
Prefetch(); // np
|
Prefetch(); // np
|
||||||
MoveToStateSpecific(Decode);
|
MoveToStateSpecific(Decode);
|
||||||
|
|
||||||
|
BeginState(BusOrAddressErrorException):
|
||||||
|
// "The microcode pushes the stack frame in a non consecutive order"
|
||||||
|
// per Ijor's document, but little further information is given.
|
||||||
|
//
|
||||||
|
// So the below is a cross-your-fingers guess based on the constraints
|
||||||
|
// that the information writen, from lowest address to highest is:
|
||||||
|
//
|
||||||
|
// R/W, I/N, function code word; [at -2]
|
||||||
|
// access address; [-6]
|
||||||
|
// instruction register; [-8]
|
||||||
|
// status register; [-10]
|
||||||
|
// program counter. [-14]
|
||||||
|
//
|
||||||
|
// With the instruction register definitely being written before the
|
||||||
|
// function code word.
|
||||||
|
//
|
||||||
|
// And the documented bus pattern is:
|
||||||
|
//
|
||||||
|
// nn ns ns nS ns ns ns nS nV nv np n np
|
||||||
|
//
|
||||||
|
// So, based on the hoopy ordering of a standard exception, maybe:
|
||||||
|
//
|
||||||
|
// 1) status register;
|
||||||
|
// 2) program counter;
|
||||||
|
// 3) instruction register;
|
||||||
|
// 4) function code;
|
||||||
|
// 5) access address?
|
||||||
|
|
||||||
|
captured_status_.w = status_.status();
|
||||||
|
IdleBus(2);
|
||||||
|
|
||||||
|
// Switch to supervisor mode, disable interrupts.
|
||||||
|
status_.is_supervisor = true;
|
||||||
|
status_.trace_flag = 0;
|
||||||
|
status_.interrupt_level = 7;
|
||||||
|
did_update_status();
|
||||||
|
|
||||||
|
SetupDataAccess(0, Microcycle::SelectWord);
|
||||||
|
SetDataAddress(registers_[15].l);
|
||||||
|
|
||||||
|
registers_[15].l -= 10;
|
||||||
|
Access(captured_status_); // ns
|
||||||
|
|
||||||
|
temporary_address_.l = program_counter_.l;
|
||||||
|
registers_[15].l -= 2;
|
||||||
|
Access(temporary_address_.low); // ns
|
||||||
|
|
||||||
|
registers_[15].l -= 2;
|
||||||
|
Access(temporary_address_.high); // nS
|
||||||
|
|
||||||
|
registers_[15].l += 6;
|
||||||
|
temporary_value_.w = opcode_;
|
||||||
|
Access(temporary_value_.low); // ns
|
||||||
|
|
||||||
|
// TODO: construct the function code.
|
||||||
|
temporary_value_.w = (temporary_value_.w & ~31);
|
||||||
|
|
||||||
|
registers_[15].l += 6;
|
||||||
|
Access(temporary_value_.low); // ns
|
||||||
|
|
||||||
|
temporary_address_.l = *bus_error_.address;
|
||||||
|
registers_[15].l -= 2;
|
||||||
|
Access(temporary_value_.low); // ns
|
||||||
|
|
||||||
|
registers_[15].l -= 2;
|
||||||
|
Access(temporary_value_.high); // nS
|
||||||
|
registers_[15].l -= 8;
|
||||||
|
|
||||||
|
// Grab new program counter.
|
||||||
|
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
|
||||||
|
SetDataAddress(temporary_address_.l);
|
||||||
|
|
||||||
|
temporary_address_.l = uint32_t(exception_vector_ << 2);
|
||||||
|
Access(program_counter_.high); // nV
|
||||||
|
|
||||||
|
temporary_address_.l += 2;
|
||||||
|
Access(program_counter_.low); // nv
|
||||||
|
|
||||||
|
// Populate the prefetch queue.
|
||||||
|
Prefetch(); // np
|
||||||
|
IdleBus(1); // n
|
||||||
|
Prefetch(); // np
|
||||||
|
|
||||||
|
MoveToStateSpecific(Decode);
|
||||||
|
|
||||||
// Acknowledge an interrupt, thereby obtaining an exception vector,
|
// Acknowledge an interrupt, thereby obtaining an exception vector,
|
||||||
// and do the exception.
|
// and do the exception.
|
||||||
BeginState(DoInterrupt):
|
BeginState(DoInterrupt):
|
||||||
@ -2292,16 +2380,6 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
exception_vector_ = InstructionSet::M68k::Exception::TRAPV;
|
exception_vector_ = InstructionSet::M68k::Exception::TRAPV;
|
||||||
MoveToStateSpecific(StandardException);
|
MoveToStateSpecific(StandardException);
|
||||||
|
|
||||||
//
|
|
||||||
// Various states TODO.
|
|
||||||
//
|
|
||||||
#define TODOState(x) \
|
|
||||||
BeginState(x): [[fallthrough]];
|
|
||||||
|
|
||||||
BeginState(BusOrAddressErrorException):
|
|
||||||
assert(false);
|
|
||||||
MoveToStateSpecific(Decode);
|
|
||||||
|
|
||||||
#undef TODOState
|
#undef TODOState
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -136,6 +136,9 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
|
|||||||
/// determine the size of the bus operation.
|
/// determine the size of the bus operation.
|
||||||
Microcycle::OperationT select_flag_ = 0;
|
Microcycle::OperationT select_flag_ = 0;
|
||||||
|
|
||||||
|
// Captured bus/address-error state.
|
||||||
|
Microcycle bus_error_;
|
||||||
|
|
||||||
// Flow controller methods implemented.
|
// Flow controller methods implemented.
|
||||||
using Preinstruction = InstructionSet::M68k::Preinstruction;
|
using Preinstruction = InstructionSet::M68k::Preinstruction;
|
||||||
template <typename IntT> void did_mulu(IntT);
|
template <typename IntT> void did_mulu(IntT);
|
||||||
|
Loading…
Reference in New Issue
Block a user