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:
parent
7b14df82e0
commit
fe6a88c5df
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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()).
|
||||
|
@ -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.
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ public:
|
||||
Segments(const Registers<model> ®isters) : 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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user