mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-29 04:01:27 +01:00
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.
This commit is contained in:
1 parent
ea52ae3bbc
commit
c87f361bb5
26 files changed
+526
-552
No files matched your search
+1
-1
@@ -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 <FEXCore/Core/SignalDelegator.h>
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
#include <FEXCore/Debug/InternalThreadState.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/HLE/SyscallHandler.h>
|
||||
#include <FEXCore/HLE/SourcecodeResolver.h>
|
||||
#include <FEXCore/HLE/Linux/ThreadManagement.h>
|
||||
|
||||
+1
-1
@@ -7,6 +7,7 @@ $end_info$
|
||||
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/Frontend.h"
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <array>
|
||||
#include <assert.h>
|
||||
@@ -14,7 +15,6 @@ $end_info$
|
||||
#include <cstring>
|
||||
#include <FEXCore/Config/Config.h>
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/HLE/SyscallHandler.h>
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/HLE/SyscallHandler.h>
|
||||
#include <FEXCore/Utils/Telemetry.h>
|
||||
#include <FEXCore/fextl/set.h>
|
||||
|
||||
@@ -7,12 +7,12 @@ $end_info$
|
||||
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/OpcodeDispatcher.h"
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Config/Config.h>
|
||||
#include <FEXCore/Core/Context.h>
|
||||
#include <FEXCore/Core/CoreState.h>
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/HLE/SyscallHandler.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/IR/IREmitter.h>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "Interface/Core/Frontend.h"
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
#include "Interface/Context/Context.h"
|
||||
|
||||
#include <FEXCore/Config/Config.h>
|
||||
#include <FEXCore/Core/Context.h>
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/IR/IntrusiveIRList.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/IR/IREmitter.h>
|
||||
|
||||
@@ -5,7 +5,8 @@ desc: Handles x86/64 Crypto instructions to IR
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/IR/IREmitter.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include "Interface/Core/OpcodeDispatcher.h"
|
||||
|
||||
@@ -7,10 +7,10 @@ $end_info$
|
||||
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/OpcodeDispatcher.h"
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
#include <FEXCore/Config/Config.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ $end_info$
|
||||
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/Core/OpcodeDispatcher.h"
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Config/Config.h>
|
||||
#include <FEXCore/Core/CoreState.h>
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/OpcodeDispatcher.h"
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Core/CoreState.h>
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/Utils/EnumUtils.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/IR/IREmitter.h>
|
||||
|
||||
@@ -6,10 +6,10 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/OpcodeDispatcher.h"
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Core/CoreState.h>
|
||||
#include <FEXCore/Core/X86Enums.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/Utils/EnumUtils.h>
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <FEXCore/IR/IREmitter.h>
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
#ifndef NDEBUG
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
#include <tuple>
|
||||
|
||||
|
||||
+2
-1
@@ -5,8 +5,9 @@ tags: frontend|x86-tables
|
||||
$end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Core/Context.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
namespace FEXCore::X86Tables {
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ $end_info$
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Core/Context.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ $end_info$
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace FEXCore::X86Tables {
|
||||
|
||||
@@ -6,8 +6,6 @@ $end_info$
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace FEXCore::X86Tables {
|
||||
|
||||
@@ -5,7 +5,6 @@ $end_info$
|
||||
*/
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
#include <iterator>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -6,7 +6,6 @@ $end_info$
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/Core/Context.h>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
@@ -7,7 +7,6 @@ $end_info$
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Core/Context.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ $end_info$
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
#include <iterator>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ $end_info$
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace FEXCore::X86Tables {
|
||||
|
||||
@@ -7,7 +7,6 @@ $end_info$
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Core/Context.h>
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ $end_info$
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <iterator>
|
||||
|
||||
namespace FEXCore::X86Tables {
|
||||
|
||||
+509
-1
@@ -5,13 +5,514 @@ $end_info$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <FEXCore/Core/Context.h>
|
||||
|
||||
#include <FEXCore/Utils/LogManager.h>
|
||||
|
||||
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 = <Reserved>
|
||||
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<X86InstInfo>::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<X86InstInfo, MAX_PRIMARY_TABLE_SIZE> BaseOps;
|
||||
extern std::array<X86InstInfo, MAX_SECOND_TABLE_SIZE> SecondBaseOps;
|
||||
extern std::array<X86InstInfo, MAX_REP_MOD_TABLE_SIZE> RepModOps;
|
||||
extern std::array<X86InstInfo, MAX_REPNE_MOD_TABLE_SIZE> RepNEModOps;
|
||||
extern std::array<X86InstInfo, MAX_OPSIZE_MOD_TABLE_SIZE> OpSizeModOps;
|
||||
|
||||
extern std::array<X86InstInfo, MAX_INST_GROUP_TABLE_SIZE> PrimaryInstGroupOps;
|
||||
extern std::array<X86InstInfo, MAX_INST_SECOND_GROUP_TABLE_SIZE> SecondInstGroupOps;
|
||||
extern std::array<X86InstInfo, MAX_SECOND_MODRM_TABLE_SIZE> SecondModRMTableOps;
|
||||
extern std::array<X86InstInfo, MAX_X87_TABLE_SIZE> X87Ops;
|
||||
extern std::array<X86InstInfo, MAX_3DNOW_TABLE_SIZE> DDDNowOps;
|
||||
extern std::array<X86InstInfo, MAX_0F_38_TABLE_SIZE> H0F38TableOps;
|
||||
extern std::array<X86InstInfo, MAX_0F_3A_TABLE_SIZE> H0F3ATableOps;
|
||||
|
||||
// VEX
|
||||
extern std::array<X86InstInfo, MAX_VEX_TABLE_SIZE> VEXTableOps;
|
||||
extern std::array<X86InstInfo, MAX_VEX_GROUP_TABLE_SIZE> VEXTableGroupOps;
|
||||
|
||||
// XOP
|
||||
extern std::array<X86InstInfo, MAX_XOP_TABLE_SIZE> XOPTableOps;
|
||||
extern std::array<X86InstInfo, MAX_XOP_GROUP_TABLE_SIZE> XOPTableGroupOps;
|
||||
|
||||
// EVEX
|
||||
extern std::array<X86InstInfo, MAX_EVEX_TABLE_SIZE> EVEXTableOps;
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
extern uint64_t Total;
|
||||
extern uint64_t NumInsts;
|
||||
@@ -102,3 +603,10 @@ void InitializeInfoTables(Context::OperatingMode Mode);
|
||||
|
||||
}
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<FEXCore::X86Tables::DecodedOperand::OpType> : formatter<uint32_t> {
|
||||
template <typename FormatContext>
|
||||
auto format(FEXCore::X86Tables::DecodedOperand::OpType type, FormatContext& ctx) const {
|
||||
return fmt::formatter<uint32_t>::format(static_cast<uint32_t>(type), ctx);
|
||||
}
|
||||
};
|
||||
@@ -6,7 +6,6 @@ $end_info$
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
#include <iterator>
|
||||
|
||||
namespace FEXCore::X86Tables {
|
||||
|
||||
@@ -6,8 +6,6 @@ $end_info$
|
||||
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
|
||||
#include <FEXCore/Debug/X86Tables.h>
|
||||
|
||||
#include <iterator>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
-522
@@ -1,522 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
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 = <Reserved>
|
||||
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<X86InstInfo>::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<X86InstInfo, MAX_PRIMARY_TABLE_SIZE> BaseOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_SECOND_TABLE_SIZE> SecondBaseOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_REP_MOD_TABLE_SIZE> RepModOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_REPNE_MOD_TABLE_SIZE> RepNEModOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_OPSIZE_MOD_TABLE_SIZE> OpSizeModOps;
|
||||
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_INST_GROUP_TABLE_SIZE> PrimaryInstGroupOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_INST_SECOND_GROUP_TABLE_SIZE> SecondInstGroupOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_SECOND_MODRM_TABLE_SIZE> SecondModRMTableOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_X87_TABLE_SIZE> X87Ops;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_3DNOW_TABLE_SIZE> DDDNowOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_0F_38_TABLE_SIZE> H0F38TableOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_0F_3A_TABLE_SIZE> H0F3ATableOps;
|
||||
|
||||
// VEX
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_VEX_TABLE_SIZE> VEXTableOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_VEX_GROUP_TABLE_SIZE> VEXTableGroupOps;
|
||||
|
||||
// XOP
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_XOP_TABLE_SIZE> XOPTableOps;
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_XOP_GROUP_TABLE_SIZE> XOPTableGroupOps;
|
||||
|
||||
// EVEX
|
||||
extern FEX_DEFAULT_VISIBILITY std::array<X86InstInfo, MAX_EVEX_TABLE_SIZE> EVEXTableOps;
|
||||
}
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<FEXCore::X86Tables::DecodedOperand::OpType> : formatter<uint32_t> {
|
||||
template <typename FormatContext>
|
||||
auto format(FEXCore::X86Tables::DecodedOperand::OpType type, FormatContext& ctx) const {
|
||||
return fmt::formatter<uint32_t>::format(static_cast<uint32_t>(type), ctx);
|
||||
}
|
||||
};
|
||||
Reference in new issue
Block a user