From 7fadf01e4ec355a50ef715ebe67b6a6a836a1651 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 24 Sep 2023 18:06:53 -0400 Subject: [PATCH] BP in isolation acts as a base. --- InstructionSets/x86/Decoder.cpp | 4 +- OSBindings/Mac/Clock SignalTests/8088Tests.mm | 173 +++++++++--------- 2 files changed, 90 insertions(+), 87 deletions(-) diff --git a/InstructionSets/x86/Decoder.cpp b/InstructionSets/x86/Decoder.cpp index e78ddfae8..b154e0693 100644 --- a/InstructionSets/x86/Decoder.cpp +++ b/InstructionSets/x86/Decoder.cpp @@ -672,12 +672,12 @@ std::pair::InstructionT> Decoder::decode(con ScaleIndexBase(0, Source::eDI, Source::eBP), ScaleIndexBase(0, Source::eSI, Source::eAX), ScaleIndexBase(0, Source::eDI, Source::eAX), - ScaleIndexBase(0, Source::eBP, Source::eAX), + ScaleIndexBase(0, Source::None, Source::eBP), ScaleIndexBase(0, Source::eBX, Source::eAX), }; sib_ = rm_table[rm]; - memreg = rm >= 4 ? Source::IndirectNoBase : Source::Indirect; + memreg = (rm >= 4 && rm != 6) ? Source::IndirectNoBase : Source::Indirect; } } diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 3722dde11..ac656c85a 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -25,6 +25,88 @@ namespace { // provide their real path here. constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1"; +std::string to_hex(int value, int digits) { + auto stream = std::stringstream(); + stream << std::setfill('0') << std::uppercase << std::hex << std::setw(digits); + switch(digits) { + case 2: stream << +uint8_t(value); break; + case 4: stream << +uint16_t(value); break; + default: stream << value; break; + } + stream << 'h'; + return stream.str(); +}; + +template +std::string to_string(InstructionSet::x86::DataPointer pointer, const InstructionT &instruction, bool abbreviateOffset) { + std::string operand; + + using Source = InstructionSet::x86::Source; + const Source source = pointer.source(); + switch(source) { + // to_string handles all direct register names correctly. + default: return InstructionSet::x86::to_string(source, instruction.operation_size()); + + case Source::Immediate: + return to_hex( + instruction.operand(), + instruction.operation_size() == InstructionSet::x86::DataSize::Byte ? 2 : 4 + ); + + case Source::DirectAddress: + case Source::Indirect: + case Source::IndirectNoBase: { + std::stringstream stream; + + if(!InstructionSet::x86::mnemonic_implies_data_size(instruction.operation)) { + stream << InstructionSet::x86::to_string(instruction.operation_size()) << ' '; + } + + Source segment = instruction.data_segment(); + if(segment == Source::None) { + segment = pointer.default_segment(); + if(segment == Source::None) { + segment = Source::DS; + } + } + stream << InstructionSet::x86::to_string(segment, InstructionSet::x86::DataSize::None) << ':'; + + stream << '['; + bool addOffset = false; + switch(source) { + default: break; + case Source::Indirect: + stream << InstructionSet::x86::to_string(pointer.base(), data_size(instruction.address_size())); + if(pointer.index() != Source::None) { + stream << '+' << InstructionSet::x86::to_string(pointer.index(), data_size(instruction.address_size())); + } + addOffset = true; + break; + case Source::IndirectNoBase: + stream << InstructionSet::x86::to_string(pointer.index(), data_size(instruction.address_size())); + addOffset = true; + break; + case Source::DirectAddress: + stream << to_hex(instruction.offset(), 4); + break; + } + if(addOffset) { + if(instruction.offset()) { + if(abbreviateOffset && !(instruction.offset() & 0xff00)) { + stream << '+' << to_hex(instruction.offset(), 2); + } else { + stream << '+' << to_hex(instruction.offset(), 4); + } + } + } + stream << ']'; + return stream.str(); + } + } + + return operand; +}; + } @interface i8088Tests : XCTestCase @@ -88,94 +170,15 @@ constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1" operation += to_string(instruction.operation, instruction.operation_size()); - auto to_hex = [] (int value, int digits) -> std::string { - auto stream = std::stringstream(); - stream << std::setfill('0') << std::uppercase << std::hex << std::setw(digits); - switch(digits) { - case 2: stream << +uint8_t(value); break; - case 4: stream << +uint16_t(value); break; - default: stream << value; break; - } - stream << 'h'; - return stream.str(); - }; - - auto to_string = [&to_hex, abbreviateOffset] (InstructionSet::x86::DataPointer pointer, const auto &instruction) -> std::string { - std::string operand; - - using Source = InstructionSet::x86::Source; - const Source source = pointer.source(); - switch(source) { - // to_string handles all direct register names correctly. - default: return InstructionSet::x86::to_string(source, instruction.operation_size()); - - case Source::Immediate: - return to_hex( - instruction.operand(), - instruction.operation_size() == InstructionSet::x86::DataSize::Byte ? 2 : 4 - ); - - case Source::DirectAddress: - case Source::Indirect: - case Source::IndirectNoBase: { - std::stringstream stream; - - if(!InstructionSet::x86::mnemonic_implies_data_size(instruction.operation)) { - stream << InstructionSet::x86::to_string(instruction.operation_size()) << ' '; - } - - Source segment = instruction.data_segment(); - if(segment == Source::None) { - segment = pointer.default_segment(); - if(segment == Source::None) { - segment = Source::DS; - } - } - stream << InstructionSet::x86::to_string(segment, InstructionSet::x86::DataSize::None) << ':'; - - stream << '['; - bool addOffset = false; - switch(source) { - default: break; - case Source::Indirect: - stream << InstructionSet::x86::to_string(pointer.base(), data_size(instruction.address_size())); - stream << '+' << InstructionSet::x86::to_string(pointer.index(), data_size(instruction.address_size())); - addOffset = true; - break; - case Source::IndirectNoBase: - stream << InstructionSet::x86::to_string(pointer.index(), data_size(instruction.address_size())); - addOffset = true; - break; - case Source::DirectAddress: - stream << to_hex(instruction.offset(), 4); - break; - } - if(addOffset) { - if(instruction.offset()) { - if(abbreviateOffset && !(instruction.offset() & 0xff00)) { - stream << '+' << to_hex(instruction.offset(), 2); - } else { - stream << '+' << to_hex(instruction.offset(), 4); - } - } - } - stream << ']'; - return stream.str(); - } - } - - return operand; - }; - const int operands = num_operands(instruction.operation); const bool displacement = has_displacement(instruction.operation); operation += " "; if(operands > 1) { - operation += to_string(instruction.destination(), instruction); + operation += to_string(instruction.destination(), instruction, abbreviateOffset); operation += ", "; } if(operands > 0) { - operation += to_string(instruction.source(), instruction); + operation += to_string(instruction.source(), instruction, abbreviateOffset); } if(displacement) { operation += to_hex(instruction.displacement(), 2); @@ -233,10 +236,10 @@ constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1" }; (void)sources; -// const auto destination = instruction.second.destination(); -// to_string(destination, instruction.second); -// const auto source = instruction.second.source(); -// to_string(source, instruction.second); + const auto destination = instruction.second.destination(); + to_string(destination, instruction.second, false); + const auto source = instruction.second.source(); + to_string(source, instruction.second, false); return false; }