1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-07 05:30:30 +00:00

Add easy exceptions.

This commit is contained in:
Thomas Harte 2024-02-28 14:25:12 -05:00
parent 474f9da3c2
commit 4d400c3cb7
2 changed files with 56 additions and 8 deletions

View File

@ -64,9 +64,6 @@ struct Registers {
overflow_flag_ = value;
}
void begin_irq() { interrupt_flags_ |= ConditionCode::IRQDisable; }
void begin_fiq() { interrupt_flags_ |= ConditionCode::FIQDisable; }
/// @returns The full PC + status bits.
uint32_t pc_status(uint32_t offset) const {
return
@ -106,6 +103,46 @@ struct Registers {
return (active[15] + offset) & ConditionCode::Address;
}
// MARK: - Exceptions.
enum class Exception {
Reset = 0x00,
UndefinedInstruction = 0x04,
SoftwareInterrupt = 0x08,
PrefetchAbort = 0x0c,
DataAbort = 0x10,
Address = 0x14,
IRQ = 0x18,
FIQ = 0x1c,
};
template <Exception exception>
void exception() {
interrupt_flags_ |= ConditionCode::IRQDisable;
if constexpr (exception == Exception::Reset || exception == Exception::FIQ) {
interrupt_flags_ |= ConditionCode::FIQDisable;
}
switch(exception) {
case Exception::IRQ:
set_mode(Mode::IRQ);
active[14] = pc(8);
break;
case Exception::FIQ:
set_mode(Mode::FIQ);
active[14] = pc(8);
break;
default:
set_mode(Mode::Supervisor);
active[14] = pc(4);
break;
}
set_pc(uint32_t(exception));
}
// MARK: - Condition tests.
bool test(Condition condition) {
const auto ne = [&]() -> bool {
return zero_result_;

View File

@ -226,12 +226,23 @@ struct Scheduler {
template <Operation, Flags> void perform(Condition, SingleDataTransfer) {}
template <Operation, Flags> void perform(Condition, BlockDataTransfer) {}
template <Operation, Flags> void perform(Condition, CoprocessorRegisterTransfer) {}
template <Flags> void perform(Condition, CoprocessorDataOperation) {}
template<Operation, Flags> void perform(Condition, CoprocessorDataTransfer) {}
void software_interrupt() {
registers_.exception<Registers::Exception::SoftwareInterrupt>();
}
void unknown() {
registers_.exception<Registers::Exception::UndefinedInstruction>();
}
void software_interrupt() {}
void unknown(uint32_t) {}
// Act as if no coprocessors present.
template <Flags> void perform(CoprocessorRegisterTransfer) {
registers_.exception<Registers::Exception::UndefinedInstruction>();
}
template <Flags> void perform(CoprocessorDataOperation) {
registers_.exception<Registers::Exception::UndefinedInstruction>();
}
template <Flags> void perform(CoprocessorDataTransfer) {
registers_.exception<Registers::Exception::UndefinedInstruction>();
}
private:
Registers registers_;