diff --git a/InstructionSets/M68k/Executor.hpp b/InstructionSets/M68k/Executor.hpp index 209485ab8..11de04b10 100644 --- a/InstructionSets/M68k/Executor.hpp +++ b/InstructionSets/M68k/Executor.hpp @@ -32,6 +32,7 @@ struct BusHandler { template void write(uint32_t address, IntT value, FunctionCode function); template IntT read(uint32_t address, FunctionCode function); void reset(); + int acknowlege_interrupt(int); }; /// Ties together the decoder, sequencer and performer to provide an executor for 680x0 instruction streams. @@ -52,6 +53,9 @@ template class Executor: public NullFlowContr /// this will raise a C++ exception, and therefore doesn't return. [[noreturn]] void signal_bus_error(FunctionCode, uint32_t address); + /// Sets the current input interrupt level. + void set_interrupt_level(int); + // Flow control; Cf. Perform.hpp. template void raise_exception(int); @@ -123,6 +127,9 @@ template class Executor: public NullFlowContr uint16_t instruction_opcode_; int active_stack_pointer_ = 0; + // Bus state. + int interrupt_input_ = 0; + // A lookup table to ensure that A7 is adjusted by 2 rather than 1 in // postincrement and predecrement mode. static constexpr uint32_t byte_increments[] = { diff --git a/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp b/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp index 6469a46eb..6e045a0f4 100644 --- a/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp +++ b/InstructionSets/M68k/Implementation/ExecutorImplementation.hpp @@ -227,6 +227,11 @@ void Executor::signal_bus_error(FunctionCode code, uint32_t a throw AccessException(code, address, Exception::AccessFault); } +template +void Executor::set_interrupt_level(int level) { + interrupt_input_ = level; +} + template void Executor::run_for_instructions(int count) { while(count > 0) { @@ -267,7 +272,16 @@ void Executor::run_for_instructions(int count) { template void Executor::run(int &count) { while(count--) { - // TODO: interrupts. + // Check for a new interrupt. + if(interrupt_input_ > status_.interrupt_level) { + const int vector = bus_handler_.acknowlege_interrupt(interrupt_input_); + if(vector >= 0) { + raise_exception(vector); + } else { + raise_exception(Exception::InterruptAutovectorBase - 1 + interrupt_input_); + } + status_.interrupt_level = interrupt_input_; + } // Capture the trace bit, indicating whether to trace // after this instruction. diff --git a/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm b/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm index 60bd3b520..b313c2e3b 100644 --- a/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm +++ b/OSBindings/Mac/Clock SignalTests/68000ComparativeTests.mm @@ -77,6 +77,9 @@ struct Test68000 { } void reset() {} + int acknowlege_interrupt(int) { + return -1; + } }; }