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:
parent
474f9da3c2
commit
4d400c3cb7
@ -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_;
|
||||
|
@ -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_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user