mirror of
https://github.com/TomHarte/CLK.git
synced 2026-04-24 05:18:36 +00:00
Take initial swing at LLDT.
This commit is contained in:
@@ -82,7 +82,6 @@ struct SegmentDescriptor {
|
||||
|
||||
// Tested at loading (?): present(), privilege_level().
|
||||
|
||||
|
||||
if(type == AccessType::Read && executable() && !readable()) {
|
||||
throw_exception();
|
||||
}
|
||||
@@ -99,6 +98,9 @@ struct SegmentDescriptor {
|
||||
/// @returns The base of this segment descriptor.
|
||||
uint32_t base() const { return base_; }
|
||||
|
||||
/// @returns The offset of this segment descriptor.
|
||||
uint32_t offset() const { return offset_; }
|
||||
|
||||
/// @returns The bounds of this segment descriptor; will be either [0, limit] or [limit, INT_MAX] depending on descriptor type.
|
||||
/// Accesses must be `>= bounds().begin` and `<= bounds().end`.
|
||||
DescriptorBounds bounds() const { return bounds_; }
|
||||
|
||||
@@ -124,6 +124,28 @@ void ldt(
|
||||
context.segments.did_update(table);
|
||||
}
|
||||
|
||||
template <typename AddressT, typename ContextT>
|
||||
void lldt(
|
||||
read_t<AddressT> source_segment,
|
||||
ContextT &context
|
||||
) {
|
||||
const auto ldt =
|
||||
descriptor_at<SegmentDescriptor>(
|
||||
context.linear_memory,
|
||||
context.registers.template get<DescriptorTable::Global>(),
|
||||
source_segment & ~7);
|
||||
|
||||
DescriptorTablePointer location;
|
||||
location.limit = ldt.base();
|
||||
location.base = ldt.offset();
|
||||
if constexpr (std::is_same_v<AddressT, uint16_t>) {
|
||||
location.base &= 0xff'ff'ff;
|
||||
}
|
||||
|
||||
context.registers.template set<DescriptorTable::Local>(location);
|
||||
context.segments.did_update(DescriptorTable::Local);
|
||||
}
|
||||
|
||||
template <DescriptorTable table, typename AddressT, typename InstructionT, typename ContextT>
|
||||
void sdt(
|
||||
read_t<AddressT> destination_address,
|
||||
|
||||
@@ -340,6 +340,13 @@ template <
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
case Operation::LLDT:
|
||||
if constexpr (ContextT::model >= Model::i80286) {
|
||||
Primitive::lldt<AddressT>(source_r(), context);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
case Operation::SIDT:
|
||||
if constexpr (ContextT::model >= Model::i80286) {
|
||||
Primitive::sdt<DescriptorTable::Interrupt, AddressT>(source_indirect(), instruction, context);
|
||||
|
||||
@@ -109,10 +109,11 @@ public:
|
||||
|
||||
template <DescriptorTable table>
|
||||
void set(const DescriptorTablePointer location) {
|
||||
static constexpr bool is_global = table == DescriptorTable::Global;
|
||||
static_assert(is_global || table == DescriptorTable::Interrupt);
|
||||
auto &target = is_global ? global_ : interrupt_;
|
||||
target = location;
|
||||
switch(table) {
|
||||
case DescriptorTable::Local: local_ = location; break;
|
||||
case DescriptorTable::Global: global_ = location; break;
|
||||
case DescriptorTable::Interrupt: interrupt_ = location; break;
|
||||
}
|
||||
}
|
||||
|
||||
template <DescriptorTable table>
|
||||
|
||||
Reference in New Issue
Block a user