mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-06 13:31:55 +00:00
Merge branch '68000Mk2' into InMacintosh
This commit is contained in:
commit
f93bf06b99
@ -17,8 +17,6 @@
|
|||||||
namespace CPU {
|
namespace CPU {
|
||||||
namespace MC68000Mk2 {
|
namespace MC68000Mk2 {
|
||||||
|
|
||||||
// TODO: obeyance of the trace flag, the address/bus error exception.
|
|
||||||
|
|
||||||
/// 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.
|
||||||
/// These are negative to avoid ambiguity with the other group.
|
/// These are negative to avoid ambiguity with the other group.
|
||||||
@ -270,6 +268,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_) { \
|
||||||
@ -349,6 +349,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
status_.is_supervisor = true;
|
status_.is_supervisor = true;
|
||||||
status_.interrupt_level = 7;
|
status_.interrupt_level = 7;
|
||||||
status_.trace_flag = 0;
|
status_.trace_flag = 0;
|
||||||
|
should_trace_ = 0;
|
||||||
did_update_status();
|
did_update_status();
|
||||||
|
|
||||||
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
|
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
|
||||||
@ -375,9 +376,11 @@ 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;
|
||||||
|
should_trace_ = 0;
|
||||||
did_update_status();
|
did_update_status();
|
||||||
|
|
||||||
SetupDataAccess(0, Microcycle::SelectWord);
|
SetupDataAccess(0, Microcycle::SelectWord);
|
||||||
@ -412,6 +415,92 @@ 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;
|
||||||
|
should_trace_ = 0;
|
||||||
|
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):
|
||||||
@ -422,6 +511,7 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
status_.is_supervisor = true;
|
status_.is_supervisor = true;
|
||||||
status_.trace_flag = 0;
|
status_.trace_flag = 0;
|
||||||
status_.interrupt_level = captured_interrupt_level_;
|
status_.interrupt_level = captured_interrupt_level_;
|
||||||
|
should_trace_ = 0;
|
||||||
did_update_status();
|
did_update_status();
|
||||||
|
|
||||||
// Prepare for stack activity.
|
// Prepare for stack activity.
|
||||||
@ -484,6 +574,15 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
MoveToStateSpecific(DoInterrupt);
|
MoveToStateSpecific(DoInterrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Potentially perform a trace.
|
||||||
|
if(should_trace_) {
|
||||||
|
exception_vector_ = InstructionSet::M68k::Exception::Trace;
|
||||||
|
MoveToStateSpecific(StandardException);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture the current trace flag.
|
||||||
|
should_trace_ = status_.trace_flag;
|
||||||
|
|
||||||
// Read and decode an opcode.
|
// Read and decode an opcode.
|
||||||
opcode_ = prefetch_.high.w;
|
opcode_ = prefetch_.high.w;
|
||||||
instruction_ = decoder_.decode(opcode_);
|
instruction_ = decoder_.decode(opcode_);
|
||||||
@ -2292,18 +2391,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
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Unhandled state: %d; opcode is %04x\n", state_, opcode_);
|
printf("Unhandled state: %d; opcode is %04x\n", state_, opcode_);
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -58,6 +58,9 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
|
|||||||
/// Current input interrupt level.
|
/// Current input interrupt level.
|
||||||
int bus_interrupt_level_ = 0;
|
int bus_interrupt_level_ = 0;
|
||||||
|
|
||||||
|
// Whether to trace at the end of this instruction.
|
||||||
|
InstructionSet::M68k::Status::FlagT should_trace_ = 0;
|
||||||
|
|
||||||
// I don't have great information on the 68000 interrupt latency; as a first
|
// I don't have great information on the 68000 interrupt latency; as a first
|
||||||
// guess, capture the bus interrupt level upon every prefetch, and use that for
|
// guess, capture the bus interrupt level upon every prefetch, and use that for
|
||||||
// the inner-loop decision.
|
// the inner-loop decision.
|
||||||
@ -136,6 +139,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…
x
Reference in New Issue
Block a user