You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bddisasm/bddisasm/include/tabledefs.h

488 lines
14 KiB

/*
* Copyright (c) 2020 Bitdefender
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _TABLEDEFS_H_
#define _TABLEDEFS_H_
//
// Types of tables.
//
typedef enum _ND_ILUT_TYPE
{
ND_ILUT_INSTRUCTION = 0,// Table contains one entry that directly points to an instruction.
ND_ILUT_OPCODE, // Table contains 256 entries. Next entry is selected using an opcode.
ND_ILUT_OPCODE_3DNOW, // Table contains 256 entries. Next entry is selected using an opcode, but the
// opcode follows the instruction.
ND_ILUT_MODRM_MOD, // Table contains 2 entries. Next entry is selected using modrm.mod (0 - mem, 1 - reg)
ND_ILUT_MODRM_REG, // Table contains 8 entries. Next entry is selected using modrm.reg.
ND_ILUT_MODRM_RM, // Table contains 8 entries. Next entry is selected using modrm.rm.
ND_ILUT_MAN_PREFIX, // Table contains 4 entries. Next entry is 0 (no prefix), 1 (0x66), 2 (0xF3), 3 (0xF2).
ND_ILUT_MODE, // Table contains 4 entries. Next entry is 0 (16 bit mode), 1 (32 bit mode), 2 (64 bit mode).
ND_ILUT_DSIZE, // Table contains 4 entries. Next entry is 0 (16 bit size), 1 (32 bit size), 2 (64 bit size).
// This DOES NOT take into consideration forced/default sizes.
ND_ILUT_ASIZE, // Default addressing mode is used to transition
ND_ILUT_AUXILIARY, // Table contains 8 entries. Next entry is 0 (no prefix), 1 (rex), 2 (rex.w), 3 (64 bit),
// 4 (default op size 16), 5 (default op size 32), 6 (default op size 64),
ND_ILUT_VENDOR, // Preferred vendor is used to transition. Default is entry 0. Otherwise, preferred
// vendor selects an alternate entry.
ND_ILUT_VEX_MMMMM, // Table contains 32 entries. Next entry is vex/xop/evex.mmmmm
ND_ILUT_VEX_PP, // Table contains 4 entries. Next entry is vex/xop/evex.pp
ND_ILUT_VEX_L, // Table contains 4 entries. Next entry is vex/xop.l or evex.l'l
ND_ILUT_VEX_W, // Table contains 2 entries. Next entry is vex/xop/evex.w
} ND_ILUT_TYPE;
// Index definitions
#define ND_ILUT_INDEX_MOD_MEM 0
#define ND_ILUT_INDEX_MOD_REG 1
#define ND_ILUT_INDEX_MAN_PREF_NONE 0
#define ND_ILUT_INDEX_MAN_PREF_66 1
#define ND_ILUT_INDEX_MAN_PREF_F3 2
#define ND_ILUT_INDEX_MAN_PREF_F2 3
#define ND_ILUT_INDEX_MODE_NONE 0
#define ND_ILUT_INDEX_MODE_16 1
#define ND_ILUT_INDEX_MODE_32 2
#define ND_ILUT_INDEX_MODE_64 3
#define ND_ILUT_INDEX_DSIZE_NONE 0
#define ND_ILUT_INDEX_DSIZE_16 1
#define ND_ILUT_INDEX_DSIZE_32 2
#define ND_ILUT_INDEX_DSIZE_64 3
#define ND_ILUT_INDEX_DSIZE_DEF64 4
#define ND_ILUT_INDEX_DSIZE_F64 5
#define ND_ILUT_INDEX_ASIZE_NONE 0
#define ND_ILUT_INDEX_ASIZE_16 1
#define ND_ILUT_INDEX_ASIZE_32 2
#define ND_ILUT_INDEX_ASIZE_64 3
#define ND_ILUT_INDEX_AUX_NONE 0
#define ND_ILUT_INDEX_AUX_REX 1
#define ND_ILUT_INDEX_AUX_REXW 2
#define ND_ILUT_INDEX_AUX_O64 3
#define ND_ILUT_INDEX_AUX_F3 4
#define ND_ILUT_INDEX_AUX_REP 5
typedef struct _ND_TABLE
{
uint32_t Type;
const void *Table[1];
} ND_TABLE, *PND_TABLE;
typedef struct _ND_TABLE_INSTRUCTION
{
uint32_t Type;
const void *Instruction;
} ND_TABLE_INSTRUCTION, *PND_TABLE_INSTRUCTION;
typedef struct _ND_TABLE_OPCODE
{
uint32_t Type;
const void *Table[256];
} ND_TABLE_OPCODE, *PND_TABLE_OPCODE;
typedef struct _ND_TABLE_MODRM_MOD
{
uint32_t Type;
const void *Table[2];
} ND_TABLE_MODRM_MOD, *PND_TABLE_MODRM_MOD;
typedef struct _ND_TABLE_MODRM_REG
{
uint32_t Type;
const void *Table[8];
} ND_TABLE_MODRM_REG, *PND_TABLE_MODRM_REG;
typedef struct _ND_TABLE_MODRM_RM
{
uint32_t Type;
const void *Table[8];
} ND_TABLE_MODRM_RM, *PND_TABLE_MODRM_RM;
typedef struct _ND_TABLE_MPREFIX
{
uint32_t Type;
const void *Table[4];
} ND_TABLE_MPREFIX, *PND_TABLE_MPREFIX;
typedef struct _ND_TABLE_AUXILIARY
{
uint32_t Type;
const void *Table[6];
} ND_TABLE_AUXILIARY, *PND_TABLE_AUXILIARY;
typedef struct _ND_TABLE_VENDOR
{
uint32_t Type;
const void *Table[6];
} ND_TABLE_VENDOR;
typedef struct _ND_TABLE_DSIZE
{
uint32_t Type;
const void *Table[6];
} ND_TABLE_DSIZE, *PND_TABLE_DSIZE;
typedef struct _ND_TABLE_ASIZE
{
uint32_t Type;
const void *Table[4];
} ND_TABLE_ASIZE, *PND_TABLE_ASIZE;
typedef struct _ND_TABLE_MODE
{
uint32_t Type;
const void *Table[4];
} ND_TABLE_MODE, *PND_TABLE_MODE;
typedef struct _ND_TABLE_VEX_MMMMM
{
uint32_t Type;
const void *Table[32];
} ND_TABLE_VEX_MMMMM, *PND_TABLE_VEX_MMMMM;
typedef struct _ND_TABLE_VEX_PP
{
uint32_t Type;
const void *Table[4];
} ND_TABLE_VEX_PP, *PND_TABLE_VEX_PP;
typedef struct _ND_TABLE_VEX_L
{
uint32_t Type;
const void *Table[4];
} ND_TABLE_VEX_L, *PND_TABLE_VEX_L;
typedef struct _ND_TABLE_VEX_W
{
uint32_t Type;
const void *Table[8];
} ND_TABLE_VEX_W, *PND_TABLE_VEX_W;
//
// One instruction entry. This structure should be maintained bellow 2 cache lines in size (128 bytes).
//
#ifdef _MSC_VER
__declspec(align(128))
#pragma warning(push)
#pragma warning(disable: 4214)
#else
__attribute__((aligned(128)))
#endif
typedef struct _ND_INSTRUCTION
{
uint16_t Instruction; // Instruction identifier. Check ND_INS_CLASS definitions.
uint8_t Category; // Instruction category. Check ND_INS_TYPE.
uint8_t IsaSet; // Instruction set. Check ND_INS_SET.
uint16_t Mnemonic; // Mnemonic (index inside the global mnemonic table).
uint16_t ValidModes; // Valid operating modes for the instruction.
uint16_t ValidPrefixes; // Accepted prefixes.
uint8_t ValidDecorators;// Accepted decorators (valid for EVEX instructions).
uint8_t OpsCount; // Low 4 bits: explicit operands count; high 4 bits: implicit ops count.
uint8_t TupleType; // EVEX tuple type.
uint8_t ExcType : 5; // SSE/VEX/EVEX/OPMASK/AMX exception type.
uint8_t ExcClass : 3; // Indicates the exception class (SSE/AVX, EVEX, OPMASK or AMX).
uint8_t FpuFlags; // FPU status word C0, C1, C2 & C3 access type.
uint8_t Reserved2;
uint32_t Reserved3;
uint32_t Attributes; // Instruction attributes.
uint64_t CpuidFlag; // Required CPUID feature flag.
// Per-flag access. Undefined flags will have their bit set in both the "Set" and "Cleared" mask, since a flag
// cannot be both cleared and set.
uint32_t TestedFlags; // Tested flags.
uint32_t ModifiedFlags; // Modified flags.
uint32_t SetFlags; // Flags that are always set to 1.
uint32_t ClearedFlags; // Flags that are always cleared.
uint64_t Operands[10];
} ND_INSTRUCTION, *PND_INSTRUCTION;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
//
// The following definitions are per-operand specific.
//
// Packed operand structure:
// Byte 0: operand type
// Byte 1: operand size
// Byte 2: operand flags
// Byte 3: operand decorators
// Byte 4: operand block addressing mode - 0 if not block addressing
//
#define ND_OP(type, size, flags, dec, block) (((uint64_t)((type) & 0xFF) << 0) | \
((uint64_t)((size) & 0xFF) << 8) | \
((uint64_t)((flags) & 0xFF) << 16) | \
((uint64_t)((dec) & 0xFF) << 24) | \
((uint64_t)((block) & 0xFF) << 32))
#define OP ND_OP
#define ND_OPS_CNT(expo, impo) ((expo) | ((impo) << 4))
#define ND_EXP_OPS_CNT(cnt) ((cnt) & 0xF)
#define ND_IMP_OPS_CNT(cnt) ((cnt) >> 4)
#define ND_OP_TYPE(op) ((op) & 0xFF)
#define ND_OP_SIZE(op) (((op) >> 8) & 0xFF)
#define ND_OP_FLAGS(op) (((op) >> 16) & 0xFF)
#define ND_OP_DECORATORS(op) (((op) >> 24) & 0xFF)
#define ND_OP_BLOCK(op) (((op) >> 32) & 0xFF)
//
// Operand sizes descriptors. These are internal and stored inside the specifier. They must be interpreted
// accordingly to extract the actual size used in the instruction. These should not be used by anyone using
// the disassembler. Use the "Size" and "RawSize" fields inside the operand instead.
//
// For info on what each enum means, check out the valid_opsize field inside disasmlib.py.
//
typedef enum _ND_OPERAND_SIZE_SPEC
{
ND_OPS_none = 0,
ND_OPS_0,
ND_OPS_asz,
ND_OPS_ssz,
ND_OPS_a,
ND_OPS_c,
ND_OPS_b,
ND_OPS_w,
ND_OPS_d,
ND_OPS_q,
ND_OPS_dq,
ND_OPS_qq,
ND_OPS_oq,
ND_OPS_v,
ND_OPS_y,
ND_OPS_yf,
ND_OPS_z,
ND_OPS_s,
ND_OPS_p,
ND_OPS_fa,
ND_OPS_fw,
ND_OPS_fd,
ND_OPS_fq,
ND_OPS_ft,
ND_OPS_fe,
ND_OPS_fs,
ND_OPS_l,
ND_OPS_rx,
ND_OPS_cl,
ND_OPS_sd,
ND_OPS_ss,
ND_OPS_ps,
ND_OPS_pd,
ND_OPS_e,
ND_OPS_f,
ND_OPS_h,
ND_OPS_x,
ND_OPS_n,
ND_OPS_u,
ND_OPS_t, // Tile register size, can be up to 1K.
// Stack sizes - indicates number of words. Also, hybrid sizes - sizes where from a large register (say 32 bit GPR)
// only a smaller amount of data is used (for example, 8 bit).
ND_OPS_v2,
ND_OPS_v3,
ND_OPS_v4,
ND_OPS_v8,
// 4 + 8 bytes accessed on the shadow stack by the SAVPREVSSP instruction.
ND_OPS_12,
// MIB
ND_OPS_mib,
// VSIB sizes (for both the index and the accessed data).
ND_OPS_vm32x,
ND_OPS_vm32y,
ND_OPS_vm32z,
ND_OPS_vm32h,
ND_OPS_vm32n,
ND_OPS_vm64x,
ND_OPS_vm64y,
ND_OPS_vm64z,
ND_OPS_vm64h,
ND_OPS_vm64n,
// Used for arbitrary sized buffers.
ND_OPS_unknown,
} ND_OPERAND_SIZE_SPEC;
//
// Operand types. These definitions are internal and have to be interpreted in order to find out what each
// operand represents. These should not be used by anyone using the disassembler. Use the "Type" field inside
// the operand structure instead.
//
// For more info on what each operand type means, please check out the valid_optype field inside disasmlib.py.
//
typedef enum _ND_OPERAND_TYPE_SPEC
{
ND_OPT_A,
ND_OPT_B,
ND_OPT_C,
ND_OPT_D,
ND_OPT_E,
ND_OPT_F,
ND_OPT_G,
ND_OPT_H,
ND_OPT_I,
ND_OPT_J,
ND_OPT_K,
ND_OPT_L,
ND_OPT_M,
ND_OPT_N,
ND_OPT_O,
ND_OPT_P,
ND_OPT_Q,
ND_OPT_R,
ND_OPT_S,
ND_OPT_T,
ND_OPT_U,
ND_OPT_V,
ND_OPT_W,
ND_OPT_X,
ND_OPT_Y,
ND_OPT_Z,
ND_OPT_rB,
ND_OPT_mB,
ND_OPT_rK,
ND_OPT_vK,
ND_OPT_mK,
ND_OPT_aK,
ND_OPT_rM,
ND_OPT_mM,
ND_OPT_rT,
ND_OPT_mT,
ND_OPT_vT,
ND_OPT_CONST_1,
// These are implicit arguments inside instructions.
// Special registers.
ND_OPT_RIP,
ND_OPT_MXCSR,
ND_OPT_PKRU,
ND_OPT_SSP,
// General Purpose REgisters.
ND_OPT_GPR_AH,
ND_OPT_GPR_rAX,
ND_OPT_GPR_rCX,
ND_OPT_GPR_rDX,
ND_OPT_GPR_rBX,
ND_OPT_GPR_rSP,
ND_OPT_GPR_rBP,
ND_OPT_GPR_rSI,
ND_OPT_GPR_rDI,
ND_OPT_GPR_rR11,
// Segment registers.
ND_OPT_SEG_CS,
ND_OPT_SEG_SS,
ND_OPT_SEG_DS,
ND_OPT_SEG_ES,
ND_OPT_SEG_FS,
ND_OPT_SEG_GS,
// FPU registers.
ND_OPT_FPU_ST0,
ND_OPT_FPU_STX,
// SSE registers.
ND_OPT_SSE_XMM0,
// Implicit memory operands.
ND_OPT_MEM_rBX_AL,
ND_OPT_MEM_rDI,
ND_OPT_MEM_SHS,
ND_OPT_MEM_SHSP,
ND_OPT_MEM_SHS0,
// Special immediates.
ND_OPT_Im2z,
// Misc CR/XCR/MSR/SYS registers.
ND_OPT_CR_0,
ND_OPT_SYS_IDTR,
ND_OPT_SYS_GDTR,
ND_OPT_SYS_LDTR,
ND_OPT_SYS_TR,
ND_OPT_X87_CONTROL,
ND_OPT_X87_TAG,
ND_OPT_X87_STATUS,
ND_OPT_MSR,
ND_OPT_XCR,
ND_OPT_MSR_TSC,
ND_OPT_MSR_TSCAUX,
ND_OPT_MSR_SEIP,
ND_OPT_MSR_SESP,
ND_OPT_MSR_SCS,
ND_OPT_MSR_STAR,
ND_OPT_MSR_LSTAR,
ND_OPT_MSR_FMASK,
ND_OPT_MSR_FSBASE,
ND_OPT_MSR_GSBASE,
ND_OPT_MSR_KGSBASE,
ND_OPT_XCR_0,
ND_OPT_REG_BANK,
} ND_OPERAND_TYPE_SPEC;
//
// Operand flags.
//
#define ND_OPF_DEFAULT 0x01 // The operand is default, no need to show it in disassembly.
#define ND_OPF_SEX_OP1 0x02 // The operand is sign-extended to the first operands' size.
#define ND_OPF_SEX_DWS 0x04 // The operand is sign-extended to the default word size.
#define ND_OPF_N 0x00 // The operand is not accessed.
#define ND_OPF_R 0x10 // The operand is read.
#define ND_OPF_W 0x20 // The operand is written.
#define ND_OPF_CR 0x40 // The operand is read conditionally.
#define ND_OPF_CW 0x80 // The operand is written conditionally.
#define ND_OPF_RW 0x30 // Read-Write access.
#define ND_OPF_RCW 0x90 // Read-Conditional Write access.
#define ND_OPF_CRW 0X60 // Conditional Read-Write access.
#define ND_OPF_CRCW 0xC0 // Conditional Read-Conditional Write access.
//
// Operand decorator flags.
//
#define ND_OPD_MASK 0x01 // Mask accepted.
#define ND_OPD_Z 0x02 // Zeroing accepted.
#define ND_OPD_B32 0x04 // 32 bit broadcast supported.
#define ND_OPD_B64 0x08 // 64 bit broadcast supported.
#define ND_OPD_SAE 0x10 // Suppress all exceptions supported.
#define ND_OPD_ER 0x20 // Embedded rounding supported.
//
// Include auto-generated stuff.
//
#include "mnemonics.h"
#include "../inc/constants.h"
#include "instructions.h"
#include "prefixes.h"
#include "table_root.h"
#include "table_xop.h"
#include "table_vex.h"
#include "table_evex.h"
#endif // _TABLEDEFS_H_