1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-11 08:30:55 +00:00

Be overt about what's here to aid with printing only.

This commit is contained in:
Thomas Harte 2023-10-04 22:15:13 -04:00
parent 92c46faf84
commit 40af162214
3 changed files with 120 additions and 85 deletions

View File

@ -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 "???";
}
}

View File

@ -9,6 +9,8 @@
#ifndef InstructionSets_x86_Instruction_h
#define InstructionSets_x86_Instruction_h
#include "Model.hpp"
#include <cstddef>
#include <cstdint>
#include <string>
@ -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<bool is_32bit> class Instruction {
static_assert(sizeof(Instruction<true>) <= 16);
static_assert(sizeof(Instruction<false>) <= 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 */

View File

@ -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) {