From 40af162214aff5c28de1aeecebb0b05a085b717c Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 4 Oct 2023 22:15:13 -0400 Subject: [PATCH] Be overt about what's here to aid with printing only. --- InstructionSets/x86/Instruction.cpp | 91 +++++++++++++++- InstructionSets/x86/Instruction.hpp | 103 +++++------------- OSBindings/Mac/Clock SignalTests/8088Tests.mm | 11 +- 3 files changed, 120 insertions(+), 85 deletions(-) diff --git a/InstructionSets/x86/Instruction.cpp b/InstructionSets/x86/Instruction.cpp index bacbbd9d7..b7a51a605 100644 --- a/InstructionSets/x86/Instruction.cpp +++ b/InstructionSets/x86/Instruction.cpp @@ -12,7 +12,80 @@ using namespace InstructionSet::x86; -std::string InstructionSet::x86::to_string(Operation operation, DataSize size) { +bool InstructionSet::x86::has_displacement(Operation operation) { + switch(operation) { + default: return false; + + case Operation::JO: case Operation::JNO: + case Operation::JB: case Operation::JNB: + case Operation::JZ: case Operation::JNZ: + case Operation::JBE: case Operation::JNBE: + case Operation::JS: case Operation::JNS: + case Operation::JP: case Operation::JNP: + case Operation::JL: case Operation::JNL: + case Operation::JLE: case Operation::JNLE: + case Operation::LOOPNE: case Operation::LOOPE: + case Operation::LOOP: case Operation::JCXZ: + case Operation::CALLrel: case Operation::JMPrel: + return true; + } +} + +int InstructionSet::x86::max_displayed_operands(Operation operation) { + switch(operation) { + default: return 2; + + case Operation::INC: case Operation::DEC: + case Operation::POP: case Operation::PUSH: + case Operation::MUL: case Operation::IMUL_1: + case Operation::IDIV: case Operation::DIV: + case Operation::ESC: + case Operation::AAM: case Operation::AAD: + case Operation::INT: + case Operation::JMPabs: case Operation::JMPfar: + case Operation::CALLabs: case Operation::CALLfar: + case Operation::NEG: case Operation::NOT: + case Operation::RETnear: + case Operation::RETfar: + return 1; + + // Pedantically, these have an displacement rather than an operand. + case Operation::JO: case Operation::JNO: + case Operation::JB: case Operation::JNB: + case Operation::JZ: case Operation::JNZ: + case Operation::JBE: case Operation::JNBE: + case Operation::JS: case Operation::JNS: + case Operation::JP: case Operation::JNP: + case Operation::JL: case Operation::JNL: + case Operation::JLE: case Operation::JNLE: + case Operation::LOOPNE: case Operation::LOOPE: + case Operation::LOOP: case Operation::JCXZ: + case Operation::CALLrel: case Operation::JMPrel: + // Genuine zero-operand instructions: + case Operation::CMPS: case Operation::LODS: + case Operation::MOVS: case Operation::SCAS: + case Operation::STOS: + case Operation::CLC: case Operation::CLD: + case Operation::CLI: + case Operation::STC: case Operation::STD: + case Operation::STI: + case Operation::CMC: + case Operation::LAHF: case Operation::SAHF: + case Operation::AAA: case Operation::AAS: + case Operation::DAA: case Operation::DAS: + case Operation::CBW: case Operation::CWD: + case Operation::INTO: + case Operation::PUSHF: case Operation::POPF: + case Operation::IRET: + case Operation::NOP: + case Operation::XLAT: + case Operation::SALC: + case Operation::Invalid: + return 0; + } +} + +std::string InstructionSet::x86::to_string(Operation operation, DataSize size, Model model) { switch(operation) { case Operation::AAA: return "aaa"; case Operation::AAD: return "aad"; @@ -138,8 +211,19 @@ std::string InstructionSet::x86::to_string(Operation operation, DataSize size) { case Operation::XLAT: return "xlat"; case Operation::SALC: return "salc"; - case Operation::SETMO: return "setmo"; - case Operation::SETMOC: return "setmoc"; + case Operation::SETMO: + if(model == Model::i8086) { + return "setmo"; + } else { + return "enter"; + } + + case Operation::SETMOC: + if(model == Model::i8086) { + return "setmoc"; + } else { + return "bound"; + } case Operation::Invalid: return "invalid"; @@ -220,4 +304,3 @@ std::string InstructionSet::x86::to_string(Source source, DataSize size) { default: return "???"; } } - diff --git a/InstructionSets/x86/Instruction.hpp b/InstructionSets/x86/Instruction.hpp index 44b9316fb..51e2d8a80 100644 --- a/InstructionSets/x86/Instruction.hpp +++ b/InstructionSets/x86/Instruction.hpp @@ -9,6 +9,8 @@ #ifndef InstructionSets_x86_Instruction_h #define InstructionSets_x86_Instruction_h +#include "Model.hpp" + #include #include #include @@ -360,78 +362,6 @@ enum class Operation: uint8_t { MOVtoTr, MOVfromTr, }; -constexpr bool has_displacement(Operation operation) { - switch(operation) { - default: return false; - - case Operation::JO: case Operation::JNO: - case Operation::JB: case Operation::JNB: - case Operation::JZ: case Operation::JNZ: - case Operation::JBE: case Operation::JNBE: - case Operation::JS: case Operation::JNS: - case Operation::JP: case Operation::JNP: - case Operation::JL: case Operation::JNL: - case Operation::JLE: case Operation::JNLE: - case Operation::LOOPNE: case Operation::LOOPE: - case Operation::LOOP: case Operation::JCXZ: - case Operation::CALLrel: case Operation::JMPrel: - return true; - } -} - -constexpr int max_num_operands(Operation operation) { - switch(operation) { - default: return 2; - - case Operation::INC: case Operation::DEC: - case Operation::POP: case Operation::PUSH: - case Operation::MUL: case Operation::IMUL_1: - case Operation::IDIV: case Operation::DIV: - case Operation::ESC: - case Operation::AAM: case Operation::AAD: - case Operation::INT: - case Operation::JMPabs: case Operation::JMPfar: - case Operation::CALLabs: case Operation::CALLfar: - case Operation::NEG: case Operation::NOT: - case Operation::RETnear: - case Operation::RETfar: - return 1; - - // Pedantically, these have an displacement rather than an operand. - case Operation::JO: case Operation::JNO: - case Operation::JB: case Operation::JNB: - case Operation::JZ: case Operation::JNZ: - case Operation::JBE: case Operation::JNBE: - case Operation::JS: case Operation::JNS: - case Operation::JP: case Operation::JNP: - case Operation::JL: case Operation::JNL: - case Operation::JLE: case Operation::JNLE: - case Operation::LOOPNE: case Operation::LOOPE: - case Operation::LOOP: case Operation::JCXZ: - case Operation::CALLrel: case Operation::JMPrel: - // Genuine zero-operand instructions: - case Operation::CMPS: case Operation::LODS: - case Operation::MOVS: case Operation::SCAS: - case Operation::STOS: - case Operation::CLC: case Operation::CLD: - case Operation::CLI: - case Operation::STC: case Operation::STD: - case Operation::STI: - case Operation::CMC: - case Operation::LAHF: case Operation::SAHF: - case Operation::AAA: case Operation::AAS: - case Operation::DAA: case Operation::DAS: - case Operation::CBW: case Operation::CWD: - case Operation::INTO: - case Operation::PUSHF: case Operation::POPF: - case Operation::IRET: - case Operation::NOP: - case Operation::XLAT: - case Operation::SALC: - case Operation::Invalid: - return 0; - } -} enum class DataSize: uint8_t { Byte = 0, @@ -447,9 +377,6 @@ constexpr int byte_size(DataSize size) { constexpr int bit_size(DataSize size) { return (8 << int(size)) & 0x3f; } -std::string to_string(Operation, DataSize); -std::string to_string(DataSize); -bool mnemonic_implies_data_size(Operation); enum class AddressSize: uint8_t { b16 = 0, @@ -525,12 +452,12 @@ enum class Source: uint8_t { /// getter is used). IndirectNoBase = Indirect - 1, }; -std::string to_string(Source, DataSize); enum class Repetition: uint8_t { None, RepE, RepNE }; +/// @returns @c true if @c operation supports repetition mode @c repetition; @c false otherwise. constexpr bool supports(Operation operation, Repetition repetition) { switch(operation) { default: return false; @@ -930,6 +857,30 @@ template class Instruction { static_assert(sizeof(Instruction) <= 16); static_assert(sizeof(Instruction) <= 10); +// +// Disassembly aids. +// + +/// @returns @c true if @c operation uses a @c displacement(). +bool has_displacement(Operation operation); + +/// @returns The maximum number of operands to print in a disassembly of @c operation; +/// i.e. 2 for both source() and destination(), 1 for source() alone, 0 for neither. This is a maximum +/// only — if either source is Source::None then it should not be printed. +int max_displayed_operands(Operation operation); + +/// Provides the idiomatic name of the @c Operation given an operation @c DataSize and processor @c Model. +std::string to_string(Operation, DataSize, Model); + +/// @returns @c true if the idiomatic name of @c Operation implies the data size (e.g. stosb), @c false otherwise (e.g. ld). +bool mnemonic_implies_data_size(Operation); + +/// Provides the name of the @c DataSize, i.e. 'byte', 'word' or 'dword'. +std::string to_string(DataSize); + +/// Provides the name of the @c Source at @c DataSize, e.g. for Source::eAX it might return AL, AX or EAX. +std::string to_string(Source, DataSize); + } #endif /* InstructionSets_x86_Instruction_h */ diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index fe45246bc..5ab098f92 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -192,19 +192,20 @@ std::string to_string( case Repetition::RepNE: operation += "repne "; break; } - operation += to_string(instruction.operation, instruction.operation_size()); + operation += to_string(instruction.operation, instruction.operation_size(), InstructionSet::x86::Model::i8086); // Deal with a few special cases up front. switch(instruction.operation) { default: { - const int operands = max_num_operands(instruction.operation); + const int operands = max_displayed_operands(instruction.operation); const bool displacement = has_displacement(instruction.operation); operation += " "; - if(operands > 1 && instruction.destination().source() != Source::None) { + const bool print_first = operands > 1 && instruction.destination().source() != Source::None; + if(print_first) { operation += to_string(instruction.destination(), instruction, offsetLength, immediateLength); } if(operands > 0 && instruction.source().source() != Source::None) { - if(operands > 1) operation += ", "; + if(print_first) operation += ", "; operation += to_string(instruction.source(), instruction, offsetLength, immediateLength); } if(displacement) { @@ -272,7 +273,7 @@ std::string to_string( case Operation::SAL: case Operation::SAR: case Operation::SHR: case Operation::SETMO: case Operation::SETMOC: - const int operands = max_num_operands(instruction.operation); + const int operands = max_displayed_operands(instruction.operation); const bool displacement = has_displacement(instruction.operation); operation += " "; if(operands > 1) {