mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-09 05:25:01 +00:00
117 lines
2.5 KiB
C++
117 lines
2.5 KiB
C++
//
|
||
// Interrupts.hpp
|
||
// Clock Signal
|
||
//
|
||
// Created by Thomas Harte on 06/10/2023.
|
||
// Copyright © 2023 Thomas Harte. All rights reserved.
|
||
//
|
||
|
||
#pragma once
|
||
|
||
namespace InstructionSet::x86 {
|
||
|
||
enum Interrupt {
|
||
//
|
||
// Present on all devices.
|
||
//
|
||
DivideError = 0,
|
||
SingleStep = 1,
|
||
NMI = 2,
|
||
Breakpoint = 3,
|
||
Overflow = 4,
|
||
BoundRangeExceeded = 5,
|
||
|
||
//
|
||
// Added by the 80286
|
||
//
|
||
InvalidOpcode = 6,
|
||
DeviceNotAvailable = 7,
|
||
DoubleFault = 8,
|
||
CoprocessorSegmentOverrun = 9,
|
||
InvalidTSS = 10,
|
||
SegmentNotPresent = 11,
|
||
StackSegmentFault = 12,
|
||
GeneralProtectionFault = 13,
|
||
FloatingPointException = 16,
|
||
|
||
//
|
||
// Added by the 80286
|
||
//
|
||
PageFault = 14,
|
||
AlignmentCheck = 17,
|
||
MachineCheck = 18,
|
||
};
|
||
|
||
constexpr bool has_error_code(const Interrupt interrupt) {
|
||
switch(interrupt) {
|
||
default: assert(false); // 386 exceptions; I don't know yet.
|
||
|
||
case Interrupt::DivideError:
|
||
case Interrupt::SingleStep:
|
||
case Interrupt::NMI:
|
||
case Interrupt::Breakpoint:
|
||
case Interrupt::Overflow:
|
||
case Interrupt::BoundRangeExceeded:
|
||
case Interrupt::InvalidOpcode:
|
||
case Interrupt::DeviceNotAvailable:
|
||
case Interrupt::CoprocessorSegmentOverrun:
|
||
case Interrupt::FloatingPointException:
|
||
return false;
|
||
|
||
case Interrupt::DoubleFault:
|
||
case Interrupt::InvalidTSS:
|
||
case Interrupt::SegmentNotPresent:
|
||
case Interrupt::StackSegmentFault:
|
||
case Interrupt::GeneralProtectionFault:
|
||
return true;
|
||
}
|
||
}
|
||
|
||
constexpr bool posts_next_instruction_ip(const Interrupt interrupt) {
|
||
switch(interrupt) {
|
||
default:
|
||
return false;
|
||
|
||
case Interrupt::SingleStep:
|
||
case Interrupt::Breakpoint:
|
||
case Interrupt::Overflow:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
struct Code {
|
||
uint16_t value = 0;
|
||
|
||
Code() = default;
|
||
Code(
|
||
const uint16_t index,
|
||
const bool is_local,
|
||
const bool is_interrupt,
|
||
const bool was_external) noexcept :
|
||
value(
|
||
index |
|
||
(is_local ? 0x4 : 0x0) |
|
||
(is_interrupt ? 0x2 : 0x0) |
|
||
(was_external ? 0x1 : 0x0)
|
||
) {}
|
||
|
||
// i.e.:
|
||
// b3–b15: IDT/GDT/LDT entry
|
||
// b2: 1 => in LDT; 0 => in GDT;
|
||
// b1: 1 => in IDT, ignore b2; 0 => use b2;
|
||
// b0:
|
||
// 1 => trigger was external to program code;
|
||
// 0 => trigger was caused by the instruction described by the CS:IP that is on the stack.
|
||
};
|
||
|
||
struct Exception {
|
||
Interrupt cause;
|
||
Code code;
|
||
|
||
Exception() = default;
|
||
constexpr Exception(const Interrupt cause) noexcept : cause(cause) {}
|
||
constexpr Exception(const Interrupt cause, const Code code) noexcept : cause(cause), code(code) {}
|
||
};
|
||
|
||
}
|