1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-04-17 22:38:59 +00:00

Install [L/S][I/G]DT wiring.

This commit is contained in:
Thomas Harte 2025-03-18 22:11:28 -04:00
parent 7b14df82e0
commit fe6a88c5df
6 changed files with 76 additions and 4 deletions

View File

@ -85,18 +85,46 @@ void smsw(
destination = context.registers.msw();
}
template <DescriptorTable table, typename IntT, typename InstructionT, typename ContextT>
template <DescriptorTable table, typename AddressT, typename InstructionT, typename ContextT>
void ldt(
read_t<IntT> source_address,
read_t<AddressT> source_address,
const InstructionT &instruction,
ContextT &context
) {
const auto segment = instruction.data_segment();
context.memory.preauthorise_read(
instruction.data_segment(),
segment,
source_address,
6);
assert(false);
DescriptorTableLocation location;
location.limit =
context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(segment, source_address);
location.base =
context.memory.template access<uint32_t, AccessType::PreauthorisedRead>(segment, AddressT(source_address + 2));
if constexpr (std::is_same_v<AddressT, uint16_t>) {
location.base &= 0xff'ff'ff;
}
context.registers.template set<table>(location);
context.segments.did_update(table);
}
template <DescriptorTable table, typename AddressT, typename InstructionT, typename ContextT>
void sdt(
read_t<AddressT> destination_address,
const InstructionT &instruction,
ContextT &context
) {
const auto segment = instruction.data_segment();
context.memory.preauthorise_write(
segment,
destination_address,
6);
const auto location = context.registers.template get<table>();
context.memory.template preauthorised_write<uint16_t>(segment, destination_address, location.limit);
context.memory.template preauthorised_write<uint32_t>(segment, AddressT(destination_address + 2), location.base);
}
}

View File

@ -311,6 +311,20 @@ template <
assert(false);
}
break;
case Operation::SIDT:
if constexpr (ContextT::model >= Model::i80286) {
Primitive::sdt<DescriptorTable::Interrupt, AddressT>(source_indirect(), instruction, context);
} else {
assert(false);
}
break;
case Operation::SGDT:
if constexpr (ContextT::model >= Model::i80286) {
Primitive::sdt<DescriptorTable::Global, AddressT>(source_indirect(), instruction, context);
} else {
assert(false);
}
break;
case Operation::JO: jcc(context.flags.template condition<Condition::Overflow>()); return;
case Operation::JNO: jcc(!context.flags.template condition<Condition::Overflow>()); return;

View File

@ -554,6 +554,11 @@ constexpr Operation rep_operation(Operation operation, Repetition repetition) {
enum class DescriptorTable {
Global, Local, Interrupt,
};
struct DescriptorTableLocation {
uint16_t limit;
uint32_t base;
};
/// Provides a 32-bit-style scale, index and base; to produce the address this represents,
/// calcluate base() + (index() << scale()).

View File

@ -38,6 +38,8 @@ public:
void preauthorise_stack_read([[maybe_unused]] uint32_t length) {}
void preauthorise_read([[maybe_unused]] InstructionSet::x86::Source segment, [[maybe_unused]] uint16_t start, [[maybe_unused]] uint32_t length) {}
void preauthorise_read([[maybe_unused]] uint32_t start, [[maybe_unused]] uint32_t length) {}
void preauthorise_write([[maybe_unused]] InstructionSet::x86::Source segment, [[maybe_unused]] uint16_t start, [[maybe_unused]] uint32_t length) {}
void preauthorise_write([[maybe_unused]] uint32_t start, [[maybe_unused]] uint32_t length) {}
//
// Access call-ins.

View File

@ -8,6 +8,7 @@
#pragma once
#include "InstructionSets/x86/Instruction.hpp" // For DescriptorTable.
#include "InstructionSets/x86/Model.hpp"
#include "Numeric/RegisterSizes.hpp"
@ -87,8 +88,27 @@ public:
uint16_t msw() const { return machine_status_; }
using DescriptorTable = InstructionSet::x86::DescriptorTable;
using DescriptorTableLocation = InstructionSet::x86::DescriptorTableLocation;
template <DescriptorTable table>
void set(const DescriptorTableLocation location) {
static constexpr bool is_global = table == DescriptorTable::Global;
static_assert(is_global || table == DescriptorTable::Interrupt);
auto &target = is_global ? global_ : interrupt_;
target = location;
}
template <DescriptorTable table>
DescriptorTableLocation get() {
static constexpr bool is_global = table == DescriptorTable::Global;
static_assert(is_global || table == DescriptorTable::Interrupt);
return is_global ? global_ : interrupt_;
}
private:
uint16_t machine_status_;
DescriptorTableLocation global_, interrupt_;
};
}

View File

@ -21,6 +21,7 @@ public:
Segments(const Registers<model> &registers) : registers_(registers) {}
using Source = InstructionSet::x86::Source;
using DescriptorTable = InstructionSet::x86::DescriptorTable;
/// Posted by @c perform after any operation which *might* have affected a segment register.
void did_update(const Source segment) {
@ -33,6 +34,8 @@ public:
}
}
void did_update(DescriptorTable) {}
void reset() {
did_update(Source::ES);
did_update(Source::CS);