1
0
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:
Thomas Harte 2022-05-24 15:42:50 -04:00
parent 780954f27b
commit 01e93ba916
2 changed files with 93 additions and 12 deletions

View File

@ -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:

View File

@ -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);