1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-25 16:31:42 +00:00

Catch interrupt enables.

This commit is contained in:
Thomas Harte 2024-04-07 22:08:12 -04:00
parent ffd298218c
commit 4f58664f97
2 changed files with 27 additions and 5 deletions

View File

@ -29,11 +29,21 @@ DestinationT read_bus(SourceT value) {
} }
} }
struct NullStatusHandler {
void did_set_status() {}
};
/// A class compatible with the @c OperationMapper definition of a scheduler which applies all actions /// A class compatible with the @c OperationMapper definition of a scheduler which applies all actions
/// immediately, updating either a set of @c Registers or using the templated @c MemoryT to access /// immediately, updating either a set of @c Registers or using the templated @c MemoryT to access
/// memory. No hooks are currently provided for applying realistic timing. /// memory. No hooks are currently provided for applying realistic timing.
template <Model model, typename MemoryT> ///
/// If a StatusObserverT is specified, it'll receive calls to @c did_set_status() following every direct
/// write to the status bits — i.e. any change that can affect mode or interrupt flags.
template <Model model, typename MemoryT, typename StatusObserverT = NullStatusHandler>
struct Executor { struct Executor {
template <typename... Args>
Executor(StatusObserverT &observer, Args &&...args) : status_observer_(observer), bus(std::forward<Args>(args)...) {}
template <typename... Args> template <typename... Args>
Executor(Args &&...args) : bus(std::forward<Args>(args)...) {} Executor(Args &&...args) : bus(std::forward<Args>(args)...) {}
@ -193,6 +203,7 @@ struct Executor {
// PSR flags which are not protected by virtue of the processor mode" // PSR flags which are not protected by virtue of the processor mode"
if(fields.destination() == 15) { if(fields.destination() == 15) {
registers_.set_status(conditions); registers_.set_status(conditions);
status_observer_.did_set_status();
} else { } else {
// Set N and Z in a unified way. // Set N and Z in a unified way.
registers_.set_nz(conditions); registers_.set_nz(conditions);
@ -546,6 +557,7 @@ struct Executor {
registers_.set_pc(pc_proxy); registers_.set_pc(pc_proxy);
if constexpr (flags.load_psr()) { if constexpr (flags.load_psr()) {
registers_.set_status(pc_proxy); registers_.set_status(pc_proxy);
status_observer_.did_set_status();
} }
} }
} }
@ -601,6 +613,12 @@ struct Executor {
MemoryT bus; MemoryT bus;
private: private:
using StatusObserverTStorage =
typename std::conditional<
std::is_same_v<StatusObserverT, NullStatusHandler>,
StatusObserverT,
StatusObserverT &>::type;
StatusObserverTStorage status_observer_;
Registers registers_; Registers registers_;
static bool is_invalid_address(uint32_t address) { static bool is_invalid_address(uint32_t address) {
@ -613,8 +631,8 @@ private:
/// Executes the instruction @c instruction which should have been fetched from @c executor.pc(), /// Executes the instruction @c instruction which should have been fetched from @c executor.pc(),
/// modifying @c executor. /// modifying @c executor.
template <Model model, typename MemoryT> template <Model model, typename MemoryT, typename StatusObserverT>
void execute(uint32_t instruction, Executor<model, MemoryT> &executor) { void execute(uint32_t instruction, Executor<model, MemoryT, StatusObserverT> &executor) {
executor.set_pc(executor.pc() + 4); executor.set_pc(executor.pc() + 4);
dispatch<model>(instruction, executor); dispatch<model>(instruction, executor);
} }

View File

@ -390,7 +390,7 @@ class ConcreteMachine:
ConcreteMachine( ConcreteMachine(
const Analyser::Static::Target &target, const Analyser::Static::Target &target,
const ROMMachine::ROMFetcher &rom_fetcher const ROMMachine::ROMFetcher &rom_fetcher
) : executor_(*this, *this) { ) : executor_(*this, *this, *this) {
set_clock_rate(ClockRate); set_clock_rate(ClockRate);
constexpr ROM::Name risc_os = ROM::Name::AcornRISCOS311; constexpr ROM::Name risc_os = ROM::Name::AcornRISCOS311;
@ -416,6 +416,10 @@ class ConcreteMachine:
} }
} }
void did_set_status() {
update_interrupts();
}
void update_clock_rates() { void update_clock_rates() {
video_divider_ = executor_.bus.video().clock_divider(); video_divider_ = executor_.bus.video().clock_divider();
} }
@ -501,7 +505,7 @@ class ConcreteMachine:
// MARK: - ARM execution // MARK: - ARM execution
static constexpr auto arm_model = InstructionSet::ARM::Model::ARMv2; static constexpr auto arm_model = InstructionSet::ARM::Model::ARMv2;
using Executor = InstructionSet::ARM::Executor<arm_model, MemoryController<ConcreteMachine, ConcreteMachine>>; using Executor = InstructionSet::ARM::Executor<arm_model, MemoryController<ConcreteMachine, ConcreteMachine>, ConcreteMachine>;
Executor executor_; Executor executor_;
// MARK: - Yucky, temporary junk. // MARK: - Yucky, temporary junk.