mirror of https://github.com/x64dbg/zydis
Reimplemented decoding of 3DNOW instructions and improved EVEX decoding
This commit is contained in:
parent
702f6b8d53
commit
6caa68b674
|
@ -711,14 +711,14 @@ enum ZydisVectorLengths
|
||||||
/* ---------------------------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Defines the @c ZydisEVEXTupleType datatype.
|
* @brief Defines the @c ZydisTupleType datatype.
|
||||||
*/
|
*/
|
||||||
typedef uint8_t ZydisEVEXTupleType;
|
typedef uint8_t ZydisTupleType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Values that represent EVEX tuple-types.
|
* @brief Values that represent EVEX tuple-types.
|
||||||
*/
|
*/
|
||||||
enum ZydisEVEXTupleTypes
|
enum ZydisTupleTypes
|
||||||
{
|
{
|
||||||
ZYDIS_TUPLETYPE_INVALID,
|
ZYDIS_TUPLETYPE_INVALID,
|
||||||
/**
|
/**
|
||||||
|
@ -779,6 +779,31 @@ enum ZydisEVEXTupleTypes
|
||||||
ZYDIS_TUPLETYPE_DUP
|
ZYDIS_TUPLETYPE_DUP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* AVX mask mode */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Defines the @c ZydisMaskMode datatype.
|
||||||
|
*/
|
||||||
|
typedef uint8_t ZydisMaskMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Values that represent AVX mask-modes.
|
||||||
|
*/
|
||||||
|
enum ZydisMaskModes
|
||||||
|
{
|
||||||
|
ZYDIS_MASKMODE_INVALID,
|
||||||
|
/**
|
||||||
|
* @brief Merge mode. This is the default mode for all EVEX-instructions.
|
||||||
|
*/
|
||||||
|
ZYDIS_MASKMODE_MERGE,
|
||||||
|
/**
|
||||||
|
* @brief The zeroing mode is enabled for this instruction.
|
||||||
|
*/
|
||||||
|
ZYDIS_MASKMODE_ZERO
|
||||||
|
};
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
/* AVX broadcast-mode */
|
/* AVX broadcast-mode */
|
||||||
/* ---------------------------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
@ -800,6 +825,55 @@ enum ZydisBroadcastModes
|
||||||
ZYDIS_BROADCAST_MODE_1_TO_16
|
ZYDIS_BROADCAST_MODE_1_TO_16
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
/* AVX rounding-mode */
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Defines the @c ZydisRoundingMode datatype.
|
||||||
|
*/
|
||||||
|
typedef uint8_t ZydisRoundingMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Values that represent AVX rounding-modes.
|
||||||
|
*/
|
||||||
|
enum ZydisRoundingModes
|
||||||
|
{
|
||||||
|
ZYDIS_RNDMODE_INVALID,
|
||||||
|
/**
|
||||||
|
* @brief Round to nearest.
|
||||||
|
*/
|
||||||
|
ZYDIS_RNDMODE_RN,
|
||||||
|
/**
|
||||||
|
* @brief Round down.
|
||||||
|
*/
|
||||||
|
ZYDIS_RNDMODE_RD,
|
||||||
|
/**
|
||||||
|
* @brief Round up.
|
||||||
|
*/
|
||||||
|
ZYDIS_RNDMODE_RU,
|
||||||
|
/**
|
||||||
|
* @brief Round towards zero.
|
||||||
|
*/
|
||||||
|
ZYDIS_RNDMODE_RZ,
|
||||||
|
/**
|
||||||
|
* @brief Round to nearest and suppress all exceptions.
|
||||||
|
*/
|
||||||
|
ZYDIS_RNDMODE_RN_SAE,
|
||||||
|
/**
|
||||||
|
* @brief Round down and suppress all exceptions.
|
||||||
|
*/
|
||||||
|
ZYDIS_RNDMODE_RD_SAE,
|
||||||
|
/**
|
||||||
|
* @brief Round up and suppress all exceptions.
|
||||||
|
*/
|
||||||
|
ZYDIS_RNDMODE_RU_SAE,
|
||||||
|
/**
|
||||||
|
* @brief Round towards zero and suppress all exceptions.
|
||||||
|
*/
|
||||||
|
ZYDIS_RNDMODE_RZ_SAE
|
||||||
|
};
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
/* Instruction info */
|
/* Instruction info */
|
||||||
/* ---------------------------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
@ -874,11 +948,34 @@ typedef struct ZydisInstructionInfo_
|
||||||
*/
|
*/
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief The AVX vector-length.
|
||||||
|
*/
|
||||||
ZydisVectorLength vectorLength;
|
ZydisVectorLength vectorLength;
|
||||||
ZydisEVEXTupleType tupleType;
|
/**
|
||||||
|
* @brief The AVX tuple-type (EVEX only).
|
||||||
|
*/
|
||||||
|
ZydisTupleType tupleType;
|
||||||
|
/**
|
||||||
|
* @brief The AVX element-size.
|
||||||
|
*/
|
||||||
uint8_t elementSize;
|
uint8_t elementSize;
|
||||||
|
/**
|
||||||
|
* @brief The scale-factor for compressed 8-bit displacement values.
|
||||||
|
*/
|
||||||
uint8_t compressedDisp8Scale;
|
uint8_t compressedDisp8Scale;
|
||||||
|
/**
|
||||||
|
* @brief The AVX mask-mode.
|
||||||
|
*/
|
||||||
|
ZydisMaskMode maskMode;
|
||||||
|
/**
|
||||||
|
* @brief The AVX broadcast-mode.
|
||||||
|
*/
|
||||||
ZydisBroadcastMode broadcastMode;
|
ZydisBroadcastMode broadcastMode;
|
||||||
|
/**
|
||||||
|
* @brief The AVX rounding-mode.
|
||||||
|
*/
|
||||||
|
ZydisRoundingMode roundingMode;
|
||||||
} avx;
|
} avx;
|
||||||
/**
|
/**
|
||||||
* @brief Extended info about different instruction-parts like ModRM, SIB or
|
* @brief Extended info about different instruction-parts like ModRM, SIB or
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -151,10 +151,14 @@ enum ZydisInstructionTreeNodeTypes
|
||||||
* @brief Reference to an EVEX.b filter.
|
* @brief Reference to an EVEX.b filter.
|
||||||
*/
|
*/
|
||||||
ZYDIS_NODETYPE_FILTER_EVEX_B = 0x11,
|
ZYDIS_NODETYPE_FILTER_EVEX_B = 0x11,
|
||||||
|
/**
|
||||||
|
* @brief Reference to an EVEX.z filter.
|
||||||
|
*/
|
||||||
|
ZYDIS_NODETYPE_FILTER_EVEX_Z = 0x12,
|
||||||
/**
|
/**
|
||||||
* @brief Reference to an MVEX.E filter.
|
* @brief Reference to an MVEX.E filter.
|
||||||
*/
|
*/
|
||||||
ZYDIS_NODETYPE_FILTER_MVEX_E = 0x12,
|
ZYDIS_NODETYPE_FILTER_MVEX_E = 0x13,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
@ -230,6 +234,61 @@ typedef struct ZydisOperandDefinition_
|
||||||
/* Instruction definition */
|
/* Instruction definition */
|
||||||
/* ---------------------------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Defines the @c ZydisEVEXFunctionality datatype.
|
||||||
|
*/
|
||||||
|
typedef uint8_t ZydisEVEXFunctionality;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Values that represent EVEX-functionalities.
|
||||||
|
*/
|
||||||
|
enum ZydisEVEXFunctionalities
|
||||||
|
{
|
||||||
|
ZYDIS_EVEX_FUNC_INVALID,
|
||||||
|
/**
|
||||||
|
* @brief @c EVEX.b enables broadcast functionality.
|
||||||
|
*/
|
||||||
|
ZYDIS_EVEX_FUNC_BC,
|
||||||
|
/**
|
||||||
|
* @brief @c EVEX.b enables embedded-rounding functionality.
|
||||||
|
*/
|
||||||
|
ZYDIS_EVEX_FUNC_RC,
|
||||||
|
/**
|
||||||
|
* @brief @c EVEX.b enables sae functionality.
|
||||||
|
*/
|
||||||
|
ZYDIS_EVEX_FUNC_SAE
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Defines the @c ZydisMaskPolicy datatype.
|
||||||
|
*/
|
||||||
|
typedef uint8_t ZydisMaskPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Values that represent AVX mask policies.
|
||||||
|
*/
|
||||||
|
enum ZydisMaskPolicies
|
||||||
|
{
|
||||||
|
ZYDIS_MASK_POLICY_INVALID,
|
||||||
|
/**
|
||||||
|
* @brief The instruction accepts mask-registers other than the default-mask (K0), but
|
||||||
|
* does not require them.
|
||||||
|
*/
|
||||||
|
ZYDIS_MASK_POLICY_ALLOWED,
|
||||||
|
/**
|
||||||
|
* @brief The instruction requires a mask-register other than the default-mask (K0).
|
||||||
|
*/
|
||||||
|
ZYDIS_MASK_POLICY_REQUIRED,
|
||||||
|
/**
|
||||||
|
* @brief The instruction does not allow a mask-register other than the default-mask (K0).
|
||||||
|
*/
|
||||||
|
ZYDIS_MASK_POLICY_FORBIDDEN
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#define ZYDIS_INSTRUCTION_DEFINITION_BASE \
|
#define ZYDIS_INSTRUCTION_DEFINITION_BASE \
|
||||||
ZydisInstructionMnemonic mnemonic : 11; \
|
ZydisInstructionMnemonic mnemonic : 11; \
|
||||||
uint8_t operandCount : 4; \
|
uint8_t operandCount : 4; \
|
||||||
|
@ -277,8 +336,10 @@ typedef struct ZydisInstructionDefinitionVEX_
|
||||||
typedef struct ZydisInstructionDefinitionEVEX_
|
typedef struct ZydisInstructionDefinitionEVEX_
|
||||||
{
|
{
|
||||||
ZYDIS_INSTRUCTION_DEFINITION_BASE;
|
ZYDIS_INSTRUCTION_DEFINITION_BASE;
|
||||||
ZydisEVEXTupleType tupleType : 4;
|
ZydisTupleType tupleType : 4;
|
||||||
uint8_t elementSize : 7;
|
uint8_t elementSize : 7;
|
||||||
|
ZydisEVEXFunctionality functionality : 2;
|
||||||
|
ZydisMaskPolicy maskPolicy : 2;
|
||||||
} ZydisInstructionDefinitionEVEX;
|
} ZydisInstructionDefinitionEVEX;
|
||||||
|
|
||||||
typedef struct ZydisInstructionDefinitionMVEX_
|
typedef struct ZydisInstructionDefinitionMVEX_
|
||||||
|
|
|
@ -117,13 +117,6 @@ enum ZydisStatusCode
|
||||||
ZYDIS_STATUS_INVALID_MASK,
|
ZYDIS_STATUS_INVALID_MASK,
|
||||||
ZYDIS_STATUS_INVALID_VSIB,
|
ZYDIS_STATUS_INVALID_VSIB,
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------ */
|
|
||||||
/* Encoder */
|
|
||||||
/* ------------------------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
// TODO:
|
|
||||||
ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION,
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
/* Formatter */
|
/* Formatter */
|
||||||
/* ------------------------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
|
|
|
@ -1791,9 +1791,14 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
|
||||||
(const ZydisInstructionDefinitionEVEX*)definition;
|
(const ZydisInstructionDefinitionEVEX*)definition;
|
||||||
|
|
||||||
info->avx.tupleType = def->tupleType;
|
info->avx.tupleType = def->tupleType;
|
||||||
info->avx.elementSize = def->elementSize;
|
if (info->avx.tupleType)
|
||||||
|
{
|
||||||
|
ZYDIS_ASSERT(info->details.modrm.mod != 3);
|
||||||
ZYDIS_ASSERT((def->elementSize == 8) || (def->elementSize == 16) ||
|
ZYDIS_ASSERT((def->elementSize == 8) || (def->elementSize == 16) ||
|
||||||
(def->elementSize == 32) || (def->elementSize == 64));
|
(def->elementSize == 32) || (def->elementSize == 64));
|
||||||
|
info->avx.elementSize = def->elementSize;
|
||||||
|
|
||||||
|
// Compressed disp8 scale and broadcast-factor
|
||||||
switch (info->avx.tupleType)
|
switch (info->avx.tupleType)
|
||||||
{
|
{
|
||||||
case ZYDIS_TUPLETYPE_FV:
|
case ZYDIS_TUPLETYPE_FV:
|
||||||
|
@ -1816,6 +1821,7 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
ZYDIS_ASSERT(def->functionality == ZYDIS_EVEX_FUNC_BC);
|
||||||
switch (context->cache.W)
|
switch (context->cache.W)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -2045,8 +2051,20 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
|
||||||
default:
|
default:
|
||||||
ZYDIS_UNREACHABLE;
|
ZYDIS_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// TODO: Add tuple type
|
||||||
|
ZYDIS_ASSERT(info->details.modrm.mod == 3);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Set Mask Mode
|
// Rounding mode
|
||||||
|
if (def->functionality == ZYDIS_EVEX_FUNC_RC)
|
||||||
|
{
|
||||||
|
info->avx.roundingMode = ZYDIS_RNDMODE_RN_SAE + context->cache.LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mask mode
|
||||||
|
info->avx.maskMode = ZYDIS_MASKMODE_MERGE + info->details.evex.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2566,6 +2584,17 @@ static ZydisStatus ZydisNodeHandlerEvexB(ZydisInstructionInfo* info, uint16_t* i
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ZydisStatus ZydisNodeHandlerEvexZ(ZydisInstructionInfo* info, uint16_t* index)
|
||||||
|
{
|
||||||
|
ZYDIS_ASSERT(info);
|
||||||
|
ZYDIS_ASSERT(index);
|
||||||
|
|
||||||
|
ZYDIS_ASSERT(info->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX);
|
||||||
|
ZYDIS_ASSERT(info->details.evex.isDecoded);
|
||||||
|
*index = info->details.evex.z;
|
||||||
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisNodeHandlerMvexE(ZydisInstructionInfo* info, uint16_t* index)
|
static ZydisStatus ZydisNodeHandlerMvexE(ZydisInstructionInfo* info, uint16_t* index)
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(info);
|
ZYDIS_ASSERT(info);
|
||||||
|
@ -2656,6 +2685,9 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, ZydisIns
|
||||||
case ZYDIS_NODETYPE_FILTER_EVEX_B:
|
case ZYDIS_NODETYPE_FILTER_EVEX_B:
|
||||||
status = ZydisNodeHandlerEvexB(info, &index);
|
status = ZydisNodeHandlerEvexB(info, &index);
|
||||||
break;
|
break;
|
||||||
|
case ZYDIS_NODETYPE_FILTER_EVEX_Z:
|
||||||
|
status = ZydisNodeHandlerEvexZ(info, &index);
|
||||||
|
break;
|
||||||
case ZYDIS_NODETYPE_FILTER_MVEX_E:
|
case ZYDIS_NODETYPE_FILTER_MVEX_E:
|
||||||
status = ZydisNodeHandlerMvexE(info, &index);
|
status = ZydisNodeHandlerMvexE(info, &index);
|
||||||
break;
|
break;
|
||||||
|
@ -2674,7 +2706,18 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, ZydisIns
|
||||||
if (info->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW)
|
if (info->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW)
|
||||||
{
|
{
|
||||||
ZYDIS_CHECK(ZydisInputNext(context, info, &info->opcode));
|
ZYDIS_CHECK(ZydisInputNext(context, info, &info->opcode));
|
||||||
// TODO: Load new instruction definition
|
node = ZydisInstructionTreeGetRootNode();
|
||||||
|
node = ZydisInstructionTreeGetChildNode(node, 0x0F);
|
||||||
|
node = ZydisInstructionTreeGetChildNode(node, 0x0F);
|
||||||
|
node = ZydisInstructionTreeGetChildNode(node, info->opcode);
|
||||||
|
if (node->type == ZYDIS_NODETYPE_INVALID)
|
||||||
|
{
|
||||||
|
return ZYDIS_STATUS_DECODING_ERROR;
|
||||||
|
}
|
||||||
|
ZYDIS_ASSERT(node->type == ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT);
|
||||||
|
node = ZydisInstructionTreeGetChildNode(
|
||||||
|
node, (info->details.modrm.mod == 0x3) ? 0 : 1);
|
||||||
|
ZydisGetInstructionDefinition(node, &definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
info->mnemonic = definition->mnemonic;
|
info->mnemonic = definition->mnemonic;
|
||||||
|
|
|
@ -229,6 +229,13 @@ extern const ZydisInstructionTreeNode filtersREXB[][2];
|
||||||
*/
|
*/
|
||||||
extern const ZydisInstructionTreeNode filtersEVEXB[][2];
|
extern const ZydisInstructionTreeNode filtersEVEXB[][2];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Contains all EVEX.z filters.
|
||||||
|
*
|
||||||
|
* Indexed by the numeric value of the EVEX.z field.
|
||||||
|
*/
|
||||||
|
extern const ZydisInstructionTreeNode filtersEVEXZ[][2];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Contains all MVEX.E filters.
|
* @brief Contains all MVEX.E filters.
|
||||||
*
|
*
|
||||||
|
@ -383,6 +390,9 @@ const ZydisInstructionTreeNode* ZydisInstructionTreeGetChildNode(
|
||||||
case ZYDIS_NODETYPE_FILTER_EVEX_B:
|
case ZYDIS_NODETYPE_FILTER_EVEX_B:
|
||||||
ZYDIS_ASSERT(index < 2);
|
ZYDIS_ASSERT(index < 2);
|
||||||
return &filtersEVEXB[parent->value][index];
|
return &filtersEVEXB[parent->value][index];
|
||||||
|
case ZYDIS_NODETYPE_FILTER_EVEX_Z:
|
||||||
|
ZYDIS_ASSERT(index < 2);
|
||||||
|
return &filtersEVEXZ[parent->value][index];
|
||||||
case ZYDIS_NODETYPE_FILTER_MVEX_E:
|
case ZYDIS_NODETYPE_FILTER_MVEX_E:
|
||||||
ZYDIS_ASSERT(index < 2);
|
ZYDIS_ASSERT(index < 2);
|
||||||
return &filtersMVEXE[parent->value][index];
|
return &filtersMVEXE[parent->value][index];
|
||||||
|
|
Loading…
Reference in New Issue