mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-22 12:33:29 +00:00
Catch interrupt enables.
This commit is contained in:
parent
ffd298218c
commit
4f58664f97
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user