diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index 0a736e6a9..3f84adc73 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -903,9 +903,9 @@ void jump_far(InstructionT &instruction, ContextT &context) { const Source source_segment = instruction.data_segment(); context.memory.preauthorise_read(source_segment, source_address, sizeof(uint16_t) * 2); - const uint16_t offset = context.memory.template access(source_segment, source_address); + const uint16_t offset = context.memory.template access(source_segment, source_address); source_address += 2; - const uint16_t segment =context. memory.template access(source_segment, source_address); + const uint16_t segment = context.memory.template access(source_segment, source_address); context.flow_controller.jump(segment, offset); } @@ -945,11 +945,12 @@ void ld( auto source_address = address(instruction, pointer, context); const Source source_segment = instruction.data_segment(); - destination = context.memory.template access(source_segment, source_address); + context.memory.preauthorise_read(source_segment, source_address, 4); + destination = context.memory.template access(source_segment, source_address); source_address += 2; switch(selector) { - case Source::DS: context.registers.ds() = context.memory.template access(source_segment, source_address); break; - case Source::ES: context.registers.es() = context.memory.template access(source_segment, source_address); break; + case Source::DS: context.registers.ds() = context.memory.template access(source_segment, source_address); break; + case Source::ES: context.registers.es() = context.memory.template access(source_segment, source_address); break; } } @@ -1919,8 +1920,8 @@ template < context.memory.preauthorise_read(address, sizeof(uint16_t) * 2); context.memory.preauthorise_stack_write(sizeof(uint16_t) * 3); - const uint16_t ip = context.memory.template access(address); - const uint16_t cs = context.memory.template access(address + 2); + const uint16_t ip = context.memory.template access(address); + const uint16_t cs = context.memory.template access(address + 2); auto flags = context.status.get(); Primitive::push(flags, context); diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 3991743a3..f5621db6c 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "NSData+dataWithContentsOfGZippedFile.h" @@ -125,10 +127,32 @@ struct Memory { } // Preauthorisation call-ins. - void preauthorise_stack_write(uint32_t) {} - void preauthorise_stack_read(uint32_t) {} - void preauthorise_read(InstructionSet::x86::Source, uint16_t, uint32_t) {} - void preauthorise_read(uint16_t, uint32_t) {} + void preauthorise_stack_write(uint32_t length) { + uint16_t sp = registers_.sp_; + while(length--) { + --sp; + preauthorise(InstructionSet::x86::Source::SS, sp); + } + } + void preauthorise_stack_read(uint32_t length) { + uint16_t sp = registers_.sp_; + while(length--) { + preauthorise(InstructionSet::x86::Source::SS, sp); + ++sp; + } + } + void preauthorise_read(InstructionSet::x86::Source segment, uint16_t start, uint32_t length) { + while(length--) { + preauthorise(segment, start); + ++start; + } + } + void preauthorise_read(uint32_t start, uint32_t length) { + while(length--) { + preauthorise(start); + ++start; + } + } // Access call-ins. @@ -179,10 +203,26 @@ struct Memory { Accessed, }; + std::unordered_set preauthorisations; std::unordered_map tags; std::vector memory; const Registers ®isters_; + void preauthorise(uint32_t address) { + preauthorisations.insert(address); + } + void preauthorise(InstructionSet::x86::Source segment, uint16_t address) { + preauthorise((segment_base(segment) + address) & 0xf'ffff); + } + bool test_preauthorisation(uint32_t address) { + auto authorisation = preauthorisations.find(address); + if(authorisation == preauthorisations.end()) { + return false; + } + preauthorisations.erase(authorisation); + return true; + } + uint32_t segment_base(InstructionSet::x86::Source segment) { uint32_t physical_address; using Source = InstructionSet::x86::Source; @@ -208,6 +248,12 @@ struct Memory { // to a selector, they're just at an absolute location. template typename ReturnType::type &access(uint32_t address, Tag tag) { + if constexpr (type == AccessType::PreauthorisedRead || type == AccessType::PreauthorisedWrite) { + if(!test_preauthorisation(address)) { + printf("Non preauthorised access\n"); + } + } + // Check for address wraparound if(address > 0x10'0000 - sizeof(IntT)) { if constexpr (std::is_same_v) { @@ -225,7 +271,7 @@ struct Memory { } if(tags.find(address) == tags.end()) { - printf("Access to unexpected RAM address"); + printf("Access to unexpected RAM address\n"); } tags[address] = tag; return *reinterpret_cast(&memory[address]);