From c87f361bb57b9b5998d4ab02bc49eaca4ebde9ef Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sun, 23 Apr 2023 09:38:03 -0700 Subject: [PATCH] FEXCore: Stop exposing the x86 table data symbols This was only used for the unit test fuzzing framework. Which has been removed and unused for pretty much its entire lifespan. These can now be internal only. --- .../FEXCore/Source/Interface/Core/Core.cpp | 2 +- .../Source/Interface/Core/Frontend.cpp | 2 +- .../FEXCore/Source/Interface/Core/Frontend.h | 3 +- .../Interface/Core/OpcodeDispatcher.cpp | 2 +- .../Source/Interface/Core/OpcodeDispatcher.h | 2 +- .../Core/OpcodeDispatcher/Crypto.cpp | 3 +- .../Interface/Core/OpcodeDispatcher/Flags.cpp | 2 +- .../Core/OpcodeDispatcher/Vector.cpp | 2 +- .../Interface/Core/OpcodeDispatcher/X87.cpp | 2 +- .../Core/OpcodeDispatcher/X87F64.cpp | 2 +- .../Source/Interface/Core/X86DebugInfo.cpp | 4 +- .../Source/Interface/Core/X86Tables.cpp | 3 +- .../Interface/Core/X86Tables/BaseTables.cpp | 1 - .../Interface/Core/X86Tables/DDDTables.cpp | 2 - .../Interface/Core/X86Tables/EVEXTables.cpp | 2 - .../Interface/Core/X86Tables/H0F38Tables.cpp | 1 - .../Interface/Core/X86Tables/H0F3ATables.cpp | 1 - .../Core/X86Tables/PrimaryGroupTables.cpp | 1 - .../Core/X86Tables/SecondaryGroupTables.cpp | 2 - .../Core/X86Tables/SecondaryModRMTables.cpp | 2 - .../Core/X86Tables/SecondaryTables.cpp | 1 - .../Interface/Core/X86Tables/VEXTables.cpp | 1 - .../Interface/Core/X86Tables/X86Tables.h | 510 ++++++++++++++++- .../Interface/Core/X86Tables/X87Tables.cpp | 1 - .../Interface/Core/X86Tables/XOPTables.cpp | 2 - .../FEXCore/include/FEXCore/Debug/X86Tables.h | 522 ------------------ 26 files changed, 526 insertions(+), 552 deletions(-) delete mode 100644 External/FEXCore/include/FEXCore/Debug/X86Tables.h diff --git a/External/FEXCore/Source/Interface/Core/Core.cpp b/External/FEXCore/Source/Interface/Core/Core.cpp index 7912f2868..d1190862c 100644 --- a/External/FEXCore/Source/Interface/Core/Core.cpp +++ b/External/FEXCore/Source/Interface/Core/Core.cpp @@ -19,6 +19,7 @@ $end_info$ #include "Interface/Core/Interpreter/InterpreterCore.h" #include "Interface/Core/JIT/JITCore.h" #include "Interface/Core/Dispatcher/Dispatcher.h" +#include "Interface/Core/X86Tables/X86Tables.h" #include "Interface/HLE/Thunks/Thunks.h" #include "Interface/IR/Passes/RegisterAllocationPass.h" #include "Interface/IR/Passes.h" @@ -32,7 +33,6 @@ $end_info$ #include #include #include -#include #include #include #include diff --git a/External/FEXCore/Source/Interface/Core/Frontend.cpp b/External/FEXCore/Source/Interface/Core/Frontend.cpp index 3ef39a812..5d5ecb8da 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.cpp +++ b/External/FEXCore/Source/Interface/Core/Frontend.cpp @@ -7,6 +7,7 @@ $end_info$ #include "Interface/Context/Context.h" #include "Interface/Core/Frontend.h" +#include "Interface/Core/X86Tables/X86Tables.h" #include #include @@ -14,7 +15,6 @@ $end_info$ #include #include #include -#include #include #include #include diff --git a/External/FEXCore/Source/Interface/Core/Frontend.h b/External/FEXCore/Source/Interface/Core/Frontend.h index 77e476668..7eb1b973c 100644 --- a/External/FEXCore/Source/Interface/Core/Frontend.h +++ b/External/FEXCore/Source/Interface/Core/Frontend.h @@ -1,6 +1,7 @@ #pragma once -#include +#include "Interface/Core/X86Tables/X86Tables.h" + #include #include #include diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index efc8a872b..f6b20e36f 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -7,12 +7,12 @@ $end_info$ #include "Interface/Context/Context.h" #include "Interface/Core/OpcodeDispatcher.h" +#include "Interface/Core/X86Tables/X86Tables.h" #include #include #include #include -#include #include #include #include diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index afab6b13e..70d89314c 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -1,12 +1,12 @@ #pragma once #include "Interface/Core/Frontend.h" +#include "Interface/Core/X86Tables/X86Tables.h" #include "Interface/Context/Context.h" #include #include #include -#include #include #include #include diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Crypto.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Crypto.cpp index 94b1275b6..4c0c288d0 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Crypto.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Crypto.cpp @@ -5,7 +5,8 @@ desc: Handles x86/64 Crypto instructions to IR $end_info$ */ -#include +#include "Interface/Core/X86Tables/X86Tables.h" + #include #include #include "Interface/Core/OpcodeDispatcher.h" diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp index 5f3c0b248..d8675fc53 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Flags.cpp @@ -7,10 +7,10 @@ $end_info$ #include "Interface/Context/Context.h" #include "Interface/Core/OpcodeDispatcher.h" +#include "Interface/Core/X86Tables/X86Tables.h" #include #include -#include #include #include diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index 9ea7aa8cf..6e912307b 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -7,11 +7,11 @@ $end_info$ #include "Interface/Context/Context.h" #include "Interface/Core/OpcodeDispatcher.h" +#include "Interface/Core/X86Tables/X86Tables.h" #include #include #include -#include #include #include diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp index bd15fbfa2..028f90aa5 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87.cpp @@ -6,10 +6,10 @@ $end_info$ */ #include "Interface/Core/OpcodeDispatcher.h" +#include "Interface/Core/X86Tables/X86Tables.h" #include #include -#include #include #include #include diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp index 7b48453b9..8ec02fc9e 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher/X87F64.cpp @@ -6,10 +6,10 @@ $end_info$ */ #include "Interface/Core/OpcodeDispatcher.h" +#include "Interface/Core/X86Tables/X86Tables.h" #include #include -#include #include #include #include diff --git a/External/FEXCore/Source/Interface/Core/X86DebugInfo.cpp b/External/FEXCore/Source/Interface/Core/X86DebugInfo.cpp index 21b8fec59..596a685bb 100644 --- a/External/FEXCore/Source/Interface/Core/X86DebugInfo.cpp +++ b/External/FEXCore/Source/Interface/Core/X86DebugInfo.cpp @@ -1,5 +1,7 @@ #ifndef NDEBUG -#include + +#include "Interface/Core/X86Tables/X86Tables.h" + #include #include diff --git a/External/FEXCore/Source/Interface/Core/X86Tables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables.cpp index 54953a3e6..ef277c808 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables.cpp @@ -5,8 +5,9 @@ tags: frontend|x86-tables $end_info$ */ +#include "Interface/Core/X86Tables/X86Tables.h" + #include -#include namespace FEXCore::X86Tables { diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp index 27d75166f..bd961b3d6 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/BaseTables.cpp @@ -7,7 +7,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" #include -#include #include diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/DDDTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/DDDTables.cpp index d086aedee..700513ec7 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/DDDTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/DDDTables.cpp @@ -6,8 +6,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" -#include - #include namespace FEXCore::X86Tables { diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/EVEXTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/EVEXTables.cpp index 8f1f43a60..e3f38258b 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/EVEXTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/EVEXTables.cpp @@ -6,8 +6,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" -#include - #include namespace FEXCore::X86Tables { diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp index a7c95e899..8519c54fa 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/H0F38Tables.cpp @@ -5,7 +5,6 @@ $end_info$ */ #include "Interface/Core/X86Tables/X86Tables.h" -#include #include #include diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/H0F3ATables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/H0F3ATables.cpp index 7575f9167..58b76d014 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/H0F3ATables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/H0F3ATables.cpp @@ -6,7 +6,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" -#include #include #include diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp index a0a110c7a..04f37ab63 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/PrimaryGroupTables.cpp @@ -7,7 +7,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" #include -#include #include diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryGroupTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryGroupTables.cpp index dcc74edcb..1cefac9a6 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryGroupTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryGroupTables.cpp @@ -6,8 +6,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" -#include - #include #include diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryModRMTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryModRMTables.cpp index 89d9a7f51..984e2f2a9 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryModRMTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryModRMTables.cpp @@ -6,8 +6,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" -#include - #include namespace FEXCore::X86Tables { diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp index 1a510d235..4a55ca290 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/SecondaryTables.cpp @@ -7,7 +7,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" #include -#include #include diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp index d5972939b..c42aeceb3 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/VEXTables.cpp @@ -6,7 +6,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" -#include #include namespace FEXCore::X86Tables { diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h b/External/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h index f0362bc3c..5e8594af2 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h +++ b/External/FEXCore/Source/Interface/Core/X86Tables/X86Tables.h @@ -5,13 +5,514 @@ $end_info$ */ #pragma once -#include #include #include +namespace FEXCore::IR { +///< Forward declaration of OpDispatchBuilder +class OpDispatchBuilder; +} + namespace FEXCore::X86Tables { +///< Forward declaration of X86InstInfo +struct X86InstInfo; + +namespace DecodeFlags { +constexpr uint32_t FLAG_OPERAND_SIZE = (1 << 0); +constexpr uint32_t FLAG_ADDRESS_SIZE = (1 << 1); +constexpr uint32_t FLAG_LOCK = (1 << 2); +constexpr uint32_t FLAG_LEGACY_PREFIX = (1 << 3); +constexpr uint32_t FLAG_REX_PREFIX = (1 << 4); +// Hole where 1 << 5 is +// Hole where 1 << 6 is +constexpr uint32_t FLAG_REX_WIDENING = (1 << 7); +constexpr uint32_t FLAG_REX_XGPR_B = (1 << 8); +constexpr uint32_t FLAG_REX_XGPR_X = (1 << 9); +constexpr uint32_t FLAG_REX_XGPR_R = (1 << 10); +constexpr uint32_t FLAG_ES_PREFIX = (1 << 11); +constexpr uint32_t FLAG_CS_PREFIX = (1 << 12); +constexpr uint32_t FLAG_SS_PREFIX = (1 << 13); +constexpr uint32_t FLAG_DS_PREFIX = (1 << 14); +constexpr uint32_t FLAG_FS_PREFIX = (1 << 15); +constexpr uint32_t FLAG_GS_PREFIX = (1 << 16); +constexpr uint32_t FLAG_SEGMENTS = (0b11'1111 << 11); + +constexpr uint32_t FLAG_REP_PREFIX = (1 << 17); +constexpr uint32_t FLAG_REPNE_PREFIX = (1 << 18); +// Size flags +constexpr uint32_t FLAG_SIZE_DST_OFF = 19; +constexpr uint32_t FLAG_SIZE_SRC_OFF = FLAG_SIZE_DST_OFF + 3; +constexpr uint32_t SIZE_MASK = 0b111; +constexpr uint32_t SIZE_DEF = 0b000; // This should be invalid past decoding +constexpr uint32_t SIZE_8BIT = 0b001; +constexpr uint32_t SIZE_16BIT = 0b010; +constexpr uint32_t SIZE_32BIT = 0b011; +constexpr uint32_t SIZE_64BIT = 0b100; +constexpr uint32_t SIZE_128BIT = 0b101; +constexpr uint32_t SIZE_256BIT = 0b110; + +constexpr uint32_t FLAG_OPADDR_OFF = (FLAG_SIZE_SRC_OFF + 3); +constexpr uint32_t FLAG_OPADDR_STACKSIZE = 4; // Two level deep stack +constexpr uint32_t FLAG_OPADDR_FLAG_SIZE = 2; +constexpr uint32_t FLAG_OPADDR_MASK = (((1 << FLAG_OPADDR_STACKSIZE) - 1) << FLAG_OPADDR_OFF); + +// 00 = NONE +constexpr uint32_t FLAG_OPERAND_SIZE_LAST = 0b01; +constexpr uint32_t FLAG_WIDENING_SIZE_LAST = 0b10; + +constexpr uint32_t GetSizeDstFlags(uint32_t Flags) { return (Flags >> FLAG_SIZE_DST_OFF) & SIZE_MASK; } +constexpr uint32_t GetSizeSrcFlags(uint32_t Flags) { return (Flags >> FLAG_SIZE_SRC_OFF) & SIZE_MASK; } + +constexpr uint32_t GenSizeDstSize(uint32_t Size) { return Size << FLAG_SIZE_DST_OFF; } +constexpr uint32_t GenSizeSrcSize(uint32_t Size) { return Size << FLAG_SIZE_SRC_OFF; } + +constexpr uint32_t GetOpAddr(uint32_t Flags, uint32_t Index) { + return (((Flags & FLAG_OPADDR_MASK) >> FLAG_OPADDR_OFF) >> (Index * 2)) & ((1 << FLAG_OPADDR_FLAG_SIZE) - 1); +} + +inline void PushOpAddr(uint32_t *Flags, uint32_t Flag) { + uint32_t TmpFlags = *Flags; + uint32_t BottomOfStack = ((TmpFlags & FLAG_OPADDR_MASK) >> FLAG_OPADDR_OFF) & ((1 << FLAG_OPADDR_FLAG_SIZE) - 1); + + TmpFlags &= ~(FLAG_OPADDR_MASK); + TmpFlags |= + (BottomOfStack << (FLAG_OPADDR_OFF + FLAG_OPADDR_FLAG_SIZE)) | + (Flag << FLAG_OPADDR_OFF); + + *Flags = TmpFlags; +} + +inline void PopOpAddrIf(uint32_t *Flags, uint32_t Flag) { + uint32_t TmpFlags = *Flags; + uint32_t BottomOfStack = ((TmpFlags & FLAG_OPADDR_MASK) >> FLAG_OPADDR_OFF) & ((1 << FLAG_OPADDR_FLAG_SIZE) - 1); + + // Only pop the stack if the bottom flag is the one we care about + // Necessary for escape prefixes that overlap regular prefixes + if (BottomOfStack != Flag) { + return; + } + + uint32_t TopOfStack = ((TmpFlags & FLAG_OPADDR_MASK) >> (FLAG_OPADDR_OFF + FLAG_OPADDR_FLAG_SIZE)) & ((1 << FLAG_OPADDR_FLAG_SIZE) - 1); + + TmpFlags &= ~(FLAG_OPADDR_MASK); + TmpFlags |= (TopOfStack << FLAG_OPADDR_OFF); + + *Flags = TmpFlags; +} + +} + +struct DecodedOperand { + enum class OpType : uint8_t { + Nothing, + GPR, + GPRDirect, + GPRIndirect, + RIPRelative, + Literal, + SIB, + }; + + bool IsNone() const { + return Type == OpType::Nothing; + } + bool IsGPR() const { + return Type == OpType::GPR; + } + bool IsGPRDirect() const { + return Type == OpType::GPRDirect; + } + bool IsGPRIndirect() const { + return Type == OpType::GPRIndirect; + } + bool IsRIPRelative() const { + return Type == OpType::RIPRelative; + } + bool IsLiteral() const { + return Type == OpType::Literal; + } + bool IsSIB() const { + return Type == OpType::SIB; + } + + union TypeUnion { + struct { + bool HighBits; + uint8_t GPR; + } GPR; + + struct { + int32_t Displacement; + uint8_t GPR; + } GPRIndirect; + + struct { + union { + int32_t s; + uint32_t u; + } Value; + } RIPLiteral; + + struct { + uint64_t Value; + uint8_t Size; + } Literal; + + struct { + int32_t Offset; + uint8_t Scale; + uint8_t Index; // ~0 invalid + uint8_t Base; // ~0 invalid + } SIB; + }; + + TypeUnion Data; + OpType Type; +}; + +struct DecodedInst { + uint64_t PC; + + DecodedOperand Dest; + DecodedOperand Src[3]; + + // Constains the dispatcher handler pointer + X86InstInfo const* TableInfo; + + uint32_t Flags; + uint16_t OP; + + uint8_t ModRM; + uint8_t SIB; + uint8_t InstSize; + uint8_t LastEscapePrefix; + bool DecodedModRM; + bool DecodedSIB; +}; + +union ModRMDecoded { + uint8_t Hex{}; + struct { + uint8_t rm : 3; + uint8_t reg : 3; + uint8_t mod : 2; + }; +}; + +union SIBDecoded { + uint8_t Hex{}; + struct { + uint8_t base : 3; + uint8_t index : 3; + uint8_t scale : 2; + }; +}; + +enum InstType { + TYPE_UNKNOWN, + TYPE_LEGACY_PREFIX, + TYPE_PREFIX, + TYPE_REX_PREFIX, + TYPE_SECONDARY_TABLE_PREFIX, + TYPE_X87_TABLE_PREFIX, + TYPE_VEX_TABLE_PREFIX, + TYPE_XOP_TABLE_PREFIX, + TYPE_INST, + TYPE_X87 = TYPE_INST, + TYPE_INVALID, + TYPE_COPY_OTHER, + + // Must be in order + // Groups 1, 1a, 2, 3, 4, 5, 11 are for the primary op table + // Groups 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, p are for the secondary op table + TYPE_GROUP_1, + TYPE_GROUP_1A, + TYPE_GROUP_2, + TYPE_GROUP_3, + TYPE_GROUP_4, + TYPE_GROUP_5, + TYPE_GROUP_11, + + // Must be in order + // Groups 6-p Are for the secondary op table + TYPE_GROUP_6, + TYPE_GROUP_7, + TYPE_GROUP_8, + TYPE_GROUP_9, + TYPE_GROUP_10, + TYPE_GROUP_12, + TYPE_GROUP_13, + TYPE_GROUP_14, + TYPE_GROUP_15, + TYPE_GROUP_16, + TYPE_GROUP_17, + TYPE_GROUP_P, + + // The secondary op extension table allows further extensions + // Group 7 allows additional extensions to this table + TYPE_SECOND_GROUP_MODRM, + + TYPE_VEX_GROUP_12, + TYPE_VEX_GROUP_13, + TYPE_VEX_GROUP_14, + TYPE_VEX_GROUP_15, + TYPE_VEX_GROUP_17, + + TYPE_GROUP_EVEX, + + // Exists in the table but isn't decoded correctly + TYPE_UNDEC = TYPE_INVALID, + TYPE_MMX = TYPE_INVALID, + TYPE_PRIV = TYPE_INVALID, + TYPE_0F38_TABLE = TYPE_INVALID, + TYPE_0F3A_TABLE = TYPE_INVALID, + TYPE_3DNOW_TABLE = TYPE_INVALID, +}; + +namespace InstFlags { + +using InstFlagType = uint64_t; + +constexpr InstFlagType FLAGS_NONE = 0; +constexpr InstFlagType FLAGS_DEBUG = (1ULL << 1); +constexpr InstFlagType FLAGS_DEBUG_MEM_ACCESS = (1ULL << 2); +constexpr InstFlagType FLAGS_SUPPORTS_REP = (1ULL << 3); +constexpr InstFlagType FLAGS_BLOCK_END = (1ULL << 4); +constexpr InstFlagType FLAGS_SETS_RIP = (1ULL << 5); + +constexpr InstFlagType FLAGS_DISPLACE_SIZE_MUL_2 = (1ULL << 6); +constexpr InstFlagType FLAGS_DISPLACE_SIZE_DIV_2 = (1ULL << 7); +constexpr InstFlagType FLAGS_SRC_SEXT = (1ULL << 8); +constexpr InstFlagType FLAGS_MEM_OFFSET = (1ULL << 9); + +// Enables XMM based subflags +// Current reserved range for this SF is [10, 15] +constexpr InstFlagType FLAGS_XMM_FLAGS = (1ULL << 10); + +// X87 flags aliased to XMM flags selection +// Allows X87 instruction table that is abusing the flag for 64BIT selection to work +constexpr InstFlagType FLAGS_X87_FLAGS = (1ULL << 10); + + // Non-XMM subflags + constexpr InstFlagType FLAGS_SF_DST_RAX = (1ULL << 11); + constexpr InstFlagType FLAGS_SF_DST_RDX = (1ULL << 12); + constexpr InstFlagType FLAGS_SF_SRC_RAX = (1ULL << 13); + constexpr InstFlagType FLAGS_SF_SRC_RCX = (1ULL << 14); + constexpr InstFlagType FLAGS_SF_REX_IN_BYTE = (1ULL << 15); + + // XMM subflags + constexpr InstFlagType FLAGS_SF_UNUSED = (1ULL << 11); // No assigned behavior yet + constexpr InstFlagType FLAGS_SF_DST_GPR = (1ULL << 12); + constexpr InstFlagType FLAGS_SF_SRC_GPR = (1ULL << 13); + constexpr InstFlagType FLAGS_SF_MMX_DST = (1ULL << 14); + constexpr InstFlagType FLAGS_SF_MMX_SRC = (1ULL << 15); + constexpr InstFlagType FLAGS_SF_MMX = FLAGS_SF_MMX_DST | FLAGS_SF_MMX_SRC; + +// Enables MODRM specific subflags +// Current reserved range for this SF is [14, 17] +constexpr InstFlagType FLAGS_MODRM = (1ULL << 16); + + // With ModRM SF flag enabled + // Direction of ModRM. Dst ^ Src + // Set means destination is rm bits + // Unset means src is rm bits + constexpr InstFlagType FLAGS_SF_MOD_DST = (1ULL << 17); + + // If the instruction is restricted to mem or reg only + // 0b00 = Regular ModRM support + // 0b01 = Memory accesses only + // 0b10 = Register accesses only + // 0b11 = + constexpr InstFlagType FLAGS_SF_MOD_MEM_ONLY = (1ULL << 18); + constexpr InstFlagType FLAGS_SF_MOD_REG_ONLY = (1ULL << 19); + +// The secondary Opcode Map uses prefix bytes to overlay more instruction +// But some instructions need to ignore this overlay and consume these prefixes. +constexpr InstFlagType FLAGS_NO_OVERLAY = (1ULL << 20); +// Some instructions partially ignore overlay +// Ignore OpSize (0x66) in this case +constexpr InstFlagType FLAGS_NO_OVERLAY66 = (1ULL << 21); + +// x87 +constexpr InstFlagType FLAGS_POP = (1ULL << 22); + +// Only SEXT if the instruction is operating in 64bit operand size +constexpr InstFlagType FLAGS_SRC_SEXT64BIT = (1ULL << 23); + +// Whether or not the instruction has a VEX prefix for the first source operand +constexpr InstFlagType FLAGS_VEX_1ST_SRC = (1ULL << 24); +// Whether or not the instruction has a VEX prefix for the second source operand +constexpr InstFlagType FLAGS_VEX_2ND_SRC = (1ULL << 25); +// Whether or not the instruction has a VEX prefix for the destination +constexpr InstFlagType FLAGS_VEX_DST = (1ULL << 26); + +constexpr InstFlagType FLAGS_SIZE_DST_OFF = 58; +constexpr InstFlagType FLAGS_SIZE_SRC_OFF = FLAGS_SIZE_DST_OFF + 3; + +constexpr InstFlagType SIZE_MASK = 0b111; +constexpr InstFlagType SIZE_DEF = 0b000; +constexpr InstFlagType SIZE_8BIT = 0b001; +constexpr InstFlagType SIZE_16BIT = 0b010; +constexpr InstFlagType SIZE_32BIT = 0b011; +constexpr InstFlagType SIZE_64BIT = 0b100; +constexpr InstFlagType SIZE_128BIT = 0b101; +constexpr InstFlagType SIZE_256BIT = 0b110; +constexpr InstFlagType SIZE_64BITDEF = 0b111; // Default mode is 64bit instead of typical 32bit + +constexpr InstFlagType GetSizeDstFlags(InstFlagType Flags) { return (Flags >> FLAGS_SIZE_DST_OFF) & SIZE_MASK; } +constexpr InstFlagType GetSizeSrcFlags(InstFlagType Flags) { return (Flags >> FLAGS_SIZE_SRC_OFF) & SIZE_MASK; } + +constexpr InstFlagType GenFlagsDstSize(InstFlagType Size) { return Size << FLAGS_SIZE_DST_OFF; } +constexpr InstFlagType GenFlagsSrcSize(InstFlagType Size) { return Size << FLAGS_SIZE_SRC_OFF; } +constexpr InstFlagType GenFlagsSameSize(InstFlagType Size) { return (Size << FLAGS_SIZE_DST_OFF) | (Size << FLAGS_SIZE_SRC_OFF); } +constexpr InstFlagType GenFlagsSizes(InstFlagType Dest, InstFlagType Src) { return (Dest << FLAGS_SIZE_DST_OFF) | (Src << FLAGS_SIZE_SRC_OFF); } + +// If it has an xmm subflag +#define HAS_XMM_SUBFLAG(x, flag) (((x) & (FEXCore::X86Tables::InstFlags::FLAGS_XMM_FLAGS | (flag))) == (FEXCore::X86Tables::InstFlags::FLAGS_XMM_FLAGS | (flag))) + +// If it has non-xmm subflag +#define HAS_NON_XMM_SUBFLAG(x, flag) (((x) & (FEXCore::X86Tables::InstFlags::FLAGS_XMM_FLAGS | (flag))) == (flag)) +} + +constexpr uint8_t OpToIndex(uint8_t Op) { + switch (Op) { + // Group 1 + case 0x80: return 0; + case 0x81: return 1; + case 0x82: return 2; + case 0x83: return 3; + // Group 2 + case 0xC0: return 0; + case 0xC1: return 1; + case 0xD0: return 2; + case 0xD1: return 3; + case 0xD2: return 4; + case 0xD3: return 5; + // Group 3 + case 0xF6: return 0; + case 0xF7: return 1; + // Group 4 + case 0xFE: return 0; + // Group 5 + case 0xFF: return 0; + // Group 11 + case 0xC6: return 0; + case 0xC7: return 1; + } + return 0; +} + +using DecodedOp = DecodedInst const*; +using OpDispatchPtr = void (IR::OpDispatchBuilder::*)(DecodedOp); + +#ifndef NDEBUG +namespace X86InstDebugInfo { +constexpr uint64_t FLAGS_MEM_ALIGN_4 = (1 << 0); +constexpr uint64_t FLAGS_MEM_ALIGN_8 = (1 << 1); +constexpr uint64_t FLAGS_MEM_ALIGN_16 = (1 << 2); +constexpr uint64_t FLAGS_MEM_ALIGN_SIZE = (1 << 3); // If instruction size changes depending on prefixes +constexpr uint64_t FLAGS_MEM_ACCESS = (1 << 4); +constexpr uint64_t FLAGS_DEBUG = (1 << 5); +constexpr uint64_t FLAGS_DIVIDE = (1 << 6); + + +struct Flags { + uint64_t DebugFlags; +}; +void InstallDebugInfo(); +} + +#endif + +struct X86InstInfo { + char const *Name; + InstType Type; + InstFlags::InstFlagType Flags; ///< Must be larger than InstFlags enum + uint8_t MoreBytes; + OpDispatchPtr OpcodeDispatcher; +#ifndef NDEBUG + X86InstDebugInfo::Flags DebugInfo; + uint32_t NumUnitTestsGenerated; +#endif + + bool operator==(const X86InstInfo &b) const { + if (strcmp(Name, b.Name) != 0 || + Type != b.Type || + Flags != b.Flags || + MoreBytes != b.MoreBytes) + return false; + + // We don't care if the opcode dispatcher differs + return true; + } + bool operator!=(const X86InstInfo &b) const { + return !operator==(b); + } +}; + +static_assert(std::is_trivial::value, "X86InstInfo needs to be trivial"); + +constexpr size_t MAX_PRIMARY_TABLE_SIZE = 256; +constexpr size_t MAX_SECOND_TABLE_SIZE = 256; +constexpr size_t MAX_REP_MOD_TABLE_SIZE = 256; +constexpr size_t MAX_REPNE_MOD_TABLE_SIZE = 256; +constexpr size_t MAX_OPSIZE_MOD_TABLE_SIZE = 256; +// 6 (groups) | 6 (max indexes) | 8 ops = 0b111'111'111 = 9 bits +constexpr size_t MAX_INST_GROUP_TABLE_SIZE = 512; +// 12 (groups) | 3(max indexes) | 8 ops = 0b1111'11'111 = 9 bits +constexpr size_t MAX_INST_SECOND_GROUP_TABLE_SIZE = 512; +constexpr size_t MAX_X87_TABLE_SIZE = 1 << 11; +constexpr size_t MAX_SECOND_MODRM_TABLE_SIZE = 32; +// (3 bit prefixes) | 8 bit opcode +constexpr size_t MAX_0F_38_TABLE_SIZE = (1 << 11); +// 1 REX | 1 prefixes | 8 bit opcode +constexpr size_t MAX_0F_3A_TABLE_SIZE = (1 << 11); +constexpr size_t MAX_3DNOW_TABLE_SIZE = 256; +// VEX +// map_select(2 bits for now) | vex.pp (2 bits) | opcode (8bit) +constexpr size_t MAX_VEX_TABLE_SIZE = (1 << 13); +// VEX group ops +// group select (3 bits for now) | ModRM opcode (3 bits) +constexpr size_t MAX_VEX_GROUP_TABLE_SIZE = (1 << 7); + +// XOP +// group (2 bits for now) | vex.pp (2 bits) | opcode (8bit) +constexpr size_t MAX_XOP_TABLE_SIZE = (1 << 13); + +// XOP group ops +// group select (2 bits for now) | modrm opcode (3 bits) +constexpr size_t MAX_XOP_GROUP_TABLE_SIZE = (1 << 6); + +constexpr size_t MAX_EVEX_TABLE_SIZE = 256; + +extern std::array BaseOps; +extern std::array SecondBaseOps; +extern std::array RepModOps; +extern std::array RepNEModOps; +extern std::array OpSizeModOps; + +extern std::array PrimaryInstGroupOps; +extern std::array SecondInstGroupOps; +extern std::array SecondModRMTableOps; +extern std::array X87Ops; +extern std::array DDDNowOps; +extern std::array H0F38TableOps; +extern std::array H0F3ATableOps; + +// VEX +extern std::array VEXTableOps; +extern std::array VEXTableGroupOps; + +// XOP +extern std::array XOPTableOps; +extern std::array XOPTableGroupOps; + +// EVEX +extern std::array EVEXTableOps; + + #ifndef NDEBUG extern uint64_t Total; extern uint64_t NumInsts; @@ -102,3 +603,10 @@ void InitializeInfoTables(Context::OperatingMode Mode); } +template <> +struct fmt::formatter : formatter { + template + auto format(FEXCore::X86Tables::DecodedOperand::OpType type, FormatContext& ctx) const { + return fmt::formatter::format(static_cast(type), ctx); + } +}; diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp index 1d9817d2a..c9ba17432 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/X87Tables.cpp @@ -6,7 +6,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" -#include #include namespace FEXCore::X86Tables { diff --git a/External/FEXCore/Source/Interface/Core/X86Tables/XOPTables.cpp b/External/FEXCore/Source/Interface/Core/X86Tables/XOPTables.cpp index 000f49a11..0539cde52 100644 --- a/External/FEXCore/Source/Interface/Core/X86Tables/XOPTables.cpp +++ b/External/FEXCore/Source/Interface/Core/X86Tables/XOPTables.cpp @@ -6,8 +6,6 @@ $end_info$ #include "Interface/Core/X86Tables/X86Tables.h" -#include - #include #include diff --git a/External/FEXCore/include/FEXCore/Debug/X86Tables.h b/External/FEXCore/include/FEXCore/Debug/X86Tables.h deleted file mode 100644 index a5f47c144..000000000 --- a/External/FEXCore/include/FEXCore/Debug/X86Tables.h +++ /dev/null @@ -1,522 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include - -#include - -namespace FEXCore::IR { -///< Forward declaration of OpDispatchBuilder -class OpDispatchBuilder; -} - -namespace FEXCore::X86Tables { - -///< Forward declaration of X86InstInfo -struct X86InstInfo; - -namespace DecodeFlags { -constexpr uint32_t FLAG_OPERAND_SIZE = (1 << 0); -constexpr uint32_t FLAG_ADDRESS_SIZE = (1 << 1); -constexpr uint32_t FLAG_LOCK = (1 << 2); -constexpr uint32_t FLAG_LEGACY_PREFIX = (1 << 3); -constexpr uint32_t FLAG_REX_PREFIX = (1 << 4); -// Hole where 1 << 5 is -// Hole where 1 << 6 is -constexpr uint32_t FLAG_REX_WIDENING = (1 << 7); -constexpr uint32_t FLAG_REX_XGPR_B = (1 << 8); -constexpr uint32_t FLAG_REX_XGPR_X = (1 << 9); -constexpr uint32_t FLAG_REX_XGPR_R = (1 << 10); -constexpr uint32_t FLAG_ES_PREFIX = (1 << 11); -constexpr uint32_t FLAG_CS_PREFIX = (1 << 12); -constexpr uint32_t FLAG_SS_PREFIX = (1 << 13); -constexpr uint32_t FLAG_DS_PREFIX = (1 << 14); -constexpr uint32_t FLAG_FS_PREFIX = (1 << 15); -constexpr uint32_t FLAG_GS_PREFIX = (1 << 16); -constexpr uint32_t FLAG_SEGMENTS = (0b11'1111 << 11); - -constexpr uint32_t FLAG_REP_PREFIX = (1 << 17); -constexpr uint32_t FLAG_REPNE_PREFIX = (1 << 18); -// Size flags -constexpr uint32_t FLAG_SIZE_DST_OFF = 19; -constexpr uint32_t FLAG_SIZE_SRC_OFF = FLAG_SIZE_DST_OFF + 3; -constexpr uint32_t SIZE_MASK = 0b111; -constexpr uint32_t SIZE_DEF = 0b000; // This should be invalid past decoding -constexpr uint32_t SIZE_8BIT = 0b001; -constexpr uint32_t SIZE_16BIT = 0b010; -constexpr uint32_t SIZE_32BIT = 0b011; -constexpr uint32_t SIZE_64BIT = 0b100; -constexpr uint32_t SIZE_128BIT = 0b101; -constexpr uint32_t SIZE_256BIT = 0b110; - -constexpr uint32_t FLAG_OPADDR_OFF = (FLAG_SIZE_SRC_OFF + 3); -constexpr uint32_t FLAG_OPADDR_STACKSIZE = 4; // Two level deep stack -constexpr uint32_t FLAG_OPADDR_FLAG_SIZE = 2; -constexpr uint32_t FLAG_OPADDR_MASK = (((1 << FLAG_OPADDR_STACKSIZE) - 1) << FLAG_OPADDR_OFF); - -// 00 = NONE -constexpr uint32_t FLAG_OPERAND_SIZE_LAST = 0b01; -constexpr uint32_t FLAG_WIDENING_SIZE_LAST = 0b10; - -constexpr uint32_t GetSizeDstFlags(uint32_t Flags) { return (Flags >> FLAG_SIZE_DST_OFF) & SIZE_MASK; } -constexpr uint32_t GetSizeSrcFlags(uint32_t Flags) { return (Flags >> FLAG_SIZE_SRC_OFF) & SIZE_MASK; } - -constexpr uint32_t GenSizeDstSize(uint32_t Size) { return Size << FLAG_SIZE_DST_OFF; } -constexpr uint32_t GenSizeSrcSize(uint32_t Size) { return Size << FLAG_SIZE_SRC_OFF; } - -constexpr uint32_t GetOpAddr(uint32_t Flags, uint32_t Index) { - return (((Flags & FLAG_OPADDR_MASK) >> FLAG_OPADDR_OFF) >> (Index * 2)) & ((1 << FLAG_OPADDR_FLAG_SIZE) - 1); -} - -inline void PushOpAddr(uint32_t *Flags, uint32_t Flag) { - uint32_t TmpFlags = *Flags; - uint32_t BottomOfStack = ((TmpFlags & FLAG_OPADDR_MASK) >> FLAG_OPADDR_OFF) & ((1 << FLAG_OPADDR_FLAG_SIZE) - 1); - - TmpFlags &= ~(FLAG_OPADDR_MASK); - TmpFlags |= - (BottomOfStack << (FLAG_OPADDR_OFF + FLAG_OPADDR_FLAG_SIZE)) | - (Flag << FLAG_OPADDR_OFF); - - *Flags = TmpFlags; -} - -inline void PopOpAddrIf(uint32_t *Flags, uint32_t Flag) { - uint32_t TmpFlags = *Flags; - uint32_t BottomOfStack = ((TmpFlags & FLAG_OPADDR_MASK) >> FLAG_OPADDR_OFF) & ((1 << FLAG_OPADDR_FLAG_SIZE) - 1); - - // Only pop the stack if the bottom flag is the one we care about - // Necessary for escape prefixes that overlap regular prefixes - if (BottomOfStack != Flag) { - return; - } - - uint32_t TopOfStack = ((TmpFlags & FLAG_OPADDR_MASK) >> (FLAG_OPADDR_OFF + FLAG_OPADDR_FLAG_SIZE)) & ((1 << FLAG_OPADDR_FLAG_SIZE) - 1); - - TmpFlags &= ~(FLAG_OPADDR_MASK); - TmpFlags |= (TopOfStack << FLAG_OPADDR_OFF); - - *Flags = TmpFlags; -} - -} - -struct DecodedOperand { - enum class OpType : uint8_t { - Nothing, - GPR, - GPRDirect, - GPRIndirect, - RIPRelative, - Literal, - SIB, - }; - - bool IsNone() const { - return Type == OpType::Nothing; - } - bool IsGPR() const { - return Type == OpType::GPR; - } - bool IsGPRDirect() const { - return Type == OpType::GPRDirect; - } - bool IsGPRIndirect() const { - return Type == OpType::GPRIndirect; - } - bool IsRIPRelative() const { - return Type == OpType::RIPRelative; - } - bool IsLiteral() const { - return Type == OpType::Literal; - } - bool IsSIB() const { - return Type == OpType::SIB; - } - - union TypeUnion { - struct { - bool HighBits; - uint8_t GPR; - } GPR; - - struct { - int32_t Displacement; - uint8_t GPR; - } GPRIndirect; - - struct { - union { - int32_t s; - uint32_t u; - } Value; - } RIPLiteral; - - struct { - uint64_t Value; - uint8_t Size; - } Literal; - - struct { - int32_t Offset; - uint8_t Scale; - uint8_t Index; // ~0 invalid - uint8_t Base; // ~0 invalid - } SIB; - }; - - TypeUnion Data; - OpType Type; -}; - -struct DecodedInst { - uint64_t PC; - - DecodedOperand Dest; - DecodedOperand Src[3]; - - // Constains the dispatcher handler pointer - X86InstInfo const* TableInfo; - - uint32_t Flags; - uint16_t OP; - - uint8_t ModRM; - uint8_t SIB; - uint8_t InstSize; - uint8_t LastEscapePrefix; - bool DecodedModRM; - bool DecodedSIB; -}; - -union ModRMDecoded { - uint8_t Hex{}; - struct { - uint8_t rm : 3; - uint8_t reg : 3; - uint8_t mod : 2; - }; -}; - -union SIBDecoded { - uint8_t Hex{}; - struct { - uint8_t base : 3; - uint8_t index : 3; - uint8_t scale : 2; - }; -}; - -enum InstType { - TYPE_UNKNOWN, - TYPE_LEGACY_PREFIX, - TYPE_PREFIX, - TYPE_REX_PREFIX, - TYPE_SECONDARY_TABLE_PREFIX, - TYPE_X87_TABLE_PREFIX, - TYPE_VEX_TABLE_PREFIX, - TYPE_XOP_TABLE_PREFIX, - TYPE_INST, - TYPE_X87 = TYPE_INST, - TYPE_INVALID, - TYPE_COPY_OTHER, - - // Must be in order - // Groups 1, 1a, 2, 3, 4, 5, 11 are for the primary op table - // Groups 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, p are for the secondary op table - TYPE_GROUP_1, - TYPE_GROUP_1A, - TYPE_GROUP_2, - TYPE_GROUP_3, - TYPE_GROUP_4, - TYPE_GROUP_5, - TYPE_GROUP_11, - - // Must be in order - // Groups 6-p Are for the secondary op table - TYPE_GROUP_6, - TYPE_GROUP_7, - TYPE_GROUP_8, - TYPE_GROUP_9, - TYPE_GROUP_10, - TYPE_GROUP_12, - TYPE_GROUP_13, - TYPE_GROUP_14, - TYPE_GROUP_15, - TYPE_GROUP_16, - TYPE_GROUP_17, - TYPE_GROUP_P, - - // The secondary op extension table allows further extensions - // Group 7 allows additional extensions to this table - TYPE_SECOND_GROUP_MODRM, - - TYPE_VEX_GROUP_12, - TYPE_VEX_GROUP_13, - TYPE_VEX_GROUP_14, - TYPE_VEX_GROUP_15, - TYPE_VEX_GROUP_17, - - TYPE_GROUP_EVEX, - - // Exists in the table but isn't decoded correctly - TYPE_UNDEC = TYPE_INVALID, - TYPE_MMX = TYPE_INVALID, - TYPE_PRIV = TYPE_INVALID, - TYPE_0F38_TABLE = TYPE_INVALID, - TYPE_0F3A_TABLE = TYPE_INVALID, - TYPE_3DNOW_TABLE = TYPE_INVALID, -}; - -namespace InstFlags { - -using InstFlagType = uint64_t; - -constexpr InstFlagType FLAGS_NONE = 0; -constexpr InstFlagType FLAGS_DEBUG = (1ULL << 1); -constexpr InstFlagType FLAGS_DEBUG_MEM_ACCESS = (1ULL << 2); -constexpr InstFlagType FLAGS_SUPPORTS_REP = (1ULL << 3); -constexpr InstFlagType FLAGS_BLOCK_END = (1ULL << 4); -constexpr InstFlagType FLAGS_SETS_RIP = (1ULL << 5); - -constexpr InstFlagType FLAGS_DISPLACE_SIZE_MUL_2 = (1ULL << 6); -constexpr InstFlagType FLAGS_DISPLACE_SIZE_DIV_2 = (1ULL << 7); -constexpr InstFlagType FLAGS_SRC_SEXT = (1ULL << 8); -constexpr InstFlagType FLAGS_MEM_OFFSET = (1ULL << 9); - -// Enables XMM based subflags -// Current reserved range for this SF is [10, 15] -constexpr InstFlagType FLAGS_XMM_FLAGS = (1ULL << 10); - -// X87 flags aliased to XMM flags selection -// Allows X87 instruction table that is abusing the flag for 64BIT selection to work -constexpr InstFlagType FLAGS_X87_FLAGS = (1ULL << 10); - - // Non-XMM subflags - constexpr InstFlagType FLAGS_SF_DST_RAX = (1ULL << 11); - constexpr InstFlagType FLAGS_SF_DST_RDX = (1ULL << 12); - constexpr InstFlagType FLAGS_SF_SRC_RAX = (1ULL << 13); - constexpr InstFlagType FLAGS_SF_SRC_RCX = (1ULL << 14); - constexpr InstFlagType FLAGS_SF_REX_IN_BYTE = (1ULL << 15); - - // XMM subflags - constexpr InstFlagType FLAGS_SF_UNUSED = (1ULL << 11); // No assigned behavior yet - constexpr InstFlagType FLAGS_SF_DST_GPR = (1ULL << 12); - constexpr InstFlagType FLAGS_SF_SRC_GPR = (1ULL << 13); - constexpr InstFlagType FLAGS_SF_MMX_DST = (1ULL << 14); - constexpr InstFlagType FLAGS_SF_MMX_SRC = (1ULL << 15); - constexpr InstFlagType FLAGS_SF_MMX = FLAGS_SF_MMX_DST | FLAGS_SF_MMX_SRC; - -// Enables MODRM specific subflags -// Current reserved range for this SF is [14, 17] -constexpr InstFlagType FLAGS_MODRM = (1ULL << 16); - - // With ModRM SF flag enabled - // Direction of ModRM. Dst ^ Src - // Set means destination is rm bits - // Unset means src is rm bits - constexpr InstFlagType FLAGS_SF_MOD_DST = (1ULL << 17); - - // If the instruction is restricted to mem or reg only - // 0b00 = Regular ModRM support - // 0b01 = Memory accesses only - // 0b10 = Register accesses only - // 0b11 = - constexpr InstFlagType FLAGS_SF_MOD_MEM_ONLY = (1ULL << 18); - constexpr InstFlagType FLAGS_SF_MOD_REG_ONLY = (1ULL << 19); - -// The secondary Opcode Map uses prefix bytes to overlay more instruction -// But some instructions need to ignore this overlay and consume these prefixes. -constexpr InstFlagType FLAGS_NO_OVERLAY = (1ULL << 20); -// Some instructions partially ignore overlay -// Ignore OpSize (0x66) in this case -constexpr InstFlagType FLAGS_NO_OVERLAY66 = (1ULL << 21); - -// x87 -constexpr InstFlagType FLAGS_POP = (1ULL << 22); - -// Only SEXT if the instruction is operating in 64bit operand size -constexpr InstFlagType FLAGS_SRC_SEXT64BIT = (1ULL << 23); - -// Whether or not the instruction has a VEX prefix for the first source operand -constexpr InstFlagType FLAGS_VEX_1ST_SRC = (1ULL << 24); -// Whether or not the instruction has a VEX prefix for the second source operand -constexpr InstFlagType FLAGS_VEX_2ND_SRC = (1ULL << 25); -// Whether or not the instruction has a VEX prefix for the destination -constexpr InstFlagType FLAGS_VEX_DST = (1ULL << 26); - -constexpr InstFlagType FLAGS_SIZE_DST_OFF = 58; -constexpr InstFlagType FLAGS_SIZE_SRC_OFF = FLAGS_SIZE_DST_OFF + 3; - -constexpr InstFlagType SIZE_MASK = 0b111; -constexpr InstFlagType SIZE_DEF = 0b000; -constexpr InstFlagType SIZE_8BIT = 0b001; -constexpr InstFlagType SIZE_16BIT = 0b010; -constexpr InstFlagType SIZE_32BIT = 0b011; -constexpr InstFlagType SIZE_64BIT = 0b100; -constexpr InstFlagType SIZE_128BIT = 0b101; -constexpr InstFlagType SIZE_256BIT = 0b110; -constexpr InstFlagType SIZE_64BITDEF = 0b111; // Default mode is 64bit instead of typical 32bit - -constexpr InstFlagType GetSizeDstFlags(InstFlagType Flags) { return (Flags >> FLAGS_SIZE_DST_OFF) & SIZE_MASK; } -constexpr InstFlagType GetSizeSrcFlags(InstFlagType Flags) { return (Flags >> FLAGS_SIZE_SRC_OFF) & SIZE_MASK; } - -constexpr InstFlagType GenFlagsDstSize(InstFlagType Size) { return Size << FLAGS_SIZE_DST_OFF; } -constexpr InstFlagType GenFlagsSrcSize(InstFlagType Size) { return Size << FLAGS_SIZE_SRC_OFF; } -constexpr InstFlagType GenFlagsSameSize(InstFlagType Size) { return (Size << FLAGS_SIZE_DST_OFF) | (Size << FLAGS_SIZE_SRC_OFF); } -constexpr InstFlagType GenFlagsSizes(InstFlagType Dest, InstFlagType Src) { return (Dest << FLAGS_SIZE_DST_OFF) | (Src << FLAGS_SIZE_SRC_OFF); } - -// If it has an xmm subflag -#define HAS_XMM_SUBFLAG(x, flag) (((x) & (FEXCore::X86Tables::InstFlags::FLAGS_XMM_FLAGS | (flag))) == (FEXCore::X86Tables::InstFlags::FLAGS_XMM_FLAGS | (flag))) - -// If it has non-xmm subflag -#define HAS_NON_XMM_SUBFLAG(x, flag) (((x) & (FEXCore::X86Tables::InstFlags::FLAGS_XMM_FLAGS | (flag))) == (flag)) -} - -constexpr uint8_t OpToIndex(uint8_t Op) { - switch (Op) { - // Group 1 - case 0x80: return 0; - case 0x81: return 1; - case 0x82: return 2; - case 0x83: return 3; - // Group 2 - case 0xC0: return 0; - case 0xC1: return 1; - case 0xD0: return 2; - case 0xD1: return 3; - case 0xD2: return 4; - case 0xD3: return 5; - // Group 3 - case 0xF6: return 0; - case 0xF7: return 1; - // Group 4 - case 0xFE: return 0; - // Group 5 - case 0xFF: return 0; - // Group 11 - case 0xC6: return 0; - case 0xC7: return 1; - } - return 0; -} - -using DecodedOp = DecodedInst const*; -using OpDispatchPtr = void (IR::OpDispatchBuilder::*)(DecodedOp); - -#ifndef NDEBUG -namespace X86InstDebugInfo { -constexpr uint64_t FLAGS_MEM_ALIGN_4 = (1 << 0); -constexpr uint64_t FLAGS_MEM_ALIGN_8 = (1 << 1); -constexpr uint64_t FLAGS_MEM_ALIGN_16 = (1 << 2); -constexpr uint64_t FLAGS_MEM_ALIGN_SIZE = (1 << 3); // If instruction size changes depending on prefixes -constexpr uint64_t FLAGS_MEM_ACCESS = (1 << 4); -constexpr uint64_t FLAGS_DEBUG = (1 << 5); -constexpr uint64_t FLAGS_DIVIDE = (1 << 6); - - -struct Flags { - uint64_t DebugFlags; -}; -void InstallDebugInfo(); -} - -#endif - -struct X86InstInfo { - char const *Name; - InstType Type; - InstFlags::InstFlagType Flags; ///< Must be larger than InstFlags enum - uint8_t MoreBytes; - OpDispatchPtr OpcodeDispatcher; -#ifndef NDEBUG - X86InstDebugInfo::Flags DebugInfo; - uint32_t NumUnitTestsGenerated; -#endif - - bool operator==(const X86InstInfo &b) const { - if (strcmp(Name, b.Name) != 0 || - Type != b.Type || - Flags != b.Flags || - MoreBytes != b.MoreBytes) - return false; - - // We don't care if the opcode dispatcher differs - return true; - } - bool operator!=(const X86InstInfo &b) const { - return !operator==(b); - } -}; - -static_assert(std::is_trivial::value, "X86InstInfo needs to be trivial"); - -constexpr size_t MAX_PRIMARY_TABLE_SIZE = 256; -constexpr size_t MAX_SECOND_TABLE_SIZE = 256; -constexpr size_t MAX_REP_MOD_TABLE_SIZE = 256; -constexpr size_t MAX_REPNE_MOD_TABLE_SIZE = 256; -constexpr size_t MAX_OPSIZE_MOD_TABLE_SIZE = 256; -// 6 (groups) | 6 (max indexes) | 8 ops = 0b111'111'111 = 9 bits -constexpr size_t MAX_INST_GROUP_TABLE_SIZE = 512; -// 12 (groups) | 3(max indexes) | 8 ops = 0b1111'11'111 = 9 bits -constexpr size_t MAX_INST_SECOND_GROUP_TABLE_SIZE = 512; -constexpr size_t MAX_X87_TABLE_SIZE = 1 << 11; -constexpr size_t MAX_SECOND_MODRM_TABLE_SIZE = 32; -// (3 bit prefixes) | 8 bit opcode -constexpr size_t MAX_0F_38_TABLE_SIZE = (1 << 11); -// 1 REX | 1 prefixes | 8 bit opcode -constexpr size_t MAX_0F_3A_TABLE_SIZE = (1 << 11); -constexpr size_t MAX_3DNOW_TABLE_SIZE = 256; -// VEX -// map_select(2 bits for now) | vex.pp (2 bits) | opcode (8bit) -constexpr size_t MAX_VEX_TABLE_SIZE = (1 << 13); -// VEX group ops -// group select (3 bits for now) | ModRM opcode (3 bits) -constexpr size_t MAX_VEX_GROUP_TABLE_SIZE = (1 << 7); - -// XOP -// group (2 bits for now) | vex.pp (2 bits) | opcode (8bit) -constexpr size_t MAX_XOP_TABLE_SIZE = (1 << 13); - -// XOP group ops -// group select (2 bits for now) | modrm opcode (3 bits) -constexpr size_t MAX_XOP_GROUP_TABLE_SIZE = (1 << 6); - -constexpr size_t MAX_EVEX_TABLE_SIZE = 256; - -extern FEX_DEFAULT_VISIBILITY std::array BaseOps; -extern FEX_DEFAULT_VISIBILITY std::array SecondBaseOps; -extern FEX_DEFAULT_VISIBILITY std::array RepModOps; -extern FEX_DEFAULT_VISIBILITY std::array RepNEModOps; -extern FEX_DEFAULT_VISIBILITY std::array OpSizeModOps; - -extern FEX_DEFAULT_VISIBILITY std::array PrimaryInstGroupOps; -extern FEX_DEFAULT_VISIBILITY std::array SecondInstGroupOps; -extern FEX_DEFAULT_VISIBILITY std::array SecondModRMTableOps; -extern FEX_DEFAULT_VISIBILITY std::array X87Ops; -extern FEX_DEFAULT_VISIBILITY std::array DDDNowOps; -extern FEX_DEFAULT_VISIBILITY std::array H0F38TableOps; -extern FEX_DEFAULT_VISIBILITY std::array H0F3ATableOps; - -// VEX -extern FEX_DEFAULT_VISIBILITY std::array VEXTableOps; -extern FEX_DEFAULT_VISIBILITY std::array VEXTableGroupOps; - -// XOP -extern FEX_DEFAULT_VISIBILITY std::array XOPTableOps; -extern FEX_DEFAULT_VISIBILITY std::array XOPTableGroupOps; - -// EVEX -extern FEX_DEFAULT_VISIBILITY std::array EVEXTableOps; -} - -template <> -struct fmt::formatter : formatter { - template - auto format(FEXCore::X86Tables::DecodedOperand::OpType type, FormatContext& ctx) const { - return fmt::formatter::format(static_cast(type), ctx); - } -};