From ca94e9038eb2622f5adab76a54b989b6caac76b9 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 14 Jan 2021 22:15:38 -0500 Subject: [PATCH] Introduces 'far' test, fixes parsing. --- .../Mac/Clock SignalTests/x86DecoderTests.mm | 17 +++++++++++++++-- Processors/Decoders/x86/x86.cpp | 2 ++ Processors/Decoders/x86/x86.hpp | 4 +++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm b/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm index 084f6bde2..8cfc6c3b8 100644 --- a/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm +++ b/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm @@ -95,6 +95,12 @@ namespace { XCTAssertEqual(instruction.displacement(), 0); } +- (void)assert:(Instruction &)instruction operation:(Operation)operation segment:(uint16_t)segment offset:(uint16_t)offset { + XCTAssertEqual(instruction.operation, operation); + XCTAssertEqual(instruction.segment(), segment); + XCTAssertEqual(instruction.offset(), offset); +} + // MARK: - Decoder - (void)decode:(const std::initializer_list &)stream { @@ -312,12 +318,19 @@ namespace { 0x83, 0x2f, 0x09, // subw $0x9,(%bx) }]; - // 68 instructions are expected. XCTAssertEqual(instructions.size(), 3); - [self assert:instructions[0] operation:Operation::ADC size:2 source:Source::Immediate destination:Source::IndBXPlusSI operand:0xff80]; [self assert:instructions[1] operation:Operation::CMP size:2 source:Source::Immediate destination:Source::IndBPPlusDI operand:0x4]; [self assert:instructions[2] operation:Operation::SUB size:2 source:Source::Immediate destination:Source::IndBX operand:0x9]; } +- (void)testFar { + [self decode:{ + 0x9a, 0x12, 0x34, 0x56, 0x78, // lcall 0x7856, 0x3412 + }]; + + XCTAssertEqual(instructions.size(), 1); + [self assert:instructions[0] operation:Operation::CALLF segment:0x7856 offset:0x3412]; +} + @end diff --git a/Processors/Decoders/x86/x86.cpp b/Processors/Decoders/x86/x86.cpp index e414a0a40..3dfae8f89 100644 --- a/Processors/Decoders/x86/x86.cpp +++ b/Processors/Decoders/x86/x86.cpp @@ -585,7 +585,9 @@ std::pair Decoder::decode(const uint8_t *source, size_t length operand_ |= (operand_ & 0x80) ? 0xff00 : 0x0000; } break; + case 4: displacement_size_ = 2; [[fallthrough]]; case 2: operand_ = inward_data_ >> 48; inward_data_ <<= 16; break; + break; } switch(displacement_size_) { default: displacement_ = 0; break; diff --git a/Processors/Decoders/x86/x86.hpp b/Processors/Decoders/x86/x86.hpp index 2929aed44..841da5360 100644 --- a/Processors/Decoders/x86/x86.hpp +++ b/Processors/Decoders/x86/x86.hpp @@ -37,10 +37,11 @@ enum class Operation: uint8_t { ADD, /// And; source, destination, operand and displacement will be populated appropriately. AND, - /// Far call; followed by a 32-bit operand. + /// Far call; see the segment() and offset() fields. CALLF, /// Displacement call; followed by a 16-bit operand providing a call offset. CALLD, + /// Near call. CALLN, /// Convert byte into word; source will be AL, destination will be AH. CBW, @@ -155,6 +156,7 @@ class Instruction { Size operation_size() const { return Size(repetition_size_ >> 2); } uint16_t segment() const { return uint16_t(operand_); } + uint16_t offset() const { return uint16_t(displacement_); } int16_t displacement() const { return displacement_; } uint16_t operand() const { return operand_; }