mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-02 16:38:51 +00:00
Attempt interrupt support.
This commit is contained in:
parent
3a4fb81242
commit
3349bcaaed
@ -29,7 +29,7 @@ enum Exception {
|
|||||||
FormatError = 14,
|
FormatError = 14,
|
||||||
UninitialisedInterrupt = 15,
|
UninitialisedInterrupt = 15,
|
||||||
SpuriousInterrupt = 24,
|
SpuriousInterrupt = 24,
|
||||||
InterruptAutovectorBase = 25,
|
InterruptAutovectorBase = 25, // This is the vector for interrupt level _1_.
|
||||||
TrapBase = 32,
|
TrapBase = 32,
|
||||||
FPBranchOrSetOnUnorderedCondition = 48,
|
FPBranchOrSetOnUnorderedCondition = 48,
|
||||||
FPInexactResult = 49,
|
FPInexactResult = 49,
|
||||||
|
@ -44,6 +44,7 @@ enum ExecutionState: int {
|
|||||||
|
|
||||||
StandardException,
|
StandardException,
|
||||||
BusOrAddressErrorException,
|
BusOrAddressErrorException,
|
||||||
|
DoInterrupt,
|
||||||
|
|
||||||
// Specific addressing mode fetches.
|
// Specific addressing mode fetches.
|
||||||
//
|
//
|
||||||
@ -313,8 +314,9 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
|
|
||||||
// Reads one futher word from the program counter and inserts it into
|
// Reads one futher word from the program counter and inserts it into
|
||||||
// the prefetch queue.
|
// the prefetch queue.
|
||||||
#define Prefetch() \
|
#define Prefetch() \
|
||||||
prefetch_.high = prefetch_.low; \
|
captured_interrupt_level_ = bus_interrupt_level_; \
|
||||||
|
prefetch_.high = prefetch_.low; \
|
||||||
ReadProgramWord(prefetch_.low)
|
ReadProgramWord(prefetch_.low)
|
||||||
|
|
||||||
using Mode = InstructionSet::M68k::AddressingMode;
|
using Mode = InstructionSet::M68k::AddressingMode;
|
||||||
@ -335,7 +337,11 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
|
|
||||||
// Spin in place until an interrupt arrives.
|
// Spin in place until an interrupt arrives.
|
||||||
BeginState(STOP):
|
BeginState(STOP):
|
||||||
assert(false); // TODO
|
IdleBus(1);
|
||||||
|
captured_interrupt_level_ = bus_interrupt_level_;
|
||||||
|
if(captured_interrupt_level_ > status_.interrupt_level) {
|
||||||
|
MoveToStateSpecific(DoInterrupt);
|
||||||
|
}
|
||||||
MoveToStateSpecific(STOP);
|
MoveToStateSpecific(STOP);
|
||||||
|
|
||||||
// Perform the RESET exception, which seeds the stack pointer and program
|
// Perform the RESET exception, which seeds the stack pointer and program
|
||||||
@ -410,14 +416,80 @@ void Processor<BusHandler, dtack_is_implicit, permit_overrun, signal_will_perfor
|
|||||||
Prefetch(); // np
|
Prefetch(); // np
|
||||||
MoveToStateSpecific(Decode);
|
MoveToStateSpecific(Decode);
|
||||||
|
|
||||||
|
// Acknowledge an interrupt, thereby obtaining an exception vector,
|
||||||
|
// and do the exception.
|
||||||
|
BeginState(DoInterrupt):
|
||||||
|
IdleBus(3); // n nn
|
||||||
|
|
||||||
|
// Capture status and switch to supervisor mode.
|
||||||
|
captured_status_.w = status_.status();
|
||||||
|
status_.is_supervisor = true;
|
||||||
|
status_.trace_flag = 0;
|
||||||
|
did_update_status();
|
||||||
|
|
||||||
|
// Prepare for stack activity.
|
||||||
|
SetupDataAccess(0, Microcycle::SelectWord);
|
||||||
|
SetDataAddress(registers_[15].l);
|
||||||
|
|
||||||
|
// Push status.
|
||||||
|
registers_[15].l -= 2;
|
||||||
|
Access(captured_status_); // ns
|
||||||
|
|
||||||
|
// Do the interrupt cycle, to obtain a vector.
|
||||||
|
temporary_address_.l = captured_interrupt_level_;
|
||||||
|
SetupDataAccess(0, Microcycle::InterruptAcknowledge);
|
||||||
|
SetDataAddress(temporary_address_.l);
|
||||||
|
Access(temporary_value_.low); // ni
|
||||||
|
|
||||||
|
// If VPA is set, autovector.
|
||||||
|
if(vpa_) {
|
||||||
|
temporary_value_.w = InstructionSet::M68k::Exception::InterruptAutovectorBase - 1 + captured_interrupt_level_;
|
||||||
|
}
|
||||||
|
|
||||||
|
IdleBus(3); // n- n
|
||||||
|
|
||||||
|
// Do the rest of the stack work.
|
||||||
|
SetupDataAccess(0, Microcycle::SelectWord);
|
||||||
|
SetDataAddress(registers_[15].l);
|
||||||
|
|
||||||
|
registers_[15].l -= 2;
|
||||||
|
Access(instruction_address_.high); // ns
|
||||||
|
|
||||||
|
registers_[15].l -= 2;
|
||||||
|
Access(instruction_address_.low); // nS
|
||||||
|
|
||||||
|
// Grab new program counter.
|
||||||
|
SetupDataAccess(Microcycle::Read, Microcycle::SelectWord);
|
||||||
|
SetDataAddress(temporary_address_.l);
|
||||||
|
|
||||||
|
temporary_address_.l <<= 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);
|
||||||
|
|
||||||
// Inspect the prefetch queue in order to decode the next instruction,
|
// Inspect the prefetch queue in order to decode the next instruction,
|
||||||
// and segue into the fetching of operands.
|
// and segue into the fetching of operands.
|
||||||
BeginState(Decode):
|
BeginState(Decode):
|
||||||
CheckOverrun();
|
CheckOverrun();
|
||||||
|
|
||||||
|
// Capture the address of the next instruction.
|
||||||
|
instruction_address_.l = program_counter_.l - 4;
|
||||||
|
|
||||||
|
// Head off into an interrupt if one is found.
|
||||||
|
if(captured_interrupt_level_ > status_.interrupt_level) {
|
||||||
|
MoveToStateSpecific(DoInterrupt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read and decode an opcode.
|
||||||
opcode_ = prefetch_.high.w;
|
opcode_ = prefetch_.high.w;
|
||||||
instruction_ = decoder_.decode(opcode_);
|
instruction_ = decoder_.decode(opcode_);
|
||||||
instruction_address_.l = program_counter_.l - 4;
|
|
||||||
|
|
||||||
// Signal the bus handler if requested.
|
// Signal the bus handler if requested.
|
||||||
if constexpr (signal_will_perform) {
|
if constexpr (signal_will_perform) {
|
||||||
|
@ -58,6 +58,11 @@ struct ProcessorBase: public InstructionSet::M68k::NullFlowController {
|
|||||||
/// Current input interrupt level.
|
/// Current input interrupt level.
|
||||||
int bus_interrupt_level_ = 0;
|
int bus_interrupt_level_ = 0;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// the inner-loop decision.
|
||||||
|
int captured_interrupt_level_ = 0;
|
||||||
|
|
||||||
/// Contains the prefetch queue; the most-recently fetched thing is the
|
/// Contains the prefetch queue; the most-recently fetched thing is the
|
||||||
/// low portion of this word, and the thing fetched before that has
|
/// low portion of this word, and the thing fetched before that has
|
||||||
/// proceeded to the high portion.
|
/// proceeded to the high portion.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user