From f96c33102a18a66d10cfa927b5341e3d4f67219f Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 4 Nov 2023 22:22:50 -0400 Subject: [PATCH] Add documentation. --- .../Implementation/PerformImplementation.hpp | 43 +++++++++++++------ OSBindings/Mac/Clock SignalTests/8088Tests.mm | 2 + 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index 3bf4b7615..ba9d89448 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -28,13 +28,14 @@ IntT *resolve( IntT *immediate = nullptr ); +/// Calculates the absolute address for @c pointer given the registers and memory provided in @c context and taking any +/// referenced offset from @c instruction. template uint32_t address( InstructionT &instruction, DataPointer pointer, ContextT &context ) { - // TODO: non-word indexes and bases. if constexpr (source == Source::DirectAddress) { return instruction.offset(); } @@ -53,6 +54,9 @@ uint32_t address( return address + *resolve(instruction, pointer.base(), pointer, context); } +/// @returns a pointer to the contents of the register identified by the combination of @c IntT and @c Source if any; +/// @c nullptr otherwise. @c access is currently unused but is intended to provide the hook upon which updates to +/// segment registers can be tracked for protected modes. template IntT *register_(ContextT &context) { static constexpr bool supports_dword = is_32bit(ContextT::model); @@ -103,10 +107,21 @@ IntT *register_(ContextT &context) { else if constexpr (std::is_same_v) { return &context.registers.bh(); } else { return nullptr; } + // Segment registers are always 16-bit. + case Source::ES: if constexpr (std::is_same_v) return &context.registers.es(); else return nullptr; + case Source::CS: if constexpr (std::is_same_v) return &context.registers.cs(); else return nullptr; + case Source::SS: if constexpr (std::is_same_v) return &context.registers.ss(); else return nullptr; + case Source::DS: if constexpr (std::is_same_v) return &context.registers.ds(); else return nullptr; + + // 16-bit models don't have FS and GS. + case Source::FS: if constexpr (is_32bit(ContextT::model) && std::is_same_v) return &context.registers.fs(); else return nullptr; + case Source::GS: if constexpr (is_32bit(ContextT::model) && std::is_same_v) return &context.registers.gs(); else return nullptr; + default: return nullptr; } } +///Obtains the address described by @c pointer from @c instruction given the registers and memory as described by @c context. template uint32_t address( InstructionT &instruction, @@ -131,6 +146,13 @@ uint32_t address( } } +/// Obtain a pointer to the value desribed by @c source, which is one of those named by @c pointer, using @c instruction and @c context +/// for offsets, registers and memory contents. +/// +/// If @c source is Source::None then @c none is returned. +/// +/// If @c source is Source::Immediate then the appropriate portion of @c instrucion's operand +/// is copied to @c *immediate and @c immediate is returned. template IntT *resolve( InstructionT &instruction, @@ -146,6 +168,7 @@ IntT *resolve( // * otherwise return the appropriate value. uint32_t target_address; switch(source) { + // Defer all register accesses to the register-specific lookup. case Source::eAX: return register_(context); case Source::eCX: return register_(context); case Source::eDX: return register_(context); @@ -154,23 +177,19 @@ IntT *resolve( case Source::eBPorCH: return register_(context); case Source::eSIorDH: return register_(context); case Source::eDIorBH: return register_(context); + case Source::ES: return register_(context); + case Source::CS: return register_(context); + case Source::SS: return register_(context); + case Source::DS: return register_(context); + case Source::FS: return register_(context); + case Source::GS: return register_(context); - // Segment registers are always 16-bit. - case Source::ES: if constexpr (std::is_same_v) return &context.registers.es(); else return nullptr; - case Source::CS: if constexpr (std::is_same_v) return &context.registers.cs(); else return nullptr; - case Source::SS: if constexpr (std::is_same_v) return &context.registers.ss(); else return nullptr; - case Source::DS: if constexpr (std::is_same_v) return &context.registers.ds(); else return nullptr; - - // 16-bit models don't have FS and GS. - case Source::FS: if constexpr (is_32bit(ContextT::model) && std::is_same_v) return &context.registers.fs(); else return nullptr; - case Source::GS: if constexpr (is_32bit(ContextT::model) && std::is_same_v) return &context.registers.gs(); else return nullptr; + case Source::None: return none; case Source::Immediate: *immediate = instruction.operand(); return immediate; - case Source::None: return none; - case Source::Indirect: target_address = address(instruction, pointer, context); break; diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 831223d1c..90d4dfbaa 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -126,7 +126,9 @@ struct Memory { tags[address] = Tag::AccessExpected; } + // // Preauthorisation call-ins. + // void preauthorise_stack_write(uint32_t length) { uint16_t sp = registers_.sp_; while(length--) {